hiiro 0.1.343 → 0.1.344

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: e0b4a52f12f6b8206e79bc9c467c11523d8b6c09592e83ee88617133112ee60a
4
- data.tar.gz: 3190f9942e4f705fb7b4de299ed992d0b0123e5d57c5e375a3476f0b018b4867
3
+ metadata.gz: dfbd49f6a3303a03b9568647851914d4a1c30e7c81a6f9aa8ef5d9808728769d
4
+ data.tar.gz: 1245ec1dcc474ff962d48405c357ac315734c30a2cc573697e5c28ee3b35057f
5
5
  SHA512:
6
- metadata.gz: a6ce0e2c104da7509260220b5fc02162dde679457bc56012b704b17cb02ede55e51cd0e47f06b626ac40fd129b8f84991c0043e19523513e7012e11b4d8942b8
7
- data.tar.gz: c1b053c3f8cac1f4af5433a64e217dfdc79c93dcf017eab287efbfeb1f2e90ea696012bb37da1a599aab43c069e309b6488c3cab530cdefbd7cfc0cf6c69dde7
6
+ metadata.gz: dfaa031a3b826d422c64f8378108278cc845d4ec09a26da1f37fa85da34edb3c326c919d612873c1213331883cead770cd684d688ab521d38ec77dd50645d273
7
+ data.tar.gz: 1d0eb4479c705c13f898da37389b65d60104830d5daae7e9af38dba289cf871feeef60d8b6efd7fe9461cdfa490ba00a6fa53303520f4214b7d28ff0868a3faa
data/lib/hiiro/shell.rb CHANGED
@@ -22,5 +22,119 @@ class Hiiro
22
22
 
23
23
  selected&.chomp
24
24
  end
25
+
26
+ def self.run(*command, **env)
27
+ env = env.transform_keys(&:to_s).transform_values(&:to_s)
28
+ stdout, status = Open3.capture2(env, *command)
29
+ Result.new(stdout, status)
30
+ end
31
+
32
+ def self.run_combined(*command, **env)
33
+ env = env.transform_keys(&:to_s).transform_values(&:to_s)
34
+ output, status = Open3.capture2e(env, *command)
35
+ Result.new(output, status)
36
+ end
37
+
38
+ def self.run3(*command, **env)
39
+ env = env.transform_keys(&:to_s).transform_values(&:to_s)
40
+ stdout, stderr, status = Open3.capture3(env, *command)
41
+ Result.new(stdout, status, stderr: stderr)
42
+ end
43
+
44
+ # Stream stdout live to $stdout as chunks arrive, buffering for Result.
45
+ # stderr passes through to the parent process (not captured).
46
+ #
47
+ # ~/bin/h-tds does this manually with popen2e for Chromatic:
48
+ #
49
+ # Open3.popen2e('unbuffer pnpm chromatic') do |stdin, stdout_err, wait_thr|
50
+ # stdin.close
51
+ # loop do
52
+ # chunk = stdout_err.readpartial(4096)
53
+ # $stdout.write(chunk)
54
+ # @output << chunk
55
+ # rescue EOFError
56
+ # break
57
+ # end
58
+ # @exit_status = wait_thr.value
59
+ # end
60
+ #
61
+ # stream_combined replaces that pattern — stderr merged in, one Result back.
62
+ def self.stream(*command, tee: $stdout, **env)
63
+ env = env.transform_keys(&:to_s).transform_values(&:to_s)
64
+ Open3.popen2(env, *command) do |stdin, stdout, wait_thr|
65
+ stdin.close
66
+ return Result.collect_chunks(stdout, wait_thr, tee: tee)
67
+ end
68
+ end
69
+
70
+ def self.stream_combined(*command, tee: $stdout, **env)
71
+ env = env.transform_keys(&:to_s).transform_values(&:to_s)
72
+ Open3.popen2e(env, *command) do |stdin, stdout_err, wait_thr|
73
+ stdin.close
74
+ return Result.collect_chunks(stdout_err, wait_thr, tee: tee)
75
+ end
76
+ end
77
+ end
78
+
79
+ class Result
80
+ # Matches the full ANSI/VT100 escape sequence spec:
81
+ # cursor movement, erase, colors, SGR — everything a terminal interprets.
82
+ # [^[] catches all single-char Fe sequences (e.g. \eM, \eD); \[...] catches CSI.
83
+ ANSI_PATTERN = /\e(?:\[[0-?]*[ -/]*[@-~]|[^[])/
84
+
85
+ attr_reader :stdout, :stderr, :status
86
+
87
+ def initialize(stdout, status, stderr: nil)
88
+ @stdout = stdout
89
+ @stderr = stderr
90
+ @status = status
91
+ end
92
+
93
+ def success?
94
+ status.success?
95
+ end
96
+
97
+ def failed?
98
+ !success?
99
+ end
100
+
101
+ def exit_code
102
+ status.exitstatus
103
+ end
104
+
105
+ # Replay buffered output to the terminal with ANSI sequences intact —
106
+ # colors, cursor movement, line clears all work as they did live.
107
+ # Returns self so you can chain: result.display.lines
108
+ def display(out: $stdout)
109
+ out.write(stdout)
110
+ out.flush
111
+ self
112
+ end
113
+
114
+ # Strip ANSI escape codes for text processing or filtering.
115
+ # Also strips bare \r (carriage-return-only, used by progress bars).
116
+ def plain_text
117
+ stdout.gsub(ANSI_PATTERN, '').gsub(/\r(?!\n)/, '')
118
+ end
119
+
120
+ # Plain text split into non-empty lines.
121
+ def lines
122
+ plain_text.split("\n").reject(&:empty?)
123
+ end
124
+
125
+ # Factory: reads chunks from an IO (popen handle), optionally tee-ing
126
+ # each chunk to `tee` as it arrives. Used by Shell.stream / stream_combined.
127
+ # Pass tee: nil to capture without printing.
128
+ def self.collect_chunks(io, wait_thr, tee: $stdout)
129
+ output = +""
130
+ loop do
131
+ chunk = io.readpartial(4096)
132
+ tee&.write(chunk)
133
+ output << chunk
134
+ rescue EOFError
135
+ break
136
+ end
137
+ new(output, wait_thr.value)
138
+ end
25
139
  end
26
140
  end
data/lib/hiiro/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Hiiro
2
- VERSION = "0.1.343"
2
+ VERSION = "0.1.344"
3
3
  end
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.343
4
+ version: 0.1.344
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Toyota