mirror of
https://github.com/1j01/textual-paint.git
synced 2024-12-22 06:11:37 +03:00
Add docstrings, rename method
The new method name reflects the fact that it handles some input as commands, not just recording the events.
This commit is contained in:
parent
96ef2dfdff
commit
2a7b4412e1
@ -16,6 +16,7 @@ from textual_paint.paint import PaintApp
|
|||||||
|
|
||||||
|
|
||||||
def unique_file(path: str) -> str:
|
def unique_file(path: str) -> str:
|
||||||
|
"""Return a path that doesn't exist yet, by appending a number to the filename."""
|
||||||
filename, extension = os.path.splitext(path)
|
filename, extension = os.path.splitext(path)
|
||||||
counter = 1
|
counter = 1
|
||||||
|
|
||||||
@ -26,9 +27,11 @@ def unique_file(path: str) -> str:
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
def indent(text: str, spaces: int) -> str:
|
def indent(text: str, spaces: int) -> str:
|
||||||
|
"""Return the text indented by the given number of spaces (including the first line)."""
|
||||||
return "\n".join(" " * spaces + line for line in text.splitlines())
|
return "\n".join(" " * spaces + line for line in text.splitlines())
|
||||||
|
|
||||||
async def async_exec(code: str, **kwargs: object) -> object:
|
async def async_exec(code: str, **kwargs: object) -> object:
|
||||||
|
"""Execute the given code in an async function and return the result. Keyword arguments are made available as variables."""
|
||||||
# This dict will be used for passing variables to the `exec`ed code
|
# This dict will be used for passing variables to the `exec`ed code
|
||||||
# as well as retrieving the function defined by the code.
|
# as well as retrieving the function defined by the code.
|
||||||
scope = kwargs
|
scope = kwargs
|
||||||
@ -69,6 +72,7 @@ def get_selector(target: DOMNode) -> tuple[str, int|None]:
|
|||||||
original_on_event = PaintApp.on_event
|
original_on_event = PaintApp.on_event
|
||||||
|
|
||||||
class PilotRecorder():
|
class PilotRecorder():
|
||||||
|
"""Record (and undo and replay) interactions with an app, and save as a test."""
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.app: PaintApp | None = None
|
self.app: PaintApp | None = None
|
||||||
self.steps: list[tuple[Event, Offset, str, int|None]] = []
|
self.steps: list[tuple[Event, Offset, str, int|None]] = []
|
||||||
@ -84,11 +88,12 @@ class PilotRecorder():
|
|||||||
# I don't claim to understand the forwarding scheme, but ignoring either
|
# I don't claim to understand the forwarding scheme, but ignoring either
|
||||||
# the forwarded or the un-forwarded events seems workable.
|
# the forwarded or the un-forwarded events seems workable.
|
||||||
if not event._forwarded:
|
if not event._forwarded:
|
||||||
recorder.record_event(event)
|
recorder.handle_event(event)
|
||||||
await original_on_event(self, event)
|
await original_on_event(self, event)
|
||||||
self.app_on_event = on_event
|
self.app_on_event = on_event
|
||||||
|
|
||||||
def record_event(self, event: Event) -> None:
|
def handle_event(self, event: Event) -> None:
|
||||||
|
"""Record the event as a step, or handle certain key presses as commands."""
|
||||||
assert self.app is not None, "app should be set if we're recording an event from it"
|
assert self.app is not None, "app should be set if we're recording an event from it"
|
||||||
# Handling any event means including it in the undo stack right now.
|
# Handling any event means including it in the undo stack right now.
|
||||||
# Don't want to undo a single mouse-move, especially when it doesn't do anything yet.
|
# Don't want to undo a single mouse-move, especially when it doesn't do anything yet.
|
||||||
@ -118,10 +123,12 @@ class PilotRecorder():
|
|||||||
self.steps_changed()
|
self.steps_changed()
|
||||||
|
|
||||||
def steps_changed(self) -> None:
|
def steps_changed(self) -> None:
|
||||||
|
"""Save the steps any time they change."""
|
||||||
# Could implement a debug view of the steps, but just saving to the file is good enough for now.
|
# Could implement a debug view of the steps, but just saving to the file is good enough for now.
|
||||||
self.save_replay()
|
self.save_replay()
|
||||||
|
|
||||||
async def replay_steps(self, pilot: Pilot[Any]) -> None:
|
async def replay_steps(self, pilot: Pilot[Any]) -> None:
|
||||||
|
"""Replay the recorded steps, in the current app instance."""
|
||||||
if not self.steps:
|
if not self.steps:
|
||||||
return
|
return
|
||||||
self.replaying = True
|
self.replaying = True
|
||||||
@ -129,7 +136,9 @@ class PilotRecorder():
|
|||||||
self.replaying = False
|
self.replaying = False
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
|
"""Start the app, or restart it to replay the recorded steps."""
|
||||||
def startup_and_replay() -> None:
|
def startup_and_replay() -> None:
|
||||||
|
"""Start the app, hook its events, and replay steps if there are any."""
|
||||||
self.next_after_exit = None # important to allowing you to exit; don't keep launching the app
|
self.next_after_exit = None # important to allowing you to exit; don't keep launching the app
|
||||||
self.app = PaintApp()
|
self.app = PaintApp()
|
||||||
self.app.on_event = self.app_on_event.__get__(self.app)
|
self.app.on_event = self.app_on_event.__get__(self.app)
|
||||||
@ -146,6 +155,7 @@ class PilotRecorder():
|
|||||||
startup_and_replay()
|
startup_and_replay()
|
||||||
|
|
||||||
def get_replay_code(self) -> str:
|
def get_replay_code(self) -> str:
|
||||||
|
"""Return code to replay the recorded steps."""
|
||||||
steps_code = ""
|
steps_code = ""
|
||||||
for event, offset, selector, index in self.steps:
|
for event, offset, selector, index in self.steps:
|
||||||
if isinstance(event, MouseDown):
|
if isinstance(event, MouseDown):
|
||||||
@ -167,6 +177,7 @@ class PilotRecorder():
|
|||||||
return steps_code or "pass"
|
return steps_code or "pass"
|
||||||
|
|
||||||
def save_replay(self) -> None:
|
def save_replay(self) -> None:
|
||||||
|
"""Save the recorded steps as a test file."""
|
||||||
assert self.app is not None, "app should be set by now"
|
assert self.app is not None, "app should be set by now"
|
||||||
|
|
||||||
script = f"""\
|
script = f"""\
|
||||||
|
Loading…
Reference in New Issue
Block a user