fix: The input prompt box supports selection using the up and down arrow keys (#76)

* Add the ability to read text from the system clipboard

* The input prompt box supports selection using the up and down arrow keys.
This commit is contained in:
Allen
2026-03-19 16:15:01 +01:00
committed by GitHub
parent 47e5ef6219
commit 97d00808e1
2 changed files with 28 additions and 5 deletions
+8 -2
View File
@@ -59,11 +59,17 @@ def _paste_native() -> str | None:
result = subprocess.run(
["powershell", "-command", "Get-Clipboard"],
capture_output=True,
text=True,
timeout=2,
)
if result.returncode == 0:
return result.stdout.rstrip("\r\n")
# Try UTF-8 first, fall back to system encoding
for encoding in ("utf-8", "gbk", "cp936"):
try:
return result.stdout.decode(encoding).rstrip("\r\n")
except UnicodeDecodeError:
continue
# Last resort: decode with errors ignored
return result.stdout.decode("utf-8", errors="ignore").rstrip("\r\n")
except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
pass
else:
+20 -3
View File
@@ -1604,6 +1604,13 @@ def run_textual_interactive(
def action_edit_queued(self) -> None:
"""Pop the last queued message back into input for editing."""
# Handle completion list selection (up key)
comp_widget = self.query_one("#completions", Static)
if comp_widget.display and self._comp_items:
self._comp_index = (self._comp_index - 1) % len(self._comp_items)
self._render_completions()
return
# Skip if an ApprovalWidget, AskUserWidget, ThreadPickerWidget, or SkillBrowserWidget has focus
focused = self.focused
if focused is not None:
@@ -1638,6 +1645,13 @@ def run_textual_interactive(
def action_down_delegate(self) -> None:
"""Delegate down key to focused interactive widget."""
# Handle completion list selection (down key)
comp_widget = self.query_one("#completions", Static)
if comp_widget.display and self._comp_items:
self._comp_index = (self._comp_index + 1) % len(self._comp_items)
self._render_completions()
return
focused = self.focused
if focused is not None:
from .widgets.approval_widget import ApprovalWidget
@@ -1690,23 +1704,26 @@ def run_textual_interactive(
event.prevent_default()
event.stop()
self._comp_index = (self._comp_index + 1) % len(self._comp_items)
self._apply_selected_completion()
self._render_completions()
elif event.key == "up":
event.prevent_default()
event.stop()
self._comp_index = (self._comp_index - 1) % len(self._comp_items)
self._apply_selected_completion()
self._render_completions()
elif event.key == "enter" and self._comp_index >= 0:
event.prevent_default()
event.stop()
self._apply_selected_completion()
self._hide_completions()
def _apply_selected_completion(self) -> None:
"""Apply the currently selected completion to the input field."""
if self._comp_index < 0 or self._comp_index >= len(self._comp_items):
return
selected_cmd = self._comp_items[self._comp_index][0]
prompt = self.query_one("#prompt", Input)
prompt.value = selected_cmd + " "
prompt.cursor_position = len(prompt.value)
self._render_completions()
def _hide_completions(self) -> None:
self._comp_items = []