termapy 0.76.0__tar.gz → 0.77.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {termapy-0.76.0 → termapy-0.77.1}/PKG-INFO +105 -162
- {termapy-0.76.0 → termapy-0.77.1}/README.md +103 -161
- termapy-0.76.0/pyproject.toml.orig → termapy-0.77.1/pyproject.toml +26 -12
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/app.py +402 -393
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/app_dirs.py +15 -15
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/app_hooks.py +102 -120
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/_cfg_icon.py +36 -8
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/_run_record.py +2 -3
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/_xmodem_handlers.py +2 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/_ymodem_handlers.py +5 -4
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/app.py +23 -34
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/cap.py +69 -33
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/cfg.py +179 -81
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/cls.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/credits.py +1 -1
- termapy-0.77.1/src/termapy/builtins/commands/dev.py +504 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/edit.py +103 -69
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/env.py +19 -16
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/exit.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/find.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/grep.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/help.py +173 -123
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/log.py +3 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/mcp.py +54 -27
- termapy-0.77.1/src/termapy/builtins/commands/mem.py +1195 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/os_cmd.py +3 -3
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/ping.py +2 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/plugin.py +6 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/port.py +64 -47
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/profile.py +38 -20
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/proto.py +427 -265
- termapy-0.77.1/src/termapy/builtins/commands/raw.py +54 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/run.py +37 -54
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/search.py +21 -21
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/seq.py +12 -11
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/show.py +2 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/ss.py +5 -3
- termapy-0.77.1/src/termapy/builtins/commands/sym.py +464 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/term.py +142 -69
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/var.py +22 -8
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/xfer.py +14 -15
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/demo.cfg +2 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/demo.profile.json +7 -0
- termapy-0.77.1/src/termapy/builtins/demo/demo.symbols.json +23 -0
- termapy-0.77.1/src/termapy/builtins/demo/demo_legacy.profile.json +30 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/plugin/cmd.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/plugin/probe.py +2 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/plugin/temp_plot.py +3 -3
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/plugin/traffic.py +29 -23
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/capture.py +121 -67
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/capture_view.py +12 -5
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/cli.py +96 -92
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/cli_flags.py +34 -32
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/config.py +422 -104
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/config_resolve.py +11 -15
- termapy-0.77.1/src/termapy/converters.py +144 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/defaults.py +22 -12
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/demo.py +242 -26
- termapy-0.77.1/src/termapy/devices/__init__.py +1085 -0
- termapy-0.77.1/src/termapy/devices/converters/__init__.py +34 -0
- termapy-0.77.1/src/termapy/devices/converters/svd.py +433 -0
- termapy-0.77.1/src/termapy/dialogs/_common.py +215 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/cfg_confirm.py +1 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/config_editor.py +72 -54
- termapy-0.77.1/src/termapy/dialogs/config_picker.py +367 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/confirm_dialog.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/filename_dialog.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/proto_editor.py +5 -3
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/proto_picker.py +5 -5
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/script_editor.py +5 -3
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/script_picker.py +6 -6
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/update_available.py +1 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/welcome_dialog.py +2 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/entry.py +35 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/env_flags.py +73 -17
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/folder_ops.py +117 -43
- termapy-0.77.1/src/termapy/folders.py +239 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/authoring-profiles.md +15 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/cli.md +18 -9
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/commands.md +80 -25
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/config.md +34 -10
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/demo.md +3 -1
- termapy-0.77.1/src/termapy/help/devices.md +140 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/environment.md +13 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/getting-started.md +20 -3
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/index.md +3 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/mcp-server.md +5 -3
- termapy-0.77.1/src/termapy/help/memory.md +304 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/protocol-testing.md +77 -18
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/scripting.md +23 -5
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/serial-tools.md +13 -2
- termapy-0.77.1/src/termapy/help/symbols.md +283 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/toolbar.md +10 -5
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/using-git.md +9 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/variables.md +10 -6
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/writing-plugins.md +157 -27
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help_dynamic.py +14 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help_tooltip.py +8 -7
- termapy-0.77.1/src/termapy/history_nav.py +128 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/404.html +99 -17
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/acknowledgments.html +100 -18
- termapy-0.77.1/src/termapy/html/assets/javascripts/bundle.a2388154.min.js +10 -0
- termapy-0.77.1/src/termapy/html/assets/javascripts/workers/search.c47bb847.min.js +1 -0
- termapy-0.77.1/src/termapy/html/assets/stylesheets/classic/main.68ef4dbf.min.css +6 -0
- termapy-0.77.1/src/termapy/html/assets/stylesheets/classic/palette.813d4b3f.min.css +4 -0
- termapy-0.77.1/src/termapy/html/assets/stylesheets/modern/main.e442bf79.min.css +6 -0
- termapy-0.77.1/src/termapy/html/assets/stylesheets/modern/palette.b60ce83d.min.css +4 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/authoring-profiles.html +199 -84
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/cli.html +119 -29
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/commands.html +306 -47
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/config.html +178 -50
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/custom-buttons.html +101 -19
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/data-capture.html +104 -22
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/demo.html +105 -21
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/device-help.html +101 -19
- termapy-0.77.1/src/termapy/html/devices.html +1363 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/environment.html +130 -36
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/file-transfer.html +104 -22
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/getting-started.html +128 -30
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/index.html +104 -19
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/installation.html +100 -18
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/mcp-server.html +109 -22
- termapy-0.77.1/src/termapy/html/memory.html +1620 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/on-ai-assistance.html +101 -19
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/ports.html +101 -19
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/protocol-testing.html +217 -51
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/scripting.html +121 -23
- termapy-0.77.1/src/termapy/html/search.json +1 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/serial-tools.html +113 -21
- termapy-0.77.1/src/termapy/html/symbols.html +1788 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/toolbar.html +110 -24
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/using-git.html +122 -32
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/variables.html +110 -24
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/vt100.html +101 -19
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/writing-plugins.html +432 -178
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/legacy.py +5 -7
- termapy-0.77.1/src/termapy/markup.py +95 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/mcp/catalog.py +10 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/mcp/server.py +206 -116
- termapy-0.77.1/src/termapy/memory.py +862 -0
- termapy-0.77.1/src/termapy/memory_views.py +298 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/migration.py +54 -5
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/pickers.py +22 -11
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/__init__.py +11 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/capabilities.py +109 -10
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/command.py +162 -6
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/context.py +33 -13
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/handles/fs.py +2 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/handles/internal.py +27 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/handles/io.py +5 -4
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/handles/serial.py +5 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/handles/ui.py +2 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/loader.py +94 -23
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/output_levels.py +30 -25
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/params.py +19 -2
- termapy-0.77.1/src/termapy/plugins/views.py +170 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/port_control.py +131 -109
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/port_format.py +24 -11
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/profile/loader.py +9 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/profile/schema.json +20 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/profile/types.py +12 -3
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/proto_debug.py +72 -64
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/protocol/__init__.py +6 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/protocol/core.py +423 -133
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/protocol/runner.py +152 -79
- termapy-0.77.1/src/termapy/protocol/type_codes.py +71 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/repl.py +653 -138
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/request_response.py +4 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/response_parsers.py +6 -2
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/run_docstring.py +8 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/run_legacy.py +13 -16
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/run_profile_hooks.py +9 -17
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/scripting.py +100 -34
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/serial_engine.py +175 -109
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/serial_port.py +117 -26
- termapy-0.77.1/src/termapy/symbols/__init__.py +99 -0
- termapy-0.77.1/src/termapy/symbols/address.py +226 -0
- termapy-0.77.1/src/termapy/symbols/converters/__init__.py +61 -0
- termapy-0.77.1/src/termapy/symbols/converters/xc32.py +227 -0
- termapy-0.77.1/src/termapy/symbols/format.py +266 -0
- termapy-0.77.1/src/termapy/symbols/provenance.py +193 -0
- termapy-0.77.1/src/termapy/symbols/session.py +226 -0
- termapy-0.77.1/src/termapy/symbols/table.py +552 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/terminal_host.py +94 -37
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/title_bar.py +7 -5
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/tree_render.py +7 -6
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/widgets/status_bar.py +3 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/widgets/suggester.py +26 -3
- termapy-0.76.0/pyproject.toml +0 -138
- termapy-0.76.0/src/termapy/builtins/commands/run_edit.py +0 -40
- termapy-0.76.0/src/termapy/dialogs/_common.py +0 -168
- termapy-0.76.0/src/termapy/dialogs/config_picker.py +0 -228
- termapy-0.76.0/src/termapy/folders.py +0 -107
- termapy-0.76.0/src/termapy/history_nav.py +0 -68
- termapy-0.76.0/src/termapy/html/assets/javascripts/bundle.49251538.min.js +0 -10
- termapy-0.76.0/src/termapy/html/assets/javascripts/workers/search.7d14d953.min.js +0 -1
- termapy-0.76.0/src/termapy/html/assets/stylesheets/classic/main.38807bfb.min.css +0 -1
- termapy-0.76.0/src/termapy/html/assets/stylesheets/classic/palette.c7ab7c71.min.css +0 -1
- termapy-0.76.0/src/termapy/html/assets/stylesheets/modern/main.5da3a30f.min.css +0 -1
- termapy-0.76.0/src/termapy/html/assets/stylesheets/modern/palette.812a03bb.min.css +0 -1
- termapy-0.76.0/src/termapy/html/objects.inv +0 -0
- termapy-0.76.0/src/termapy/html/search.json +0 -1
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/__main__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/_crc_verbs.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/confirm.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/print.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/repeat.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/commands/stop.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/crc/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/crc/sum16.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/crc/sum8.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/.gitignore +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/demo_ndjson.profile.json +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/plugin/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/proto/at_test.pro +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/proto/bitfield_inline.pro +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/proto/modbus_inline.pro +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/at_demo.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/crc_tour.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/doc_screenshots.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/expect_test.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/gps_demo.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/smoke_test.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/status_check.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/var_demo.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/demo/run/welcome.run +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/viz/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/viz/hex_view.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/viz/modbus_view.py.old +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/builtins/viz/text_view.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/credits_data.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/demo_ndjson.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/demo_vt100.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/name_picker.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/port_picker.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/quick_setup.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/dialogs/set_var_dialog.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/.coverage +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/acknowledgments.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/custom-buttons.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/data-capture.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/device-help.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/file-transfer.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_01_main_tui.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_02_help.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_03_help_proto.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_04_proto_send.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_05_proto_crc.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_06_proto_delay.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_07_crc_python.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_08_variables.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_09_target_help.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_10_config_info.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_11_proto_run.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_12_cap_struct.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_13_cap_progress.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_14_port_list.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_15_xfer.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_16_toolbar.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_17_proto_debug.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_20_palette.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_21_script_picker.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_22_script_editor.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_23_config_editor.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_24_cmd_picker.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_30_new_cfg.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_31_cli_completion.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_32_port_picker.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_33_port_tooltip.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_34_latency_timer.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_35_vt100_menu.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_36_vt100_status.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/img/doc_37_config_picker.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/installation.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/on-ai-assistance.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/ports.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/help/vt100.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/.coverage +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/assets/images/favicon.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/assets/javascripts/LICENSE +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_01_main_tui.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_02_help.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_03_help_proto.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_04_proto_send.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_05_proto_crc.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_06_proto_delay.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_07_crc_python.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_08_variables.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_09_target_help.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_10_config_info.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_11_proto_run.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_12_cap_struct.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_13_cap_progress.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_14_port_list.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_15_xfer.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_16_toolbar.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_17_proto_debug.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_20_palette.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_21_script_picker.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_22_script_editor.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_23_config_editor.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_24_cmd_picker.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_30_new_cfg.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_31_cli_completion.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_32_port_picker.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_33_port_tooltip.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_34_latency_timer.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_35_vt100_menu.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_36_vt100_status.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/img/doc_37_config_picker.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/html/sitemap.xml +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/info_views.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/install_info.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/mcp/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/mcp/prompts.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/palette_provider.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/plugins/handles/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/profile/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/profile/matcher.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/protocol/crc.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/protocol/viz.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/smoke.txt +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/templates/icons/termapy.icns +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/templates/icons/termapy.ico +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/templates/icons/termapy.png +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/templates/icons/termapy.svg +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/templates/linux/termapy.desktop.template +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/templates/macos/Termapy.app/Contents/Info.plist +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/templates/macos/Termapy.app/Contents/MacOS/launcher.template +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/update_check.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/usb/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/usb/_vendors_full.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/usb/aliases.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/usb/chips.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/usb/vendors.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/usb_tree.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/variables.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/LICENSES.md +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/__main__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/rfc2217.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/rs485.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/serialcli.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/serialjava.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/serialposix.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/serialutil.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/serialwin32.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/threaded/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/hexlify_codec.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/list_ports.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/list_ports_common.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/list_ports_linux.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/list_ports_osx.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/list_ports_posix.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/list_ports_windows.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/tools/miniterm.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/protocol_alt.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/protocol_cp2110.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/protocol_hwgrep.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/protocol_loop.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/protocol_rfc2217.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/protocol_socket.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/urlhandler/protocol_spy.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/serial/win32.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/xmodem.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/ymodem/CRC.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/ymodem/Platform.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/ymodem/Protocol.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/ymodem/Socket.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/ymodem/Version.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vendor/ymodem/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/vt100.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/widgets/__init__.py +0 -0
- {termapy-0.76.0 → termapy-0.77.1}/src/termapy/widgets/checkbox.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: termapy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.77.1
|
|
4
4
|
Summary: A TUI serial terminal with ANSI color support, built on Textual and pyserial
|
|
5
5
|
Keywords: serial,terminal,tui,textual,pyserial,embedded,xmodem,ymodem
|
|
6
6
|
Author: Chuck Bass
|
|
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
20
|
Classifier: Topic :: Communications
|
|
20
21
|
Classifier: Topic :: System :: Hardware
|
|
21
22
|
Classifier: Topic :: Terminals :: Serial
|
|
@@ -46,11 +47,11 @@ Description-Content-Type: text/markdown
|
|
|
46
47
|
|
|
47
48
|
# termapy
|
|
48
49
|
|
|
49
|
-
**Project Status:** [](https://github.com/hucker/termapy/actions/workflows/tests.yml) [](https://github.com/hucker/termapy/actions/workflows/tests.yml) [](https://codecov.io/gh/hucker/termapy) [](https://github.com/astral-sh/ty)  [](https://hucker.github.io/termapy/)
|
|
50
51
|
|
|
51
52
|
**Powered by:** [](https://textual.textualize.io/) [](https://pyserial.readthedocs.io/) [](https://github.com/hucker/zensical)
|
|
52
53
|
|
|
53
|
-
**Built with:**  [](https://docs.astral.sh/uv/) [](https://pytest.org/) [](https://coverage.readthedocs.io/)
|
|
54
55
|
|
|
55
56
|
Pronounced "ter-map-ee"
|
|
56
57
|
|
|
@@ -153,6 +154,8 @@ Termapy runs with your privileges and does whatever you — or a connected MCP c
|
|
|
153
154
|
| Network sockets (`socket://`, `rfc2217://`) | `TERMAPY_MCP_NET_EGRESS=1` |
|
|
154
155
|
| Environment variables (`/env`, `$(env.X)`) | `TERMAPY_MCP_ENV_ENABLED=1` |
|
|
155
156
|
|
|
157
|
+
Each flag takes any boolean token (`1`, `on`, `true`, `yes`, ...); a value outside that vocabulary refuses to start, naming the variable, rather than silently meaning off.
|
|
158
|
+
|
|
156
159
|
<details>
|
|
157
160
|
<summary><strong>The basics</strong> - keyboard shortcuts, title bar, REPL commands</summary>
|
|
158
161
|
|
|
@@ -194,15 +197,15 @@ The most common ones:
|
|
|
194
197
|
|
|
195
198
|
| Command | Description |
|
|
196
199
|
| ------------------------------------ | --------------------------------------------------- |
|
|
197
|
-
| `/help
|
|
200
|
+
| `/help {cmd}` | List commands or show help for one |
|
|
198
201
|
| `/port.list` | List available serial ports |
|
|
199
202
|
| `/port.connect {name} {baud} {mode}` | Connect with optional baud rate and mode (e.g. N81) |
|
|
200
203
|
| `/port.info` | Show port status and parameters |
|
|
201
|
-
| `/cfg
|
|
202
|
-
| `/ss.svg
|
|
204
|
+
| `/cfg {key {value}}` | Open Cfg picker (bare TUI), or get/set values |
|
|
205
|
+
| `/ss.svg {name}` | Save SVG screenshot |
|
|
203
206
|
| `/cls` | Clear the terminal |
|
|
204
207
|
| `/run {filename}` | Open Run picker (bare TUI), or run a named script |
|
|
205
|
-
| `/term.echo
|
|
208
|
+
| `/term.echo {on\|off\|toggle}` | Local echo of device commands sent to the wire |
|
|
206
209
|
| `/grep <pattern>` | Search scrollback |
|
|
207
210
|
| `/exit` | Exit termapy |
|
|
208
211
|
|
|
@@ -211,9 +214,9 @@ The most common ones:
|
|
|
211
214
|
|
|
212
215
|
| Command | Description |
|
|
213
216
|
| ------------------------------------ | ----------------------------------------------------------------------------- |
|
|
214
|
-
| `/help
|
|
217
|
+
| `/help {cmd}` | List commands or show extended help for one |
|
|
215
218
|
| `/help.dev <cmd>` | Show a command handler's Python docstring |
|
|
216
|
-
| `/port {name}` | Open Port picker (bare TUI), list
|
|
219
|
+
| `/port {name}` | Open Port picker (bare TUI), list ports (bare CLI), or open by name |
|
|
217
220
|
| `/port.help` | Same as `/help port` |
|
|
218
221
|
| `/port.list` | List available serial ports |
|
|
219
222
|
| `/port.connect {name} {baud} {mode}` | Connect with optional baud and mode (e.g. /port.connect COM3 9600 N81) |
|
|
@@ -225,21 +228,21 @@ The most common ones:
|
|
|
225
228
|
| `/port.parity {value}` | Show or set parity (hardware only) |
|
|
226
229
|
| `/port.stop_bits {value}` | Show or set stop bits (hardware only) |
|
|
227
230
|
| `/port.flow_control {m}` | Show or set flow control: none, rtscts, xonxoff, manual |
|
|
228
|
-
| `/port.dtr {
|
|
229
|
-
| `/port.rts {
|
|
231
|
+
| `/port.dtr {on\|off}` | Show or set DTR line |
|
|
232
|
+
| `/port.rts {on\|off}` | Show or set RTS line |
|
|
230
233
|
| `/port.cts` | Show CTS state (read-only) |
|
|
231
234
|
| `/port.dsr` | Show DSR state (read-only) |
|
|
232
235
|
| `/port.ri` | Show RI state (read-only) |
|
|
233
236
|
| `/port.cd` | Show CD state (read-only) |
|
|
234
237
|
| `/port.break {ms}` | Send break signal (default 250ms) |
|
|
235
|
-
| `/cfg
|
|
238
|
+
| `/cfg {key {value}}` | Open Cfg picker (bare TUI), list configs (bare CLI), or get/set with args |
|
|
236
239
|
| `/cfg.auto <key> <value>` | Set an in-memory config key immediately (no confirmation) |
|
|
237
240
|
| `/cfg.list` | List all config files |
|
|
238
241
|
| `/cfg.load <name>` | Switch to a different config by name |
|
|
239
242
|
| `/cfg.show` | Open the current config file in the system viewer |
|
|
240
243
|
| `/cfg.help` | Same as `/help cfg` |
|
|
241
|
-
| `/ss.svg
|
|
242
|
-
| `/ss.txt
|
|
244
|
+
| `/ss.svg {name}` | Save SVG screenshot |
|
|
245
|
+
| `/ss.txt {name} {N}` | Save text screenshot (all, or an N-line slice) |
|
|
243
246
|
| `/ss.list` | List screenshots, newest first, with size and age |
|
|
244
247
|
| `/ss.explore` | Open the screenshot folder in the system file explorer |
|
|
245
248
|
| `/cls` | Clear the terminal screen |
|
|
@@ -258,34 +261,51 @@ The most common ones:
|
|
|
258
261
|
| `/show.cfg` | Show the current config file |
|
|
259
262
|
| `/term` | Terminal display / session toggles (echo, line_no, timestamps, ...) |
|
|
260
263
|
| `/term.info` | Snapshot the state of every `/term.*` toggle |
|
|
261
|
-
| `/term.echo
|
|
262
|
-
| `/term.echo_repl
|
|
263
|
-
| `/term.line_no
|
|
264
|
-
| `/term.eol.markers
|
|
265
|
-
| `/term.output {level}`
|
|
266
|
-
| `/term.timestamps
|
|
267
|
-
| `/term.hex
|
|
264
|
+
| `/term.echo {on\|off\|toggle}` | Local echo of device commands sent to the wire (persisted via cfg `echo`) |
|
|
265
|
+
| `/term.echo_repl {on\|off\|toggle}` | Local echo of REPL (slash) commands, session only; off inside scripts |
|
|
266
|
+
| `/term.line_no {on\|off\|toggle}` | Toggle line numbers in serial output (TUI only) |
|
|
267
|
+
| `/term.eol.markers {on\|off\|toggle}` | Toggle visible `\r` `\n` markers for line-ending troubleshooting |
|
|
268
|
+
| `/term.output {level\|cycle}` | Show or set output level (silent/quiet/normal/verbose) |
|
|
269
|
+
| `/term.timestamps {on\|off\|toggle}` | Toggle `[HH:MM:SS.mmm]` timestamp prefix |
|
|
270
|
+
| `/term.hex {on\|off\|toggle}` | Toggle hex display of incoming bytes |
|
|
268
271
|
| `/term.encoding {name}` | Show or set byte-decoding encoding (utf-8, latin-1, ...) |
|
|
269
|
-
| `/term.
|
|
272
|
+
| `/term.json {compact\|indent\|color\|cycle}` | How JSON answers print: one line, indented, or indented and colored |
|
|
273
|
+
| `/term.send_bare_enter {on\|off\|toggle}` | Send line ending on empty Enter |
|
|
270
274
|
| `/edit <file>` | Edit a project file (`run/`/`proto/` path) |
|
|
271
275
|
| `/edit.cfg` | Edit the current config file |
|
|
272
276
|
| `/edit.log` | Open the session log in the system viewer |
|
|
273
277
|
| `/edit.info` | Open the info report in the system viewer |
|
|
274
278
|
| `/os <cmd>` | Run a shell command (10s timeout, requires `TERMAPY_OS_CMD_ENABLED=1` in env) |
|
|
275
279
|
| `/grep <pattern>` | Search scrollback for regex matches (case-insensitive, skips own output) |
|
|
276
|
-
| `/cfg.info {--display}` |
|
|
277
|
-
| `/proto` | Open Proto picker (bare TUI) or
|
|
280
|
+
| `/cfg.info {--display}` | Write and show the project report (folder tree, config, buttons, log and history tails); also written at exit; `--display` opens it |
|
|
281
|
+
| `/proto` | Open Proto picker (bare TUI) or list proto/ (bare CLI) |
|
|
278
282
|
| `/proto.help` | Same as `/help proto` |
|
|
279
283
|
| `/proto.send <hex>` | Send raw hex bytes and/or quoted text, display response as hex (see below) |
|
|
280
284
|
| `/proto.run <file>` | Run a binary protocol test script (.pro) with pass/fail |
|
|
281
285
|
| `/proto.list` | List .pro files in proto/, newest first, with size and age |
|
|
282
286
|
| `/proto.rename <old> <new>` | Rename a protocol script (`.pro` kept; never overwrites) |
|
|
283
|
-
| `/proto.hex
|
|
287
|
+
| `/proto.hex {on\|off\|toggle}` | Same flag as `/term.hex` |
|
|
284
288
|
| `/proto.crc.list {pat}` | List available CRC algorithms (optional glob filter) |
|
|
285
289
|
| `/proto.crc.info <name>` | Show CRC algorithm parameters and description |
|
|
286
|
-
| `/proto.crc.calc <n> {d}` | Compute CRC over hex bytes, text, or file; omit data to verify check string
|
|
287
|
-
| `/proto.crc.find
|
|
290
|
+
| `/proto.crc.calc <n> {d}` | Compute CRC over hex bytes, quoted text, or a file; omit data to verify check string |
|
|
291
|
+
| `/proto.crc.find bin=<hex>\|asc=<text>\|cmd=<trigger>` | Identify CRC algorithm from a captured packet, text, or a command's reply |
|
|
288
292
|
| `/proto.info` | Print current protocol state |
|
|
293
|
+
| `/mem.dump <target> {len} {type}` | Hexdump or typed word columns at an address or symbol |
|
|
294
|
+
| `/mem.read <target> {type}` | One typed value: scalar, char, register field, bit or slice |
|
|
295
|
+
| `/mem.write <target> <hex>` | Write hex bytes, or set a register field/bit (audited; destructive over MCP) |
|
|
296
|
+
| `/mem.or <target> <mask>` | Boolean ops on one word (also `.and`, `.clear`, `.xor`, `.not`); atomic via `MEM.M` where expressible |
|
|
297
|
+
| `/mem.str <target> {max}` | Read a NUL-terminated string as a first-class value |
|
|
298
|
+
| `/mem.info` | Memory access config: dialect, block limit, width, endian, atomic modify |
|
|
299
|
+
| `/sym <addr\|name>` | Symbol table: name to address, or address to `name+offset` |
|
|
300
|
+
| `/sym.import {file} {format=<value>}` | Convert a linker map to `sym/<cfg>.symbols.json` and load it (bare: re-import the same map) |
|
|
301
|
+
| `/sym.info` | Show the loaded symbol table: file, source, counts by section, range |
|
|
302
|
+
| `/sym.load {path}` | Load a symbol table (default: the cfg sidecar `/sym.import` writes) |
|
|
303
|
+
| `/sym.search <pattern>` | Search symbols by name: exact, glob, regex, or substring |
|
|
304
|
+
| `/sym.unload` | Clear the loaded symbol table |
|
|
305
|
+
| `/dev.import <file> {format=<value>} {category=<value>} {to=<value>} {use=on\|off}` | Convert a vendor register description (CMSIS-SVD) into this config's `lib/` and reference it from `dev/` (`to=global` shares it) |
|
|
306
|
+
| `/dev.lib {pattern}` | List the parts the libraries hold (available, not loaded), with their layer |
|
|
307
|
+
| `/dev.list` | List the devices this config has loaded, with layer and placement |
|
|
308
|
+
| `/dev.use <part> {at=<value>}` | Add a library part to this config; `at=NAME@ADDR ...` places a relocatable one |
|
|
289
309
|
| `/var {name}` | List user variables, or show one by name |
|
|
290
310
|
| `/var.set <NAME> <value>` | Set a user variable |
|
|
291
311
|
| `/var.clear` | Clear all user variables |
|
|
@@ -297,7 +317,7 @@ The most common ones:
|
|
|
297
317
|
| `/cap.struct <f> ...` | Capture binary data, decode with format spec to CSV |
|
|
298
318
|
| `/cap.hex <f> ...` | Capture hex text lines, decode with format spec to CSV |
|
|
299
319
|
| `/cap.stop` | Stop an active capture |
|
|
300
|
-
| `/raw <text>` | Send text
|
|
320
|
+
| `/raw <text>` | Send text exactly as typed: no line ending, expansion or transforms |
|
|
301
321
|
| `/exit` | Exit termapy |
|
|
302
322
|
|
|
303
323
|
</details>
|
|
@@ -315,12 +335,13 @@ Everything termapy creates (configs, scripts, test files, plugins, logs) lives i
|
|
|
315
335
|
|
|
316
336
|
```text
|
|
317
337
|
termapy_cfg/
|
|
318
|
-
├── plugin/ # global plugins (all configs)
|
|
338
|
+
├── plugin/ # global plugins (all configs), once you add one
|
|
319
339
|
└── demo/
|
|
320
340
|
├── demo.cfg # config file
|
|
341
|
+
├── demo_legacy.profile.json # /mem.* through the device's own `mem` grammar
|
|
321
342
|
├── demo.log # session log
|
|
322
343
|
├── demo.history # command history
|
|
323
|
-
├──
|
|
344
|
+
├── demo.md # project report (/cfg.info), rewritten at exit
|
|
324
345
|
├── run/ # script files for /run
|
|
325
346
|
│ ├── at_demo.run
|
|
326
347
|
│ ├── smoke_test.run
|
|
@@ -331,16 +352,14 @@ termapy_cfg/
|
|
|
331
352
|
│ ├── probe.py
|
|
332
353
|
│ ├── temp_plot.py
|
|
333
354
|
│ └── traffic.py
|
|
334
|
-
├──
|
|
335
|
-
├── prof/ # /run.profile timing CSVs
|
|
336
|
-
├── viz/ # per-config packet visualizers
|
|
355
|
+
├── sym/ # symbol tables (demo.symbols.json, auto-loaded)
|
|
337
356
|
└── proto/ # protocol test scripts
|
|
338
357
|
├── at_test.pro
|
|
339
358
|
├── bitfield_inline.pro
|
|
340
359
|
└── modbus_inline.pro
|
|
341
360
|
```
|
|
342
361
|
|
|
343
|
-
Your own configs follow the same layout.
|
|
362
|
+
Your own configs follow the same layout, minus the demo content: a new config is its `.cfg` beside the log and history. Data folders appear on first use (`ss/` at the first screenshot, `cap/` at the first capture, `prof/` at the first `/run.profile`, `viz/` when you drop a visualizer in), and a folder you empty is removed at the next load, so a plain terminal session never sees a folder it has no use for.
|
|
344
363
|
|
|
345
364
|
### Version control
|
|
346
365
|
|
|
@@ -356,19 +375,18 @@ Since COM port names differ between machines, use `$(env.NAME)` placeholders in
|
|
|
356
375
|
|
|
357
376
|
```json
|
|
358
377
|
{
|
|
359
|
-
"port": "$(env.COMPORT|COM4)",
|
|
360
|
-
"baud_rate": 115200,
|
|
378
|
+
"serial": {"port": "$(env.COMPORT|COM4)", "baud_rate": 115200},
|
|
361
379
|
"auto_connect": true
|
|
362
380
|
}
|
|
363
381
|
```
|
|
364
382
|
|
|
365
|
-
On a machine with `COMPORT=COM7`, termapy connects to COM7. On a machine without `COMPORT` set, it falls back to COM4. The config file on disk keeps the raw `$(env.COMPORT|COM4)` template. It's expanded in memory at load time, so your checked-in config stays portable.
|
|
383
|
+
On a machine with `COMPORT=COM7`, termapy connects to COM7. On a machine without `COMPORT` set, it falls back to COM4. The config file on disk keeps the raw `$(env.COMPORT|COM4)` template. It's expanded in memory at load time, so your checked-in config stays portable. A boolean key can be templated the same way (`"echo": "$(env.ECHO|false)"`); the expanded text is read with the boolean vocabulary (`on`, `off`, `true`, `false`, `yes`, `no`, `1`, `0`, ...), and a value outside it refuses the load naming the key.
|
|
366
384
|
|
|
367
|
-
Environment variables work in any string config value, not just `port`:
|
|
385
|
+
Environment variables work in any string config value, not just `serial.port`:
|
|
368
386
|
|
|
369
387
|
```json
|
|
370
388
|
{
|
|
371
|
-
"port": "$(env.COMPORT|COM4)",
|
|
389
|
+
"serial": {"port": "$(env.COMPORT|COM4)"},
|
|
372
390
|
"title": "$(env.DEVICE_NAME|Dev Board)",
|
|
373
391
|
"log_file": "$(env.LOG_DIR|logs)/session.log"
|
|
374
392
|
}
|
|
@@ -449,7 +467,7 @@ Any datetime variable takes an optional `strftime` format after a colon — `$(D
|
|
|
449
467
|
|
|
450
468
|
**vs. environment variables:** `$(env.NAME)` pulls from the OS environment and works in config files. `$(NAME)` is for user-defined session variables in commands and scripts. Both use the `$(...)` syntax. The `env.` prefix is required to access environment variables explicitly.
|
|
451
469
|
|
|
452
|
-
**Escaping:** Use `\$` to prevent expansion of a single reference, or `/
|
|
470
|
+
**Escaping:** Use `\$` to prevent expansion of a single reference, or `/term.send` to send an entire line without expansion (`/raw` does the same with no line ending).
|
|
453
471
|
|
|
454
472
|
Add a `.gitignore` for session files you don't need to track:
|
|
455
473
|
|
|
@@ -500,13 +518,12 @@ When you create a new config, termapy writes a complete `.cfg` file with all def
|
|
|
500
518
|
|
|
501
519
|
```json
|
|
502
520
|
{
|
|
503
|
-
"port": "COM4",
|
|
504
|
-
"baud_rate": 115200,
|
|
521
|
+
"serial": {"port": "COM4", "baud_rate": 115200},
|
|
505
522
|
"auto_connect": true,
|
|
506
523
|
"auto_reconnect": true,
|
|
507
524
|
"title": "Sensor A",
|
|
508
525
|
"border_color": "blue",
|
|
509
|
-
"on_connect_cmd": "
|
|
526
|
+
"on_connect_cmd": "/run startup"
|
|
510
527
|
}
|
|
511
528
|
```
|
|
512
529
|
|
|
@@ -534,13 +551,11 @@ Add toolbar buttons that send commands, run scripts, or chain multiple actions.
|
|
|
534
551
|
|
|
535
552
|
### Hardware line control
|
|
536
553
|
|
|
537
|
-
Set `flow_control` to `"manual"` to get DTR, RTS, and Break buttons in the toolbar. This is useful for devices that use these lines for reset or bootloader entry:
|
|
554
|
+
Set `serial.flow_control` to `"manual"` to get DTR, RTS, and Break buttons in the toolbar. This is useful for devices that use these lines for reset or bootloader entry:
|
|
538
555
|
|
|
539
556
|
```json
|
|
540
557
|
{
|
|
541
|
-
"port": "COM4",
|
|
542
|
-
"baud_rate": 115200,
|
|
543
|
-
"flow_control": "manual",
|
|
558
|
+
"serial": {"port": "COM4", "baud_rate": 115200, "flow_control": "manual"},
|
|
544
559
|
"title": "Hardware Debug"
|
|
545
560
|
}
|
|
546
561
|
```
|
|
@@ -551,7 +566,7 @@ Set `flow_control` to `"manual"` to get DTR, RTS, and Break buttons in the toolb
|
|
|
551
566
|
<!-- validate-config-keys -->
|
|
552
567
|
```json
|
|
553
568
|
{
|
|
554
|
-
"config_version":
|
|
569
|
+
"config_version": 30,
|
|
555
570
|
"title": "",
|
|
556
571
|
"border_color": "",
|
|
557
572
|
"max_lines": 10000,
|
|
@@ -602,6 +617,7 @@ Set `flow_control` to `"manual"` to get DTR, RTS, and Break buttons in the toolb
|
|
|
602
617
|
"hex": false,
|
|
603
618
|
"request_mode": false,
|
|
604
619
|
"request_err_pattern": "(?i)^(ERROR|ERR|FAULT)\\b",
|
|
620
|
+
"json_style": "compact",
|
|
605
621
|
"strip_device_echo": false,
|
|
606
622
|
"max_grep_lines": 100,
|
|
607
623
|
"file_xfer_root": "",
|
|
@@ -761,18 +777,22 @@ expect_fmt = "Title:Modbus_Response Slave:H1 Func:H2 Bytes:U3 R0:U4-5 R1:U6-7 CR
|
|
|
761
777
|
|
|
762
778
|
Each column is `Name:TypeBytes` where the type controls how bytes are displayed:
|
|
763
779
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
|
767
|
-
|
|
|
768
|
-
| `
|
|
769
|
-
| `
|
|
770
|
-
| `
|
|
771
|
-
| `
|
|
772
|
-
| `
|
|
773
|
-
| `F` | IEEE 754 float
|
|
774
|
-
| `
|
|
775
|
-
| `
|
|
780
|
+
<!-- format-types:start (generated by scripts/sync_format_tables.py from protocol/type_codes.py -- do not edit by hand) -->
|
|
781
|
+
|
|
782
|
+
| Code | Meaning | Example | Output |
|
|
783
|
+
| ------ | ---------------- | ------------------ | ------------ |
|
|
784
|
+
| `H` | Hex bytes | `H1`, `H3-4` | `0A`, `01FF` |
|
|
785
|
+
| `h` | Hex, per byte | `h3-4` | `01 FF` |
|
|
786
|
+
| `U` | Unsigned integer | `U1`, `U3-4` | `10`, `256` |
|
|
787
|
+
| `I` | Signed integer | `I1`, `I3-4` | `-1`, `+127` |
|
|
788
|
+
| `S` | ASCII string | `S1-5` | `Hello` |
|
|
789
|
+
| `F` | IEEE 754 float | `F1-4` | `3.14` |
|
|
790
|
+
| `B` | Bit field | `B1.3`, `B1-2.7-9` | `1`, `5` |
|
|
791
|
+
| `b` | Bit field, bits | `b1.0-7` | `00000110` |
|
|
792
|
+
| `_` | Padding (hidden) | `_3-4` | *(skipped)* |
|
|
793
|
+
| `crc*` | CRC verify | `crc16-modbus` | pass/fail |
|
|
794
|
+
|
|
795
|
+
<!-- format-types:end -->
|
|
776
796
|
|
|
777
797
|
Byte indices are 1-based. Ranges use `-` (e.g. `U3-4` = bytes 3-4). **Byte order is controlled by the index direction.** This is how you handle big-endian vs little-endian protocols:
|
|
778
798
|
|
|
@@ -942,7 +962,7 @@ Passing a `.run` file to `--cli` automatically infers the config from the file's
|
|
|
942
962
|
|
|
943
963
|
- Rich colored output (toggle with `/term.color on|off` or `--no-color`)
|
|
944
964
|
- Command history shared with TUI (up/down arrows, persisted across sessions)
|
|
945
|
-
- Tab completion for REPL commands
|
|
965
|
+
- Tab completion for REPL commands and for the file names they take (`/run`, `/proto.run`, `/cap.dump`, ...)
|
|
946
966
|
- Script execution with `/run` (same scripts work in both TUI and CLI)
|
|
947
967
|
- `/delay` with progress bar for waits of a second or longer (Ctrl+C to cancel)
|
|
948
968
|
- All `/port`, `/cfg`, `/var`, `/env`, `/proto.crc`, `/edit` commands work
|
|
@@ -983,6 +1003,10 @@ It's also a reversible toggle from inside the TUI, like `/cli` <-> `/tui`: `/vt1
|
|
|
983
1003
|
<details>
|
|
984
1004
|
<summary><strong>Extending termapy</strong> - plugins, subcommands, visualizers</summary>
|
|
985
1005
|
|
|
1006
|
+
### Symbols, memory and parts
|
|
1007
|
+
|
|
1008
|
+
`/sym.import build/mem.map` turns your linker map into names, so `/mem.read gTemp` reads a variable by name instead of by address. `/dev.import part.svd` does the same for the silicon: a vendor CMSIS-SVD becomes a **device file** -- every register of the part with its bit fields -- stored once in the config's `lib/` and referenced from its `dev/`, so `/mem.read PORT_GROUP0_DIR` works and a checked-in config folder carries its parts. A part on the external bus (two ADCs, an FPGA block) is written once with register offsets and placed per board: `/dev.use acme-adc16 at=ADC1@0x60000000 ADC2@0x60001000`. Registers are live silicon, not variables, so `/mem.*` refuses bulk reads over them, refuses reads of write-only registers, and logs the rest. The device side is the MEM wire spec (`examples/firmware/termapy_mem.c`, a drop-in) or a profile block describing your monitor's own peek/poke grammar. See the Symbols, Devices and Memory help pages.
|
|
1009
|
+
|
|
986
1010
|
### Plugins
|
|
987
1011
|
|
|
988
1012
|
Every built-in command (`/help`, `/cfg`, `/grep`, all of them) is itself a plugin loaded from the same folder you'd drop your own into. If something was hard to build as a plugin, the API was wrong. [Dogfooding](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) all the way down.
|
|
@@ -1013,86 +1037,9 @@ COMMAND = Command(
|
|
|
1013
1037
|
3. **Per-config:** `termapy_cfg/<name>/plugin/*.py`, specific to one config
|
|
1014
1038
|
4. **App hooks:** frontend-specific commands (`/ss`, `/delay`, `/run`, etc.)
|
|
1015
1039
|
|
|
1016
|
-
|
|
1017
|
-
<summary>Subcommands</summary>
|
|
1018
|
-
|
|
1019
|
-
Use `sub_commands` for related operations. Users invoke them with dot notation (`/tool.run`):
|
|
1020
|
-
|
|
1021
|
-
```python
|
|
1022
|
-
from termapy.plugins import Command
|
|
1023
|
-
|
|
1024
|
-
def _run(ctx, args):
|
|
1025
|
-
ctx.io.status(f"Running {args}...")
|
|
1040
|
+
Resolution is the same in every frontend (TUI, CLI, MCP server) and reruns on every config switch; a folder plugin can never take an app hook's name.
|
|
1026
1041
|
|
|
1027
|
-
|
|
1028
|
-
ctx.io.result("All good.")
|
|
1029
|
-
|
|
1030
|
-
# ── COMMAND (must be at end of file) ──────────────────────────────────────────
|
|
1031
|
-
COMMAND = Command(
|
|
1032
|
-
name="tool",
|
|
1033
|
-
help="A tool with subcommands.",
|
|
1034
|
-
sub_commands={
|
|
1035
|
-
"run": Command(args="<file>", help="Run a file.", handler=_run),
|
|
1036
|
-
"status": Command(help="Show status.", handler=_status),
|
|
1037
|
-
},
|
|
1038
|
-
)
|
|
1039
|
-
```
|
|
1040
|
-
|
|
1041
|
-
The user types `/tool.run myfile` or `/tool.status`.
|
|
1042
|
-
|
|
1043
|
-
</details>
|
|
1044
|
-
|
|
1045
|
-
<details>
|
|
1046
|
-
<summary>PluginContext API</summary>
|
|
1047
|
-
|
|
1048
|
-
The `ctx` object passed to every handler is a thin shell over **five capability handles**, each owning one domain:
|
|
1049
|
-
|
|
1050
|
-
| Member | Description |
|
|
1051
|
-
| --------------------------------- | ----------------------------------------------------------------- |
|
|
1052
|
-
| `ctx.cfg` | Current config (read-only mapping) |
|
|
1053
|
-
| `ctx.config_path` | Path to the current `.cfg` config file |
|
|
1054
|
-
| `ctx.io.result(text, color)` | The command's answer; shown at quiet+ (suppressed at silent) |
|
|
1055
|
-
| `ctx.io.output(text, color)` | Bulk data: listings, dumps; shown at normal+ |
|
|
1056
|
-
| `ctx.io.status(text)` | Progress chatter; shown only at verbose |
|
|
1057
|
-
| `ctx.io.result_markup(text)` | Like `result` but text is Rich markup (`[red]X[/]`) |
|
|
1058
|
-
| `ctx.io.output_markup(text)` | Like `output` but text is Rich markup |
|
|
1059
|
-
| `ctx.io.status_markup(text)` | Like `status` but text is Rich markup |
|
|
1060
|
-
| `ctx.io.notify(text)` | Always-works fallback notification (toast in TUI, plain in CLI) |
|
|
1061
|
-
| `ctx.io.log(prefix, text)` | Write to session log: `">"` TX, `"<"` RX, `"#"` status |
|
|
1062
|
-
| `ctx.serial.is_connected` | Bool: serial port is open |
|
|
1063
|
-
| `ctx.serial.write(data)` | Send bytes to the serial port (auto-logged as TX) |
|
|
1064
|
-
| `ctx.serial.read_raw(timeout_ms)` | Read raw bytes with timeout framing (returns `bytes`) |
|
|
1065
|
-
| `ctx.serial.drain()` | Drain pending RX data |
|
|
1066
|
-
| `ctx.serial.wait_idle()` | Wait until serial output settles |
|
|
1067
|
-
| `ctx.serial.io()` | Context manager for exclusive serial I/O |
|
|
1068
|
-
| `ctx.serial.rx_observer()` | Context manager: passive RX byte tap |
|
|
1069
|
-
| `ctx.serial.tx_observer()` | Context manager: passive TX byte tap |
|
|
1070
|
-
| `ctx.fs.ss_dir` | Screenshot directory (`Path`) |
|
|
1071
|
-
| `ctx.fs.scripts_dir` | Scripts directory (`Path`) |
|
|
1072
|
-
| `ctx.fs.proto_dir` | Proto-test directory (`Path`) |
|
|
1073
|
-
| `ctx.fs.cap_dir` | Capture-output directory (`Path`) |
|
|
1074
|
-
| `ctx.fs.open_file(path)` | Open in system viewer/editor (gated on `gui_apps` capability) |
|
|
1075
|
-
| `ctx.ui.confirm(message)` | Yes/Cancel dialog (TUI-only; declare `confirm_dialog` capability) |
|
|
1076
|
-
| `ctx.ui.notify(text)` | TUI-strict notification (declare `ui_notify`) |
|
|
1077
|
-
| `ctx.ui.clear_screen()` | Clear the terminal output (declare `tui_mode`) |
|
|
1078
|
-
| `ctx.ui.screenshot(path)` | Save an SVG screenshot (declare `screen_capture`) |
|
|
1079
|
-
| `ctx.dispatch(cmd)` | Re-route a command through the full pipeline |
|
|
1080
|
-
| `ctx.ns(name)` | Get/create a session-scoped state dict |
|
|
1081
|
-
| `ctx.plugin_cfg(name)` | Get a per-plugin persistent config dict |
|
|
1082
|
-
|
|
1083
|
-
**Capability gating.** Methods on `ctx.ui` and `ctx.fs.open_file` are gated on `CapabilitySet` flags. Calling a gated method without declaring the capability raises `MissingCapability`, which the dispatcher converts to `CmdResult.fail`. Declare what your command needs:
|
|
1084
|
-
|
|
1085
|
-
```python
|
|
1086
|
-
COMMAND = Command(
|
|
1087
|
-
name="ask", help="Prompt user.",
|
|
1088
|
-
needs=CapabilitySet(confirm_dialog=True), # refuse to dispatch in CLI
|
|
1089
|
-
handler=_handler,
|
|
1090
|
-
)
|
|
1091
|
-
```
|
|
1092
|
-
|
|
1093
|
-
There is also `ctx.internal`, a privileged escape hatch for built-ins (config save, capture, port control, engine forwarders, etc.). This is used by built-in commands and may change between versions, so external plugins should avoid it.
|
|
1094
|
-
|
|
1095
|
-
</details>
|
|
1042
|
+
Subcommands (`/tool.run`, `/tool.status`), typed parameters, scriptable return values, the full `PluginContext` API with its five handles and capability gating, and the `ctx.internal` escape hatch that built-ins use are all in the [Writing plugins](src/termapy/help/writing-plugins.md) guide, which also ships in the in-app help.
|
|
1096
1043
|
|
|
1097
1044
|
<details>
|
|
1098
1045
|
<summary>Example plugins</summary>
|
|
@@ -1104,7 +1051,6 @@ See `examples/plugins/` for working examples:
|
|
|
1104
1051
|
- **timestamp.py:** print the current date/time
|
|
1105
1052
|
- **ping.py:** send a command and measure response time
|
|
1106
1053
|
- **traffic.py:** passive RX/TX byte tap (count, hexdump, rate, snoop) -- also shipped with `--demo`
|
|
1107
|
-
- **pic_map.py:** decode a PIC memory map
|
|
1108
1054
|
|
|
1109
1055
|
More complete examples ship with `--demo`: `probe.py` demonstrates the drain → write → read → parse cycle for device interaction; `traffic.py` (with `/traffic.count`, `/traffic.hexdump`, `/traffic.rate`, `/traffic.snoop`) demonstrates the passive RX/TX observer pattern via the `ctx.serial.rx_observer()` / `ctx.serial.tx_observer()` context managers. Run `/help probe` or `/help traffic` to see the documentation, or `/help.dev <name>` for the source docstrings.
|
|
1110
1056
|
|
|
@@ -1140,16 +1086,22 @@ Actual: 01 00 C9 FF FE 0A -> ID:01 Temp:201 Signed:-2 Status:0A
|
|
|
1140
1086
|
<details>
|
|
1141
1087
|
<summary>Supported types</summary>
|
|
1142
1088
|
|
|
1089
|
+
<!-- format-types:start (generated by scripts/sync_format_tables.py from protocol/type_codes.py -- do not edit by hand) -->
|
|
1090
|
+
|
|
1143
1091
|
| Code | Meaning | Example | Output |
|
|
1144
1092
|
| ------ | ---------------- | ------------------ | ------------ |
|
|
1145
1093
|
| `H` | Hex bytes | `H1`, `H3-4` | `0A`, `01FF` |
|
|
1094
|
+
| `h` | Hex, per byte | `h3-4` | `01 FF` |
|
|
1146
1095
|
| `U` | Unsigned integer | `U1`, `U3-4` | `10`, `256` |
|
|
1147
1096
|
| `I` | Signed integer | `I1`, `I3-4` | `-1`, `+127` |
|
|
1148
|
-
| `S` | ASCII string | `
|
|
1097
|
+
| `S` | ASCII string | `S1-5` | `Hello` |
|
|
1149
1098
|
| `F` | IEEE 754 float | `F1-4` | `3.14` |
|
|
1150
1099
|
| `B` | Bit field | `B1.3`, `B1-2.7-9` | `1`, `5` |
|
|
1151
|
-
| `
|
|
1152
|
-
| `
|
|
1100
|
+
| `b` | Bit field, bits | `b1.0-7` | `00000110` |
|
|
1101
|
+
| `_` | Padding (hidden) | `_3-4` | *(skipped)* |
|
|
1102
|
+
| `crc*` | CRC verify | `crc16-modbus` | pass/fail |
|
|
1103
|
+
|
|
1104
|
+
<!-- format-types:end -->
|
|
1153
1105
|
|
|
1154
1106
|
Integers support 1, 2, 3, 4, and 8 byte widths. Floats are 4-byte (F32) or 8-byte (F64).
|
|
1155
1107
|
|
|
@@ -1239,33 +1191,24 @@ From the REPL:
|
|
|
1239
1191
|
<details>
|
|
1240
1192
|
<summary><strong>Portability</strong></summary>
|
|
1241
1193
|
|
|
1242
|
-
Developed and tested on **Windows**. Basic usage verified on **macOS** (serial, ANSI rendering, screenshots). macOS support is **alpha** until further testing. **Linux** is exercised by GitHub Actions CI on every push (the full test suite, including the CLI gold-standard integration test, runs on Ubuntu against Python 3.11 through 3.
|
|
1194
|
+
Developed and tested on **Windows**. Basic usage verified on **macOS** (serial, ANSI rendering, screenshots). macOS support is **alpha** until further testing. **Linux** is exercised by GitHub Actions CI on every push (the full test suite, including the CLI gold-standard integration test, runs on Ubuntu against Python 3.11 through 3.15), but interactive use on Linux has not been hand-verified by the author.
|
|
1243
1195
|
|
|
1244
1196
|
</details>
|
|
1245
1197
|
|
|
1246
1198
|
<details>
|
|
1247
1199
|
<summary><strong>Architecture</strong> - threading model</summary>
|
|
1248
1200
|
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
| Worker | Lifetime | Purpose |
|
|
1252
|
-
| ------------------- | ----------- | ------------------------------------------------------- |
|
|
1253
|
-
| `SerialEngine.read_loop()` | Long-lived | The reader thread (`start_reader` / `stop_reader`); hands RX to the UI without blocking |
|
|
1254
|
-
| `_run_reconnect()` | Short-lived | Retries serial connection every 2.5s until success |
|
|
1255
|
-
| `_run_lines()` | Short-lived | Sends multiple commands with inter-command delay |
|
|
1256
|
-
| `_run_script()` | Short-lived | Executes a `.run` script file line by line |
|
|
1257
|
-
| `_send_test()` | Short-lived | Runs a single protocol test case (`proto_debug.py`) |
|
|
1258
|
-
| `_run_cmds()` | Short-lived | Sends setup/teardown commands for protocol tests (`proto_debug.py`) |
|
|
1259
|
-
|
|
1260
|
-
Only the reader is long-lived. At most two workers run concurrently: the serial reader plus one command/script/test worker.
|
|
1201
|
+
Every command runs on a worker thread, the serial reader is the only long-lived thread, and the UI thread never parks on a lock a worker holds. The one description of the threads, their hand-offs, and the rules each relies on is the [Threading model](ARCHITECTURE.md#threading-model) section of ARCHITECTURE.md.
|
|
1261
1202
|
|
|
1262
1203
|
</details>
|
|
1263
1204
|
|
|
1264
1205
|
<details>
|
|
1265
|
-
<summary><strong>Test coverage</strong> -
|
|
1206
|
+
<summary><strong>Test coverage</strong> - 4913 tests</summary>
|
|
1266
1207
|
|
|
1267
1208
|
Run the full suite with `uv run pytest`. (The count above is the one place it
|
|
1268
|
-
is tracked; `release_prep` refreshes it each release.)
|
|
1209
|
+
is tracked; `release_prep` refreshes it each release.) The coverage figure is
|
|
1210
|
+
the coverage badge at the top, live from Codecov, measured by CI on every
|
|
1211
|
+
push to main.
|
|
1269
1212
|
|
|
1270
1213
|
Tests are scoped to **termapy's own concerns** — REPL dispatch, serial
|
|
1271
1214
|
engine, CLI flow, plugin loading, capture, protocol toolkit. CRC
|
|
@@ -1279,7 +1222,7 @@ generator permutation.
|
|
|
1279
1222
|
|
|
1280
1223
|
**Built-in plugins:** broad coverage via `test_builtins.py` plus per-plugin test files (`test_var.py`, `test_env_var.py`, `test_xmodem.py`, `test_ymodem.py`, `test_app_plugin.py`, `test_proto_send_crc.py`, etc.).
|
|
1281
1224
|
|
|
1282
|
-
**UI code:** `app.py` is driven headless by `tests/test_app_pilot
|
|
1225
|
+
**UI code:** `app.py` is driven headless by `tests/test_app_pilot*.py` (Textual Pilot boots the real app), every dialog by `tests/test_dialogs*.py` (each pushed into a bare host app), and `proto_debug.py` has Pilot coverage for its Run and Stop controls and is otherwise exercised manually. The headline coverage figure is measured with the `builtins/` package top level and vendored code **omitted** (see `[tool.coverage.run]` in `pyproject.toml`): `builtins/` are plugins covered behaviorally through the commands they register, `vendor/` is third-party. `app.py` and `dialogs/` are counted, so the UI layer's number is real and movable rather than a flattering omission.
|
|
1283
1226
|
|
|
1284
1227
|
</details>
|
|
1285
1228
|
|
|
@@ -1290,9 +1233,9 @@ All tests run automatically on push to `main` and on pull requests via GitHub Ac
|
|
|
1290
1233
|
|
|
1291
1234
|
| Job | What it does |
|
|
1292
1235
|
| ------------ | ------------------------------------------------------------------------------------------------- |
|
|
1293
|
-
| **test** | Runs `pytest` across Python 3.11, 3.12, 3.13, and 3.
|
|
1236
|
+
| **test** | Runs `pytest` across Python 3.11, 3.12, 3.13, 3.14, and 3.15 |
|
|
1294
1237
|
| **coverage** | Runs `pytest --cov` on Python 3.14 and uploads to [Codecov](https://codecov.io/gh/hucker/termapy) |
|
|
1295
|
-
| **audit** |
|
|
1238
|
+
| **audit** | Audits `uv.lock` with `pip-audit` (every extra and group; `scripts/audit_lock.py`) |
|
|
1296
1239
|
|
|
1297
1240
|
The CI badge at the top of this README reflects the current status of the test workflow. See [`.github/workflows/tests.yml`](.github/workflows/tests.yml) for the full configuration.
|
|
1298
1241
|
|