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', '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) | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
							
								
								
									
										31
									
								
								fide.py
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								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 | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user