fix(cli): improve spinner line clearing to prevent garbled output with prompt_toolkit
This commit is contained in:
parent
e09ef6b8bc
commit
c92bdd8785
2 changed files with 17 additions and 9 deletions
|
|
@ -182,9 +182,8 @@ class KawaiiSpinner:
|
||||||
frame = self.spinner_frames[self.frame_idx % len(self.spinner_frames)]
|
frame = self.spinner_frames[self.frame_idx % len(self.spinner_frames)]
|
||||||
elapsed = time.time() - self.start_time
|
elapsed = time.time() - self.start_time
|
||||||
line = f" {frame} {self.message} ({elapsed:.1f}s)"
|
line = f" {frame} {self.message} ({elapsed:.1f}s)"
|
||||||
# Use \r + ANSI erase-to-EOL in a single write to avoid the
|
pad = max(self.last_line_len - len(line), 0)
|
||||||
# two-phase clear+redraw that flickers under patch_stdout.
|
self._write(f"\r{line}{' ' * pad}", end='', flush=True)
|
||||||
self._write(f"\r\033[K{line}", end='', flush=True)
|
|
||||||
self.last_line_len = len(line)
|
self.last_line_len = len(line)
|
||||||
self.frame_idx += 1
|
self.frame_idx += 1
|
||||||
time.sleep(0.12)
|
time.sleep(0.12)
|
||||||
|
|
@ -204,7 +203,10 @@ class KawaiiSpinner:
|
||||||
self.running = False
|
self.running = False
|
||||||
if self.thread:
|
if self.thread:
|
||||||
self.thread.join(timeout=0.5)
|
self.thread.join(timeout=0.5)
|
||||||
self._write('\r\033[K', end='', flush=True)
|
# Clear the spinner line with spaces instead of \033[K to avoid
|
||||||
|
# garbled escape codes when prompt_toolkit's patch_stdout is active.
|
||||||
|
blanks = ' ' * max(self.last_line_len + 5, 40)
|
||||||
|
self._write(f"\r{blanks}\r", end='', flush=True)
|
||||||
if final_message:
|
if final_message:
|
||||||
self._write(f" {final_message}", flush=True)
|
self._write(f" {final_message}", flush=True)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,9 +136,6 @@ def _prompt_choice(question: str, choices: list, default: int = 0) -> int:
|
||||||
|
|
||||||
def _prompt_toolset_checklist(platform_label: str, enabled: Set[str]) -> Set[str]:
|
def _prompt_toolset_checklist(platform_label: str, enabled: Set[str]) -> Set[str]:
|
||||||
"""Multi-select checklist of toolsets. Returns set of selected toolset keys."""
|
"""Multi-select checklist of toolsets. Returns set of selected toolset keys."""
|
||||||
print(color(f"Tools for {platform_label}", Colors.YELLOW))
|
|
||||||
print(color(" SPACE to toggle, ENTER to confirm.", Colors.DIM))
|
|
||||||
print()
|
|
||||||
|
|
||||||
labels = []
|
labels = []
|
||||||
for ts_key, ts_label, ts_desc in CONFIGURABLE_TOOLSETS:
|
for ts_key, ts_label, ts_desc in CONFIGURABLE_TOOLSETS:
|
||||||
|
|
@ -154,6 +151,12 @@ def _prompt_toolset_checklist(platform_label: str, enabled: Set[str]) -> Set[str
|
||||||
|
|
||||||
menu_items = [f" {label}" for label in labels]
|
menu_items = [f" {label}" for label in labels]
|
||||||
|
|
||||||
|
title_lines = [
|
||||||
|
f"Tools for {platform_label}",
|
||||||
|
" SPACE to toggle, ENTER to confirm.",
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
|
||||||
menu = TerminalMenu(
|
menu = TerminalMenu(
|
||||||
menu_items,
|
menu_items,
|
||||||
multi_select=True,
|
multi_select=True,
|
||||||
|
|
@ -166,8 +169,8 @@ def _prompt_toolset_checklist(platform_label: str, enabled: Set[str]) -> Set[str
|
||||||
menu_cursor_style=("fg_green", "bold"),
|
menu_cursor_style=("fg_green", "bold"),
|
||||||
menu_highlight_style=("fg_green",),
|
menu_highlight_style=("fg_green",),
|
||||||
cycle_cursor=True,
|
cycle_cursor=True,
|
||||||
clear_screen=False,
|
clear_screen=True,
|
||||||
clear_menu_on_exit=False,
|
title="\n".join(title_lines),
|
||||||
)
|
)
|
||||||
|
|
||||||
menu.show()
|
menu.show()
|
||||||
|
|
@ -181,6 +184,9 @@ def _prompt_toolset_checklist(platform_label: str, enabled: Set[str]) -> Set[str
|
||||||
|
|
||||||
except (ImportError, NotImplementedError):
|
except (ImportError, NotImplementedError):
|
||||||
# Fallback: numbered toggle
|
# Fallback: numbered toggle
|
||||||
|
print(color(f"Tools for {platform_label}", Colors.YELLOW))
|
||||||
|
print(color(" SPACE to toggle, ENTER to confirm.", Colors.DIM))
|
||||||
|
print()
|
||||||
selected = set(pre_selected_indices)
|
selected = set(pre_selected_indices)
|
||||||
while True:
|
while True:
|
||||||
for i, label in enumerate(labels):
|
for i, label in enumerate(labels):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue