termapy 0.74.0__tar.gz → 0.76.0__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.
Files changed (349) hide show
  1. {termapy-0.74.0 → termapy-0.76.0}/PKG-INFO +51 -44
  2. {termapy-0.74.0 → termapy-0.76.0}/README.md +49 -43
  3. {termapy-0.74.0 → termapy-0.76.0}/pyproject.toml +14 -4
  4. {termapy-0.74.0 → termapy-0.76.0}/pyproject.toml.orig +23 -3
  5. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/app.py +387 -91
  6. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/app_hooks.py +11 -7
  7. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/credits.py +29 -15
  8. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/edit.py +7 -7
  9. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/find.py +18 -4
  10. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/port.py +55 -0
  11. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/proto.py +1 -1
  12. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/repeat.py +15 -5
  13. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/run.py +24 -17
  14. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/term.py +21 -9
  15. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/var.py +63 -271
  16. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/plugin/traffic.py +1 -1
  17. termapy-0.76.0/src/termapy/builtins/demo/run/doc_screenshots.run +124 -0
  18. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/capture.py +79 -22
  19. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/capture_view.py +4 -2
  20. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/cli.py +33 -23
  21. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/cli_flags.py +124 -92
  22. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/config.py +133 -5
  23. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/config_resolve.py +56 -0
  24. termapy-0.76.0/src/termapy/credits_data.py +181 -0
  25. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/defaults.py +2 -2
  26. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/demo.py +10 -0
  27. termapy-0.76.0/src/termapy/dialogs/_common.py +168 -0
  28. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/config_picker.py +89 -14
  29. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/filename_dialog.py +5 -1
  30. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/proto_picker.py +29 -11
  31. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/script_picker.py +44 -20
  32. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/entry.py +10 -1
  33. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/folder_ops.py +185 -15
  34. termapy-0.76.0/src/termapy/help/.coverage +0 -0
  35. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/acknowledgments.md +29 -15
  36. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/authoring-profiles.md +10 -10
  37. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/cli.md +368 -356
  38. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/commands.md +35 -23
  39. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/config.md +15 -6
  40. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/custom-buttons.md +54 -50
  41. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/data-capture.md +13 -3
  42. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/demo.md +17 -12
  43. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/device-help.md +135 -133
  44. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/environment.md +3 -3
  45. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/file-transfer.md +217 -214
  46. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/getting-started.md +16 -10
  47. termapy-0.76.0/src/termapy/help/img/doc_11_proto_run.svg +205 -0
  48. termapy-0.76.0/src/termapy/help/img/doc_12_cap_struct.svg +203 -0
  49. termapy-0.76.0/src/termapy/help/img/doc_13_cap_progress.svg +200 -0
  50. termapy-0.76.0/src/termapy/help/img/doc_14_port_list.svg +201 -0
  51. termapy-0.76.0/src/termapy/help/img/doc_15_xfer.svg +203 -0
  52. termapy-0.76.0/src/termapy/help/img/doc_16_toolbar.svg +202 -0
  53. termapy-0.76.0/src/termapy/help/img/doc_17_proto_debug.svg +219 -0
  54. termapy-0.76.0/src/termapy/help/img/doc_20_palette.svg +209 -0
  55. termapy-0.76.0/src/termapy/help/img/doc_21_script_picker.svg +213 -0
  56. termapy-0.76.0/src/termapy/help/img/doc_22_script_editor.svg +212 -0
  57. termapy-0.76.0/src/termapy/help/img/doc_23_config_editor.svg +217 -0
  58. termapy-0.76.0/src/termapy/help/img/doc_24_cmd_picker.svg +208 -0
  59. termapy-0.76.0/src/termapy/help/img/doc_35_vt100_menu.png +0 -0
  60. termapy-0.76.0/src/termapy/help/img/doc_36_vt100_status.png +0 -0
  61. termapy-0.76.0/src/termapy/help/img/doc_37_config_picker.svg +213 -0
  62. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/index.md +4 -2
  63. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/installation.md +132 -132
  64. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/mcp-server.md +19 -3
  65. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/ports.md +76 -7
  66. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/protocol-testing.md +207 -174
  67. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/scripting.md +46 -8
  68. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/serial-tools.md +42 -34
  69. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/toolbar.md +121 -107
  70. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/using-git.md +109 -110
  71. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/variables.md +13 -7
  72. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/vt100.md +91 -85
  73. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/writing-plugins.md +66 -8
  74. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help_tooltip.py +13 -17
  75. termapy-0.76.0/src/termapy/html/.coverage +0 -0
  76. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/404.html +9 -9
  77. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/acknowledgments.html +39 -24
  78. termapy-0.76.0/src/termapy/html/assets/javascripts/bundle.49251538.min.js +10 -0
  79. termapy-0.76.0/src/termapy/html/assets/stylesheets/classic/main.38807bfb.min.css +1 -0
  80. termapy-0.76.0/src/termapy/html/assets/stylesheets/classic/palette.c7ab7c71.min.css +1 -0
  81. termapy-0.76.0/src/termapy/html/assets/stylesheets/modern/main.5da3a30f.min.css +1 -0
  82. termapy-0.76.0/src/termapy/html/assets/stylesheets/modern/palette.812a03bb.min.css +1 -0
  83. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/authoring-profiles.html +19 -19
  84. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/cli.html +39 -13
  85. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/commands.html +50 -46
  86. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/config.html +21 -15
  87. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/custom-buttons.html +15 -12
  88. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/data-capture.html +18 -12
  89. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/demo.html +35 -22
  90. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/device-help.html +12 -11
  91. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/environment.html +12 -12
  92. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/file-transfer.html +11 -9
  93. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/getting-started.html +27 -22
  94. termapy-0.76.0/src/termapy/html/img/doc_11_proto_run.svg +205 -0
  95. termapy-0.76.0/src/termapy/html/img/doc_12_cap_struct.svg +203 -0
  96. termapy-0.76.0/src/termapy/html/img/doc_13_cap_progress.svg +200 -0
  97. termapy-0.76.0/src/termapy/html/img/doc_14_port_list.svg +201 -0
  98. termapy-0.76.0/src/termapy/html/img/doc_15_xfer.svg +203 -0
  99. termapy-0.76.0/src/termapy/html/img/doc_16_toolbar.svg +202 -0
  100. termapy-0.76.0/src/termapy/html/img/doc_17_proto_debug.svg +219 -0
  101. termapy-0.76.0/src/termapy/html/img/doc_20_palette.svg +209 -0
  102. termapy-0.76.0/src/termapy/html/img/doc_21_script_picker.svg +213 -0
  103. termapy-0.76.0/src/termapy/html/img/doc_22_script_editor.svg +212 -0
  104. termapy-0.76.0/src/termapy/html/img/doc_23_config_editor.svg +217 -0
  105. termapy-0.76.0/src/termapy/html/img/doc_24_cmd_picker.svg +208 -0
  106. termapy-0.76.0/src/termapy/html/img/doc_35_vt100_menu.png +0 -0
  107. termapy-0.76.0/src/termapy/html/img/doc_36_vt100_status.png +0 -0
  108. termapy-0.76.0/src/termapy/html/img/doc_37_config_picker.svg +213 -0
  109. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/index.html +13 -11
  110. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/installation.html +11 -11
  111. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/mcp-server.html +67 -12
  112. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/on-ai-assistance.html +9 -9
  113. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/ports.html +138 -28
  114. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/protocol-testing.html +106 -44
  115. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/scripting.html +83 -28
  116. termapy-0.76.0/src/termapy/html/search.json +1 -0
  117. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/serial-tools.html +49 -43
  118. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/toolbar.html +55 -40
  119. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/using-git.html +16 -17
  120. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/variables.html +39 -17
  121. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/vt100.html +15 -10
  122. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/writing-plugins.html +220 -146
  123. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/mcp/catalog.py +8 -14
  124. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/mcp/server.py +140 -94
  125. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/pickers.py +45 -6
  126. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/__init__.py +1 -1
  127. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/command.py +23 -12
  128. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/context.py +11 -0
  129. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/port_control.py +490 -55
  130. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/port_format.py +98 -4
  131. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/repl.py +288 -69
  132. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/run_profile_hooks.py +9 -8
  133. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/scripting.py +101 -8
  134. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/serial_engine.py +141 -40
  135. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/serial_port.py +82 -6
  136. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/tree_render.py +3 -13
  137. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/usb/_vendors_full.py +4 -4
  138. termapy-0.76.0/src/termapy/usb_tree.py +565 -0
  139. termapy-0.76.0/src/termapy/variables.py +371 -0
  140. termapy-0.74.0/src/termapy/builtins/demo/run/doc_screenshots.run +0 -78
  141. termapy-0.74.0/src/termapy/dialogs/_common.py +0 -67
  142. termapy-0.74.0/src/termapy/html/assets/javascripts/bundle.e886cdf1.min.js +0 -10
  143. termapy-0.74.0/src/termapy/html/assets/stylesheets/classic/main.39e53929.min.css +0 -1
  144. termapy-0.74.0/src/termapy/html/assets/stylesheets/classic/palette.7dc9a0ad.min.css +0 -1
  145. termapy-0.74.0/src/termapy/html/assets/stylesheets/modern/main.20815dad.min.css +0 -1
  146. termapy-0.74.0/src/termapy/html/assets/stylesheets/modern/palette.dfe2e883.min.css +0 -1
  147. termapy-0.74.0/src/termapy/html/search.json +0 -1
  148. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/__init__.py +0 -0
  149. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/__main__.py +0 -0
  150. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/app_dirs.py +0 -0
  151. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/__init__.py +0 -0
  152. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/_cfg_icon.py +0 -0
  153. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/_crc_verbs.py +0 -0
  154. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/_run_record.py +0 -0
  155. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/_xmodem_handlers.py +0 -0
  156. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/_ymodem_handlers.py +0 -0
  157. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/app.py +0 -0
  158. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/cap.py +0 -0
  159. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/cfg.py +0 -0
  160. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/cls.py +0 -0
  161. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/confirm.py +0 -0
  162. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/env.py +0 -0
  163. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/exit.py +0 -0
  164. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/grep.py +0 -0
  165. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/help.py +0 -0
  166. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/log.py +0 -0
  167. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/mcp.py +0 -0
  168. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/os_cmd.py +0 -0
  169. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/ping.py +0 -0
  170. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/plugin.py +0 -0
  171. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/print.py +0 -0
  172. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/profile.py +0 -0
  173. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/run_edit.py +0 -0
  174. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/search.py +0 -0
  175. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/seq.py +0 -0
  176. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/show.py +0 -0
  177. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/ss.py +0 -0
  178. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/stop.py +0 -0
  179. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/commands/xfer.py +0 -0
  180. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/crc/__init__.py +0 -0
  181. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/crc/sum16.py +0 -0
  182. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/crc/sum8.py +0 -0
  183. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/.gitignore +0 -0
  184. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/__init__.py +0 -0
  185. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/demo.cfg +0 -0
  186. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/demo.profile.json +0 -0
  187. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/demo_ndjson.profile.json +0 -0
  188. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/plugin/__init__.py +0 -0
  189. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/plugin/cmd.py +0 -0
  190. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/plugin/probe.py +0 -0
  191. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/plugin/temp_plot.py +0 -0
  192. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/proto/at_test.pro +0 -0
  193. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/proto/bitfield_inline.pro +0 -0
  194. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/proto/modbus_inline.pro +0 -0
  195. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/at_demo.run +0 -0
  196. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/crc_tour.run +0 -0
  197. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/expect_test.run +0 -0
  198. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/gps_demo.run +0 -0
  199. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/smoke_test.run +0 -0
  200. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/status_check.run +0 -0
  201. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/var_demo.run +0 -0
  202. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/demo/run/welcome.run +0 -0
  203. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/viz/__init__.py +0 -0
  204. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/viz/hex_view.py +0 -0
  205. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/viz/modbus_view.py.old +0 -0
  206. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/builtins/viz/text_view.py +0 -0
  207. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/demo_ndjson.py +0 -0
  208. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/demo_vt100.py +0 -0
  209. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/__init__.py +0 -0
  210. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/cfg_confirm.py +0 -0
  211. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/config_editor.py +0 -0
  212. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/confirm_dialog.py +0 -0
  213. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/name_picker.py +0 -0
  214. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/port_picker.py +0 -0
  215. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/proto_editor.py +0 -0
  216. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/quick_setup.py +0 -0
  217. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/script_editor.py +0 -0
  218. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/set_var_dialog.py +0 -0
  219. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/update_available.py +0 -0
  220. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/dialogs/welcome_dialog.py +0 -0
  221. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/env_flags.py +0 -0
  222. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/folders.py +0 -0
  223. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_01_main_tui.svg +0 -0
  224. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_02_help.svg +0 -0
  225. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_03_help_proto.svg +0 -0
  226. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_04_proto_send.svg +0 -0
  227. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_05_proto_crc.svg +0 -0
  228. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_06_proto_delay.svg +0 -0
  229. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_07_crc_python.svg +0 -0
  230. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_08_variables.svg +0 -0
  231. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_09_target_help.svg +0 -0
  232. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/img/doc_10_config_info.svg +0 -0
  233. /termapy-0.74.0/src/termapy/help/img/new_cfg.png → /termapy-0.76.0/src/termapy/help/img/doc_30_new_cfg.png +0 -0
  234. /termapy-0.74.0/src/termapy/help/img/cli_completion.png → /termapy-0.76.0/src/termapy/help/img/doc_31_cli_completion.png +0 -0
  235. /termapy-0.74.0/src/termapy/help/img/com_port_select.png → /termapy-0.76.0/src/termapy/help/img/doc_32_port_picker.png +0 -0
  236. /termapy-0.74.0/src/termapy/help/img/com_port_tooltip.png → /termapy-0.76.0/src/termapy/help/img/doc_33_port_tooltip.png +0 -0
  237. /termapy-0.74.0/src/termapy/help/img/latency_picker.png → /termapy-0.76.0/src/termapy/help/img/doc_34_latency_timer.png +0 -0
  238. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help/on-ai-assistance.md +0 -0
  239. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/help_dynamic.py +0 -0
  240. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/history_nav.py +0 -0
  241. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/assets/images/favicon.png +0 -0
  242. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/assets/javascripts/LICENSE +0 -0
  243. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/assets/javascripts/workers/search.7d14d953.min.js +0 -0
  244. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_01_main_tui.svg +0 -0
  245. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_02_help.svg +0 -0
  246. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_03_help_proto.svg +0 -0
  247. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_04_proto_send.svg +0 -0
  248. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_05_proto_crc.svg +0 -0
  249. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_06_proto_delay.svg +0 -0
  250. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_07_crc_python.svg +0 -0
  251. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_08_variables.svg +0 -0
  252. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_09_target_help.svg +0 -0
  253. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/img/doc_10_config_info.svg +0 -0
  254. /termapy-0.74.0/src/termapy/html/img/new_cfg.png → /termapy-0.76.0/src/termapy/html/img/doc_30_new_cfg.png +0 -0
  255. /termapy-0.74.0/src/termapy/html/img/cli_completion.png → /termapy-0.76.0/src/termapy/html/img/doc_31_cli_completion.png +0 -0
  256. /termapy-0.74.0/src/termapy/html/img/com_port_select.png → /termapy-0.76.0/src/termapy/html/img/doc_32_port_picker.png +0 -0
  257. /termapy-0.74.0/src/termapy/html/img/com_port_tooltip.png → /termapy-0.76.0/src/termapy/html/img/doc_33_port_tooltip.png +0 -0
  258. /termapy-0.74.0/src/termapy/html/img/latency_picker.png → /termapy-0.76.0/src/termapy/html/img/doc_34_latency_timer.png +0 -0
  259. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/objects.inv +0 -0
  260. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/html/sitemap.xml +0 -0
  261. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/info_views.py +0 -0
  262. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/install_info.py +0 -0
  263. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/legacy.py +0 -0
  264. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/mcp/__init__.py +0 -0
  265. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/mcp/prompts.py +0 -0
  266. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/migration.py +0 -0
  267. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/palette_provider.py +0 -0
  268. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/capabilities.py +0 -0
  269. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/handles/__init__.py +0 -0
  270. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/handles/fs.py +0 -0
  271. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/handles/internal.py +0 -0
  272. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/handles/io.py +0 -0
  273. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/handles/serial.py +0 -0
  274. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/handles/ui.py +0 -0
  275. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/loader.py +0 -0
  276. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/output_levels.py +0 -0
  277. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/plugins/params.py +0 -0
  278. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/profile/__init__.py +0 -0
  279. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/profile/loader.py +0 -0
  280. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/profile/matcher.py +0 -0
  281. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/profile/schema.json +0 -0
  282. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/profile/types.py +0 -0
  283. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/proto_debug.py +0 -0
  284. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/protocol/__init__.py +0 -0
  285. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/protocol/core.py +0 -0
  286. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/protocol/crc.py +0 -0
  287. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/protocol/runner.py +0 -0
  288. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/protocol/viz.py +0 -0
  289. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/request_response.py +0 -0
  290. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/response_parsers.py +0 -0
  291. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/run_docstring.py +0 -0
  292. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/run_legacy.py +0 -0
  293. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/smoke.txt +0 -0
  294. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/templates/icons/termapy.icns +0 -0
  295. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/templates/icons/termapy.ico +0 -0
  296. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/templates/icons/termapy.png +0 -0
  297. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/templates/icons/termapy.svg +0 -0
  298. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/templates/linux/termapy.desktop.template +0 -0
  299. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/templates/macos/Termapy.app/Contents/Info.plist +0 -0
  300. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/templates/macos/Termapy.app/Contents/MacOS/launcher.template +0 -0
  301. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/terminal_host.py +0 -0
  302. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/title_bar.py +0 -0
  303. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/update_check.py +0 -0
  304. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/usb/__init__.py +0 -0
  305. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/usb/aliases.py +0 -0
  306. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/usb/chips.py +0 -0
  307. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/usb/vendors.py +0 -0
  308. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/LICENSES.md +0 -0
  309. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/__init__.py +0 -0
  310. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/__init__.py +0 -0
  311. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/__main__.py +0 -0
  312. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/rfc2217.py +0 -0
  313. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/rs485.py +0 -0
  314. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/serialcli.py +0 -0
  315. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/serialjava.py +0 -0
  316. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/serialposix.py +0 -0
  317. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/serialutil.py +0 -0
  318. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/serialwin32.py +0 -0
  319. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/threaded/__init__.py +0 -0
  320. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/__init__.py +0 -0
  321. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/hexlify_codec.py +0 -0
  322. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/list_ports.py +0 -0
  323. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/list_ports_common.py +0 -0
  324. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/list_ports_linux.py +0 -0
  325. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/list_ports_osx.py +0 -0
  326. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/list_ports_posix.py +0 -0
  327. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/list_ports_windows.py +0 -0
  328. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/tools/miniterm.py +0 -0
  329. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/__init__.py +0 -0
  330. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/protocol_alt.py +0 -0
  331. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/protocol_cp2110.py +0 -0
  332. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/protocol_hwgrep.py +0 -0
  333. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/protocol_loop.py +0 -0
  334. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/protocol_rfc2217.py +0 -0
  335. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/protocol_socket.py +0 -0
  336. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/urlhandler/protocol_spy.py +0 -0
  337. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/serial/win32.py +0 -0
  338. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/xmodem.py +0 -0
  339. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/ymodem/CRC.py +0 -0
  340. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/ymodem/Platform.py +0 -0
  341. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/ymodem/Protocol.py +0 -0
  342. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/ymodem/Socket.py +0 -0
  343. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/ymodem/Version.py +0 -0
  344. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vendor/ymodem/__init__.py +0 -0
  345. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/vt100.py +0 -0
  346. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/widgets/__init__.py +0 -0
  347. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/widgets/checkbox.py +0 -0
  348. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/widgets/status_bar.py +0 -0
  349. {termapy-0.74.0 → termapy-0.76.0}/src/termapy/widgets/suggester.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: termapy
3
- Version: 0.74.0
3
+ Version: 0.76.0
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
@@ -27,6 +27,7 @@ Requires-Dist: tree-sitter-json>=0.24.0,<0.25 ; python_full_version >= '3.10'
27
27
  Requires-Dist: tree-sitter-toml>=0.6.0,<0.8 ; python_full_version >= '3.10'
28
28
  Requires-Dist: tree-sitter-bash>=0.23.0,<0.26 ; python_full_version >= '3.10'
29
29
  Requires-Dist: packaging>=24.0
30
+ Requires-Dist: frist>=0.21
30
31
  Requires-Dist: platformdirs>=4.0
31
32
  Requires-Dist: crcglot>=0.31.0
32
33
  Requires-Dist: termapy[mcp,web] ; extra == 'all'
@@ -49,7 +50,7 @@ Description-Content-Type: text/markdown
49
50
 
50
51
  **Powered by:** [![Textual](https://img.shields.io/badge/Textual-TUI-blue?logo=python)](https://textual.textualize.io/) [![pySerial](https://img.shields.io/badge/pySerial-serial%20I%2FO-orange?logo=python)](https://pyserial.readthedocs.io/) [![zensical](https://img.shields.io/badge/zensical-docs-green)](https://github.com/hucker/zensical)
51
52
 
52
- **Built with:** ![python](https://img.shields.io/badge/python-3.11--3.14-blue) [![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet?logo=astral)](https://docs.astral.sh/uv/) [![pytest](https://img.shields.io/badge/pytest-testing-yellow?logo=pytest)](https://pytest.org/) [![coverage](https://img.shields.io/badge/coverage-73%25-yellow)](https://coverage.readthedocs.io/)
53
+ **Built with:** ![python](https://img.shields.io/badge/python-3.11--3.14-blue) [![uv](https://img.shields.io/badge/uv-package%20manager-blueviolet?logo=astral)](https://docs.astral.sh/uv/) [![pytest](https://img.shields.io/badge/pytest-testing-yellow?logo=pytest)](https://pytest.org/) [![coverage](https://img.shields.io/badge/coverage-72%25-yellow)](https://coverage.readthedocs.io/)
53
54
 
54
55
  Pronounced "ter-map-ee"
55
56
 
@@ -57,7 +58,7 @@ Runs on Windows, macOS, and Linux. A serial interface terminal like PuTTY or Ter
57
58
 
58
59
  Low time commitment: about 1 minute from scratch, or under 10 seconds if you already have [uv](https://docs.astral.sh/uv/) installed.
59
60
 
60
- ![termapy screenshot](img/main.png)
61
+ ![termapy screenshot](src/termapy/help/img/doc_01_main_tui.svg)
61
62
 
62
63
  ## Install and connect
63
64
 
@@ -108,7 +109,7 @@ There's a lot more: scripting, binary protocol testing, every CRC algorithm in t
108
109
 
109
110
  1. **Connect:** click the port button in the title bar, pick your COM port, click the status button to connect (it turns green)
110
111
  2. **Type:** enter commands in the input box at the bottom and press Enter
111
- 3. **Change settings:** click `Cfg` to edit port, baud rate, and other settings through the UI
112
+ 3. **Change settings:** click the config name in the title bar (or `Cfg` → `Edit`) to change port, baud rate, and other settings through the UI
112
113
 
113
114
  Everything works through the UI. No config files to edit unless you want to.
114
115
 
@@ -163,6 +164,7 @@ Termapy runs with your privileges and does whatever you — or a connected MCP c
163
164
  | Ctrl+S | Save SVG screenshot |
164
165
  | Ctrl+T | Save text screenshot |
165
166
  | Ctrl+P | Command palette |
167
+ | F1–F4 | Help / Cfg / Run / Proto buttons (Ctrl+Shift+1–4 in VS Code); F10 edits the config |
166
168
  | Up/Down | Cycle through command history |
167
169
  | Escape | Clear input / exit history browsing |
168
170
  | Right | Accept type-ahead suggestion |
@@ -175,10 +177,11 @@ macOS Option-as-Meta, KVM cross-platform keyboards, etc.).
175
177
 
176
178
  | Button | Action |
177
179
  | ------ | ------------------------------------------------------------------- |
178
- | `?` | Open the help guide |
179
- | `#` | Toggle line numbers (green when active) |
180
- | `Cfg` | Open the config picker |
181
- | `Run` | Open the script picker |
180
+ | `Help` | Open the help guide |
181
+ | `Cfg` | Open the config picker (Load / Edit / New / Rename / Delete) |
182
+ | `Run` | Open the script picker (Run / Edit / New / Rename / Delete) |
183
+ | `Proto`| Open the protocol-test picker |
184
+ | `Update` | Appears only when a newer termapy is on PyPI |
182
185
  | Center | Click to edit the current config |
183
186
  | Port | Click to select a serial port |
184
187
  | Status | Click to connect/disconnect (red = disconnected, green = connected) |
@@ -199,7 +202,7 @@ The most common ones:
199
202
  | `/ss.svg [name]` | Save SVG screenshot |
200
203
  | `/cls` | Clear the terminal |
201
204
  | `/run {filename}` | Open Run picker (bare TUI), or run a named script |
202
- | `/term.echo [on \| off]` | Toggle command echo |
205
+ | `/term.echo [on \| off]` | Local echo of device commands sent to the wire |
203
206
  | `/grep <pattern>` | Search scrollback |
204
207
  | `/exit` | Exit termapy |
205
208
 
@@ -231,17 +234,18 @@ The most common ones:
231
234
  | `/port.break {ms}` | Send break signal (default 250ms) |
232
235
  | `/cfg [key [value]]` | Open Cfg picker (bare TUI), dump JSON (bare CLI), or get/set with args |
233
236
  | `/cfg.auto <key> <value>` | Set an in-memory config key immediately (no confirmation) |
234
- | `/cfg.configs` | List all config files |
237
+ | `/cfg.list` | List all config files |
235
238
  | `/cfg.load <name>` | Switch to a different config by name |
236
239
  | `/cfg.show` | Open the current config file in the system viewer |
237
240
  | `/cfg.help` | Same as `/help cfg` |
238
241
  | `/ss.svg [name]` | Save SVG screenshot |
239
242
  | `/ss.txt [name]` | Save text screenshot |
240
- | `/ss.dir` | Show the screenshot folder |
243
+ | `/ss.list` | List screenshots, newest first, with size and age |
244
+ | `/ss.explore` | Open the screenshot folder in the system file explorer |
241
245
  | `/cls` | Clear the terminal screen |
242
- | `/run {filename} {-v}` | Open Run picker (bare TUI), list scripts (bare CLI), or run; nests 5 deep |
243
- | `/run.list` | List .run files in the run/ directory |
244
- | `/run.load <filename>` | Run a script file (same as /run) |
246
+ | `/run {filename}` | Open Run picker (bare TUI), list scripts (bare CLI), or run; nests 5 deep |
247
+ | `/run.list` | List .run files in run/, newest first, with size, age, and summary |
248
+ | `/run.rename <old> <new>` | Rename a script (`.run` kept; never overwrites) |
245
249
  | `/run.help` | Same as `/help run` |
246
250
  | `/delay <duration>` | Wait for a duration (e.g. `500ms`, `1.5s`) |
247
251
  | `/confirm {message}` | Show Yes/Cancel dialog; Cancel stops a running script (see `at_demo.run`) |
@@ -254,8 +258,8 @@ The most common ones:
254
258
  | `/show.cfg` | Show the current config file |
255
259
  | `/term` | Terminal display / session toggles (echo, line_no, timestamps, ...) |
256
260
  | `/term.info` | Snapshot the state of every `/term.*` toggle |
257
- | `/term.echo [on \| off]` | Toggle REPL command echo |
258
- | `/term.echo.silent <on \| off>` | Set echo on/off without echoing the change (for scripts and on_connect_cmd) |
261
+ | `/term.echo [on \| off]` | Local echo of device commands sent to the wire (persisted via cfg `echo`) |
262
+ | `/term.echo_repl [on \| off]` | Local echo of REPL (slash) commands, session only; off inside scripts |
259
263
  | `/term.line_no [on \| off]` | Toggle line numbers in serial output (TUI only) |
260
264
  | `/term.eol.markers [on \| off]` | Toggle visible `\r` `\n` markers for line-ending troubleshooting |
261
265
  | `/term.output {level}` | Show or set output level (silent/quiet/normal/verbose) |
@@ -269,20 +273,19 @@ The most common ones:
269
273
  | `/edit.info` | Open the info report in the system viewer |
270
274
  | `/os <cmd>` | Run a shell command (10s timeout, requires `TERMAPY_OS_CMD_ENABLED=1` in env) |
271
275
  | `/grep <pattern>` | Search scrollback for regex matches (case-insensitive, skips own output) |
272
- | `/cfg.info {--display}` | Show project summary; `--display` opens full report in system viewer |
273
- | `/cfg.files` | Show project directory tree |
276
+ | `/cfg.info {--display}` | Show project summary (folder tree + config + buttons); `--display` opens the full report |
274
277
  | `/proto` | Open Proto picker (bare TUI) or show long-help (bare CLI) |
275
278
  | `/proto.help` | Same as `/help proto` |
276
279
  | `/proto.send <hex>` | Send raw hex bytes and/or quoted text, display response as hex (see below) |
277
280
  | `/proto.run <file>` | Run a binary protocol test script (.pro) with pass/fail |
278
- | `/proto.list` | List .pro files in the proto/ directory |
279
- | `/proto.load <file>` | Run a protocol test script (same as /proto.run) |
281
+ | `/proto.list` | List .pro files in proto/, newest first, with size and age |
282
+ | `/proto.rename <old> <new>` | Rename a protocol script (`.pro` kept; never overwrites) |
280
283
  | `/proto.hex [on \| off]` | Toggle hex display mode for serial I/O |
281
284
  | `/proto.crc.list {pat}` | List available CRC algorithms (optional glob filter) |
282
285
  | `/proto.crc.info <name>` | Show CRC algorithm parameters and description |
283
286
  | `/proto.crc.calc <n> {d}` | Compute CRC over hex bytes, text, or file; omit data to verify check string |
284
287
  | `/proto.crc.find <pkt>` | Identify CRC algorithm from a captured packet (bin= hex or asc= text) |
285
- | `/proto.status` | Show current protocol mode state |
288
+ | `/proto.info` | Print current protocol state |
286
289
  | `/var {name}` | List user variables, or show one by name |
287
290
  | `/var.set <NAME> <value>` | Set a user variable |
288
291
  | `/var.clear` | Clear all user variables |
@@ -316,18 +319,21 @@ termapy_cfg/
316
319
  └── demo/
317
320
  ├── demo.cfg # config file
318
321
  ├── demo.log # session log
319
- ├── .cmd_history.txt # command history
322
+ ├── demo.history # command history
320
323
  ├── ss/ # screenshots
321
324
  ├── run/ # script files for /run
322
325
  │ ├── at_demo.run
323
326
  │ ├── smoke_test.run
324
- │ └── status_check.run
327
+ │ ├── status_check.run
328
+ │ └── ... # gps_demo, var_demo, expect_test, crc_tour, ...
325
329
  ├── plugin/ # per-config plugins
326
330
  │ ├── cmd.py
327
331
  │ ├── probe.py
328
332
  │ ├── temp_plot.py
329
333
  │ └── traffic.py
330
334
  ├── cap/ # data capture output files
335
+ ├── prof/ # /run.profile timing CSVs
336
+ ├── viz/ # per-config packet visualizers
331
337
  └── proto/ # protocol test scripts
332
338
  ├── at_test.pro
333
339
  ├── bitfield_inline.pro
@@ -425,7 +431,7 @@ Run `/run setup_modbus.run` then `/run test_registers.run`. The variables persis
425
431
  | `/var.set NAME val` | Set a variable (explicit command form) |
426
432
  | `/var.clear` | Clear all variables |
427
433
 
428
- **Scope:** Variables persist for the interactive session. They are automatically cleared when a script is launched from the Scripts button or Run menu, but *not* when `/run` is typed interactively or called within a script. This lets you run a setup script to define variables, then run a test script that uses them. Use `/var.clear` to reset manually.
434
+ **Scope:** Variables persist for the interactive session. They are automatically cleared when a script is launched from the Run picker, but *not* when `/run` is typed interactively or called within a script. This lets you run a setup script to define variables, then run a test script that uses them. Use `/var.clear` to reset manually.
429
435
 
430
436
  **Naming:** Variable names are case-sensitive (`$(PORT)` and `$(port)` are different variables). Names must start with a letter or underscore and contain only letters, digits, and underscores.
431
437
 
@@ -434,7 +440,7 @@ Run `/run setup_modbus.run` then `/run test_registers.run`. The variables persis
434
440
  | Variable | Set when | Updates? |
435
441
  | --------------------- | ------------------------------------------- | -------------------- |
436
442
  | `$(LAUNCH_DATETIME)` | App starts | Never - frozen |
437
- | `$(SESSION_DATETIME)` | Script launched (Scripts button / Run menu) | Per script launch |
443
+ | `$(SESSION_DATETIME)` | Script launched (Run picker) | Per script launch |
438
444
  | `$(DATETIME)` | Every expansion | Always current clock |
439
445
 
440
446
  Each group also has `_DATE` and `_TIME` variants (e.g. `$(LAUNCH_DATE)`, `$(SESSION_TIME)`).
@@ -450,7 +456,7 @@ Add a `.gitignore` for session files you don't need to track:
450
456
  ```gitignore
451
457
  # termapy_cfg - keep configs and scripts, ignore session files
452
458
  termapy_cfg/*/*.log
453
- termapy_cfg/*/.cmd_history.txt
459
+ termapy_cfg/*/*.history
454
460
  termapy_cfg/*/ss/
455
461
  ```
456
462
 
@@ -611,7 +617,7 @@ See the **[config field reference](src/termapy/help/config.md#config-field-refer
611
617
 
612
618
  **Note on `eol_markers`:** This is a debug mode for troubleshooting line-ending mismatches (`\r` vs `\n` vs `\r\n`). When enabled, dim `\r` and `\n` markers appear inline in serial output before the characters are consumed by line splitting. Sent commands also show the configured line ending. Since the markers use ANSI escape sequences, they may interfere with device ANSI color output, so turn `eol_markers` off when not actively debugging.
613
619
 
614
- **Note on device color (ANSI):** The TUI and CLI render ANSI color (SGR) from device output inline, so colored log lines appear colored. termapy is line-oriented by design and does **not** emulate cursor addressing or full-screen redraws in the TUI - for devices that drive the terminal that way (menus, `top`/`vi` on an embedded console, bootloader UIs), use `--vt100` (see the VT100 mode section below), which hands raw bytes to your own terminal to emulate. In the CLI, `--no-color` (or `/term.color off`) strips color for clean piping.
620
+ **Note on device color (ANSI):** The TUI and CLI render ANSI color (SGR) from device output inline, so colored log lines appear colored. termapy is line-oriented by design and does **not** emulate cursor addressing or full-screen redraws in the TUI - for devices that drive the terminal that way (menus, `top`/`vi` on an embedded console, bootloader UIs), use `--vt100` (see the VT100 mode section below), which hands raw bytes to your own terminal to emulate. In the CLI, `--no-color` (or `/term.color off`) strips color for clean piping. Over MCP, color defaults **off** so device ANSI is stripped from the JSON an agent receives (`/term.color on` re-enables passthrough); silence it at the source with the device's own `color off` in `mcp_on_connect_cmd`.
615
621
 
616
622
  </details>
617
623
 
@@ -620,9 +626,9 @@ See the **[config field reference](src/termapy/help/config.md#config-field-refer
620
626
  <details>
621
627
  <summary><strong>Scripting</strong> - automate command sequences with text files</summary>
622
628
 
623
- ![Run menu / script picker dialog](img/run.png)
629
+ ![Run picker: newest first, with size, updated, and docstring summary](src/termapy/help/img/doc_21_script_picker.svg)
624
630
 
625
- Create text files with one command per line and run them from the Run button or with the `/run` or the Scripts button. IN the file ines starting with `/` are REPL commands, lines starting with `#` are comments and everything else is sent to the device.
631
+ Create text files with one command per line and run them from the **Run** button or with `/run`. In the file, lines starting with `/` are REPL commands, lines starting with `#` are comments and everything else is sent to the device.
626
632
 
627
633
  ```text
628
634
  # Quick status check
@@ -842,7 +848,7 @@ Summary: 4/4 PASS (4 tests)
842
848
 
843
849
  ### CRC algorithms
844
850
 
845
- Every CRC algorithm in the [reveng catalog](https://reveng.sourceforge.io/crc-catalogue/all.htm) (maintained by Greg Cook -- see [ACKNOWLEDGMENTS](src/termapy/help/acknowledgments.md)) is built in, with full parameterization (poly, init, refin, refout, xorout) and each one verified against its catalog check value in the test suite. If you need a CRC and it has a name, termapy already has it, correctly. Browse with `/proto.crc.list`, inspect with `/proto.crc.info <name>`, compute with `/proto.crc.calc`, identify an unknown one from a captured packet with `/proto.crc.find`. You can also generate standalone C, Python, or Rust source for any of them with `/proto.crc.python`, `/proto.crc.c`, `/proto.crc.rust` so you never have to port one by hand again.
851
+ Every CRC algorithm in the [reveng catalog](https://reveng.sourceforge.io/crc-catalogue/all.htm) (maintained by Greg Cook -- see [ACKNOWLEDGMENTS](src/termapy/help/acknowledgments.md)) is built in, with full parameterization (poly, init, refin, refout, xorout) and each one verified against its catalog check value in the test suite. If you need a CRC and it has a name, termapy already has it, correctly. Browse with `/proto.crc.list`, inspect with `/proto.crc.info <name>`, compute with `/proto.crc.calc`, identify an unknown one from a captured packet with `/proto.crc.find`. You can also generate standalone C, C#, Go, Java, Lua, Python, Rust, TypeScript, Verilog, VHDL, or Zig source for any of them with `/proto.crc.python`, `/proto.crc.c`, `/proto.crc.rust` so you never have to port one by hand again.
846
852
 
847
853
  </details>
848
854
 
@@ -906,9 +912,9 @@ Modbus RTU supports function 0x03 (read holding registers) and 0x06 (write singl
906
912
 
907
913
  The demo comes with everything wired up so you can try each feature:
908
914
 
909
- - **Scripts:** `at_demo.run`, `smoke_test.run`, `status_check.run`. Run via the Scripts button or `/run`.
915
+ - **Scripts:** `at_demo.run`, `smoke_test.run`, `status_check.run`, `gps_demo.run`, `var_demo.run`, `expect_test.run`, `crc_tour.run`, and more. Run via the Run button or `/run`.
910
916
  - **Proto test files:** `at_test.pro`, `bitfield_inline.pro`, `modbus_inline.pro`. Run via the Proto button for pass/fail results.
911
- - **Plugins:** `/probe` sends a command sequence and reports results; `/cmd` adds a custom shortcut.
917
+ - **Plugins:** `/probe` sends a command sequence and reports results; `/cmd` adds a custom shortcut; `/temp_plot` draws a sparkline; `/traffic.*` taps RX/TX bytes.
912
918
 
913
919
  </details>
914
920
 
@@ -934,16 +940,16 @@ Passing a `.run` file to `--cli` automatically infers the config from the file's
934
940
 
935
941
  **Features:**
936
942
 
937
- - Rich colored output (toggle with `/color on|off` or `--no-color`)
943
+ - Rich colored output (toggle with `/term.color on|off` or `--no-color`)
938
944
  - Command history shared with TUI (up/down arrows, persisted across sessions)
939
945
  - Tab completion for REPL commands
940
946
  - Script execution with `/run` (same scripts work in both TUI and CLI)
941
- - `/delay` with progress bar for waits over 3 seconds (Ctrl+C to cancel)
947
+ - `/delay` with progress bar for waits of a second or longer (Ctrl+C to cancel)
942
948
  - All `/port`, `/cfg`, `/var`, `/env`, `/proto.crc`, `/edit` commands work
943
949
 
944
950
  **TUI-only features** (not available in CLI mode):
945
951
 
946
- - `/ss.svg`, `/ss.txt` - screenshots (prints "not supported" message)
952
+ - `/ss.svg`, `/ss.txt` - screenshots (fail the `screen_capture` capability gate with a clear error)
947
953
  - `/grep` - scrollback search (no scrollback buffer in CLI)
948
954
  - `/edit.cfg` - opens in system editor instead of built-in config editor
949
955
  - Mouse interaction, modal dialogs, custom buttons
@@ -1054,7 +1060,6 @@ The `ctx` object passed to every handler is a thin shell over **five capability
1054
1060
  | `ctx.io.notify(text)` | Always-works fallback notification (toast in TUI, plain in CLI) |
1055
1061
  | `ctx.io.log(prefix, text)` | Write to session log: `">"` TX, `"<"` RX, `"#"` status |
1056
1062
  | `ctx.serial.is_connected` | Bool: serial port is open |
1057
- | `ctx.serial.port` | The raw pyserial object, or `None` when disconnected |
1058
1063
  | `ctx.serial.write(data)` | Send bytes to the serial port (auto-logged as TX) |
1059
1064
  | `ctx.serial.read_raw(timeout_ms)` | Read raw bytes with timeout framing (returns `bytes`) |
1060
1065
  | `ctx.serial.drain()` | Drain pending RX data |
@@ -1098,6 +1103,8 @@ See `examples/plugins/` for working examples:
1098
1103
  - **at_test.py:** send AT commands over serial
1099
1104
  - **timestamp.py:** print the current date/time
1100
1105
  - **ping.py:** send a command and measure response time
1106
+ - **traffic.py:** passive RX/TX byte tap (count, hexdump, rate, snoop) -- also shipped with `--demo`
1107
+ - **pic_map.py:** decode a PIC memory map
1101
1108
 
1102
1109
  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.
1103
1110
 
@@ -1142,7 +1149,7 @@ Actual: 01 00 C9 FF FE 0A -> ID:01 Temp:201 Signed:-2 Status:0A
1142
1149
  | `F` | IEEE 754 float | `F1-4` | `3.14` |
1143
1150
  | `B` | Bit field | `B1.3`, `B1-2.7-9` | `1`, `5` |
1144
1151
  | `_` | Padding (hidden) | `_:_3-4` | *(skipped)* |
1145
- | `crc*` | CRC verify | `CRC:crc16m_le` | pass/fail |
1152
+ | `crc*` | CRC verify | `CRC:crc16-modbus_le` | pass/fail |
1146
1153
 
1147
1154
  Integers support 1, 2, 3, 4, and 8 byte widths. Floats are 4-byte (F32) or 8-byte (F64).
1148
1155
 
@@ -1243,19 +1250,19 @@ Textual runs on a single async event loop. Termapy uses `@work(thread=True)` for
1243
1250
 
1244
1251
  | Worker | Lifetime | Purpose |
1245
1252
  | ------------------- | ----------- | ------------------------------------------------------- |
1246
- | `read_serial()` | Long-lived | Reads serial data in a loop, posts lines to the RichLog |
1247
- | `_auto_reconnect()` | Short-lived | Retries serial connection every 2.5s until success |
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 |
1248
1255
  | `_run_lines()` | Short-lived | Sends multiple commands with inter-command delay |
1249
1256
  | `_run_script()` | Short-lived | Executes a `.run` script file line by line |
1250
- | `_send_test()` | Short-lived | Runs a single protocol test case (send/receive/match) |
1251
- | `_run_cmds()` | Short-lived | Sends setup/teardown commands for protocol tests |
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`) |
1252
1259
 
1253
- Only `read_serial()` is long-lived. At most two workers run concurrently: the serial reader plus one command/script/test worker.
1260
+ Only the reader is long-lived. At most two workers run concurrently: the serial reader plus one command/script/test worker.
1254
1261
 
1255
1262
  </details>
1256
1263
 
1257
1264
  <details>
1258
- <summary><strong>Test coverage</strong> - 3110 tests, 73% core-module coverage</summary>
1265
+ <summary><strong>Test coverage</strong> - 3394 tests, 72% core-module coverage</summary>
1259
1266
 
1260
1267
  Run the full suite with `uv run pytest`. (The count above is the one place it
1261
1268
  is tracked; `release_prep` refreshes it each release.)
@@ -1272,7 +1279,7 @@ generator permutation.
1272
1279
 
1273
1280
  **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.).
1274
1281
 
1275
- **UI code:** `app.py`, `proto_debug.py`, and `dialogs/` are the Textual UI and are tested manually (Textual Pilot + the CLI gold test), not unit-tested. The headline coverage figure is **core-module** coverage, measured with `app.py`, `dialogs/`, and `builtins/` **omitted** (see `[tool.coverage.run]` in `pyproject.toml`) — so it is *not* whole-repo coverage. Counting the whole repo (only vendored third-party code omitted) is lower, and that gap is exactly this untested UI layer. The omit is deliberate — the focus has been on extracting business logic into unit-testable modules and keeping the UI as thin delegation — but the headline number is core-module, not overall.
1282
+ **UI code:** `app.py` is driven headless by `tests/test_app_pilot.py` (Textual Pilot boots the real app), and the dialogs have Pilot tests of their own; `proto_debug.py` is still exercised manually. The headline coverage figure is **core-module** coverage, measured with `dialogs/`, the `builtins/` package top level, and vendored code **omitted** (see `[tool.coverage.run]` in `pyproject.toml`) — so it is *not* whole-repo coverage. Counting the whole repo (only vendored third-party code omitted) is lower, and that gap is exactly this untested UI layer. The omit is deliberate — the focus has been on extracting business logic into unit-testable modules and keeping the UI as thin delegation — but the headline number is core-module, not overall.
1276
1283
 
1277
1284
  </details>
1278
1285