Add buffer saving with keybinding

This commit is contained in:
Joseph Ferano 2023-11-09 12:22:47 +07:00
parent e8ea80ff66
commit dfdadef143
6 changed files with 42 additions and 16 deletions

BIN
JetBrainsMono-Regular.otf Normal file

Binary file not shown.

View File

@ -11,6 +11,7 @@ kb('insert', 'escape', lambda: keymap_push(keymappings['normal']))
kb('insert', 'backspace', buffer_delete_character_under_cursor) kb('insert', 'backspace', buffer_delete_character_under_cursor)
kb('insert', 'delete', buffer_delete_next_character) kb('insert', 'delete', buffer_delete_next_character)
kb('insert', 'return', buffer_newline_at_pos) kb('insert', 'return', buffer_newline_at_pos)
kb('insert', 'C-s', buffer_save)
kb('normal', 'i', keymap_pop) kb('normal', 'i', keymap_pop)
kb('normal', 'H', cursor_go_buffer_beginning) kb('normal', 'H', cursor_go_buffer_beginning)
kb('normal', 'L', cursor_go_buffer_end) 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', 'l', cursor_go_right)
kb('normal', '^', cursor_go_line_beginning) kb('normal', '^', cursor_go_line_beginning)
kb('normal', '$', cursor_go_line_end) kb('normal', '$', cursor_go_line_end)
kb('normal', 'C-s', buffer_save)

View File

@ -141,3 +141,10 @@ def buffer_insert_text_at_cursor(text):
# def buffer_switch_insert_mode(): # def buffer_switch_insert_mode():
# ctx.current_buffer.mode = 'insert' # 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)

31
fide.py
View File

@ -9,7 +9,7 @@ import sys
import time import time
import copy import copy
from dataclasses import dataclass from dataclasses import dataclass
from typing import List from typing import List, Optional
from code import InteractiveConsole, InteractiveInterpreter from code import InteractiveConsole, InteractiveInterpreter
@ -23,6 +23,8 @@ class Cursor:
@dataclass(slots=True) @dataclass(slots=True)
class Line: 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 piece: PieceTable
length: int length: int
@ -30,7 +32,7 @@ class Line:
class Buffer: class Buffer:
lines: List[Line] lines: List[Line]
cursor: Cursor cursor: Cursor
mode: str = 'insert' filepath: Optional[str] = None
def cursor_pos(cursor: Cursor): def cursor_pos(cursor: Cursor):
return (cursor.line_num, cursor.col) return (cursor.line_num, cursor.col)
@ -42,11 +44,11 @@ def cursor_draw(cursor: Cursor):
def line_create(text: str) -> Line: def line_create(text: str) -> Line:
return Line(PieceTable(text), len(text)) 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 = [] lines = []
for line in text.split('\n'): for line in text.split('\n'):
lines.append(line_create(line)) lines.append(line_create(line))
return Buffer(lines, cursor) return Buffer(lines, cursor, filepath)
def buffer_line_current(buf: Buffer) -> Line: def buffer_line_current(buf: Buffer) -> Line:
return buf.lines[buf.cursor.line_num] return buf.lines[buf.cursor.line_num]
@ -69,7 +71,7 @@ clock = pg.time.Clock()
pg.init() pg.init()
pg.font.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) screen = pg.display.set_mode((900, 900), pg.RESIZABLE)
pg.key.set_repeat(240, 10) pg.key.set_repeat(240, 10)
@ -81,13 +83,18 @@ def load_file(path):
@dataclass @dataclass
class GlobalContext: class GlobalContext:
cursor = Cursor(width=8, height=20) text: str
text = load_file('../gux/test.c') current_buffer: Buffer
current_buffer = buffer_create(text, cursor) cursor: Cursor
# global ctx # global ctx
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 config import *
from editing import * from editing import *
from keybindings import * from keybindings import *
@ -124,15 +131,15 @@ def main():
keymap.mapping[kb_to_test]() keymap.mapping[kb_to_test]()
if not keymap.pinned: if not keymap.pinned:
keymap_stack.pop() keymap_stack.pop()
break
passthrough = False passthrough = False
break
else: else:
if keymap.pop_not_found: if keymap.pop_not_found:
keymap_stack.pop() keymap_stack.pop()
else:
print(f"{kb_to_test} not found")
if not keymap.fallthrough: if not keymap.fallthrough:
passthrough = False passthrough = False
if len(kb_to_test.key) == 1:
print(f"{kb_to_test} not found")
break break
# No keybinding found so send the directly to the buffer # No keybinding found so send the directly to the buffer
# I think emacs instead binds every key to a function that sends the # I think emacs instead binds every key to a function that sends the

View File

@ -7,5 +7,10 @@
* DONE Basic text editing functions * DONE Basic text editing functions
* DONE Basic keybindings system * DONE Basic keybindings system
* DONE Parse keymaps so config matches pygame keys * 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

View File

@ -18,6 +18,7 @@ class Keymap:
global keymappings global keymappings
global keymap_stack global keymap_stack
global reverse_binding
def modsym_to_flag(sym: str): def modsym_to_flag(sym: str):
match sym: match sym:
@ -90,9 +91,13 @@ keymappings = {
'normal': keymap_stack[1], 'normal': keymap_stack[1],
} }
# Do we even need this?
reverse_binding = {}
def kb(mode: str, binding: str, f: Callable): def kb(mode: str, binding: str, f: Callable):
b = parse_keybinding(binding) keybinding = parse_keybinding(binding)
keymappings[mode].mapping[b] = f keymappings[mode].mapping[keybinding] = f
reverse_binding[keybinding] = binding
def keymap_push(keymap: Keymap): def keymap_push(keymap: Keymap):
keymap_stack.append(keymap) keymap_stack.append(keymap)