feat: заменен фреймворк для написания TUI, написана первая рабочая версия TUI

This commit is contained in:
ElectronixTM
2025-04-01 16:24:56 +03:00
parent 13f244d118
commit 8f63f4d09f

View File

@ -1,12 +1,10 @@
from dpdebugger import Debugger
from dataclasses import dataclass
from rich import print as rprint
from rich.layout import Layout
from rich.prompt import Prompt
from rich.panel import Panel
from rich.text import Text
from rich.console import Console
import math
import py_cui
import py_cui.keys
import re
import shlex
@dataclass
class SourceLines:
@ -14,12 +12,6 @@ class SourceLines:
begining_number: int
lines: list[str]
@dataclass
class RichedSourceLines:
active: int
begining_number: int
lines: list[Text]
def _get_source_lines(
srcline: int,
lines: list[str],
@ -49,61 +41,67 @@ def _get_source_lines(
lines=list(lines[start_bound-1:end_bound])
)
def _source_lines_to_rich(srclines: SourceLines) -> RichedSourceLines:
riched_lines = RichedSourceLines(
active=srclines.active,
begining_number=srclines.begining_number,
lines=list(map(Text, srclines.lines))
class DebuggerUI:
ACTIVE_LINE_POINTER = "~> "
def __init__(self, master: py_cui.PyCUI, debugger: Debugger, src: str):
self.master = master
self.dbg = debugger
self.src = src
self.srclines = src.split('\n')[:-1]
self.source_panel = self.master.add_text_block(
"Source code", 0, 0
)
active_index = srclines.active - srclines.begining_number
active_line = riched_lines.lines[active_index]
active_line.stylize('bold red')
return riched_lines
def _join_riched_lines(rl: RichedSourceLines) -> Text:
return Text("\n").join(rl.lines)
def _generate_source_lines(
debugger: Debugger,
srcfile: str,
size: int
) -> Panel:
sl = _get_source_lines(
lines=srcfile.split('\n')[:-1],
max_height=size,
srcline=debugger.get_current_source_line_number()
self.prompt_panel = self.master.add_text_box("Prompt",
1, 0,
row_span=1
)
rl = _source_lines_to_rich(sl)
full = _join_riched_lines(rl)
return Panel(full)
self.prompt_panel.add_key_command(py_cui.keys.KEY_ENTER, self._process_prompt)
self.terminal_panel = self.master.add_text_block("Debugger Console",
2, 0,
initial_text="to exit type in \"exit\""
)
self.master.move_focus(self.prompt_panel)
self.master.add_key_command(
py_cui.keys.KEY_ENTER,
lambda: self.master.move_focus(self.prompt_panel)
)
self._display_source_lines()
def _process_prompt(self):
user_input = self.prompt_panel.get()
if user_input == "exit":
exit()
self.prompt_panel.clear()
dbg_output = self.dbg.do_command(user_input.split())
self.terminal_panel.write(dbg_output)
self._display_source_lines()
def _display_source_lines(self):
active_line = self.dbg.get_current_source_line_number()
lines = _get_source_lines(
srcline=active_line,
lines=self.srclines,
max_height=self.source_panel.get_viewport_height()
)
# emplace line lumbers
linenos = [lines.begining_number + i
for i in range(len(lines.lines))]
lines_with_linenos: list[str] =[]
# длина самого большого числа для вычисления выравнивания
align_with = len(str(linenos[-1]))
for lineno, line in zip(linenos, lines.lines):
if lineno == lines.active:
padding = len(line) - len(stripped := line.lstrip(" "))
line = self.ACTIVE_LINE_POINTER.rjust(padding) + stripped
lines_with_linenos.append(
f"{str(lineno).rjust(align_with)}. {line}"
)
self.source_panel.set_text("\n".join(lines_with_linenos))
def main(debugger: Debugger, srcfile: str):
SRC_WIN_HEIGHT = 10
layout = Layout()
layout.split_column(
Layout(
_generate_source_lines(debugger, srcfile, SRC_WIN_HEIGHT),
size=SRC_WIN_HEIGHT,
name="source"),
Layout(name="terminal")
)
layout["source"].update(_generate_source_lines(
debugger=debugger,
srcfile=srcfile,
size=SRC_WIN_HEIGHT
))
print()
rprint(layout)
if __name__ == "__main__":
console = Console()
with open("test.dasm", 'r') as f:
lines = f.read().split('\n')[:-1]
srclines = _get_source_lines(22, lines, 7)
riched = _source_lines_to_rich(srclines)
print(f"focus: {srclines.active}; start: {srclines.begining_number}")
print("_"*20)
# rprint(*riched.lines, sep="\n")
rprint(_join_riched_lines(riched))
root = py_cui.PyCUI(3, 1)
root.set_title("Stupid DP32 debugger")
root.set_status_bar_text("")
DebuggerUI(root, debugger, srcfile)
root.start()