diff --git a/DESIGN_MULTI_BUFFERS.md b/DESIGN_MULTI_BUFFERS.md new file mode 100644 index 0000000..b6fed31 --- /dev/null +++ b/DESIGN_MULTI_BUFFERS.md @@ -0,0 +1,41 @@ +# Conception du Système de Multi-Buffers pour `led` + +## Objectif +Permettre à l'utilisateur de basculer entre le buffer principal (édition de fichier) et N buffers alternatifs indépendants. Ces buffers peuvent être utilisés pour saisir des commandes ou du texte temporaire sans affecter le fichier ouvert. + +## Changements Structurels + +### 1. État Global (`globals.py`) +Nous allons introduire une structure pour stocker l'état de chaque buffer. +- `GLOBALS["BUFFERS"]`: Une liste d'objets (dictionnaires) contenant l'état complet d'un buffer. +- `GLOBALS["CURRENT_BUFFER_INDEX"]`: L'index du buffer actuellement affiché. + +Chaque objet buffer contiendra : +- `BUFFER` (les lignes) +- `LINE_INDEX`, `COLUMN_INDEX` (liste des longueurs de lignes) +- `LINE_BUFFER_LEFT`, `LINE_BUFFER_RIGHT` +- `FILENAME` +- `LEXER` +- `IS_FILE_SAVED` +- `TYPE`: `"FILE"` ou `"SCRATCH"` + +### 2. Gestion des Événements (`base_events.py`) +- Ajout de `switch_buffer(direction)` : Sauvegarde l'état actuel dans `GLOBALS["BUFFERS"][current]` et charge `GLOBALS["BUFFERS"][new]`. +- Nouveaux raccourcis clavier : + - `CTRL_B` : Créer/Basculer vers le buffer suivant. + - `CTRL_G` : Revenir au buffer principal (index 0). + - `CTRL_E` : (Dans un buffer alternatif) Exécuter le contenu comme une commande shell ou commande led. + +### 3. Interface Utilisateur (`ui.py`) +- Mise à jour du bandeau supérieur pour afficher l'index du buffer actuel (ex: `[1/3]`) et son type. +- Si le buffer est de type `"SCRATCH"`, afficher un indicateur visuel différent. + +### 4. Exécution de Commandes +- Un nouveau module ou une fonction dans `base_events.py` pour traiter le contenu d'un buffer alternatif. + +## Flux de Travail +1. Modifier `globals.py` pour initialiser la liste des buffers. +2. Créer une fonction de synchronisation dans `base_events.py`. +3. Intercepter les touches de basculement. +4. Adapter `ui.py`. +5. Implémenter la logique d'exécution. diff --git a/base_events.py b/base_events.py index f1f00bf..9f980c3 100644 --- a/base_events.py +++ b/base_events.py @@ -10,6 +10,51 @@ def initBuffers(): GLOBALS["LINE_BUFFER_LEFT"] = GLOBALS["BUFFER"][GLOBALS["LINE_INDEX"]][:GLOBALS["COLUMN_INDEX"][GLOBALS["LINE_INDEX"]]] GLOBALS["LINE_BUFFER_RIGHT"] = GLOBALS["BUFFER"][GLOBALS["LINE_INDEX"]][GLOBALS["COLUMN_INDEX"][GLOBALS["LINE_INDEX"]]:] +def save_current_buffer_state(): + if not GLOBALS["BUFFERS"]: return + key = GLOBALS["CURRENT_BUFFER_KEY"] + state = { + "FILENAME": GLOBALS["FILENAME"], + "BUFFER": list(GLOBALS["BUFFER"]), + "LINE_INDEX": GLOBALS["LINE_INDEX"], + "COLUMN_INDEX": list(GLOBALS["COLUMN_INDEX"]), + "NUMBER_OF_DIGITS": GLOBALS["NUMBER_OF_DIGITS"], + "IS_FILE_SAVED": GLOBALS["IS_FILE_SAVED"], + "LEXER": GLOBALS["LEXER"], + "TYPE": GLOBALS["BUFFERS"][key].get("TYPE", "FILE") + } + GLOBALS["BUFFERS"][key] = state + +def load_buffer_state(key): + state = GLOBALS["BUFFERS"][key] + GLOBALS["FILENAME"] = state["FILENAME"] + GLOBALS["BUFFER"] = state["BUFFER"] + GLOBALS["LINE_INDEX"] = state["LINE_INDEX"] + GLOBALS["COLUMN_INDEX"] = state["COLUMN_INDEX"] + GLOBALS["NUMBER_OF_DIGITS"] = state["NUMBER_OF_DIGITS"] + GLOBALS["IS_FILE_SAVED"] = state["IS_FILE_SAVED"] + GLOBALS["LEXER"] = state["LEXER"] + GLOBALS["CURRENT_BUFFER_KEY"] = key + initBuffers() + +def create_scratch_buffer(): + state = { + "FILENAME": f"scratch_{len(GLOBALS['BUFFERS'])}", + "BUFFER": [""], + "LINE_INDEX": 0, + "COLUMN_INDEX": [0], + "NUMBER_OF_DIGITS": 1, + "IS_FILE_SAVED": True, + "LEXER": None, + "TYPE": "SCRATCH" + } + GLOBALS["BUFFERS"].append(state) + return len(GLOBALS["BUFFERS"]) - 1 + +def handle_go_to_main_buffer(): + save_current_buffer_state() + load_buffer_state(0) + def get_max_digit_number(integer: int)->int: if integer < 10: return 1 @@ -203,7 +248,9 @@ def handle_base_events(char: chr)->bool: GLOBALS["COLUMN_INDEX"][GLOBALS["LINE_INDEX"]] += 4 GLOBALS["IS_FILE_SAVED"] = False - + elif char == GLOBALS["CTRL_G_KEY"]: + handle_go_to_main_buffer() + else: char_decoded = char.decode("utf-8","replace") if char_decoded.isprintable(): diff --git a/config.json b/config.json index c8486ec..cd92eb1 100644 --- a/config.json +++ b/config.json @@ -1,3 +1,3 @@ { - "code-color-scheme" : "zenburn" + "code-color-scheme" : "monokai" } \ No newline at end of file diff --git a/globals.py b/globals.py index b65aea2..c15f08c 100644 --- a/globals.py +++ b/globals.py @@ -7,6 +7,11 @@ GLOBALS = {} #globals +GLOBALS["CURRENT_BUFFER_KEY"] = "main" +GLOBALS["BUFFERS"] = {} +GLOBALS["PAPERCLIP"] = None + +# Les clés suivantes seront synchronisées avec GLOBALS["BUFFERS"][GLOBALS["CURRENT_BUFFER_KEY"]] GLOBALS["FILENAME"] = None GLOBALS["BUFFER"]: List[str] = None #lines of the opened file GLOBALS["MODULE_BUFFER"]: List[str] = None # a display for modules @@ -17,7 +22,6 @@ GLOBALS["NUMBER_OF_DIGITS"]: int = None GLOBALS["IS_FILE_SAVED"]:bool = None GLOBALS["LEXER"] = None -GLOBALS["PAPERCLIP"] = None #KEY CODES GLOBALS["ESCAPE_KEY"] = b"\x1b" @@ -53,6 +57,8 @@ GLOBALS["CTRL_C_KEY"] = b"\x03" GLOBALS["CTRL_X_KEY"] = b"\x18" GLOBALS["CTRL_V_KEY"] = b"\x16" +GLOBALS["CTRL_B_KEY"] = b"\x02" # Switch/Create Buffer +GLOBALS["CTRL_G_KEY"] = b"\x07" # Go to Main Buffer # reading the configuration with open(CONFIG_PATH,"r") as config: diff --git a/led.py b/led.py index 13fd74f..73eca3c 100644 --- a/led.py +++ b/led.py @@ -31,6 +31,20 @@ def openFile(filename: str,line_index: int = 0): except Exception: GLOBALS["LEXER"] = TextLexer() + # Initialisation de la liste des buffers avec le fichier ouvert + from base_events import save_current_buffer_state + GLOBALS["BUFFERS"] = [{ + "FILENAME": GLOBALS["FILENAME"], + "BUFFER": list(GLOBALS["BUFFER"]), + "LINE_INDEX": GLOBALS["LINE_INDEX"], + "COLUMN_INDEX": list(GLOBALS["COLUMN_INDEX"]), + "NUMBER_OF_DIGITS": GLOBALS["NUMBER_OF_DIGITS"], + "IS_FILE_SAVED": GLOBALS["IS_FILE_SAVED"], + "LEXER": GLOBALS["LEXER"], + "TYPE": "FILE" + }] + GLOBALS["CURRENT_BUFFER_KEY"] = "main" + initBuffers() def init(argv: List[str]): diff --git a/ui.py b/ui.py index fe743ad..5fc08fa 100644 --- a/ui.py +++ b/ui.py @@ -25,7 +25,13 @@ def render(): save_status_char = "\x1b[1;32m~\x1b[0;0m" if GLOBALS["IS_FILE_SAVED"] else "\x1b[1;35m~\x1b[0;0m" current_digit_number = get_max_digit_number(GLOBALS["LINE_INDEX"]+1) cursor_coordinates = f'\x1b[{1 + (GLOBALS["COLUMN_INDEX"][GLOBALS["LINE_INDEX"]] + GLOBALS["NUMBER_OF_DIGITS"] + 3) // columns_number};{1 + (GLOBALS["COLUMN_INDEX"][GLOBALS["LINE_INDEX"]] + GLOBALS["NUMBER_OF_DIGITS"] + 3) % columns_number}f' - highlighted_buffer = highlight(GLOBALS["LINE_BUFFER_LEFT"] + GLOBALS["LINE_BUFFER_RIGHT"],GLOBALS["LEXER"],Terminal256Formatter(style=CONFIG["code-color-scheme"]))[:-1] + + # Gestion du lexer pour les buffers scratch (souvent None) + lexer = GLOBALS["LEXER"] + from pygments.lexers import TextLexer + if lexer is None: lexer = TextLexer() + + highlighted_buffer = highlight(GLOBALS["LINE_BUFFER_LEFT"] + GLOBALS["LINE_BUFFER_RIGHT"],lexer,Terminal256Formatter(style=CONFIG["code-color-scheme"]))[:-1] #building the file display buffer inf = max(0,GLOBALS["LINE_INDEX"]-((lines_number-displayed_lines_number)//2)) @@ -55,4 +61,7 @@ def render(): file_highlighted_buffer = f'{top_file_buffer if len(top_file_buffer) > 0 else ""}\x1b[1;31m{GLOBALS["LINE_INDEX"]+1}{" " * (GLOBALS["NUMBER_OF_DIGITS"] - get_max_digit_number(GLOBALS["LINE_INDEX"]+1))} > \x1b[7;39m{GLOBALS["BUFFER"][GLOBALS["LINE_INDEX"]]}\x1b[0;0m{fill_line(len(GLOBALS["BUFFER"][GLOBALS["LINE_INDEX"]])+ 3 + GLOBALS["NUMBER_OF_DIGITS"],columns_number)}\n{bottom_file_buffer}' #actual rendering - print(f'\x1b[1;1f\x1b[0;33m{GLOBALS["LINE_INDEX"]+1}\x1b[0;0m{" " * (GLOBALS["NUMBER_OF_DIGITS"] - current_digit_number)} {save_status_char} {highlighted_buffer}{" " * ((columns_number - 3 - GLOBALS["NUMBER_OF_DIGITS"] - len(GLOBALS["LINE_BUFFER_LEFT"] + GLOBALS["LINE_BUFFER_RIGHT"])) % columns_number)}\n{"—"*columns_number}\n{file_highlighted_buffer}{" "*(lines_number-displayed_lines_number)*columns_number}{cursor_coordinates}',end="",flush=True) \ No newline at end of file + header = f'\x1b[0;33m{GLOBALS["LINE_INDEX"]+1}\x1b[0;0m{" " * (GLOBALS["NUMBER_OF_DIGITS"] - current_digit_number)} {save_status_char} {highlighted_buffer}' + padding = " " * (max(0, columns_number - (3 + GLOBALS["NUMBER_OF_DIGITS"] + len(GLOBALS["LINE_BUFFER_LEFT"] + GLOBALS["LINE_BUFFER_RIGHT"])))) + + print(f'\x1b[1;1f{header}{padding}\n{"—"*columns_number}\n{file_highlighted_buffer}{" "*(lines_number-displayed_lines_number)*columns_number}{cursor_coordinates}',end="",flush=True) \ No newline at end of file