fix(rawcli): render ANSI, stop mangling commands, fuller Type 2 catalog

Three fixes from live hardware use:

- Colors/ANSI now render. Output routes through prompt_toolkit's
  print_formatted_text(ANSI(...)) instead of print(), which showed the
  escape codes literally under patch_stdout. Formatters force is_tty so
  the printer decides color-vs-plain. dispatch()/handlers take an `out`.
- Auto-byte-spacing no longer mangles non-hex input. byte_space() only
  regroups a *pure* hex/binary run; command words ("help transponder",
  "identify", "close") and 0x/0b-prefixed tokens are left intact (a-f in
  words used to trigger regrouping -> failed hex parse).
- Type 2 catalog gains PWD_AUTH (0x1B), COMPAT_WRITE (0xA0), HALT — the
  NTAG213 set was missing password auth.
- identify trims the firmware buffer padding off the GET_VERSION response
  (was dumping ~40 trailing 00 bytes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
michael
2026-07-14 12:50:01 -07:00
parent 6b4a4551d4
commit 41db552e05
5 changed files with 67 additions and 41 deletions

View File

@@ -127,6 +127,17 @@ class TestByteSpace:
def test_prefixed_left_alone(self):
assert byte_space("0x3004", "hex") == "0x3004" # explicit prefix not mangled
assert byte_space("0b0011", "hex") == "0b0011"
def test_leaves_command_words_alone(self):
# regression: auto-spacing must not mangle non-hex input (a-f in words used to break it)
assert byte_space("help transponder", "hex") == "help transponder"
assert byte_space("identify", "hex") == "identify"
assert byte_space("close", "hex") == "close" # c,e are hex digits but l,o,s aren't
assert byte_space("READ(4)", "hex") == "READ(4)"
def test_spaces_pure_hex(self):
assert byte_space("deadbeef", "hex") == "de ad be ef"
class TestDispatch:
@@ -253,6 +264,7 @@ class TestCatalog:
assert TYPE2.get("FAST_READ").build("0", "3") == b"\x3A\x00\x03"
assert TYPE2.get("GET_VERSION").build() == b"\x60"
assert TYPE2.get("WRITE").build("4", "01020304") == b"\xA2\x04\x01\x02\x03\x04"
assert TYPE2.get("PWD_AUTH").build("FFFFFFFF") == b"\x1B\xFF\xFF\xFF\xFF"
def test_iso15_builds(self):
assert ISO15.get("READ_BLOCK").build("4") == b"\x02\x20\x04"