import pygame as pg from pygame import Rect from piece_table import PieceTable import os import json import sys import time import copy from dataclasses import dataclass from typing import List from code import InteractiveConsole, InteractiveInterpreter from editing import * @dataclass(slots=True) class Cursor: width: float height: float line_num: int = 0 col: int = 0 want_col: int = 0 @dataclass(slots=True) class Line: piece: PieceTable length: int @dataclass(slots=True) class Buffer: lines: List[Line] cursor: Cursor def cursor_pos(cursor: Cursor): return (cursor.line_num, cursor.col) def cursor_draw(cursor: Cursor): rect = Rect(cursor.col * cursor.width, cursor.line_num * cursor.height, 3, cursor.height) pg.draw.rect(screen, "black", rect, width=2) def line_create(text: str) -> Line: return Line(PieceTable(text), len(text)) def buffer_create(text: str, cursor: Cursor) -> Buffer: lines = [] for line in text.split('\n'): lines.append(line_create(line)) return Buffer(lines, cursor) def buffer_line_current(buf: Buffer) -> Line: return buf.lines[buf.cursor.line_num] def buffer_line_num(buf: Buffer) -> int: return buf.cursor.line_num def buffer_total_lines(buf: Buffer) -> int: return len(buf.lines) def buffer_line_len(buf: Buffer) -> int: return buffer_line_current(buf).length oswinx, oswiny = 1940,50 os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (oswinx,oswiny) clock = pg.time.Clock() pg.init() pg.font.init() text_renderer = pg.font.SysFont('JetBrains Mono', 14) screen = pg.display.set_mode((900, 900), pg.RESIZABLE) pg.key.set_repeat(240, 10) def load_file(path): with open(path, 'r', encoding='utf-8') as f: text = f.read() f.close() return text @dataclass class GlobalContext: cursor = Cursor(width=8, height=20) text = load_file('../gux/test.c') current_buffer = buffer_create(text, cursor) # global ctx def main(): running = True frame_count = 0 cursor_flash = 0 cursor_on = True line_height = 20 cursor = ctx.cursor current_buffer = ctx.current_buffer console = InteractiveInterpreter(locals()) console.runsource('from editing import *') key_map = { 'left': cursor_go_left, 'right': cursor_go_right, 'up': cursor_go_up, 'down': cursor_go_down } while running: dt = clock.tick(120) / 1000.0 screen.fill('white') frame_count += 1 for event in pg.event.get(): if event.type == pg.QUIT: running = False if event.type == pg.KEYDOWN: cursor_on = True cursor_flash = 0 curr_line = buffer_line_current(current_buffer) if event.mod == 64: # Right Ctrl if event.key == pg.K_e: cursor.col = buffer_line_len(buf) cursor.want_col = cursor.col if event.key == pg.K_a: cursor.col = 0 cursor.want_col = cursor.col if event.key == pg.K_RETURN: src = buffer_line_current(current_buffer).piece.get_text() console.runsource(src[3:]) elif event.key == pg.K_RETURN: buffer_newline_at_pos() elif event.key == pg.K_BACKSPACE: buffer_delete_character_under_cursor() elif event.key == pg.K_DELETE: buffer_delete_next_character() elif event.key == pg.K_LEFT: key_map['left']() elif event.key == pg.K_RIGHT: key_map['right']() elif event.key == pg.K_UP: key_map['up']() elif event.key == pg.K_DOWN: key_map['down']() elif event.key == pg.K_SPACE: curr_line.piece.insert(u' ', cursor.col) curr_line.length += 1 cursor.col += 1 cursor.want_col = cursor.col elif event.key >= 33 and event.key <= 126 and event.mod < 2: curr_line.piece.insert(event.unicode, cursor.col) curr_line.length += 1 cursor.col += 1 cursor.want_col = cursor.col for i,curr_line in enumerate(current_buffer.lines): render = text_renderer.render(curr_line.piece.get_text(), True, 'black') screen.blit(render, (0, i * line_height)) if cursor_on and cursor_flash < 0.5: cursor_draw(cursor) elif cursor_on: cursor_on = False cursor_flash = 0 elif not cursor_on and cursor_flash > 0.5: cursor_on = True cursor_flash = 0 cursor_flash += dt pg.display.flip() if __name__ == '__main__': main()