diff --git a/JetBrainsMono-Regular.otf b/JetBrainsMono-Regular.otf new file mode 100644 index 0000000..ad950a9 Binary files /dev/null and b/JetBrainsMono-Regular.otf differ diff --git a/config.py b/config.py index bb1debb..2a280d7 100644 --- a/config.py +++ b/config.py @@ -11,6 +11,7 @@ kb('insert', 'escape', lambda: keymap_push(keymappings['normal'])) kb('insert', 'backspace', buffer_delete_character_under_cursor) kb('insert', 'delete', buffer_delete_next_character) kb('insert', 'return', buffer_newline_at_pos) +kb('insert', 'C-s', buffer_save) kb('normal', 'i', keymap_pop) kb('normal', 'H', cursor_go_buffer_beginning) kb('normal', 'L', cursor_go_buffer_end) @@ -20,3 +21,4 @@ kb('normal', 'k', cursor_go_up) kb('normal', 'l', cursor_go_right) kb('normal', '^', cursor_go_line_beginning) kb('normal', '$', cursor_go_line_end) +kb('normal', 'C-s', buffer_save) diff --git a/editing.py b/editing.py index 4ccfa41..5f41d9a 100644 --- a/editing.py +++ b/editing.py @@ -141,3 +141,10 @@ def buffer_insert_text_at_cursor(text): # def buffer_switch_insert_mode(): # ctx.current_buffer.mode = 'insert' + +def buffer_save(): + buf = ctx.current_buffer + # if buf.filepath is not None: + with open(buf.filepath, 'w') as f: + text = '\n'.join(map(lambda l: l.piece.get_text(), buf.lines)) + f.write(text) diff --git a/fide.py b/fide.py index 07beb37..5529287 100755 --- a/fide.py +++ b/fide.py @@ -9,7 +9,7 @@ import sys import time import copy from dataclasses import dataclass -from typing import List +from typing import List, Optional from code import InteractiveConsole, InteractiveInterpreter @@ -23,6 +23,8 @@ class Cursor: @dataclass(slots=True) class Line: + # Making this a PieceTable rather than a string is rather pointless right now + # But it's easier to operate on rows for the time being piece: PieceTable length: int @@ -30,7 +32,7 @@ class Line: class Buffer: lines: List[Line] cursor: Cursor - mode: str = 'insert' + filepath: Optional[str] = None def cursor_pos(cursor: Cursor): return (cursor.line_num, cursor.col) @@ -42,11 +44,11 @@ def cursor_draw(cursor: Cursor): def line_create(text: str) -> Line: return Line(PieceTable(text), len(text)) -def buffer_create(text: str, cursor: Cursor) -> Buffer: +def buffer_create(text: str, filepath: str, cursor: Cursor) -> Buffer: lines = [] for line in text.split('\n'): lines.append(line_create(line)) - return Buffer(lines, cursor) + return Buffer(lines, cursor, filepath) def buffer_line_current(buf: Buffer) -> Line: return buf.lines[buf.cursor.line_num] @@ -69,7 +71,7 @@ clock = pg.time.Clock() pg.init() pg.font.init() -text_renderer = pg.font.SysFont('JetBrains Mono', 14) +text_renderer = pg.font.Font('JetBrainsMono-Regular.otf', 14) screen = pg.display.set_mode((900, 900), pg.RESIZABLE) pg.key.set_repeat(240, 10) @@ -81,13 +83,18 @@ def load_file(path): @dataclass class GlobalContext: - cursor = Cursor(width=8, height=20) - text = load_file('../gux/test.c') - current_buffer = buffer_create(text, cursor) + text: str + current_buffer: Buffer + cursor: Cursor # global ctx global ctx -ctx = GlobalContext() +cursor = Cursor(width=8, height=20) +if len(sys.argv) <= 1: + ctx = GlobalContext("", buffer_create("", cursor), cursor) +else: + text = load_file(sys.argv[1]) + ctx = GlobalContext(text, buffer_create(text, sys.argv[1], cursor), cursor) from config import * from editing import * from keybindings import * @@ -124,15 +131,15 @@ def main(): keymap.mapping[kb_to_test]() if not keymap.pinned: keymap_stack.pop() - break passthrough = False + break else: if keymap.pop_not_found: keymap_stack.pop() - else: - print(f"{kb_to_test} not found") if not keymap.fallthrough: passthrough = False + if len(kb_to_test.key) == 1: + print(f"{kb_to_test} not found") break # No keybinding found so send the directly to the buffer # I think emacs instead binds every key to a function that sends the diff --git a/fide.todo b/fide.todo index 4d6b110..15e4b42 100644 --- a/fide.todo +++ b/fide.todo @@ -7,5 +7,10 @@ * DONE Basic text editing functions * DONE Basic keybindings system * DONE Parse keymaps so config matches pygame keys -* TODO Keymap precedence system +* DONE Keymap fallthrough/precedence stacking +* DONE Pass the file you want to edit as a command line argument +* DONE Save buffer function with a keybinding +* TODO Add reverse parsing of keymaps to show users what they're typing +* TODO Add reverse parsing of keymaps to show users what they're typing + diff --git a/keybindings.py b/keybindings.py index bd979b0..4b8e14d 100644 --- a/keybindings.py +++ b/keybindings.py @@ -18,6 +18,7 @@ class Keymap: global keymappings global keymap_stack +global reverse_binding def modsym_to_flag(sym: str): match sym: @@ -88,11 +89,15 @@ keymap_stack = [ keymappings = { 'insert': keymap_stack[0], 'normal': keymap_stack[1], - } +} + +# Do we even need this? +reverse_binding = {} def kb(mode: str, binding: str, f: Callable): - b = parse_keybinding(binding) - keymappings[mode].mapping[b] = f + keybinding = parse_keybinding(binding) + keymappings[mode].mapping[keybinding] = f + reverse_binding[keybinding] = binding def keymap_push(keymap: Keymap): keymap_stack.append(keymap)