feat(rawcli): colorized breadcrumb prompt
Color-code the prompt so the session state reads at a glance, using the trace formatter's palette so prompt and trace look like one UI: [ raw / hf / NTAG213 / 0x ] dim ^bold ^cyan ^bold-green ^yellow(hex) | magenta(binary) dim - bold `raw`; cyan RF field; bold-green identified transponder; entry mode yellow for hex, magenta for binary (so the base is obvious and flips color on Ctrl-/); dim brackets/separators. - session.colored_breadcrumb() returns the ANSI form; breadcrumb() stays plain (stripping the ANSI yields it — asserted). Prompt message renders it via ANSI(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -195,7 +195,7 @@ def run(port=None) -> int:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def message():
|
def message():
|
||||||
return state.breadcrumb() + " "
|
return ANSI(state.colored_breadcrumb() + " ")
|
||||||
|
|
||||||
with patch_stdout():
|
with patch_stdout():
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ from typing import Any
|
|||||||
HEX = "hex"
|
HEX = "hex"
|
||||||
BIN = "bin"
|
BIN = "bin"
|
||||||
|
|
||||||
|
# ANSI palette aligned with pm3py/trace/format.py so the prompt reads as part of the same UI
|
||||||
|
_DIM = "\033[2m"
|
||||||
|
_CYAN = "\033[36m"
|
||||||
|
_YELLOW = "\033[33m"
|
||||||
|
_MAGENTA = "\033[35m"
|
||||||
|
_BGREEN = "\033[1;32m"
|
||||||
|
_BOLD = "\033[1m"
|
||||||
|
_RESET = "\033[0m"
|
||||||
|
|
||||||
|
|
||||||
class RawSession:
|
class RawSession:
|
||||||
"""Mutable rawcli session state.
|
"""Mutable rawcli session state.
|
||||||
@@ -43,3 +52,17 @@ class RawSession:
|
|||||||
segments.append(self.transponder)
|
segments.append(self.transponder)
|
||||||
segments.append(self.entry_prefix)
|
segments.append(self.entry_prefix)
|
||||||
return "[" + " / ".join(segments) + "]"
|
return "[" + " / ".join(segments) + "]"
|
||||||
|
|
||||||
|
def colored_breadcrumb(self) -> str:
|
||||||
|
"""The breadcrumb with ANSI color (same palette as the trace): bold ``raw``, cyan field,
|
||||||
|
bold-green identified tag, and the entry mode in yellow (hex) or magenta (binary) so the
|
||||||
|
current base is obvious at a glance. Stripping the ANSI yields :meth:`breadcrumb`."""
|
||||||
|
segments = [f"{_BOLD}raw{_RESET}"]
|
||||||
|
if self.field:
|
||||||
|
segments.append(f"{_CYAN}{self.field}{_RESET}")
|
||||||
|
if self.transponder:
|
||||||
|
segments.append(f"{_BGREEN}{self.transponder}{_RESET}")
|
||||||
|
mode_color = _YELLOW if self.entry_mode == HEX else _MAGENTA
|
||||||
|
segments.append(f"{mode_color}{self.entry_prefix}{_RESET}")
|
||||||
|
sep = f"{_DIM} / {_RESET}"
|
||||||
|
return f"{_DIM}[{_RESET}" + sep.join(segments) + f"{_DIM}]{_RESET}"
|
||||||
|
|||||||
@@ -46,6 +46,18 @@ class TestBreadcrumb:
|
|||||||
s.field = "lf"
|
s.field = "lf"
|
||||||
assert s.breadcrumb() == "[raw / lf / 0x]"
|
assert s.breadcrumb() == "[raw / lf / 0x]"
|
||||||
|
|
||||||
|
def test_colored_matches_plain(self):
|
||||||
|
s = RawSession()
|
||||||
|
s.field, s.transponder = "hf", "NTAG213"
|
||||||
|
assert "\x1b[" in s.colored_breadcrumb() # actually colored
|
||||||
|
assert _plain(s.colored_breadcrumb()) == s.breadcrumb() # same content, ANSI stripped
|
||||||
|
|
||||||
|
def test_colored_mode_color_changes(self):
|
||||||
|
s = RawSession()
|
||||||
|
hex_prompt = s.colored_breadcrumb()
|
||||||
|
s.toggle_entry_mode()
|
||||||
|
assert hex_prompt != s.colored_breadcrumb() # hex vs binary colored differently
|
||||||
|
|
||||||
|
|
||||||
class TestTraceView:
|
class TestTraceView:
|
||||||
def test_command_and_response_lines(self):
|
def test_command_and_response_lines(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user