1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#!/usr/bin/env ruby
# lrep [-z] [-t SECS] [FILES...] - literate read-eval-print
# -*- ruby -*-
#
# To the extent possible under law,
# Christian Neukirchen <chneukirchen@gmail.com>
# has waived all copyright and related or neighboring rights to this work.
# http://creativecommons.org/publicdomain/zero/1.0/
require 'pty'
require 'io/console'
require 'optparse'
params = ARGV.getopts("t:z")
zap = params["z"]
$timeout = params["t"] ? params["t"].to_f : 0.04
def readp(output, ps, timeout=$timeout)
return "[DEAD]" if output == nil
o = ps ? output.readpartial(1024) : ""
timedout = true
loop {
if o.split("\r\n").last =~ ps
timedout = false
break
end
if IO.select([output],[],[],timeout)
begin
o << output.readpartial(1024)
rescue Errno::EIO
# eof
break
end
else
break
end
}
o = "[TIMEOUT]\r\n" + o if timedout && ps
l = o.split("\r\n")
if ps && l[-1]
l[-1].gsub!(ps, "")
l.pop if l[-1].empty?
end
l.join("\n")
end
def ind(txt)
txt.split("\n").map { |l| "\t#{l}\n" }.join
end
def kill(pid)
if pid
n = 0
until Process.waitpid(pid, Process::WNOHANG)
Process.kill(n > 10 ? "KILL" : "TERM", pid)
sleep 0.1
n += 1
end
end
end
output = input = pid = nil
trap(:SIGCHLD) { input = output = nil }
ps = nil
while line = gets
if line =~ /^\t!(.*?)(?:!(.*?))?!(.*)/
puts line
begin
if $1.empty? && $2.empty?
kill pid
output = input = pid = nil
next if zap
cmd = $3
silent = cmd.gsub!(/>-$/, '')
o = `#{cmd}`
print ind(o) unless silent
else
if $1.empty?
ps = nil
psl = /^\t.*#{Regexp.quote $2}(.*)/
else
ps = /.*?#{Regexp.union [$1,$2].compact}$/
psl = /^\t.*?#{Regexp.union [$1,$2].compact}(.*)/
end
next if zap
cmd = $3
silent = cmd.gsub!(/>-$/, '')
kill pid
output, input, pid = PTY.spawn cmd
input.echo = false
# more timeout to launch program
o = readp(output, ps, 20*$timeout)
print ind(o) unless silent
end
rescue
print ind("ERROR: #{$!.message}")
end
elsif line =~ psl
puts line
next if zap
if input
cmd = $1
silent = cmd.gsub!(/>-$/, '')
input.write cmd + "\n"
o = readp(output, ps)
print ind(o) unless silent
end
elsif line =~ /^\t/
# old output, remove
else
puts line
end
end
kill pid
|