Tab completion used a generated table (pm3line_vocabulary.h, refreshed by
hand via `make commands`) that drifted from the real command tables: new
commands were missing (e.g. `hw bwm*`), removed ones lingered, and the
"offline" flag depended on the platform of whoever regenerated it
(IfPm5() returns true offline on PM5 builds).
Build the vocabulary at startup instead:
- cmdparser: add walkCommandsRecursive(), a tree walk using a fourth
internal sentinel (XX_internal_command_walk_XX) next to the dump ones.
It hands each leaf to a visitor as its command_t chain (ancestors +
leaf). A dispatch counter detects entries shown like a category but
with their own parser (reveng) and reports them as leaves.
- pm3line_vocabulary: dynamic vocabulary holding the IsAvailable()
predicates of every command and its ancestor categories, so completion
applies exactly the rule CmdsHelp() uses, live, for both offline and
connected devices. Script entries ("script run <relpath>") come from
the same directories `script list` scans, sorted, including
subdirectories with the path `script run` needs.
- pm3line: readline and linenoise completers consume the live vocabulary.
The walk runs with output disabled so category handlers stay silent.
- Drop pm3_help2list.py and the header regeneration from `make commands`.
Behaviour change: entries whose category is hidden by `help` (e.g. `mem`,
`usart` offline) are no longer offered, matching `help`; when connected,
commands the device does not support are no longer offered either.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* add a check to prevent multiple log handler additions. Still a hack, but ok for this purpose.
* GuessKey_Statistics.__init__() now validates is_solved using same class validator as unpack()
* fix exception text to reflect allowed types for Hangman_State
* Also in Hangman_State, fix validation when input is bytes / bytearray
* In dc34_PlayHangman_validate_user_input(), strip the input before checking length.
1. remove hard-coded binary path
2. define TCP_PORT in fallback path
3. only detect device when not called from client
4. struct.pack() requires bytes / bytearray when packing a string.
5. fix typo "existing" -> "exiting"
6. remove unused imports
Works both from the command-line and from within the PM3 client:
* python3 ./client/pyscripts/dc34.py
* ./pm3 -c "script run dc34"
Supports all three games:
* TicTacToe
* Hangman
* GuessKey
See https://dc34.rfid.wtf/
All four call sites already pass `cmd` as a Python list, so Python's default of `shell=False` means there is no active command-injection risk. This change makes the security intent explicit, prevents accidental future regression if a call site is later changed to pass a string, and improves code clarity.
No functional behaviour is changed.
Updated user prompts and error messages to include warning symbols for better visibility. Added a new function to read long user input on POSIX systems. Allow writing large inputs by splitting user data into smaller, fixed-size chunks.
Signed-off-by: Trigat <trigat@protonmail.com>