about summary refs log tree commit diff
path: root/lrep
blob: 4a98148712ec615e645db75c0fb1f6163a5f6133 (plain) (blame)
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
#!/usr/bin/env ruby
# lrep [-z] [-t SECS] [FILES...] - literate read-eval-print

# -*- ruby -*-

require 'pty'
require 'io/console'

# TODO keep each session keyed by ps1?

output = input = pid = nil

trap(:SIGCHLD) { input = output = nil }

def readp(output, ps)
  return "[DEAD]"  if output == nil

  o = ps ? output.readpartial(1024) : ""
# p [:READ, o]
  timeout = true
  loop {
    if o.split("\r\n").last =~ ps
      timeout = false
      break
    end
    if IO.select([output],[],[],0.04)
      begin
	x=output.readpartial(1024)
      # p [:READ, x]
	o << x
      rescue Errno::EIO
	# eof
	break
      end
    else
      break
    end
  }

  o = "[TIMEOUT]\r\n" + o  if timeout && ps

  l = o.split("\r\n")

  if ps && l[-1]
    l[-1].gsub!(ps, "")
    l.pop  if l[-1].empty?
  end
  o = l.join("\n")

  o
end

def ind(txt)
  txt.split("\n").map { |l| "\t#{l}\n" }.join
end

ps = nil

while line = gets
  if line =~ /^\t!(.*?)(?:!(.*?))?!(.*)/
    puts line
    begin
      if $1.empty? && $2.empty?
	output = input = pid = nil
	print ind(`#{$3}`)
      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
	output, input, pid = PTY.spawn $3
	input.echo = false
	print ind(readp(output, ps))
      end
    rescue
      print ind("ERROR: #{$!.message}")
    end
  elsif line =~ psl
    puts line
    if input
#     p [:WRITE, $1 + "\n"]
      input.write $1 + "\n"
    end
    print ind(readp(output, ps))
  elsif line =~ /^\t/
    # old output, remove
  else
    puts line
  end
end