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 +4 -4
- data/lib/hiiro/shell.rb +114 -0
- data/lib/hiiro/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dfbd49f6a3303a03b9568647851914d4a1c30e7c81a6f9aa8ef5d9808728769d
|
|
4
|
+
data.tar.gz: 1245ec1dcc474ff962d48405c357ac315734c30a2cc573697e5c28ee3b35057f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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