textual-debugger 0.2.8__tar.gz → 0.2.10__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 (152) hide show
  1. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/PKG-INFO +296 -45
  2. {textual_debugger-0.2.8/src/tdb → textual_debugger-0.2.10}/README.md +294 -43
  3. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/pyproject.toml +2 -2
  4. {textual_debugger-0.2.8 → textual_debugger-0.2.10/src/tdb}/README.md +294 -43
  5. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/__init__.py +1 -1
  6. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/_timeouts.py +4 -0
  7. textual_debugger-0.2.10/src/tdb/adapters/powershell/__init__.py +3 -0
  8. textual_debugger-0.2.10/src/tdb/adapters/powershell/__main__.py +23 -0
  9. textual_debugger-0.2.10/src/tdb/adapters/powershell/locate.py +121 -0
  10. textual_debugger-0.2.10/src/tdb/adapters/powershell/output.py +80 -0
  11. textual_debugger-0.2.10/src/tdb/adapters/powershell/server.py +913 -0
  12. textual_debugger-0.2.10/src/tdb/adapters/powershell/tdb_launch.ps1 +14 -0
  13. textual_debugger-0.2.10/src/tdb/adapters/seqs.py +62 -0
  14. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/app.py +3 -0
  15. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/app_handlers/inspection.py +71 -1
  16. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/app_handlers/routing.py +36 -0
  17. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/app_handlers/ui_panels.py +39 -0
  18. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/breakpoint_hook.py +16 -1
  19. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/cli.py +215 -15
  20. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/dap/client.py +77 -1
  21. textual_debugger-0.2.10/src/tdb/eval_mode.py +314 -0
  22. textual_debugger-0.2.10/src/tdb/go_concurrency/analyzer.py +112 -0
  23. textual_debugger-0.2.10/src/tdb/go_concurrency/classifier.py +59 -0
  24. textual_debugger-0.2.10/src/tdb/go_concurrency/collector.py +122 -0
  25. textual_debugger-0.2.10/src/tdb/go_concurrency/models.py +123 -0
  26. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/base.py +25 -0
  27. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/errors.py +210 -0
  28. textual_debugger-0.2.10/src/tdb/languages/go.py +217 -0
  29. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/ocaml.py +78 -3
  30. textual_debugger-0.2.10/src/tdb/languages/powershell.py +124 -0
  31. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/registry.py +26 -3
  32. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/mcp/server.py +12 -0
  33. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/run_mode.py +64 -30
  34. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/server/handlers.py +21 -0
  35. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/server/runner.py +4 -0
  36. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/controller.py +83 -3
  37. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/inspect_service.py +12 -3
  38. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/state.py +7 -0
  39. textual_debugger-0.2.10/src/tdb/widgets/__init__.py +0 -0
  40. textual_debugger-0.2.10/src/tdb/widgets/goroutines_modal.py +354 -0
  41. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/textual_debugger.egg-info/PKG-INFO +296 -45
  42. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/textual_debugger.egg-info/SOURCES.txt +16 -0
  43. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/textual_debugger.egg-info/requires.txt +1 -1
  44. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/LICENSE +0 -0
  45. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/setup.cfg +0 -0
  46. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/__main__.py +0 -0
  47. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/__init__.py +0 -0
  48. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/bash/__init__.py +0 -0
  49. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/bash/__main__.py +0 -0
  50. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/bash/declares.py +0 -0
  51. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/bash/server.py +0 -0
  52. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/bash/session.py +0 -0
  53. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/bash/tdb_harness.sh +0 -0
  54. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/ocaml/__init__.py +0 -0
  55. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/ocaml/lldb_formatters.py +0 -0
  56. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/Devel/TdbCompile.pm +0 -0
  57. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/Devel/TdbRemote.pm +0 -0
  58. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/__init__.py +0 -0
  59. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/__main__.py +0 -0
  60. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/helpers.pl +0 -0
  61. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/protocol.py +0 -0
  62. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/refs.py +0 -0
  63. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/server.py +0 -0
  64. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/perl/session.py +0 -0
  65. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/ruby/__init__.py +0 -0
  66. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/ruby/__main__.py +0 -0
  67. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/ruby/server.py +0 -0
  68. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/__init__.py +0 -0
  69. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/__main__.py +0 -0
  70. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/breakpoints.py +0 -0
  71. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/cli.py +0 -0
  72. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/guardian.py +0 -0
  73. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/inspect.py +0 -0
  74. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/instrumenter.py +0 -0
  75. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/models.py +0 -0
  76. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/protocol.py +0 -0
  77. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/runtime.py +0 -0
  78. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/scanner.py +0 -0
  79. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/server.py +0 -0
  80. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/session.py +0 -0
  81. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/adapters/tcsh/transport.py +0 -0
  82. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/app_handlers/__init__.py +0 -0
  83. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/app_handlers/dap_events.py +0 -0
  84. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/app_helpers.py +0 -0
  85. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/dap/__init__.py +0 -0
  86. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/dap/messages.py +0 -0
  87. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/dap/protocol.py +0 -0
  88. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/dap/reverse.py +0 -0
  89. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/dap/types.py +0 -0
  90. {textual_debugger-0.2.8/src/tdb/server → textual_debugger-0.2.10/src/tdb/go_concurrency}/__init__.py +0 -0
  91. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/inspection.py +0 -0
  92. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/inspection_full.py +0 -0
  93. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/keybindings/__init__.py +0 -0
  94. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/__init__.py +0 -0
  95. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/bash.py +0 -0
  96. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/cpp.py +0 -0
  97. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/perl.py +0 -0
  98. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/python.py +0 -0
  99. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/ruby.py +0 -0
  100. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/rust.py +0 -0
  101. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/languages/tcsh.py +0 -0
  102. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/mcp/__init__.py +0 -0
  103. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/mcp/__main__.py +0 -0
  104. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/mcp/session.py +0 -0
  105. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/persist.py +0 -0
  106. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/post_mortem.py +0 -0
  107. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/processes_cache.py +0 -0
  108. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/replay.py +0 -0
  109. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/__init__.py +0 -0
  110. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/analyzer.py +0 -0
  111. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/classifier.py +0 -0
  112. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/collector.py +0 -0
  113. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/models.py +0 -0
  114. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/probes/__init__.py +0 -0
  115. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/probes/base.py +0 -0
  116. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/probes/gdb.py +0 -0
  117. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/probes/gdb_script.py +0 -0
  118. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/probes/lldb.py +0 -0
  119. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/rust_concurrency/probes/lldb_script.py +0 -0
  120. {textual_debugger-0.2.8/src/tdb/session → textual_debugger-0.2.10/src/tdb/server}/__init__.py +0 -0
  121. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/server/app.py +0 -0
  122. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/server/event_handler.py +0 -0
  123. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/server/rpc_types.py +0 -0
  124. {textual_debugger-0.2.8/src/tdb/widgets → textual_debugger-0.2.10/src/tdb/session}/__init__.py +0 -0
  125. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/child_processes.py +0 -0
  126. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/errors.py +0 -0
  127. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/event_bus.py +0 -0
  128. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/messages.py +0 -0
  129. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/post_mortem_loader.py +0 -0
  130. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/recorder.py +0 -0
  131. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/statement_stepper.py +0 -0
  132. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/terminal.py +0 -0
  133. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/session/textual_handler.py +0 -0
  134. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/source_analysis.py +0 -0
  135. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/_inspection_modal.py +0 -0
  136. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/async_tasks_modal.py +0 -0
  137. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/breakpoint_view.py +0 -0
  138. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/code_view.py +0 -0
  139. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/console_view.py +0 -0
  140. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/evaluate_console.py +0 -0
  141. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/full_contents_modal.py +0 -0
  142. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/menu_bar.py +0 -0
  143. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/modals.py +0 -0
  144. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/processes_modal.py +0 -0
  145. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/rust_concurrency_modal.py +0 -0
  146. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/stack_view.py +0 -0
  147. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/status_bar.py +0 -0
  148. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/threads_modal.py +0 -0
  149. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/tdb/widgets/variable_view.py +0 -0
  150. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/textual_debugger.egg-info/dependency_links.txt +0 -0
  151. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/textual_debugger.egg-info/entry_points.txt +0 -0
  152. {textual_debugger-0.2.8 → textual_debugger-0.2.10}/src/textual_debugger.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: textual-debugger
3
- Version: 0.2.8
3
+ Version: 0.2.10
4
4
  Summary: A TUI debugger for Python, Perl, and other languages. Based on textual.
5
5
  Author-email: Al Danial <al.danial@gmail.com>
6
6
  License: textual-debugger is licensed to you under the MIT/X Consortium license:
@@ -49,7 +49,7 @@ Requires-Python: >=3.11
49
49
  Description-Content-Type: text/markdown
50
50
  License-File: LICENSE
51
51
  Requires-Dist: textual>=8.0.0
52
- Requires-Dist: debugpy>=1.8.0
52
+ Requires-Dist: debugpy>=1.8.12
53
53
  Requires-Dist: pygments>=2.17.0
54
54
  Requires-Dist: fastapi>=0.115.0
55
55
  Requires-Dist: uvicorn>=0.30.0
@@ -79,6 +79,8 @@ with a Debug Adapter Protocol (DAP) implementation. In addition to Python,
79
79
  - Tcsh (via source instrumentation of a stock `tcsh`)
80
80
  - Ruby (via the [debug gem](https://github.com/ruby/debug)'s `rdbg`; debug ≥ 1.9)
81
81
  - OCaml (native via `lldb-dap`/`gdb`, bytecode via [ocamlearlybird](https://github.com/hackwaly/ocamlearlybird))
82
+ - Go (via [Delve](https://github.com/go-delve/delve)'s `dlv dap`)
83
+ - PowerShell 7 (via [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices); Linux/macOS, Windows experimental)
82
84
 
83
85
  `tdb` is built with [textual](https://github.com/Textualize/textual) and speaks
84
86
  DAP to a pluggable debug adapter.
@@ -99,8 +101,9 @@ MIT License. Copyright 2026 by Al Danial.
99
101
  the richest feature set), C/C++ (via `gdb -i dap` or `lldb-dap`), Rust (via `gdb` or
100
102
  `lldb-dap`), Perl (via `perl -d`),
101
103
  Bash (via bash's own `DEBUG` trap), Tcsh (via source instrumentation of a
102
- stock `tcsh`), Ruby (via the debug gem's `rdbg`), and OCaml (native via
103
- `lldb-dap`/`gdb`, bytecode via ocamlearlybird). Most languages are
104
+ stock `tcsh`), Ruby (via the debug gem's `rdbg`), OCaml (native via
105
+ `lldb-dap`/`gdb`, bytecode via ocamlearlybird), Go (via Delve's `dlv
106
+ dap`), and PowerShell 7 (via PowerShell Editor Services). Most languages are
104
107
  auto-detected from the target; Rust intentionally requires `--lang rust`
105
108
  (ref. [Multi-Language Debugging](#multi-language-debugging)).
106
109
 
@@ -110,7 +113,7 @@ It specifically supports modules
110
113
  - `threading` (with a thread inspector)
111
114
  - `multiprocessing` / `concurrent.futures` (with automatic child process attachment and a process inspector)
112
115
 
113
- - supports remote attachment to Python, Perl, Ruby, Rust, and C/C++ programs
116
+ - supports remote attachment to Python, Perl, Ruby, Rust, C/C++, and Go programs
114
117
 
115
118
  - includes a JSON-RPC server mode, an MCP mode, and a `SKILL.md` file that enable
116
119
  programmatic debug control, making it suitable for
@@ -212,6 +215,10 @@ tdb -k 20 -k 35 -k module.py:14 my_program.py arg1 arg2
212
215
  # sessions (-t is -k minus the persistence)
213
216
  tdb -t 20 my_program.py
214
217
 
218
+ # no TUI: run at (almost) full speed, printing nr each time line 25 is
219
+ # reached, then continuing (-e may be repeated; see "Eval Mode" below)
220
+ tdb --eval my_program.py:25 "print(f'{nr=}')" my_program.py
221
+
215
222
  # use a specific virtualenv
216
223
  tdb --python /path/to/venv/bin/python my_program.py
217
224
 
@@ -238,6 +245,11 @@ tdb -r remotehost:5678 -k my_program.py:42
238
245
  # than code on the remote host
239
246
  tdb -r remotehost:5678 --local-root /my/code/dir --remote-root /app -k my_program.py:42
240
247
 
248
+ # attach to a program that pauses itself (debugpy.breakpoint() right after
249
+ # debugpy.wait_for_client()); without this flag tdb pauses the program on
250
+ # attach, which can leave it suspended after tdb quits
251
+ tdb -r remotehost:5678 --no-pause-on-attach
252
+
241
253
  # separate tdb arguments from debuggee arguments with `--`
242
254
  tdb --python /path/to/venv/bin/python -- my_program.py -k 17 --max 23.3
243
255
  ```
@@ -250,7 +262,7 @@ python -m tdb my_program.py
250
262
 
251
263
  ## Multi-Language Debugging
252
264
 
253
- `tdb` debugs any language that has a Debug Adapter Protocol backend. Eight
265
+ `tdb` debugs any language that has a Debug Adapter Protocol backend. Ten
254
266
  languages are supported out of the box:
255
267
 
256
268
  | Language | Adapter(s) | Dependencies | Feature level |
@@ -262,33 +274,42 @@ languages are supported out of the box:
262
274
  | Bash | bash-tdb (bundled) | bash ≥ 4.4 on PATH | core debugging (no remote attach) |
263
275
  | Tcsh | tcsh-tdb (bundled) | tcsh on PATH | core debugging (no remote attach, no conditional breakpoints, no pause) |
264
276
  | Ruby | `rdbg` (the [debug gem](https://github.com/ruby/debug)) | `rdbg` ≥ 1.9 on PATH | core debugging + remote attach |
265
- | OCaml (native executable) | `lldb-dap` (default), `gdb` (alternate) | OCaml ≥ 4.12; `lldb-dap` ships with LLVM ≥ 17; `gdb -i dap` requires GDB ≥ 14 | core debugging + domains-as-threads; Variables view shows no OCaml locals (upstream DWARF limitation); evaluate console is lldb/C-level, not OCaml |
266
- | OCaml (bytecode executable) | `ocamlearlybird` (default) | OCaml ≥ 4.12; `opam install earlybird` | core debugging + rich OCaml locals; no pause/`--run`, no evaluate responses, no fatal-error modal (ocamlearlybird 1.3.6 limitations); single-domain only |
277
+ | OCaml (native executable) | `lldb-dap` (default), `gdb` (alternate) | `lldb-dap` ships with LLVM ≥ 17; `gdb -i dap` requires GDB ≥ 14 | core debugging + domains-as-threads; Variables view shows no OCaml locals (upstream DWARF limitation); evaluate console is lldb/C-level, not OCaml |
278
+ | OCaml (bytecode executable) | `ocamlearlybird` (default) | `opam install earlybird` | core debugging + rich OCaml locals; no pause/`--run`, no evaluate responses, no fatal-error modal (ocamlearlybird 1.3.6 limitations); single-domain only |
279
+ | Go | `dlv` (the [Delve](https://github.com/go-delve/delve) DAP server) | Delve ≥ 1.21 on PATH (`go install github.com/go-delve/delve/cmd/dlv@latest`) | core debugging + goroutine inspection (wait graph, findings) + remote attach (no `--terminal`) |
280
+ | PowerShell 7 | `pses` (PowerShell Editor Services, driven by tdb's bundled proxy) | `pwsh` ≥ 7.2 on PATH + the PSES module (see [PowerShell](#powershell)) | core debugging (breakpoints incl. conditional/hit-count/log, stepping, stack, variables, evaluate console) + `--run`; no `--terminal`, no remote attach; Windows untested |
267
281
 
268
282
  ### Language detection and selection
269
283
 
270
284
  The language is auto-detected from the debug target:
271
285
 
272
- 1. File extension: `.py` → Python; `.pl` / `.pm` / `.t` → Perl; `.sh` / `.bash`
273
- → Bash; `.csh` / `.tcsh` → Tcsh; `.rb` → Ruby. (`.ml` / `.mli` do *not*
274
- auto-select OCaml, see point 5.)
275
- 2. Native executables (ELF, Mach-O, PE magic bytes) → C/C++, unless
276
- byte-sniffing finds an OCaml marker, either a native binary's
286
+ 1. A directory → Go, if it contains any `*.go` file (a Go package
287
+ directory, e.g. `tdb ./pkg`); otherwise an error naming `--lang`.
288
+ 2. File extension: `.py` → Python; `.go` → Go; `.pl` / `.pm` / `.t` → Perl;
289
+ `.sh` / `.bash` → Bash; `.csh` / `.tcsh` → Tcsh; `.rb` → Ruby; `.ps1` /
290
+ `.psm1` → PowerShell. (`.ml` / `.mli` do *not* auto-select OCaml, see
291
+ point 6.)
292
+ 3. Native executables (ELF, Mach-O, PE magic bytes) → C/C++, unless
293
+ byte-checking finds an OCaml marker (a native binary's
277
294
  `caml_program`/`caml_startup` runtime symbols, a bytecode file's
278
- trailing `Caml1999` marker, or a `#!...ocamlrun` shebang, in which case
279
- → OCaml (native or bytecode respectively). A stripped native OCaml
280
- binary that byte-sniffing can't identify falls back to C/C++; force it
281
- with `--lang ocaml`. Rust is never inferred from an executable; select
282
- it explicitly with `--lang rust`.
283
- 3. A `#!...python`, `#!...perl`, `#!...bash`, `#!...csh`/`#!...tcsh`, or
284
- `#!...ruby` shebang → Python / Perl / Bash / Tcsh / Ruby respectively.
285
- 4. C/C++/Rust *source* files (`.c`, `.cpp`, `.rs`, …) produce an error with a
295
+ trailing `Caml1999` marker, or a `#!...ocamlrun` shebang) → OCaml
296
+ (native or bytecode respectively), or a Go buildinfo blob (the marker
297
+ `go version` itself locates, scanned in the first 16MB of the file) →
298
+ Go. A stripped native OCaml binary, or a Go binary whose buildinfo
299
+ blob sits beyond the 16MB scan window, that byte-checking can't
300
+ identify falls back to C/C++; force it with `--lang ocaml` or `--lang
301
+ go` respectively. Rust is never inferred from an executable; select it
302
+ explicitly with `--lang rust`.
303
+ 4. A `#!...python`, `#!...perl`, `#!...bash`, `#!...csh`/`#!...tcsh`,
304
+ `#!...ruby`, or `#!...pwsh` shebang → Python / Perl / Bash / Tcsh / Ruby /
305
+ PowerShell respectively.
306
+ 5. C/C++/Rust *source* files (`.c`, `.cpp`, `.rs`, …) produce an error with a
286
307
  hint: compile with debug info (`g++ -g -O0`) and debug the binary.
287
- 5. `.ml` / `.mli` (OCaml source) produce an error too: build the project
308
+ 6. `.ml` / `.mli` (OCaml source) produce an error too: build the project
288
309
  first (dune's dev profile keeps debug info) and pass the **built
289
310
  executable** to `tdb` (`tdb ./_build/default/bin/main.exe`), never the
290
311
  `.ml` file.
291
- 6. Anything else produces an error naming the `--lang` override.
312
+ 7. Anything else produces an error naming the `--lang` override.
292
313
 
293
314
  `--lang` forces the language; `--adapter` picks a non-default adapter within
294
315
  it (`tdb --lang cpp --adapter lldb-dap ./myprog`). Rust always requires the
@@ -320,19 +341,25 @@ and the JSON-RPC / MCP programmatic modes.
320
341
 
321
342
  Python-specific features are hidden or return "not supported for this
322
343
  language" message when debugging other languages: statement-granularity
323
- stepping (non-Python languages always step per line), the async task /
324
- process inspectors and wait graph, the evaluate console's trailing-`?` help,
344
+ stepping (non-Python languages step at their debugger's native granularity
345
+ — per line, except PowerShell, whose debugger stops per statement, see
346
+ [PowerShell](#powershell)), the async task / process inspectors and wait
347
+ graph, the evaluate console's trailing-`?` help,
325
348
  `--python`/`--pv`, `--no-subprocess`, automatic child-process attachment, and
326
349
  the post-mortem / `tdb.breakpoint()` hooks (those hooks live inside Python
327
350
  programs by nature). Remote attach (`-r`) also works for Perl (see
328
351
  [Perl](#perl), `Devel::TdbRemote` in place of `debugpy.listen()`), Ruby
329
- (see [Ruby](#ruby), `rdbg --open` in place of `debugpy.listen()`), and for
352
+ (see [Ruby](#ruby), `rdbg --open` in place of `debugpy.listen()`), Go (see
353
+ [Go](#go), `dlv dap --listen` in place of `debugpy.listen()`), and for
330
354
  Rust and C/C++ native binaries (against a gdbserver/lldb-server stub, with
331
355
  a local symbol-bearing executable; see [Rust](#rust) — the same flags work
332
- for a C/C++ target without `--lang`), but not for Bash, Tcsh, or OCaml. `--terminal` works for every launch-mode
356
+ for a C/C++ target without `--lang`), but not for Bash, Tcsh, OCaml, or
357
+ PowerShell. `--terminal` works for every launch-mode
333
358
  language — Python, Perl, Bash, Tcsh, Ruby, and C/C++, OCaml native, or Rust
334
359
  sessions via `--adapter lldb-dap` — see
335
- [External Terminal Support](#external-terminal-support).
360
+ [External Terminal Support](#external-terminal-support). Go and PowerShell do
361
+ not support `--terminal` yet (`dlv dap` and PSES have no terminal-routing
362
+ mode).
336
363
 
337
364
  **Bash limitations (v1):** the bash adapter uses bash's own `DEBUG` trap and
338
365
  has a smaller feature set than Python:
@@ -397,7 +424,30 @@ picture:
397
424
  reaches `tdb`). Run the program outside the debugger to see the
398
425
  backtrace instead.
399
426
  - No Windows support, no remote attach, and a stripped native binary that
400
- byte-sniffing can't identify needs `--lang ocaml`.
427
+ byte-checking can't identify needs `--lang ocaml`.
428
+
429
+ **Go limitations (v1):**
430
+
431
+ - `--terminal` is not supported (`dlv dap` has no terminal-routing mode).
432
+ - The Goroutines workspace's wait graph shows channel-send/-receive,
433
+ mutex, and `WaitGroup` edges; a goroutine parked in a `select` is
434
+ classified but contributes no wait edge (Delve can't tell which of the
435
+ `select`'s cases it's waiting on).
436
+ - No mutex-holder identification: Go's `sync.Mutex` doesn't record an
437
+ owner at the runtime level, so unlike Python's Lock/Semaphore inspector
438
+ the wait graph can name what a goroutine is blocked on but never who
439
+ holds it.
440
+ - Goroutines spawned by `exec.Command` (child OS processes) are not
441
+ automatically attached or debugged, unlike Python's automatic
442
+ multiprocessing child attach.
443
+ - Detection of a Go binary via buildinfo check scans only the first
444
+ 16MB of the file; a huge binary whose buildinfo blob sits beyond that
445
+ falls back to C/C++ — force it with `--lang go`.
446
+ - `-a`/`--attach`'s language auto-detection (reading the target pid's
447
+ buildinfo from `/proc/PID/exe`) is Linux-only; on macOS/Windows pass
448
+ `--lang go` alongside `-a`.
449
+
450
+ See [Go](#go) below for launch details.
401
451
 
402
452
  ### C/C++ tips
403
453
 
@@ -703,18 +753,35 @@ does). Always pass the **built executable** to `tdb`, never the `.ml`
703
753
  source, as in `tdb ./_build/default/bin/main.exe`, not `tdb main.ml` (which
704
754
  errors with this exact guidance).
705
755
 
756
+ Earlybird additionally as a fragile relative path matching so for
757
+ best results provide a fully quallified path to the source files.
758
+
759
+ ```
760
+ ocamlc -g -o my_program.byte "$PWD/my_program.ml"
761
+ ```
762
+
763
+ Then, to ensure transition from bytecode to OCaml source in the
764
+ Code view, provide an explicit temporary breakpoint (`-t`)
765
+ at the first line of execution:
766
+
767
+ ```
768
+ tdb --lang ocaml --adapter ocamlearlybird -t "$PWD/my_program.ml:2" ./my_program.byte
769
+ ```
770
+
706
771
  **OCaml version:** tdb requires **OCaml ≥ 4.12**. Older runtimes print
707
772
  `Printexc` backtraces without function names, which the fatal-error
708
773
  modal's parser does not understand (frames would be dropped and the
709
774
  modal would wrongly suggest recompiling with `-g`).
710
775
 
711
- ```bash
712
- tdb ./_build/default/bin/main.exe # native, lldb-dap
713
- tdb --adapter gdb ./_build/default/bin/main.exe # native, gdb
714
- tdb ./_build/default/bin/main.byte # bytecode, ocamlearlybird
715
- ```
776
+ With native GDB, the default entry stop is translated to the first
777
+ executable line in project OCaml source; the generated C/ELF startup code is
778
+ not shown.
779
+ Unfortunately OCaml's native debug information does not always identify
780
+ tihs line correctly.
781
+ `--no-stop-on-entry` and explicit CLI breakpoints retain their
782
+ usual behavior.
716
783
 
717
- A stripped native binary that byte-sniffing can't identify as OCaml falls
784
+ A stripped native binary that byte-checking can't identify as OCaml falls
718
785
  back to C/C++; force it with `--lang ocaml`. Override the adapter or point
719
786
  at a non-`PATH` install in `config.json` (see
720
787
  [Configuration](#configuration)):
@@ -774,6 +841,139 @@ sessions can't `pause` a running program (so `--run` is unavailable for
774
841
  bytecode. Native sessions support `--run` normally); `Unix.fork` and Eio
775
842
  fibers are out of scope (only OCaml 5 domains are presented as threads).
776
843
 
844
+ ### Go
845
+
846
+ `tdb` debugs Go through [Delve](https://github.com/go-delve/delve)'s own
847
+ DAP server, `dlv dap` (Delve ≥ 1.21). Install it with:
848
+
849
+ ```bash
850
+ go install github.com/go-delve/delve/cmd/dlv@latest
851
+ ```
852
+
853
+ `dlv` must be on `PATH`, or point tdb at it with
854
+ `{"adapters": {"dlv": "/path/to/dlv"}}` in `config.json`.
855
+
856
+ **Launch modes** — `tdb` picks the right Delve mode automatically:
857
+
858
+ ```bash
859
+ tdb main.go # source file: `go run`-style debug mode
860
+ tdb ./pkg # package directory: `go run`-style debug mode
861
+ tdb ./binary # pre-built Go binary (buildinfo-detected): exec mode
862
+ tdb --test ./pkg # Go test package: Delve test mode
863
+ tdb -a PID # attach to a running local Go process by pid
864
+ tdb -r host:port --lang go # attach to a `dlv dap --listen` already running remotely
865
+ ```
866
+
867
+ `tdb --test ./pkg` debugs the package's tests under Delve's `test` mode;
868
+ pass test-binary flags after `--`, e.g. `tdb --test ./pkg -- -run TestFoo`.
869
+ `-a`/`--attach` currently supports Go only; on Linux, and only on Linux,
870
+ `tdb` can identify the target as Go from `/proc/PID/exe`'s buildinfo
871
+ without `--lang` (elsewhere pass `--lang go` alongside `-a`). Attaching
872
+ stops the process immediately so you get control right away.
873
+
874
+ **Remote attach:** start Delve's own DAP server against your program
875
+ first —
876
+
877
+ ```bash
878
+ dlv dap --listen=host:port ./binary
879
+ ```
880
+
881
+ — then connect from `tdb`:
882
+
883
+ ```bash
884
+ tdb -r host:port --lang go
885
+ ```
886
+
887
+ Do not expose the port to an untrusted network; prefer an SSH tunnel.
888
+
889
+ **Goroutine inspection:** in a Go session the Threads action (`Alt+T`, or
890
+ the **Goroutines (N)** menu label) opens the Goroutines workspace while
891
+ the debuggee is stopped — a fresh, bounded snapshot of goroutines, wait
892
+ edges, and findings, the same shape as the Rust Concurrency workspace.
893
+ Goroutines parked entirely in Go-runtime internals (GC workers,
894
+ finalizers, netpoll) are hidden by default; press `a` to reveal them
895
+ alongside the rest. The **Wait Graph** tab groups goroutines by the
896
+ channel, mutex, or `WaitGroup` they're blocked on; the **Findings** tab
897
+ surfaces stuck channels, mutex convoys, and likely leaks with a
898
+ confidence level (`confirmed` vs `probable`) — Go mutexes never record an
899
+ owner, so, unlike Python's Lock/Semaphore inspector, findings can name
900
+ what's blocked but not who holds it. The snapshot collects up to 150
901
+ goroutines; a busier program reports the header
902
+ `Goroutines (150) — N more not collected` rather than silently truncating.
903
+ Refresh (`r`) after the next stop to collect a new snapshot.
904
+
905
+ **Limitations (v1):** `--terminal` is not supported (`dlv dap` has no
906
+ terminal-routing mode); a goroutine parked in a `select` is classified but
907
+ contributes no wait edge (Delve can't tell which case it's waiting on);
908
+ no mutex-holder identification (impossible for Go's runtime); goroutines
909
+ spawned indirectly via `exec.Command` child OS processes are not
910
+ automatically attached; buildinfo-based binary detection scans only the
911
+ first 16MB of the file (`--lang go` overrides for anything larger); `-a`'s
912
+ `/proc`-based language auto-detection is Linux-only (pass `--lang go`
913
+ alongside `-a` on macOS/Windows).
914
+
915
+ ### PowerShell
916
+
917
+ tdb debugs PowerShell 7 scripts through [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices)
918
+ (PSES), the Debug Adapter Protocol server behind the VS Code PowerShell
919
+ extension. You need `pwsh` (>= 7.2; https://aka.ms/powershell) on PATH
920
+ and the PSES module. tdb looks for the module in this order:
921
+
922
+ 1. `{"adapters": {"pses": "/path/to/PowerShellEditorServices"}}` in `config.json`
923
+ 2. the `TDB_PSES_PATH` environment variable
924
+ 3. the copy bundled with an installed VS Code PowerShell extension
925
+ (`~/.vscode/extensions/ms-vscode.powershell-*/modules/PowerShellEditorServices`)
926
+
927
+ Without VS Code, download the release once:
928
+
929
+ ```bash
930
+ mkdir -p ~/.local/share/tdb/pses && cd ~/.local/share/tdb/pses
931
+ curl -sLO https://github.com/PowerShell/PowerShellEditorServices/releases/download/v4.7.0/PowerShellEditorServices.zip
932
+ unzip -q PowerShellEditorServices.zip
933
+ export TDB_PSES_PATH=~/.local/share/tdb/pses/PowerShellEditorServices
934
+ ```
935
+
936
+ A `pwsh` that isn't on PATH can be named with `{"adapters": {"pwsh": "/path/to/pwsh"}}`.
937
+
938
+ ```bash
939
+ tdb script.ps1 # launch, stop at the first statement
940
+ tdb --run script.ps1 # run immediately, debug on demand (pause works)
941
+ ```
942
+
943
+ Notes:
944
+
945
+ - Entry stop lands on the first statement of your script (comments and
946
+ function definitions are skipped): PSES has no native `stopOnEntry` for
947
+ this launch shape, so tdb sets a synthetic breakpoint on the bundled
948
+ launcher, steps in, and clears it — no line-1 breakpoint appears in the
949
+ Breakpoint view.
950
+ - The script runs inside that small bundled launcher (`tdb_launch.ps1`) so
951
+ tdb can report the script's exit code. In the Stack view, top to bottom:
952
+ PSES's `<Breakpoint>` marker frame (the frame to inspect — it tracks the
953
+ accurate current position), your script's own frames, the launcher's
954
+ `<ScriptBlock>`, and a source-less `Interactive Session` frame at the
955
+ bottom.
956
+ - Stepping is statement-granular, as in VS Code: a line containing a
957
+ `$( ... )` subexpression takes two `next` presses to clear, and `stepIn`
958
+ first lands on the called function's declaration line before its body.
959
+ - An uncaught terminating error ends the script with exit code 1 and opens
960
+ the fatal-error modal from pwsh's concise error text. Non-terminating
961
+ errors (`Write-Error`, failing cmdlets without `-ErrorAction Stop`) print
962
+ the same concise error block to the Console as stderr and let the script
963
+ continue with exit code 0, as in pwsh itself; there is no break-on-error
964
+ yet. The error block names the launcher's `& $Script` line rather than
965
+ your script's actual line for some error kinds (a known cosmetic
966
+ limitation).
967
+ - The fatal-error modal is gated on a non-zero exit code, since pwsh prints
968
+ the identical block for terminating and non-terminating errors. A script
969
+ that reports a non-terminating error and then `exit 3` can therefore still
970
+ raise the modal, showing the last error block that names a file of yours;
971
+ blocks attributed to tdb's own `tdb_launch.ps1` are skipped, so a bare
972
+ `Write-Error` before the `exit` opens no modal at all.
973
+ - `--terminal` and remote attach are not supported for PowerShell yet.
974
+ - Windows PowerShell 5.1 is not supported (pwsh 7 only). Running tdb *on*
975
+ Windows against pwsh is designed for but not yet verified (experimental).
976
+
777
977
  ## Layout
778
978
 
779
979
  ```
@@ -900,7 +1100,9 @@ stops on each physical line--useful for inspecting how a complex expression is b
900
1100
  The choice is saved to `~/.config/tdb/config.json`.
901
1101
 
902
1102
  Statement mode requires a source-language model and is currently Python-only;
903
- other languages always step per line (the Step Mode menu says so if you try).
1103
+ other languages step at their debugger's native granularity — per line,
1104
+ except PowerShell, whose debugger stops per statement, see
1105
+ [PowerShell](#powershell) (the Step Mode menu says so if you try).
904
1106
 
905
1107
  ### Breakpoints
906
1108
 
@@ -1266,12 +1468,14 @@ sessions via `--adapter lldb-dap`. Neither `gdb -i dap` (the default C/C++
1266
1468
  adapter, and an alternate for native OCaml) nor `ocamlearlybird` (the
1267
1469
  bytecode OCaml adapter) has any terminal integration -- `tdb` rejects
1268
1470
  `--terminal` up front for both, with an error pointing at `--adapter
1269
- lldb-dap` instead. `--terminal` also only applies when `tdb` launches the
1270
- program itself; it is rejected for remote-attach (`-r`), since there's no
1271
- program for `tdb` to spawn a terminal around.
1471
+ lldb-dap` instead. Go and PowerShell don't support `--terminal` either
1472
+ (`dlv dap` has no terminal-routing mode; PSES likewise). `--terminal` also
1473
+ only applies when `tdb` launches the program itself; it is rejected for
1474
+ remote-attach (`-r`), since there's no program for `tdb` to spawn a
1475
+ terminal around.
1272
1476
 
1273
1477
  The debuggee runs in a separate window of the specified terminal, including
1274
- all of its stdin/stdout/stderr -- keyboard input, program output, and
1478
+ all of its stdin/stdout/stderr. Keyboard input, program output, and
1275
1479
  anything the program itself draws to the terminal all happen in that
1276
1480
  window, not in `tdb`'s Console View. Supported choices:
1277
1481
  `xterm`, `konsole`, `gnome-terminal`, `ghostty`, `kitty`, `iterm2`, `warp`,
@@ -1309,7 +1513,7 @@ tdb --run my_program.py; echo $? # my_program.py's own exit code
1309
1513
  **Interrupting:** press Ctrl-C in the terminal (any platform), or, on Unix, send
1310
1514
  `SIGUSR1` to `tdb`'s pid from another terminal: `kill -USR1 <tdb pid>`. Either one pauses
1311
1515
  the debuggee at its currently executing line and opens the TUI with full debugging
1312
- available -- breakpoints, stepping, variable inspection, the evaluate console. The
1516
+ available (breakpoints, stepping, variable inspection, the evaluate console). The
1313
1517
  debuggee itself never receives the signal (`tdb`'s adapter runs in its own process
1314
1518
  group), so its own `SIGINT` handling is undisturbed.
1315
1519
 
@@ -1327,10 +1531,11 @@ nonzero `sys.exit()`, which `debugpy` treats as an uncaught `SystemExit` -- `tdb
1327
1531
  the TUI at the point of failure instead of exiting silently, so you can inspect the
1328
1532
  crash. Exit-code passthrough applies only to a clean exit during the headless phase.
1329
1533
 
1330
- Supported languages: Python, Perl, Bash, Tcsh, Ruby, C/C++ (both `gdb` and
1331
- `lldb-dap`), and native OCaml (both `gdb` and `lldb-dap`; bytecode/
1332
- `ocamlearlybird` sessions don't support pause, so `--run` is unavailable
1333
- for those). `--run` is rejected up front for any other language.
1534
+ Supported languages: Python, Perl, Bash, Tcsh, Ruby, PowerShell 7, C/C++
1535
+ (both `gdb` and `lldb-dap`), and native OCaml (both `gdb` and `lldb-dap`;
1536
+ bytecode/`ocamlearlybird` sessions don't support pause, so `--run` is
1537
+ unavailable for those). `--run` is rejected up front for any other
1538
+ language.
1334
1539
 
1335
1540
  **Limitation:** pausing is cooperative. If the debuggee is blocked inside a single
1336
1541
  blocking external call or syscall, the pause can't land until that call returns --
@@ -1339,6 +1544,48 @@ blocking external call or syscall, the pause can't land until that call returns
1339
1544
  **Incompatible flags:** `-r`, `-k`/`-t`, `--record`, `--replay`, `--server`,
1340
1545
  `--headless`, `--mcp`, `--terminal`.
1341
1546
 
1547
+ ### Eval Mode (`-e`/`--eval`)
1548
+
1549
+ Eval mode automates a common debugging loop--set a breakpoint, run to it,
1550
+ evaluate an expression in the Evaluate console, continue--without
1551
+ opening the TUI. `-e` takes two arguments, a location and an expression:
1552
+
1553
+ ```bash
1554
+ tdb --eval examples/digits_of_pi.py:25 "print(f'{nr=}')" examples/digits_of_pi.py
1555
+ ```
1556
+
1557
+ sets a breakpoint at line 25, runs the program, and each time that line is
1558
+ reached evaluates `print(f'{nr=}')` in the stopped frame, then continues.
1559
+ Program output and evaluation output both stream to the terminal; when the
1560
+ program exits, `tdb` exits with the same code (and with `1` if the session
1561
+ ends without one--as with a crash or killed adapter--so a scripted `tdb -e ...
1562
+ && next` can trust the exit status). `Ctrl-C` stops the program and exits
1563
+ `130`. Under `multiprocessing`, an eval point placed in child code is
1564
+ evaluated in each child process that reaches it.
1565
+
1566
+ - The location is `FILE:LINE`, or a bare `LINE` of the program being debugged,
1567
+ and is snapped to the start of a logical statement just like `-k`.
1568
+ - `-e` may be repeated to plant several eval points in one run.
1569
+ - The expression is evaluated through the debug adapter (DAP `evaluate`,
1570
+ context `repl`), just like the Evaluate console: side effects are real
1571
+ and persist in the running program, for example
1572
+ `-e my_program.py:25 "limit = 10"` changes `limit` from line 25 onward.
1573
+ - A bare expression's result is printed to stdout; statement-style
1574
+ expressions (`print(...)`, assignments) print nothing beyond their own
1575
+ output. An expression error is reported on stderr and the run continues --
1576
+ a typo isn't fatal, matching the Evaluate console.
1577
+ - Saved breakpoints are ignored, and any other stop (e.g. an
1578
+ uncaught-exception stop) is continued untouched, so the program runs to
1579
+ completion unattended.
1580
+ - For non-Python debuggees the expression must be in the debug adapter's
1581
+ own syntax, for example gdb's `print x` / `set var x=3` for C/C++, and not
1582
+ necessarily the debuggee's language. The adapter may bind the breakpoint
1583
+ to the next executable line (gdb moves one off a declaration or brace);
1584
+ the eval point matches that bound line, so the expression still runs.
1585
+
1586
+ **Incompatible flags:** `--run`, `-r`, `-a`, `-k`/`-t`, `--record`,
1587
+ `--replay`, `--server`, `--headless`, `--mcp`, `--terminal`.
1588
+
1342
1589
  ### Keybinding Schemes
1343
1590
 
1344
1591
  ```bash
@@ -1634,6 +1881,10 @@ found; it's Python code, not an external executable), so
1634
1881
  `{"adapters": {"perl": "/path/to/perl"}}`. Use this when the `perl` on
1635
1882
  `PATH` is too old (< 5.18) or you need a specific `perlbrew`/`plenv` version.
1636
1883
 
1884
+ **PowerShell** follows the same pattern with two keys: `adapters.pwsh` names
1885
+ the interpreter and `adapters.pses` names the PowerShell Editor Services
1886
+ module directory (see [PowerShell](#powershell)).
1887
+
1637
1888
  Breakpoints are saved on exit and restored when debugging a program in the same
1638
1889
  directory. Each project's breakpoints are independent. Breakpoints set with
1639
1890
  `-t`/`--to-line` are the exception: they behave like `-k` breakpoints during