hiiro 0.1.349 → 0.1.351
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 +4 -4
- data/CHANGELOG.md +17 -90
- data/bin/h-capture +200 -0
- data/lib/hiiro/capture.rb +42 -0
- data/lib/hiiro/shell.rb +17 -17
- data/lib/hiiro/version.rb +1 -1
- data/lib/hiiro.rb +1 -0
- data/script/publish +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0586a9cc0e070785c9a0ef12282146ed71172875e706480d3dca6d663f5a46e8'
|
|
4
|
+
data.tar.gz: ffec55f5b2ce8882cb06189dedf5e29ccb75a3b8214a76fc72e7dc460851f2cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e40c167924bce7ac225b17e0fd7c82855c0d6034e66814c4b3e4897ee00dc80b9214b52dafe4d3a98c7916b0194c0a7d4b234e9f55a5a51fd0d73329315132ee
|
|
7
|
+
data.tar.gz: 994e44431c7a4dc5a15a2eaaa0ffa6c9b0382229b5d84dac1521c56129b599c08316e124511e6f5cf830e7189ab326672e599c228c11b7ddb7776be42c86bfdc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- `h capture path <num>` now prints the path of the Nth most recent capture (was always printing the captures dir regardless of args)
|
|
7
|
+
- `h capture new` / `h capture file` now record to the DB even when interrupted (Ctrl-C, exception) so partial captures show up in `h capture ls`. Interrupted captures display with the existing `?` glyph and `(exit interrupted)` message.
|
|
8
|
+
|
|
9
|
+
## [0.1.350] - 2026-04-18
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- `h-capture` command and `Hiiro::Capture` module for clipboard/selection capture
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Optimize `Hiiro::Shell::Result#plain_text` and `#lines` with instance-level caching
|
|
16
|
+
- Refactor `Shell::Result#lines` to use `String#lines(chomp: true)` for improved line handling
|
|
17
|
+
- Reduce Claude API effort to `low` in publish script for faster changelog generation
|
|
18
|
+
|
|
3
19
|
## [0.1.349] - 2026-04-17
|
|
4
20
|
|
|
5
21
|
### Removed
|
|
@@ -300,93 +316,4 @@
|
|
|
300
316
|
- `h db cleanup` subcommand to preview and prune duplicate rows from SQLite tables
|
|
301
317
|
|
|
302
318
|
### Fixed
|
|
303
|
-
- Prevent duplicate pinned_prs during import with `insert_conflict` and per-row rescue
|
|
304
|
-
|
|
305
|
-
## [0.1.308.pre.6] - 2026-03-31
|
|
306
|
-
|
|
307
|
-
### Fixed
|
|
308
|
-
- Prevent duplicate pinned_prs during import with `insert_conflict` and per-row rescue
|
|
309
|
-
|
|
310
|
-
## [0.1.308.pre.5] - 2026-03-31
|
|
311
|
-
|
|
312
|
-
### Added
|
|
313
|
-
- `h-claude vim` subcommand to open all matched files in `$EDITOR`
|
|
314
|
-
|
|
315
|
-
### Fixed
|
|
316
|
-
- `h branch ls` now sorts oldest-first so most recent branches appear at bottom
|
|
317
|
-
|
|
318
|
-
## [0.1.308.pre.4] - 2026-03-31
|
|
319
|
-
|
|
320
|
-
### Fixed
|
|
321
|
-
- Don't pass empty string arg to gem when `--pre` is false
|
|
322
|
-
|
|
323
|
-
## [0.1.308.pre.3] - 2026-03-31
|
|
324
|
-
|
|
325
|
-
### Changed
|
|
326
|
-
- Poll RubyGems in `delayed_update` instead of blind sleep for more reliable version detection
|
|
327
|
-
|
|
328
|
-
### Fixed
|
|
329
|
-
- Per-row rescue in `import_todos` so one bad row doesn't abort the entire batch
|
|
330
|
-
|
|
331
|
-
## [0.1.308.pre.2] - 2026-03-31
|
|
332
|
-
|
|
333
|
-
### Added
|
|
334
|
-
- `--pre`/`-p` flag to `h install` and `h update` for installing/updating pre-release versions
|
|
335
|
-
|
|
336
|
-
### Changed
|
|
337
|
-
- Merge `prs` and `pinned_prs` tables into single `prs` table in SQLite schema
|
|
338
|
-
- Refactor PR storage to use unified table structure
|
|
339
|
-
|
|
340
|
-
### Fixed
|
|
341
|
-
- YAML migration for todos, prs, pinned_prs, and tags to correctly handle merged schema
|
|
342
|
-
|
|
343
|
-
## [0.1.308.pre.1] - 2026-03-31
|
|
344
|
-
|
|
345
|
-
### Added
|
|
346
|
-
- `Hiiro::Effects` injectable interface for testable file system and command execution
|
|
347
|
-
- `null_fs` to `TestHarness` for testing without side effects
|
|
348
|
-
- Effects helpers and accessors to `TestHarness` for controlled effect simulation
|
|
349
|
-
- `Hiiro::Invocation` and `Hiiro::InvocationResolution` tracking in PaneHome SQLite migration
|
|
350
|
-
|
|
351
|
-
### Changed
|
|
352
|
-
- Refactor effects layer: expose `executor` and `fs` as accessors on `Hiiro::Effects`
|
|
353
|
-
- `h-db` command now includes h-pane in SQLite migration
|
|
354
|
-
- Gem version handling: treat non-main branches as pre-release in publish script
|
|
355
|
-
|
|
356
|
-
### Fixed
|
|
357
|
-
- `h-branch co` and `h-branch rm` restore extra argument pass-through
|
|
358
|
-
- Test suite: add missing `TestHarness` stubs and fix pre-existing test failures
|
|
359
|
-
- Test fixtures: anchor `load_bin` path to project root instead of `Dir.pwd`
|
|
360
|
-
|
|
361
|
-
### Deprecated
|
|
362
|
-
- `SystemCallCapture` — use `Hiiro::Effects` helpers in `TestHarness` instead
|
|
363
|
-
|
|
364
|
-
## [0.1.307]
|
|
365
|
-
|
|
366
|
-
### Added
|
|
367
|
-
- `Hiiro::DB` — SQLite foundation via Sequel; `DB.setup!` creates all tables, `DB.connection` establishes connection eagerly at load time; supports `HIIRO_TEST_DB=sqlite::memory:` for tests
|
|
368
|
-
- `lib/hiiro/db.rb` — one-time YAML→SQLite migration (`migrate_yaml!`) guarded by `schema_migrations` table; dual-write mode (`dual_write?` / `disable_dual_write!`) for gradual cutover
|
|
369
|
-
- `lib/hiiro/branch.rb` — `Hiiro::Branch` Sequel model for worktree branch records
|
|
370
|
-
- `lib/hiiro/tracked_pr.rb` — `Hiiro::TrackedPr` Sequel model for tracked PR records (`:prs` table)
|
|
371
|
-
- `lib/hiiro/link.rb` — `Hiiro::Link` Sequel model with `matches?`, `display_string`, `to_h` helpers
|
|
372
|
-
- `lib/hiiro/project.rb` — `Hiiro::Project` Sequel model
|
|
373
|
-
- `lib/hiiro/pane_home.rb` — `Hiiro::PaneHome` Sequel model with `data_json` JSON blob
|
|
374
|
-
- `lib/hiiro/pin_record.rb` — `Hiiro::PinRecord` Sequel model for per-command key-value pin storage
|
|
375
|
-
- `lib/hiiro/task_record.rb` — `Hiiro::TaskRecord` Sequel model for task metadata
|
|
376
|
-
- `lib/hiiro/app_record.rb` — `Hiiro::AppRecord` Sequel model for app directory mappings
|
|
377
|
-
- `lib/hiiro/assignment.rb` — `Hiiro::Assignment` Sequel model for worktree→branch assignments
|
|
378
|
-
- `lib/hiiro/reminder.rb` — `Hiiro::Reminder` Sequel model
|
|
379
|
-
- `lib/hiiro/invocation.rb` — `Hiiro::Invocation` and `Hiiro::InvocationResolution` Sequel models; every CLI invocation is recorded to SQLite for history/analytics
|
|
380
|
-
- `bin/h-db` — new subcommand: `h db status`, `h db tables`, `h db q <sql>`, `h db migrate`, `h db restore`
|
|
381
|
-
|
|
382
|
-
### Changed
|
|
383
|
-
- `lib/hiiro/todo.rb` — `TodoItem` is now a `Sequel::Model`; `TodoManager` reads/writes via SQLite with YAML dual-write fallback
|
|
384
|
-
- `lib/hiiro/tags.rb` — `Tag` is now a `Sequel::Model`; tag operations persist to SQLite with YAML dual-write fallback
|
|
385
|
-
- `lib/hiiro/pinned_pr_manager.rb` — `PinnedPR` is now a `Sequel::Model` (`lib/hiiro/pinned_pr.rb`); `PinnedPRManager` reads/writes via SQLite with YAML dual-write
|
|
386
|
-
- `lib/hiiro/projects.rb` — `Projects#from_config` reads from `Hiiro::Project` SQLite model with YAML fallback
|
|
387
|
-
- `lib/hiiro/tasks.rb` — `TaskManager::Config` reads/writes tasks and apps via `Hiiro::TaskRecord` and `Hiiro::AppRecord` SQLite models
|
|
388
|
-
- `bin/h-branch` — `BranchManager` reads/writes via `Hiiro::Branch` and `Hiiro::TrackedPr` SQLite models with YAML dual-write fallback; adds `q`/`query` subcommands for raw SQL inspection
|
|
389
|
-
- `bin/h-link` — reads/writes links via `Hiiro::Link` SQLite model with YAML dual-write fallback; adds `q`/`query` subcommands
|
|
390
|
-
- `bin/h-pane` — load/save pane homes via `Hiiro::PaneHome` model with YAML dual-write
|
|
391
|
-
- `bin/h-pr` — adds `q`/`query` subcommands for inspecting PR records via raw SQL
|
|
392
|
-
- `plugins/pins.rb` — `Pin` class reads/writes via `Hiiro::PinRecord` SQLite model with YAML dual-write fallback
|
|
319
|
+
- Prevent duplicate pinned_prs during import with `insert_conflict` and per-row rescue
|
data/bin/h-capture
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'time'
|
|
6
|
+
require 'hiiro'
|
|
7
|
+
|
|
8
|
+
CAPTURES_DIR = File.expand_path('~/.local/share/hiiro/captures')
|
|
9
|
+
|
|
10
|
+
# TODO(USER): implement resolve_path.
|
|
11
|
+
#
|
|
12
|
+
# Given a name-or-path string from `h capture file <fpath_or_name> ...`,
|
|
13
|
+
# return the absolute filesystem path where the capture should be written.
|
|
14
|
+
#
|
|
15
|
+
# Spec from the user:
|
|
16
|
+
# - If the input has NO path separators (just a bare filename like "build.log"),
|
|
17
|
+
# the file goes in CAPTURES_DIR.
|
|
18
|
+
# - Otherwise it's a path expression — write it relative to the current
|
|
19
|
+
# working directory (or honor it as-is if already absolute).
|
|
20
|
+
#
|
|
21
|
+
# Open design questions for you to decide:
|
|
22
|
+
# - Should "~/foo.log" be expanded? (File.expand_path handles this for free)
|
|
23
|
+
# - Should we ensure parent dirs exist via FileUtils.mkdir_p?
|
|
24
|
+
# - Should paths starting with "./" be normalized?
|
|
25
|
+
#
|
|
26
|
+
# Whichever rules you pick, this 5–8 line method is the contract for where
|
|
27
|
+
# `h capture file` writes — so it's worth getting right for your workflow.
|
|
28
|
+
def resolve_path(name_or_path)
|
|
29
|
+
if File.dirname(name_or_path) != ?.
|
|
30
|
+
FileUtils.mkdir_p(File.dirname(name_or_path))
|
|
31
|
+
return name_or_path
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
FileUtils.mkdir_p(CAPTURES_DIR)
|
|
35
|
+
File.join(CAPTURES_DIR, name_or_path)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ensure_dir(path)
|
|
39
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Run cmd, tee combined stdout+stderr to terminal AND to output_path.
|
|
43
|
+
# If our own stdin is piped (not a tty), forward it into the subprocess.
|
|
44
|
+
def run_and_capture(cmd_args, output_path)
|
|
45
|
+
ensure_dir(output_path)
|
|
46
|
+
exit_status = nil
|
|
47
|
+
|
|
48
|
+
File.open(output_path, 'w') do |f|
|
|
49
|
+
Open3.popen2e(*cmd_args) do |stdin, stdout_err, wait_thr|
|
|
50
|
+
pipe_thread = if !STDIN.tty?
|
|
51
|
+
Thread.new do
|
|
52
|
+
IO.copy_stream(STDIN, stdin)
|
|
53
|
+
rescue Errno::EPIPE, IOError
|
|
54
|
+
# subprocess closed stdin early — fine
|
|
55
|
+
ensure
|
|
56
|
+
stdin.close rescue nil
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
stdin.close
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
loop do
|
|
64
|
+
chunk = stdout_err.readpartial(4096)
|
|
65
|
+
$stdout.write(chunk)
|
|
66
|
+
$stdout.flush
|
|
67
|
+
f.write(chunk)
|
|
68
|
+
rescue EOFError
|
|
69
|
+
break
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
pipe_thread&.join
|
|
73
|
+
exit_status = wait_thr.value.exitstatus
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
exit_status
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def fetch_capture(num)
|
|
81
|
+
Hiiro::Capture.at_offset(num.to_i)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def record_capture(name:, path:, command:, exit_status:)
|
|
85
|
+
Hiiro::Capture.create(
|
|
86
|
+
name: name,
|
|
87
|
+
path: path,
|
|
88
|
+
command: command,
|
|
89
|
+
exit_status: exit_status
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Run the command and record the capture even if interrupted (Ctrl-C, error).
|
|
94
|
+
# `exit_status` is nil when the process didn't reach a clean exit — the `?`
|
|
95
|
+
# glyph in Hiiro::Capture#status_glyph already handles that case.
|
|
96
|
+
def capture_and_record(args, path:, name:)
|
|
97
|
+
code = nil
|
|
98
|
+
begin
|
|
99
|
+
code = run_and_capture(args, path)
|
|
100
|
+
ensure
|
|
101
|
+
record_capture(name: name, path: path, command: args.join(' '), exit_status: code)
|
|
102
|
+
warn "\n[capture saved: #{path} (exit #{code || 'interrupted'})]"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
Hiiro.run(*ARGV) do
|
|
107
|
+
add_subcmd(:new) do |*args|
|
|
108
|
+
if args.empty?
|
|
109
|
+
puts "Usage: h capture new <command> [args...]"
|
|
110
|
+
exit 1
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
name = "#{Time.now.strftime('%Y%m%d%H%M%S')}.output"
|
|
114
|
+
path = File.join(CAPTURES_DIR, name)
|
|
115
|
+
ensure_dir(path)
|
|
116
|
+
|
|
117
|
+
capture_and_record(args, path: path, name: name)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
add_subcmd(:file) do |fpath = nil, *args|
|
|
121
|
+
if fpath.nil? || args.empty?
|
|
122
|
+
puts "Usage: h capture file <fpath_or_name> <command> [args...]"
|
|
123
|
+
exit 1
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
path = resolve_path(fpath)
|
|
127
|
+
name = File.basename(fpath)
|
|
128
|
+
|
|
129
|
+
capture_and_record(args, path: path, name: name)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
add_subcmd(:ls) do |num = nil|
|
|
133
|
+
captures = if num.nil?
|
|
134
|
+
Hiiro::Capture.recent
|
|
135
|
+
elsif num.to_i >= 0
|
|
136
|
+
cap = Hiiro::Capture.at_offset(num.to_i)
|
|
137
|
+
cap ? [cap] : []
|
|
138
|
+
else
|
|
139
|
+
Hiiro::Capture.recent(num.to_i.abs)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if captures.empty?
|
|
143
|
+
puts "No captures."
|
|
144
|
+
next
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
captures.each_with_index { |cap, i| puts cap.display_string(i) }
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
add_subcmd(:cat) do |num = 0|
|
|
151
|
+
cap = fetch_capture(num)
|
|
152
|
+
if cap.nil?
|
|
153
|
+
warn "No capture at offset #{num}."
|
|
154
|
+
exit 1
|
|
155
|
+
end
|
|
156
|
+
unless File.exist?(cap.path)
|
|
157
|
+
warn "File missing: #{cap.path}"
|
|
158
|
+
exit 1
|
|
159
|
+
end
|
|
160
|
+
$stdout.write(File.read(cap.path))
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
add_subcmd(:cppath) do |num = 0|
|
|
164
|
+
cap = fetch_capture(num)
|
|
165
|
+
if cap.nil?
|
|
166
|
+
warn "No capture at offset #{num}."
|
|
167
|
+
exit 1
|
|
168
|
+
end
|
|
169
|
+
Hiiro::Shell.pipe(cap.path, 'pbcopy')
|
|
170
|
+
puts "Copied path: #{cap.path}"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
add_subcmd(:cp) do |num = 0|
|
|
174
|
+
cap = fetch_capture(num)
|
|
175
|
+
if cap.nil?
|
|
176
|
+
warn "No capture at offset #{num}."
|
|
177
|
+
exit 1
|
|
178
|
+
end
|
|
179
|
+
unless File.exist?(cap.path)
|
|
180
|
+
warn "File missing: #{cap.path}"
|
|
181
|
+
exit 1
|
|
182
|
+
end
|
|
183
|
+
Hiiro::Shell.pipe(File.read(cap.path), 'pbcopy')
|
|
184
|
+
puts "Copied contents of: #{cap.path}"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
add_subcmd(:path) do |num = nil|
|
|
188
|
+
if num.nil?
|
|
189
|
+
print CAPTURES_DIR
|
|
190
|
+
next
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
cap = fetch_capture(num)
|
|
194
|
+
if cap.nil?
|
|
195
|
+
warn "No capture at offset #{num}."
|
|
196
|
+
exit 1
|
|
197
|
+
end
|
|
198
|
+
print cap.path
|
|
199
|
+
end
|
|
200
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'sequel'
|
|
2
|
+
|
|
3
|
+
class Hiiro
|
|
4
|
+
class Capture < Sequel::Model(:captures)
|
|
5
|
+
Hiiro::DB.register(self)
|
|
6
|
+
|
|
7
|
+
def self.create_table!(db)
|
|
8
|
+
db.create_table?(:captures) do
|
|
9
|
+
primary_key :id
|
|
10
|
+
String :name, null: false
|
|
11
|
+
String :path, null: false
|
|
12
|
+
String :command
|
|
13
|
+
Integer :exit_status
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Most-recent-first scope. id is autoincrement, so desc(:id) == chronological reverse.
|
|
18
|
+
def self.recent(limit = nil)
|
|
19
|
+
ds = order(Sequel.desc(:id))
|
|
20
|
+
limit ? ds.limit(limit).all : ds.all
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Fetch the capture at offset n from the most recent (0 = newest).
|
|
24
|
+
def self.at_offset(n)
|
|
25
|
+
order(Sequel.desc(:id)).offset(n.to_i).first
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def status_glyph
|
|
29
|
+
case exit_status
|
|
30
|
+
when 0 then "\e[32m✓\e[0m"
|
|
31
|
+
when nil then "\e[33m?\e[0m"
|
|
32
|
+
else "\e[31m✗\e[0m"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def display_string(idx)
|
|
37
|
+
cmd = command.to_s
|
|
38
|
+
cmd = cmd[0, 57] + '…' if cmd.length > 60
|
|
39
|
+
format("%4d. %s %-22s %s", idx, status_glyph, name, cmd)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/hiiro/shell.rb
CHANGED
|
@@ -77,6 +77,21 @@ class Hiiro
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
class Result
|
|
80
|
+
# Factory: reads chunks from an IO (popen handle), optionally tee-ing
|
|
81
|
+
# each chunk to `tee` as it arrives. Used by Shell.stream / stream_combined.
|
|
82
|
+
# Pass tee: nil to capture without printing.
|
|
83
|
+
def self.collect_chunks(io, wait_thr, tee: $stdout)
|
|
84
|
+
output = +""
|
|
85
|
+
loop do
|
|
86
|
+
chunk = io.readpartial(4096)
|
|
87
|
+
tee&.write(chunk)
|
|
88
|
+
output << chunk
|
|
89
|
+
rescue EOFError
|
|
90
|
+
break
|
|
91
|
+
end
|
|
92
|
+
new(output, wait_thr.value)
|
|
93
|
+
end
|
|
94
|
+
|
|
80
95
|
# Matches the full ANSI/VT100 escape sequence spec:
|
|
81
96
|
# cursor movement, erase, colors, SGR — everything a terminal interprets.
|
|
82
97
|
# [^[] catches all single-char Fe sequences (e.g. \eM, \eD); \[...] catches CSI.
|
|
@@ -115,27 +130,12 @@ class Hiiro
|
|
|
115
130
|
# Strip ANSI escape codes for text processing or filtering.
|
|
116
131
|
# Also strips bare \r (carriage-return-only, used by progress bars).
|
|
117
132
|
def plain_text
|
|
118
|
-
stdout.gsub(ANSI_PATTERN, '').gsub(/\r(?!\n)/, '')
|
|
133
|
+
@plain_text ||= stdout.gsub(ANSI_PATTERN, '').gsub(/\r(?!\n)/, '')
|
|
119
134
|
end
|
|
120
135
|
|
|
121
136
|
# Plain text split into non-empty lines.
|
|
122
137
|
def lines
|
|
123
|
-
plain_text.
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# Factory: reads chunks from an IO (popen handle), optionally tee-ing
|
|
127
|
-
# each chunk to `tee` as it arrives. Used by Shell.stream / stream_combined.
|
|
128
|
-
# Pass tee: nil to capture without printing.
|
|
129
|
-
def self.collect_chunks(io, wait_thr, tee: $stdout)
|
|
130
|
-
output = +""
|
|
131
|
-
loop do
|
|
132
|
-
chunk = io.readpartial(4096)
|
|
133
|
-
tee&.write(chunk)
|
|
134
|
-
output << chunk
|
|
135
|
-
rescue EOFError
|
|
136
|
-
break
|
|
137
|
-
end
|
|
138
|
-
new(output, wait_thr.value)
|
|
138
|
+
@lines ||= plain_text.lines(chomp: true)
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
end
|
data/lib/hiiro/version.rb
CHANGED
data/lib/hiiro.rb
CHANGED
|
@@ -21,6 +21,7 @@ require_relative "hiiro/options"
|
|
|
21
21
|
require_relative "hiiro/input_file"
|
|
22
22
|
require_relative "hiiro/paths"
|
|
23
23
|
require_relative "hiiro/link"
|
|
24
|
+
require_relative "hiiro/capture"
|
|
24
25
|
require_relative "hiiro/branch"
|
|
25
26
|
require_relative "hiiro/check_run"
|
|
26
27
|
require_relative "hiiro/tags"
|
data/script/publish
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hiiro
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.351
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Toyota
|
|
@@ -131,6 +131,7 @@ files:
|
|
|
131
131
|
- bin/h-bin
|
|
132
132
|
- bin/h-branch
|
|
133
133
|
- bin/h-buffer
|
|
134
|
+
- bin/h-capture
|
|
134
135
|
- bin/h-claude
|
|
135
136
|
- bin/h-commit
|
|
136
137
|
- bin/h-config
|
|
@@ -326,6 +327,7 @@ files:
|
|
|
326
327
|
- lib/hiiro/background.rb
|
|
327
328
|
- lib/hiiro/bins.rb
|
|
328
329
|
- lib/hiiro/branch.rb
|
|
330
|
+
- lib/hiiro/capture.rb
|
|
329
331
|
- lib/hiiro/check_run.rb
|
|
330
332
|
- lib/hiiro/config.rb
|
|
331
333
|
- lib/hiiro/db.rb
|