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
|
# File 'lib/musa-dsl/repl/repl.rb', line 9
def initialize(bind = nil, port: nil, after_eval: nil, logger: nil, highlight_exception: true)
self.bind = bind
port ||= 1327
@logger = logger || Musa::Logger::Logger.new
@highlight_exception = highlight_exception
@block_source = nil
@client_threads = []
@run = true
@main_thread = Thread.new do
@server = TCPServer.new(port)
begin
while (@connection = @server.accept) && @run
@client_threads << Thread.new do
buffer = nil
begin
while (line = @connection.gets) && @run
@logger.warn('REPL') { 'input line is nil; will close connection...' } if line.nil?
line.chomp!
case line
when '#path'
buffer = StringIO.new
when '#begin'
user_path = buffer&.string
@bind.receiver.instance_variable_set(:@user_pathname, Pathname.new(user_path)) if user_path
buffer = StringIO.new
when '#end'
@@repl_mutex.synchronize do
@block_source = buffer.string
begin
send_echo @block_source, output: @connection
@bind.receiver.execute @block_source, '(repl)', 1
rescue StandardError, ScriptError => e
@logger.warn('REPL') { 'code execution error' }
@logger.warn('REPL') { e.full_message(highlight: @highlight_exception, order: :top) }
send_exception e, output: @connection
else
after_eval.call @block_source if after_eval
end
end
else
buffer.puts line
end
end
rescue IOError, Errno::ECONNRESET, Errno::EPIPE => e
@logger.warn('REPL') { 'lost connection' }
@logger.warn('REPL') { e.full_message(highlight: @highlight_exception, order: :top) }
ensure
@logger.debug('REPL') { "closing connection (running #{@run})" }
@connection.close
end
end
end
rescue Errno::ECONNRESET, Errno::EPIPE => e
@logger.warn('REPL') { 'connection failure while getting server port; will retry...' }
@logger.warn('REPL') { e.full_message(highlight: @highlight_exception, order: :top) }
retry
end
end
end
|