From ca0938b5239e2d508a5d3ad6a619ed946097ab8e Mon Sep 17 00:00:00 2001 From: Madeleine Date: Thu, 3 Nov 2022 07:31:24 +0000 Subject: [PATCH] rust branch --- .gitignore | 6 +- Cargo.lock | 7 ++ Cargo.toml | 8 ++ README.md | 35 -------- TODO.md | 1 - core/buffers.py | 90 ------------------- core/colors.py | 51 ----------- core/components.py | 73 ---------------- core/cursors.py | 68 --------------- core/modes.py | 34 -------- core/utils.py | 209 --------------------------------------------- install.sh | 11 --- lambda | 3 - main.py | 126 --------------------------- mode/command.py | 41 --------- mode/insert.py | 29 ------- mode/normal.py | 45 ---------- src/main.rs | 21 +++++ 18 files changed, 38 insertions(+), 820 deletions(-) create mode 100644 Cargo.lock create mode 100644 Cargo.toml delete mode 100644 README.md delete mode 100644 TODO.md delete mode 100644 core/buffers.py delete mode 100644 core/colors.py delete mode 100644 core/components.py delete mode 100644 core/cursors.py delete mode 100644 core/modes.py delete mode 100644 core/utils.py delete mode 100755 install.sh delete mode 100755 lambda delete mode 100644 main.py delete mode 100644 mode/command.py delete mode 100644 mode/insert.py delete mode 100644 mode/normal.py create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index 9efad1c..ee44a96 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -__pycache__ -core/__pycache__ -mode/__pycache__ -.idea \ No newline at end of file +.idea +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..568820c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "lambda" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..108e5c1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "lambda" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/README.md b/README.md deleted file mode 100644 index b760fd7..0000000 --- a/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# λ lambda - -Next generation hackable text editor for nerds. - -### Let it be known! - -Lambda is in *very* early stages at the moment. Features may change completely, or even be removed.
-Don't expect lambda to stay the way it is. Updates are pushed often. - -### Overview - -Lambda is a similar text editor to `vim` or `kakoune`.
-However, it takes a different approach to most of the features seen in other editors. - -- Lambda is written in Python, so it is easy to hack and learn. - - It also has a good amount of comments! -- Lambda is incredibly modular, so you can easily add new features. -- Lambda follows the unix philosophy of "do one thing and do it well." - - It has no bloated features, like splits or tabs - - It contains the bare necessities and provides a few extra modules -- Lambda isn't limited to modes or keybindings. - - Keybindings and modes can be easily changed - - Other modes can be used by holding down keybindings (i.e. `ctrl-x` inside of `insert` mode) -- Lambda is extremely fast and makes use of efficient memory management. - - Neovim is slow, and actually requires [a plugin to speed it up](https://github.com/lewis6991/impatient.nvim). -- Lambda has much better default keybindings than other text editors. - -### Getting started - -```bash -git clone https://github.com/SpyHoodle/lambda.git # Clone the repository -cd lambda # Enter lambda directory -chmod +x install.sh # Make the install script executable -./install.sh # Run the install script -``` \ No newline at end of file diff --git a/TODO.md b/TODO.md deleted file mode 100644 index a16511d..0000000 --- a/TODO.md +++ /dev/null @@ -1 +0,0 @@ -## TODO \ No newline at end of file diff --git a/core/buffers.py b/core/buffers.py deleted file mode 100644 index ad7279e..0000000 --- a/core/buffers.py +++ /dev/null @@ -1,90 +0,0 @@ -import os - - -class Buffer: - def __init__(self, path: str, name: str = None, data: list = None): - self.path = path - self.name = name or "[No Name]" - self.data = data or [""] - - def render(self, instance): - for y, line in enumerate(self.data[instance.offset[0]:]): - if y <= instance.safe_height: - for x, character in enumerate(line[instance.offset[1]:]): - if x <= instance.safe_width: - instance.screen.addstr(y, x + instance.components.get_component_width( - instance.components.components["left"]), character) - - # Write blank spaces for the rest of the line - if instance.safe_width - len(line) > 0: - instance.screen.addstr(y, instance.components.get_component_width( - instance.components.components["left"]) + len(line), " " * (instance.safe_width - len(line))) - - @staticmethod - def delete_line(instance, y: int = None): - # Default to the cursor position - y = y or instance.cursor[0] - - # Remove a line from the buffer - instance.buffer.data.pop(y) - - @staticmethod - def insert_line(instance, y: int = None): - # Default to the cursor position - y = y or instance.cursor[0] - - # Insert a line into the buffer - instance.buffer.data.insert(y, "") - - @staticmethod - def delete_char(instance, y: int = None, x: int = None): - # Default to the cursor position - y = y or instance.cursor[0] - x = x or instance.cursor[1] - - # Remove a character from the line at a given index - instance.buffer.data[y] = instance.buffer.data[y][:x - 1] + instance.buffer.data[y][x:] - - @staticmethod - def insert_char(instance, char: (str, chr), y: int = None, x: int = None): - # Default to the cursor position - y = y or instance.cursor[0] - x = x or instance.cursor[1] - - # Insert a character into the line at a given index - instance.buffer.data[y] = instance.buffer.data[y][:x] + char + instance.buffer.data[y][x:] - - -def open_file(file_path): - # Open the file - with open(file_path) as f: - # Convert it into a list of lines - lines = f.readlines() - - # Add a line if the file is empty or if the last line is not empty - if lines[-1].endswith("\n") or not len(lines): - lines.append("") - - # Remove the newlines - lines = [line.rstrip("\n") for line in lines] - - # Return the list of lines - return lines - - -def load_file(file_path=None): - # Default settings for a file - file_name = "[No Name]" - file_data = [""] - - if file_path: - # Set the file's name - file_name = os.path.basename(file_path) - - # Only if the file actually exists - if os.path.exists(file_path): - # Open the file as a list of lines - file_data = open_file(file_path) - - # Return a dictionary which will become all the data about the buffer - return Buffer(file_path, file_name, file_data) diff --git a/core/colors.py b/core/colors.py deleted file mode 100644 index 1680042..0000000 --- a/core/colors.py +++ /dev/null @@ -1,51 +0,0 @@ -import curses - - -class Codes: - # Color codes - red = '\033[91m' - green = '\033[92m' - blue = '\033[94m' - yellow = '\033[93m' - cyan = '\033[96m' - magenta = '\033[95m' - white = '\033[97m' - selected_white = '\033[47m' - selected_green = '\033[42m' - strike = '\033[9m' - italic = '\033[3m' - end = '\033[0m' - - -def init_colors(): - # Activate color support - curses.start_color() - - # Foreground: WHITE, Background: BLACK - curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) - # Foreground: BLACK, Background: WHITE - curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_WHITE) - # Foreground: RED, Background: BLACK - curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLACK) - # Foreground: BLACK, Background: RED - curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_RED) - # Foreground: GREEN, Background: BLACK - curses.init_pair(5, curses.COLOR_GREEN, curses.COLOR_BLACK) - # Foreground: BLACK, Background: GREEN - curses.init_pair(6, curses.COLOR_BLACK, curses.COLOR_GREEN) - # Foreground: YELLOW, Background: BLACK - curses.init_pair(7, curses.COLOR_YELLOW, curses.COLOR_BLACK) - # Foreground: BLACK, Background: YELLOW - curses.init_pair(8, curses.COLOR_BLACK, curses.COLOR_YELLOW) - # Foreground: CYAN, Background: BLACK - curses.init_pair(9, curses.COLOR_CYAN, curses.COLOR_BLACK) - # Foreground: BLACK, Background: CYAN - curses.init_pair(10, curses.COLOR_BLACK, curses.COLOR_CYAN) - # Foreground: BLUE, Background: BLACK - curses.init_pair(11, curses.COLOR_BLUE, curses.COLOR_BLACK) - # Foreground: BLACK, Background: BLUE - curses.init_pair(12, curses.COLOR_BLACK, curses.COLOR_BLUE) - # Foreground: MAGENTA, Background: BLACK - curses.init_pair(13, curses.COLOR_MAGENTA, curses.COLOR_BLACK) - # Foreground: BLACK, Background: MAGENTA - curses.init_pair(14, curses.COLOR_BLACK, curses.COLOR_MAGENTA) diff --git a/core/components.py b/core/components.py deleted file mode 100644 index 64c2ef0..0000000 --- a/core/components.py +++ /dev/null @@ -1,73 +0,0 @@ -import curses - -from core import utils - - -class StatusBar: - def __init__(self, instance): - self.mode = instance.mode.upper() - self.file = instance.buffer.name or "[No Name]" - self.icon = instance.config["icon"] or "λ" - self.theme = "default" - self.colors = [7, 5, 13] - self.components = [self.icon, self.mode, self.file] - - def update(self, instance): - self.mode = instance.mode.upper() - self.components = [self.icon, self.mode, self.file] - - def render(self, instance): - # Clear the status bar - utils.clear_line(instance, instance.height - 2, 0) - - # Update variables - self.update(instance) - - if self.theme == "inverted": - # Initialise the x position for each component - x = 1 - - # Render each component - for count, component in enumerate(self.components): - instance.screen.addstr(instance.height - 2, x, component, - curses.color_pair(self.colors[count]) | curses.A_BOLD) - x += len(component) + 1 - - else: - # Initialise temporary colors for inverted theme - colors = [] - - # Add 1 to each color temporarily - for color in self.colors: - colors.append(color + 1) - - # Initialise the x position for each component - x = 0 - - # Render each component - for count, component in enumerate(self.components): - component = f" {component} " - instance.screen.addstr(instance.height - 2, x, component, - curses.color_pair(colors[count]) | curses.A_BOLD) - x += len(component) - - # Add a space at the end of the status bar - instance.screen.addstr(instance.height - 2, x, " " * (instance.width - x), - curses.color_pair(2)) - - -class Components: - def __init__(self, instance, components: dict = None): - self.components = components or { - "left": [" "], - "bottom": [StatusBar(instance)], - } - curses.endwin() - - @staticmethod - def get_component_width(component: list) -> int: - return len(max(component)) - - def render(self, instance): - for component in self.components["bottom"]: - component.render(instance) diff --git a/core/cursors.py b/core/cursors.py deleted file mode 100644 index c76079f..0000000 --- a/core/cursors.py +++ /dev/null @@ -1,68 +0,0 @@ -import curses - - -def mode(to_mode: str): - if to_mode == "block": - print("\033[2 q") - - elif to_mode == "line": - print("\033[6 q") - - elif to_mode == "hidden": - curses.curs_set(0) - - elif to_mode == "visible": - curses.curs_set(1) - - -def push(instance, direction: (int, str)): - if direction in (0, "up", "north"): - # If the cursor isn't at the top of the screen - if instance.raw_cursor[0] > 0: - # Move the cursor up - instance.raw_cursor[0] -= 1 - - # Move the buffer upwards if the cursor is at the top of the screen and not at the top of the buffer - if instance.raw_cursor[0] == 0 and instance.cursor[0] == instance.offset[0] and instance.cursor[0] != 0: - instance.offset[0] -= 1 - - elif direction in (2, "down", "south"): - if instance.raw_cursor[0] == instance.safe_height and instance.cursor[0] != len(instance.buffer.data) - 1: - instance.offset[0] += 1 - - # If the cursor isn't at the bottom of the screen - elif instance.raw_cursor[0] != instance.safe_height and instance.cursor[0] != len(instance.buffer.data) - 1: - # Move the cursor down - instance.raw_cursor[0] += 1 - - elif direction in (1, "right", "east"): - # Move the cursor one to the right - instance.raw_cursor[1] += 1 - - elif direction in (3, "left", "west"): - # Move the cursor one to the left - instance.raw_cursor[1] -= 1 - - -def check(instance, cursor: list) -> list: - # Prevent the cursor from going outside the buffer - cursor[1] = min(len(instance.buffer.data[instance.cursor[0]]) - 1, cursor[1]) - - # Prevent any negative values - cursor[0] = max(0, cursor[0]) - cursor[1] = max(0, cursor[1]) - - # Prevent the cursor from going outside the screen - cursor[1] = min(instance.safe_width, cursor[1]) - cursor[0] = min(instance.safe_height, cursor[0]) - - return cursor - - -def move(instance): - # Run a final check to see if the cursor is valid - instance.raw_cursor = check(instance, instance.raw_cursor) - - # Moves the cursor to anywhere on the screen - instance.screen.move(instance.raw_cursor[0], instance.raw_cursor[1] + - instance.components.get_component_width(instance.components.components["left"])) diff --git a/core/modes.py b/core/modes.py deleted file mode 100644 index 04ae88c..0000000 --- a/core/modes.py +++ /dev/null @@ -1,34 +0,0 @@ -from mode import normal, insert, command - - -def activate(instance, mode): - # Visibly update the mode - instance.mode = mode - - # Refresh the screen - instance.refresh() - - if mode == "command": - # Activate command mode - instance.components.components["bottom"][0].colors[1] = 5 - command.activate(instance) - - elif mode == "insert": - # Activate insert mode - instance.components.components["bottom"][0].colors[1] = 11 - insert.activate() - - elif mode == "normal": - # Activate normal mode - instance.components.components["bottom"][0].colors[1] = 5 - normal.activate() - - -def handle_key(instance, key): - # Normal mode - default keybindings - if instance.mode == "normal": - normal.execute(instance, key) - - # Insert mode - inserting text to the buffer - elif instance.mode == "insert": - insert.execute(instance, key) diff --git a/core/utils.py b/core/utils.py deleted file mode 100644 index 61ba8ef..0000000 --- a/core/utils.py +++ /dev/null @@ -1,209 +0,0 @@ -import curses -import json -import os -import sys -import traceback -from pathlib import Path - -from core import cursors -from core.colors import Codes as Col - - -def gracefully_exit(): - # Close the curses window - curses.endwin() - - # Finally, exit the program - sys.exit() - - -def clear_line(instance, y: int, x: int): - # Clear the line at the screen at position y, x - instance.screen.insstr(y, x, " " * (instance.width - x)) - - -def pause_screen(message: str): - # End the curses session - curses.endwin() - - # Print the message and wait for enter key - input(f"{message}\n\n Press enter to continue...") - - -def load_file(file_path: str) -> dict: - # load the json file with read permissions - with open(file_path, "r") as f: - return json.load(f) - - -def save_file(instance, file_path: str, data: list): - # Save the data to the file - with open(file_path, "w") as f: - try: - # For each line in the file - for index, line in enumerate(data): - if index == len(data) - 1: - # If this is the last line, write it without a newline - f.write(line) - - else: - # Otherwise, write the line with a newline - f.write(f"{line}\n") - - except (OSError, IOError): - # If the file could not be written, show an error message - error(instance, f"File {file_path} could not be saved.") - - -def load_config_file() -> dict: - # Parse the path of the config file - config_file_path = f"{Path.home()}/.config/lambda/config.json" - - # Only if the config file exists, attempt to load it - if os.path.exists(config_file_path): - # Return the loaded config - return load_file(config_file_path) - - -def welcome(instance): - # Startup text - title = "λ Lambda" - subtext = [ - "Next generation hackable text editor for nerds", - "", - "Type :h to open the README.md document", - "Type :o to open a file and edit", - "Type :q or to quit lambda.py" - ] - - # Centering calculations - start_x_title = int((instance.safe_width // 2) - (len(title) // 2) - len(title) % 2 + 2) - start_y = int((instance.safe_height // 2) - 1) - - # Rendering title - instance.screen.addstr(start_y, start_x_title, title, curses.color_pair(7) | curses.A_BOLD) - - # Print the subtext - for text in subtext: - start_y += 1 - start_x = int((instance.safe_width // 2) - (len(text) // 2) - len(text) % 2 + 2) - instance.screen.addstr(start_y, start_x, text) - - -def prompt(instance, message: str, color: int = 1) -> (list, None): - # Initialise the input list - inp = [] - - # Write whitespace over characters to refresh it - clear_line(instance, instance.height - 1, len(message) + len(inp) - 1) - - # Write the message to the screen - instance.screen.addstr(instance.height - 1, 0, message, curses.color_pair(color)) - - while True: - # Wait for a keypress - key = instance.screen.getch() - - # Subtracting a key (backspace) - if key in (curses.KEY_BACKSPACE, 127, '\b'): - # Write whitespace over characters to refresh it - clear_line(instance, instance.height - 1, len(message) + len(inp) - 1) - - if inp: - # Subtract a character from the input list - inp.pop() - - else: - # Exit the prompt without returning the input - return None - - elif key == 27: - # Exit the prompt, without returning the input - return None - - elif key in (curses.KEY_ENTER, ord('\n'), ord('\r'), ord(":"), ord(";")): - # Return the input list - return inp - - else: - # If any other key is typed, append it - # As long as the key is in the valid list - valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!/_-0123456789 " - if chr(key) in valid and len(inp) < (instance.width - 2): - inp.append(chr(key)) - - # Refresh the screen - instance.refresh() - - # Write the message to the screen - instance.screen.addstr(instance.height - 1, 0, message, curses.color_pair(color)) - - # Join the input together for visibility on the screen - input_text = "".join(inp) - - # Write the input text to the screen - instance.screen.addstr(instance.height - 1, len(message), input_text) - - -def press_key_to_continue(instance, message: str, color: int = 1): - # Hide the cursor - cursors.mode("hidden") - - # Clear the bottom of the screen - clear_line(instance, instance.height - 1, 0) - - # Write the entire message to the screen - instance.screen.addstr(instance.height - 1, 0, message, curses.color_pair(color)) - instance.screen.addstr(instance.height - 1, len(message) + 1, f"(press any key)") - - # Wait for a keypress - instance.screen.getch() - - # Clear the bottom of the screen - clear_line(instance, instance.height - 1, 0) - - # Show the cursor - cursors.mode("visible") - - -def error(instance, message: str): - # Parse the error message - error_message = f"ERROR: {message}" - - # Create a prompt - press_key_to_continue(instance, error_message, 3) - - -def fatal_error(exception: Exception): - # End the curses session - curses.endwin() - - # Print the error message and traceback - print(f"{Col.red}FATAL ERROR:{Col.end} " - f"{Col.yellow}{exception}{Col.end}\n") - print(traceback.format_exc()) - - # Exit, with an error exit code - sys.exit(0) - - -def goodbye(instance): - try: - # Confirm before exiting - choice = prompt(instance, "Really quit lambda? (y/n): ", 11) - - # If the user confirms, exit - if choice and choice[0] == "y": - gracefully_exit() - - # Clear the prompt if the user cancels - else: - clear_line(instance, instance.height - 1, 0) - - except KeyboardInterrupt: - # If the user presses Ctrl+C, just exit - gracefully_exit() - - except Exception as exception: - # If there is an error, print the error message and traceback - fatal_error(exception) diff --git a/install.sh b/install.sh deleted file mode 100755 index 0354a6e..0000000 --- a/install.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# Copy lambda to ~/.local/share -mkdir -p ~/.local/share/lambda -cp -rf . ~/.local/share/lambda - -# Copy lambda launcher -chmod +x ./lambda -rm -rf ~/.local/bin/lambda -ln -s ~/.local/share/lambda/lambda ~/.local/bin/lambda -chmod +x ~/.local/bin/lambda \ No newline at end of file diff --git a/lambda b/lambda deleted file mode 100755 index 7c1d1e5..0000000 --- a/lambda +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -python3 ~/.local/share/lambda/main.py "$@" diff --git a/main.py b/main.py deleted file mode 100644 index 247bc62..0000000 --- a/main.py +++ /dev/null @@ -1,126 +0,0 @@ -import argparse -import curses -import os - -from core import colors, cursors, buffers, modes, utils -from core.buffers import Buffer -from core.components import Components - - -class Lambda: - def __init__(self, buffer: Buffer = None, config: dict = None): - self.cursor = [0, 0] - self.raw_cursor = [0, 0] - self.offset = [0, 0] - self.height = 0 - self.width = 0 - self.safe_height = 0 - self.safe_width = 0 - self.mode = "normal" - self.config = config or {"icon": "λ"} - self.buffer = buffer or [""] - self.screen = curses.initscr() - self.components = Components(self) - - def update_dimensions(self): - # Calculate the entire height and width of the terminal - self.height, self.width = self.screen.getmaxyx() - - # Calculate the safe area for the buffer by removing heights & widths of components - self.safe_height = self.height - len(self.components.components["bottom"]) - 2 - self.safe_width = self.width - self.components.get_component_width(self.components.components["left"]) - 1 - - def refresh(self): - # Calculate the cursor position in the file - self.cursor[0], self.cursor[1] = self.raw_cursor[0] + self.offset[0], self.raw_cursor[1] + self.offset[1] - - # Update the dimensions of the terminal - self.update_dimensions() - - # Write the buffer to the screen - self.buffer.render(self) - - # Refresh the on-screen components - self.components.render(self) - - # Move the cursor - cursors.move(self) - - def start(self): - # Change the escape key delay to 25ms - # Fixes an issue where the "esc" key takes way too long to press - os.environ.setdefault("ESCDELAY", "25") - - # Initialise colors - colors.init_colors() - - # Change the cursor shape - cursors.mode("block") - - # Don't echo any key-presses - curses.noecho() - - # Show a welcome message if lambda opens with no file - if not self.buffer.path: - # Update the screen variables - self.refresh() - - # Show the welcome message - utils.welcome(self) - - # Main loop - self.run() - - def run(self): - try: - # The main loop, which runs until the user quits - while True: - # Update the screen variables - self.refresh() - - # Wait for a keypress - key = self.screen.getch() - - # Handle the key - modes.handle_key(self, key) - - # Refresh and clear the screen - self.screen.erase() - - except KeyboardInterrupt: # Ctrl-C - # Create a goodbye prompt - utils.goodbye(self) - - # Run the main loop again - self.run() - - -def main(): - # Shell arguments - parser = argparse.ArgumentParser(description="Next generation hackable text editor for nerds.") - parser.add_argument("file", metavar="file", type=str, nargs="?", - help="The name of a file for lambda to open") - - # Collect the arguments passed into lambda at the shell - args = parser.parse_args() - - # Load the file into a Buffer object - buffer = buffers.load_file(args.file) - - # Load the config - config = utils.load_config_file() - - # Load lambda with the buffer object - instance = Lambda(buffer, config) - - # Start the screen, this will loop until exit - try: - instance.start() - - # Excepts *any* errors that occur - except Exception as exception: - utils.fatal_error(exception) - - -if __name__ == "__main__": - main() diff --git a/mode/command.py b/mode/command.py deleted file mode 100644 index 51d28e8..0000000 --- a/mode/command.py +++ /dev/null @@ -1,41 +0,0 @@ -from core import utils - - -def execute(instance, commands: list): - # Only if commands are given - if commands: - # Check each command in the list of commands - for command in commands: - if command == "d": # Debug - # Create the debug prompt - utils.press_key_to_continue(instance, f"Cursor: {instance.cursor} Raw: {instance.raw_cursor} " - f"Len: {len(instance.buffer.data)}") - - elif command == "t": # Toggle - # Toggle the status bar theme - if instance.components.components["bottom"][0].theme == "default": - instance.components.components["bottom"][0].theme = "inverted" - else: - instance.components.components["bottom"][0].theme = "default" - - elif command == "w": # Write - # Write to the file - utils.save_file(instance, instance.buffer.path, instance.buffer.data) - - elif command == "q": # Quit - # Create a goodbye prompt - utils.goodbye(instance) - - else: # Invalid command - utils.error(instance, f"invalid command: '{command}'") - - -def activate(instance): - # Create a prompt, which returns the input (commands) - commands = utils.prompt(instance, ":") - - # Execute the commands given - execute(instance, commands) - - # Return to normal mode once all commands are executed - instance.mode = "normal" diff --git a/mode/insert.py b/mode/insert.py deleted file mode 100644 index 2e7d9cc..0000000 --- a/mode/insert.py +++ /dev/null @@ -1,29 +0,0 @@ -import curses - -from core import cursors, modes - - -def execute(instance, key): - if key == 27: # Escape - # Switch to normal mode - modes.activate(instance, "normal") - - elif key in (curses.KEY_BACKSPACE, 127, '\b'): # Backspace - if instance.cursor[1] > 0: - # Delete the character before the cursor - instance.buffer.delete_char(instance) - - # Move the cursor one to the left - cursors.push(instance, 3) - - else: - # Insert the character - instance.buffer.insert_char(instance, chr(key)) - - # Move the cursor one to the right - cursors.push(instance, 1) - - -def activate(): - # Switch the cursor to a line - cursors.mode("line") diff --git a/mode/normal.py b/mode/normal.py deleted file mode 100644 index 4bc0d44..0000000 --- a/mode/normal.py +++ /dev/null @@ -1,45 +0,0 @@ -import curses - -from core import cursors, modes, utils - - -def execute(instance, key): - if key == curses.BUTTON1_CLICKED: - # Move the cursor to the position clicked - utils.prompt(instance, str(curses.getmouse())) - - elif key in (ord("j"), curses.KEY_DOWN): - # Move the cursor down - cursors.push(instance, "down") - - elif key in (ord("k"), curses.KEY_UP): - # Move the cursor up - cursors.push(instance, "up") - - elif key in (ord("l"), curses.KEY_RIGHT): - # Move the cursor right - cursors.push(instance, "right") - - elif key in (ord("h"), curses.KEY_LEFT): - # Move the cursor left - cursors.push(instance, "left") - - elif key == ord("i"): - # Activate insert mode - modes.activate(instance, "insert") - - elif key == ord("I"): - # Move the cursor to the right - cursors.push(instance, "right") - - # Then activate insert mode - modes.activate(instance, "insert") - - elif key in (ord(":"), ord(";")): - # Activate command mode - modes.activate(instance, "command") - - -def activate(): - # Switch the cursor to a block - cursors.mode("block") diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2fe3baf --- /dev/null +++ b/src/main.rs @@ -0,0 +1,21 @@ +struct Buffer { + data: Vec, + name: &str, +} + +struct Editor { + buffer: Buffer, +} + +fn main() { + let bufffer = Buffer { + data: Vec::from([String::from("a test")]), + name: "uhh" + }; + + let editor = Editor { + buffer: bufffer, + }; + + println!("{}", editor.buffer.data[0]) +}