tui-td 0.1.3 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be8d93991312317febcad6a713d4dd58e6e670e620211bae0adc0db0bdd21da1
4
- data.tar.gz: 5618bc612addd9be3c634ebd4009800ddd6f7da9396ad5d950c8f831727398f8
3
+ metadata.gz: b8ebaa8989019a8cd573f682a538ca76a21a17daee810f29a1f178f8f35f0008
4
+ data.tar.gz: 52fecfc7d59143648f450e71612ac7b7b6839e1b697d03056cb80e0a0dd067ac
5
5
  SHA512:
6
- metadata.gz: ea0199d84e4f2a038141178e6b0adc539c1547184d99b13ee270e971e7076e37d079f315b6d6fde4b880231a032f8463677ebc359e93ad5084974ca0bc6ad30d
7
- data.tar.gz: 99e5a3c8d7bdf39ec903a7b44fb9a7d2e9c792cc405ec25b409ed8eca6f504b830b75cdf24a29271612931b79b4719f547580f61ab6f5f67aa829e74ab95bd10
6
+ metadata.gz: 9563af163f07bbaae4ea0427120785cc814c444289f7a6bc75b527d9a2e2a5a29785b99f40fa7c31c807c10708693f7f1a5cb5d9c39fea40b82a31e8d8c56964
7
+ data.tar.gz: 6912a0399394405e8678e33b13b1c95a7575ce5ef7f7731c23a514d2f55c720724c1f4d17bcb73be654a58461bade34d03adfcfd7e615509d1244c53ac8a8673
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.2.0
4
+
5
+ - Live debug modes for `tui-td test`: `-v` (verbose), `-l` (live screen-refresh), `-s` (step-by-step pause)
6
+ - Fix: skip DEC private mode sequences (`\e[?1049h` alternate screen, `\e[?25h` cursor visibility, etc.)
7
+ - TestRunner `on_step` callback API for programmatic step-by-step observation
8
+ - Vim interaction test example: type, yank, paste, substitute
9
+ - Removed aruba dev dependency from Gemfile
10
+
3
11
  ## 0.1.3
4
12
 
5
13
  - UTF-8 multi-byte character support in ANSI parser (`_utf8_char_at`)
data/README.md CHANGED
@@ -98,22 +98,45 @@ Usage: tui-td <command> [options]
98
98
 
99
99
  Commands:
100
100
  serve Start MCP server (JSON-RPC over stdio)
101
- test <file> Run JSON test file
102
- run <command> Run a TUI app and show live output
103
- drive <command> Drive a TUI with structured state output
104
101
  capture <command> Run once, capture and display state
102
+ drive <command> Drive a TUI interactively
103
+ run <command> Run a TUI app and show live output
104
+ test <file.json> Run JSON test file
105
+ help [topic] Show this help, or help test / help rspec
106
+
107
+ Examples:
108
+ tui-td capture "ls -la"
109
+ tui-td --screenshot out.png capture "htop" --timeout 5
110
+ tui-td --html out.html capture "glow README.md"
111
+ tui-td -C /my/project capture "make test"
112
+ tui-td drive "vim file.txt" --rows 24 --cols 80
113
+ tui-td test examples/echo_test.json
114
+ tui-td -vl test examples/vim_hello_world.json
115
+ tui-td serve
116
+
117
+ Interactive commands (drive mode):
118
+ state Show terminal state as pretty JSON
119
+ raw Show raw ANSI output
120
+ key <name> Send keystroke (enter, tab, escape, up, down, left, right,
121
+ backspace, ctrl_c, ctrl_d)
122
+ <text> Send text to the TUI
123
+ exit Quit drive mode
105
124
 
106
125
  Global options:
107
126
  -r, --rows N Terminal rows (default: 40)
108
127
  -c, --cols N Terminal cols (default: 120)
109
- -C, --chdir PATH Working directory for the command
110
128
  -t, --timeout N Timeout in seconds (default: 30)
129
+ -C, --chdir PATH Working directory for the command
111
130
  --screenshot PATH Save PNG screenshot
112
131
  --html PATH Save HTML render for browser viewing
113
132
  --json Output state as compact JSON (includes raw ANSI)
114
133
  --pretty Output state as pretty JSON
115
- --text Output state as plain text table (default)
116
- -h, --help Show complete reference (commands, options, examples, interactive commands)
134
+ --text Output state as plain text table
135
+ -v, --verbose Show each test step as it runs
136
+ -l, --live Show terminal state after each test step (screen-refresh)
137
+ -s, --step Pause after each test step for confirmation
138
+ --version Show version
139
+ -h, --help Show complete reference
117
140
  ```
118
141
 
119
142
  `tui-td --help` serves as the full CLI reference. `tui-td help test` shows all JSON test
@@ -103,7 +103,7 @@ module TUITD
103
103
  if processed[i] == "\e" && processed[i + 1] == "["
104
104
  # Find end of CSI sequence
105
105
  j = i + 2
106
- j += 1 while j < processed.length && !processed[j].match?(/[A-HJ-KP-SX@`fmnR]/)
106
+ j += 1 while j < processed.length && !processed[j].match?(/[A-HJ-KP-SX@`fhlmnR]/)
107
107
  seq = processed[i..j]
108
108
 
109
109
  dsr = _apply_csi(seq, cursor, attrs, grid, rows, cols)
@@ -214,7 +214,7 @@ module TUITD
214
214
  def self._apply_csi(seq, cursor, attrs, grid, rows, cols)
215
215
  # Strip leading escape char if present
216
216
  cleaned = seq.sub(/^\e/, "")
217
- match = cleaned.match(/^\[([\d;]*)([A-HJ-KP-SX@`fhmnR])$/)
217
+ match = cleaned.match(/^\[([\d;]*)([A-HJ-KP-SX@`fhlmnR])$/)
218
218
  return unless match
219
219
 
220
220
  params = match[1].split(";").map(&:to_i)
@@ -270,6 +270,8 @@ module TUITD
270
270
  next unless cursor[:row] < rows && cursor[:col] + i < cols
271
271
  grid[cursor[:row]][cursor[:col] + i][:char] = " "
272
272
  end
273
+ when "h", "l" # DEC private mode set/reset — skip (alternate screen, cursor show/hide, etc.)
274
+ nil
273
275
  when "n" # DSR — Device Status Report request
274
276
  # \e[6n = request cursor position → caller must respond with \e[row;colR
275
277
  return params[0] == 6
data/lib/tui_td/cli.rb CHANGED
@@ -32,6 +32,7 @@ module TUITD
32
32
  opts.separator " tui-td -C /my/project capture \"make test\""
33
33
  opts.separator " tui-td drive \"vim file.txt\" --rows 24 --cols 80"
34
34
  opts.separator " tui-td test examples/echo_test.json"
35
+ opts.separator " tui-td -vl test examples/vim_hello_world.json"
35
36
  opts.separator " tui-td serve"
36
37
  opts.separator ""
37
38
  opts.separator "Interactive commands (drive mode):"
@@ -71,6 +72,15 @@ module TUITD
71
72
  opts.on("--text", "Output state as plain text table") do |_|
72
73
  global_opts[:format] = :text
73
74
  end
75
+ opts.on("-v", "--verbose", "Show each test step as it runs") do |_|
76
+ global_opts[:verbose] = true
77
+ end
78
+ opts.on("-l", "--live", "Show terminal state after each step (screen-refresh)") do |_|
79
+ global_opts[:live] = true
80
+ end
81
+ opts.on("-s", "--step", "Pause after each test step for confirmation") do |_|
82
+ global_opts[:step_mode] = true
83
+ end
74
84
  opts.on("--version", "Show version") do
75
85
  puts "tui-td #{TUITD::VERSION}"
76
86
  exit 0
@@ -228,9 +238,35 @@ module TUITD
228
238
  path = args.first
229
239
  abort "File not found: #{path}" unless File.exist?(path)
230
240
 
241
+ verbose = globals[:verbose]
242
+ live = globals[:live]
243
+ step_mode = globals[:step_mode]
244
+
245
+ on_step = if verbose || live || step_mode
246
+ lambda do |info|
247
+ if live && info[:driver]
248
+ info[:driver].wait_for_stable(stable_ms: 200)
249
+ end
250
+ if verbose
251
+ status = info[:result].passed ? "PASS" : "FAIL"
252
+ puts "[#{info[:index] + 1}/#{info[:total]}] #{info[:action]}: #{info[:result].message}"
253
+ puts " → #{status}"
254
+ end
255
+ if live && info[:driver]
256
+ print "\e[2J\e[H" # clear screen, home cursor
257
+ _render_text(info[:driver].state_data)
258
+ end
259
+ if step_mode
260
+ print "\n[Enter=weiter, q=abbruch] "
261
+ input = $stdin.gets
262
+ exit 1 if input&.chomp == "q"
263
+ end
264
+ end
265
+ end
266
+
231
267
  require "json"
232
268
  plan = JSON.parse(File.read(path), symbolize_names: true)
233
- runner = TestRunner.new(plan)
269
+ runner = TestRunner.new(plan, on_step: on_step)
234
270
  result = runner.run
235
271
 
236
272
  puts
@@ -277,6 +313,10 @@ module TUITD
277
313
  Run from CLI:
278
314
 
279
315
  tui-td test examples/echo_test.json
316
+ tui-td -v test examples/echo_test.json (verbose: show each step)
317
+ tui-td -vl test examples/echo_test.json (verbose + live terminal view)
318
+ tui-td -vs test examples/echo_test.json (verbose + pause after each step)
319
+ tui-td -vls test examples/vim_hello_world.json (all three: watch vim edit live)
280
320
 
281
321
  Or from Ruby code:
282
322
 
@@ -26,10 +26,11 @@ module TUITD
26
26
  class TestRunner
27
27
  Result = Struct.new(:step, :passed, :message, keyword_init: true)
28
28
 
29
- def initialize(source)
29
+ def initialize(source, on_step: nil)
30
30
  raw = source.is_a?(String) ? JSON.parse(source) : source
31
31
  @plan = raw.transform_keys(&:to_sym)
32
32
  @plan[:steps] = @plan[:steps].map { |s| s.transform_keys(&:to_sym) }
33
+ @on_step = on_step
33
34
  end
34
35
 
35
36
  def run
@@ -150,6 +151,24 @@ module TUITD
150
151
 
151
152
  results << r
152
153
  all_passed &&= r.passed
154
+
155
+ if @on_step
156
+ state_data = nil
157
+ begin
158
+ state_data = driver.state_data if driver
159
+ rescue StandardError
160
+ # ignore — state retrieval is best-effort
161
+ end
162
+ @on_step.call(
163
+ index: results.size - 1,
164
+ total: @plan[:steps].size,
165
+ action: action,
166
+ value: value,
167
+ result: r,
168
+ driver: driver,
169
+ state_data: state_data
170
+ )
171
+ end
153
172
  end
154
173
 
155
174
  driver&.close
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TUITD
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tui-td
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Haluk Durmus