Add buffer saving with keybinding
This commit is contained in:
parent
e8ea80ff66
commit
dfdadef143
BIN
JetBrainsMono-Regular.otf
Normal file
BIN
JetBrainsMono-Regular.otf
Normal file
Binary file not shown.
@ -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)
|
||||||
|
@ -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
31
fide.py
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user