intar 2.2 → 2.5
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/LICENSE +29 -0
- data/README +45 -0
- data/lib/intar/prompt.rb +19 -5
- data/lib/intar/redirect.rb +15 -11
- data/lib/intar/version.rb +1 -1
- data/lib/intar.rb +132 -80
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cad6272b3ab1559bdebde9d6c9979fe065d4bf7bc57c49c85a0d6abf10071b0b
|
4
|
+
data.tar.gz: 3babbed5bbeab2e9f1b7da52ff16aec85f16f13da414f20fe3fdfac995ec0776
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3757b39f033d37efb3b0c36b547e788da344f084160b3f4cea112c6d23b9249db7bc0a766df605cf546f592810f1da2290e1bcf949f9179a0ed573f425b52ba
|
7
|
+
data.tar.gz: 8309a03d4e9a40a604829eaa70d18ed54db2d09d698a5d13474526e5a7cdf6a64bb1109c6fb8ab2c62443d5f97ec06225097408f206e8a3b527102f77e1558b2
|
data/LICENSE
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
= ruby-intar
|
2
|
+
|
3
|
+
Copyright (c) 2020, Bertram Scharpf <software@bertram-scharpf.de>.
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions are
|
8
|
+
met:
|
9
|
+
|
10
|
+
* Redistributions of source code must retain the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer.
|
12
|
+
|
13
|
+
* Redistributions in binary form must reproduce the above copyright
|
14
|
+
notice, this list of conditions and the following disclaimer in
|
15
|
+
the documentation and/or other materials provided with the
|
16
|
+
distribution.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
19
|
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
20
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
21
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
22
|
+
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
23
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
24
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
25
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
27
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
28
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
|
data/README
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
= ruby-intar -- Interactive Ruby
|
2
|
+
|
3
|
+
A simple Irb replacement
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
== About
|
8
|
+
|
9
|
+
The Intar project was started in times when Irb was a rather
|
10
|
+
unconvenient tool, without colors, difficult to call from
|
11
|
+
inside an application and so on.
|
12
|
+
|
13
|
+
Today, Intar is a tool far less complex than Irb.
|
14
|
+
|
15
|
+
Yet, Intar is more robust. Try this in Irb and in Intar:
|
16
|
+
|
17
|
+
prompt> Thread.new { sleep 3 ; Thread.main.raise "stop" }
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
== Usage
|
22
|
+
|
23
|
+
=== Subcommands
|
24
|
+
|
25
|
+
obj.method & enter a sub-Intar
|
26
|
+
obj.each & enter multiple sub-Intars
|
27
|
+
|
28
|
+
\q exit from the innermost sub-Intar
|
29
|
+
\q! exit from the innermost sub-Intar loop
|
30
|
+
\q!! exit from all levels
|
31
|
+
|
32
|
+
\h get a list of all subcommands
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
== Author
|
37
|
+
|
38
|
+
Bertram Scharpf <software@bertram-scharpf.de>
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
== TODO
|
43
|
+
|
44
|
+
Write some more documentation.
|
45
|
+
|
data/lib/intar/prompt.rb
CHANGED
@@ -16,11 +16,26 @@ class Intar
|
|
16
16
|
@new = 0
|
17
17
|
end
|
18
18
|
|
19
|
+
def push text
|
20
|
+
Readline.pre_input_hook = proc {
|
21
|
+
Readline.insert_text text
|
22
|
+
Readline.redisplay
|
23
|
+
}
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
19
27
|
def ask prompt
|
20
|
-
|
28
|
+
begin
|
29
|
+
Readline.readline prompt
|
30
|
+
ensure
|
31
|
+
Readline.pre_input_hook = nil
|
32
|
+
end
|
21
33
|
rescue Interrupt
|
22
|
-
puts
|
34
|
+
puts
|
23
35
|
retry
|
36
|
+
rescue Exception
|
37
|
+
puts
|
38
|
+
raise
|
24
39
|
end
|
25
40
|
|
26
41
|
def last
|
@@ -31,12 +46,11 @@ class Intar
|
|
31
46
|
i = Readline::HISTORY.length
|
32
47
|
while i > 0 do
|
33
48
|
i -= 1
|
34
|
-
|
35
|
-
yield l
|
49
|
+
yield Readline::HISTORY[i]
|
36
50
|
end
|
37
51
|
end
|
38
52
|
|
39
|
-
def
|
53
|
+
def push_history item
|
40
54
|
item.empty? and return
|
41
55
|
last != item or return
|
42
56
|
Readline::HISTORY.push item
|
data/lib/intar/redirect.rb
CHANGED
@@ -16,22 +16,24 @@ class Intar
|
|
16
16
|
class Redirect
|
17
17
|
def redirect_output
|
18
18
|
out = outfile
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
begin
|
20
|
+
stdin, stdout = $stdin.dup, $stdout.dup
|
21
|
+
$stdin .reopen "/dev/null"
|
22
|
+
$stdout.reopen out
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
$stdin .reopen stdin
|
26
|
+
$stdout.reopen stdout
|
27
|
+
out.close
|
28
|
+
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
class RedirectPipe < Redirect
|
31
33
|
class <<self
|
32
34
|
def detect line, pager
|
33
|
-
if line.slice! /\s
|
34
|
-
new pager
|
35
|
+
if line.slice! /\s+\|(\b[^|&;{}()\[\]]*)?\z/ then
|
36
|
+
new $1||pager
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -39,7 +41,9 @@ class Intar
|
|
39
41
|
@pager = pager||ENV[ "PAGER"]||"more"
|
40
42
|
end
|
41
43
|
def outfile
|
42
|
-
IO.popen @pager.to_s, "w"
|
44
|
+
IO.popen @pager.to_s, "w"
|
45
|
+
rescue Errno::ENOENT
|
46
|
+
raise Failed, "Pipe error: #$!"
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
data/lib/intar/version.rb
CHANGED
data/lib/intar.rb
CHANGED
@@ -63,7 +63,7 @@ class Intar
|
|
63
63
|
|
64
64
|
|
65
65
|
DEFAULTS = {
|
66
|
-
prompt: "%(32)c%
|
66
|
+
prompt: "%(32)c%16i%c:%1c%d:%3n%c%> ",
|
67
67
|
color: true,
|
68
68
|
show: 1,
|
69
69
|
shownil: false,
|
@@ -74,53 +74,66 @@ class Intar
|
|
74
74
|
histmax: 500,
|
75
75
|
}
|
76
76
|
|
77
|
+
@@current = nil
|
78
|
+
|
79
|
+
attr_reader :params, :prompt, :depth, :n
|
77
80
|
def initialize obj = nil, **params
|
78
81
|
@obj = obj.nil? ? (eval "self", TOPLEVEL_BINDING) : obj
|
79
|
-
|
82
|
+
if @@current then
|
83
|
+
@params = @@current.params
|
84
|
+
@prompt = @@current.prompt
|
85
|
+
@depth = @@current.depth + 1
|
86
|
+
else
|
87
|
+
@params = DEFAULTS.dup.update params
|
88
|
+
@prompt = Prompt.new
|
89
|
+
@depth = 0
|
90
|
+
end
|
91
|
+
@n = 1
|
92
|
+
|
80
93
|
@binding = @obj.intar_binding
|
81
|
-
@n = 0
|
82
|
-
@prompt = Prompt.new
|
83
94
|
end
|
84
95
|
|
85
96
|
|
86
97
|
class Quit < Exception ; end
|
87
|
-
class
|
98
|
+
class Bye < Quit ; end
|
99
|
+
class Break < Bye ; end
|
100
|
+
class Failed < StandardError ; end
|
88
101
|
|
89
102
|
def run
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
103
|
+
handle_history do
|
104
|
+
set_current do
|
105
|
+
oldset = eval OLDSET, @binding
|
106
|
+
loop do
|
107
|
+
l = readline
|
108
|
+
l or break
|
109
|
+
@redir = find_redirect l
|
110
|
+
r = begin
|
111
|
+
if l =~ /\A\\(\w+|.)\s*(.*?)\s*\Z/ then
|
112
|
+
send (get_metacommand $1).method, (eval_param $2)
|
113
|
+
else
|
114
|
+
l.sub! %r/\s*&\s*\z/, SUB
|
115
|
+
@redir.redirect_output do eval l, @binding, @file end
|
116
|
+
end
|
117
|
+
rescue Bye
|
118
|
+
raise if @depth.nonzero?
|
119
|
+
break
|
120
|
+
rescue Quit
|
121
|
+
break
|
101
122
|
rescue SyntaxError
|
102
123
|
raise if l.end_with? $/
|
103
124
|
@previous = l
|
104
125
|
next
|
126
|
+
rescue Exception
|
127
|
+
break if SystemExit === $! and not @params[ :catch_exit]
|
128
|
+
show_exception
|
129
|
+
$!
|
105
130
|
end
|
131
|
+
display r
|
132
|
+
oldset.call r, @n
|
133
|
+
@n += 1
|
106
134
|
end
|
107
|
-
rescue Quit
|
108
|
-
break
|
109
|
-
rescue Failed
|
110
|
-
switchcolor 31, 1
|
111
|
-
puts $!
|
112
|
-
switchcolor
|
113
|
-
r = $!
|
114
|
-
rescue Exception
|
115
|
-
break if SystemExit === $! and not @params[ :catch_exit]
|
116
|
-
show_exception
|
117
|
-
r = $!
|
118
|
-
else
|
119
|
-
display r
|
120
135
|
end
|
121
|
-
oldset.call r, @n
|
122
136
|
end
|
123
|
-
prompt_save_history
|
124
137
|
end
|
125
138
|
|
126
139
|
def execute code
|
@@ -130,6 +143,26 @@ class Intar
|
|
130
143
|
|
131
144
|
private
|
132
145
|
|
146
|
+
def handle_history
|
147
|
+
unless @depth.nonzero? then
|
148
|
+
begin
|
149
|
+
prompt_load_history
|
150
|
+
yield
|
151
|
+
ensure
|
152
|
+
prompt_save_history
|
153
|
+
end
|
154
|
+
else
|
155
|
+
yield
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def set_current
|
160
|
+
old, @@current = @@current, self
|
161
|
+
yield
|
162
|
+
ensure
|
163
|
+
@@current = old
|
164
|
+
end
|
165
|
+
|
133
166
|
def find_redirect line
|
134
167
|
RedirectPipe.detect line, @params[ :pager] or
|
135
168
|
RedirectFile.detect line, @params[ :output] or
|
@@ -137,6 +170,14 @@ class Intar
|
|
137
170
|
end
|
138
171
|
|
139
172
|
|
173
|
+
SUB = <<~EOT
|
174
|
+
\ do |obj|
|
175
|
+
Intar.run obj
|
176
|
+
rescue Intar::Break
|
177
|
+
break
|
178
|
+
end
|
179
|
+
EOT
|
180
|
+
|
140
181
|
OLDSET = <<~EOT
|
141
182
|
_, __, ___ = nil, nil, nil
|
142
183
|
proc { |r,n|
|
@@ -155,55 +196,66 @@ class Intar
|
|
155
196
|
|
156
197
|
def cur_prompt prev
|
157
198
|
p = @params[ :prompt].to_s
|
158
|
-
p.gsub /%
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
case $
|
164
|
-
when "s" then @obj.to_s
|
165
|
-
when "i" then $1 ? (@obj.send
|
166
|
-
when "
|
167
|
-
when "
|
168
|
-
when "
|
169
|
-
when "
|
170
|
-
when "
|
171
|
-
when "
|
172
|
-
when "
|
199
|
+
p.gsub /%
|
200
|
+
(\d+)?
|
201
|
+
(?:\(([^)]*)\)|\{([^}]*)\})?
|
202
|
+
(.)/nx do
|
203
|
+
sub = $2||$3
|
204
|
+
case $4
|
205
|
+
when "s" then str_axe $1, @obj.to_s
|
206
|
+
when "i" then str_axe $1, (sub ? (@obj.send sub) : @obj.inspect)
|
207
|
+
when "C" then str_axe $1, @obj.class.name
|
208
|
+
when "n" then "%0#$1d" % @n
|
209
|
+
when "d" then "%0#$1d" % @depth
|
210
|
+
when "t" then str_axe $1, (Time.now.strftime sub||"%X")
|
211
|
+
when "u" then str_axe $1, Etc.getpwuid.name
|
212
|
+
when "h" then str_axe $1, Socket.gethostname
|
213
|
+
when "w" then str_axe $1, cwd_short
|
214
|
+
when "W" then str_axe $1, (File.basename cwd_short)
|
215
|
+
when "c" then color [$1,sub].compact.map { |c| c.scan %r/\d+/ }.flatten
|
173
216
|
when ">" then prev ? "." : Process.uid == 0 ? "#" : ">"
|
174
|
-
when "%" then $
|
217
|
+
when "%" then $4
|
175
218
|
else $&
|
176
219
|
end
|
177
220
|
end
|
178
221
|
end
|
179
222
|
|
180
|
-
def
|
223
|
+
def str_axe len, str
|
224
|
+
if len then
|
225
|
+
str.axe len.to_i
|
226
|
+
else
|
227
|
+
str
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def color codes
|
181
232
|
if @params[ :color] then
|
182
|
-
|
183
|
-
"\e[#{s}m"
|
233
|
+
"\e[#{codes.join ';'}m"
|
184
234
|
end
|
185
235
|
end
|
186
236
|
|
187
237
|
def switchcolor *c
|
188
|
-
s = color
|
238
|
+
s = color c
|
189
239
|
print s
|
190
240
|
end
|
191
241
|
|
192
242
|
def cwd_short
|
193
243
|
r = Dir.pwd
|
194
244
|
h = Etc.getpwuid.dir
|
195
|
-
r[ 0, h.length] == h
|
245
|
+
if r[ 0, h.length] == h then
|
246
|
+
n = r[ h.length]
|
247
|
+
r[ 0, h.length] = "~" if !n || n == "/"
|
248
|
+
end
|
196
249
|
r
|
197
250
|
end
|
198
251
|
|
199
252
|
def readline
|
200
253
|
r, @previous = @previous, nil
|
201
|
-
r or @n += 1
|
202
254
|
begin
|
203
255
|
cp = cur_prompt r
|
204
256
|
l = @prompt.ask cp
|
205
257
|
return if l.nil?
|
206
|
-
@prompt.
|
258
|
+
@prompt.push_history l unless !r and @params[ :histhid] and l =~ /\A[ \t]+/
|
207
259
|
if r then
|
208
260
|
r << $/ << l
|
209
261
|
else
|
@@ -240,18 +292,19 @@ class Intar
|
|
240
292
|
puts i
|
241
293
|
end
|
242
294
|
|
295
|
+
PACKAGE_BACKTRACE = %r/#{File.basename __FILE__, ".rb"}.*:\d+:in/
|
296
|
+
|
243
297
|
def show_exception
|
244
298
|
unless $!.to_s.empty? then
|
245
|
-
switchcolor
|
299
|
+
switchcolor 1, 31
|
246
300
|
print $!
|
247
301
|
print " " unless $!.to_s =~ /\s\z/
|
248
302
|
end
|
249
|
-
switchcolor
|
303
|
+
switchcolor 22, 31
|
250
304
|
puts "(#{$!.class})"
|
251
305
|
switchcolor 33
|
252
306
|
$@.each { |b|
|
253
|
-
|
254
|
-
break if r and (b.rest r) =~ /\A:\d+:/
|
307
|
+
break if b =~ PACKAGE_BACKTRACE
|
255
308
|
puts b
|
256
309
|
}
|
257
310
|
switchcolor
|
@@ -348,36 +401,36 @@ class Intar
|
|
348
401
|
Leave Intar.
|
349
402
|
EOT
|
350
403
|
def cmd_quit x
|
351
|
-
|
404
|
+
lx = $&.length.nonzero? if x =~ /!*/
|
405
|
+
raise lx ? (lx > 1 ? Bye : Break) : Quit
|
352
406
|
end
|
353
407
|
|
354
408
|
metacmd %w(cd), "Change directory", <<~EOT
|
355
409
|
Switch to a different working directory.
|
356
|
-
Former directories will be
|
410
|
+
Former directories will be pushed to a stack.
|
357
411
|
|
358
|
-
|
359
|
-
|
360
|
-
|
412
|
+
N|PATH|% change directory and push
|
413
|
+
-N|PATH|% drop stack item
|
414
|
+
=N|PATH|% change directory but do not push
|
361
415
|
|
362
|
-
Default N is 1.
|
416
|
+
Default N or % is 1.
|
363
417
|
EOT
|
364
418
|
def cmd_cd x
|
365
419
|
@wds ||= []
|
366
420
|
y = Dir.getwd
|
367
|
-
if x =~ /\A([%=-])?(\d+)?\z/ then
|
368
|
-
x = $2 ? (@wds.delete_at -$2.to_i) : @wds.pop
|
369
|
-
x or raise Failed, ($2 ? "No directory ##$2." : "No last directory.")
|
370
|
-
case $1
|
371
|
-
when "-" then x = nil
|
372
|
-
when "=" then y = nil
|
373
|
-
end
|
374
|
-
end
|
375
421
|
if x then
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
422
|
+
cmd = x.slice! /\A[=-]/
|
423
|
+
x = case x
|
424
|
+
when /\A\d+\z/ then @wds[ -x.to_i] or raise Failed, "No directory ##{x}."
|
425
|
+
when /\A%?\z/ then @wds.last or raise Failed, "No last directory."
|
426
|
+
else File.expand_path x
|
427
|
+
end
|
428
|
+
@wds.delete x
|
429
|
+
if cmd != "-" then
|
430
|
+
Dir.chdir x
|
431
|
+
@wds.push y if cmd != "="
|
432
|
+
y = x
|
433
|
+
end
|
381
434
|
end
|
382
435
|
@redir.redirect_output do
|
383
436
|
i = @wds.length
|
@@ -464,7 +517,7 @@ class Intar
|
|
464
517
|
EOT
|
465
518
|
def cmd_input x
|
466
519
|
x or raise Failed, "No input file given."
|
467
|
-
l = File.read x
|
520
|
+
l = File.read x
|
468
521
|
@redir.redirect_output do
|
469
522
|
eval l, @binding, x
|
470
523
|
end
|
@@ -475,7 +528,7 @@ class Intar
|
|
475
528
|
EOT
|
476
529
|
def cmd_output x
|
477
530
|
if x then
|
478
|
-
File.open x, "w" do end
|
531
|
+
File.open x, "w" do end
|
479
532
|
end
|
480
533
|
@params[ :output] = x
|
481
534
|
end
|
@@ -495,7 +548,6 @@ class Intar
|
|
495
548
|
p = File.read fn
|
496
549
|
p.strip!
|
497
550
|
@prompt.push p
|
498
|
-
@redir.redirect_output do eval p, @binding, @file end
|
499
551
|
ensure
|
500
552
|
File.unlink fn
|
501
553
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: intar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '2.
|
4
|
+
version: '2.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bertram Scharpf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appl
|
@@ -47,6 +47,8 @@ executables:
|
|
47
47
|
extensions: []
|
48
48
|
extra_rdoc_files: []
|
49
49
|
files:
|
50
|
+
- LICENSE
|
51
|
+
- README
|
50
52
|
- bin/intar
|
51
53
|
- lib/intar.rb
|
52
54
|
- lib/intar/prompt.rb
|