tmm1 (owner)

Forks

Revisions

  • 5774c8 tmm1 Sat Jul 11 18:17:48 -0700 2009
gist: 145471 Download_button fork
public
Description:
networked irb server/client in EM
Public Clone URL: git://gist.github.com/145471.git
Embed All Files: show embed
em-irb-console.rb #
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
127
128
129
require 'rubygems'
require 'eventmachine'
 
module Console
  PROMPT = "\n>> ".freeze
 
  def post_init
    send_data PROMPT
    send_data "\0"
  end
 
  def receive_data data
    return close_connection if data =~ /exit|quit/
 
    begin
      @ret, @out, $stdout = :exception, $stdout, StringIO.new
      @ret = eval(data, scope, '(rirb)')
    rescue StandardError, ScriptError, Exception, SyntaxError
      $! = RuntimeError.new("unknown exception raised") unless $!
      print $!.class, ": ", $!, "\n"
 
      trace = []
      $!.backtrace.each do |line|
        trace << "\tfrom #{line}"
        break if line =~ /\(rirb\)/
      end
      
      puts trace
    ensure
      $stdout, @out = @out, $stdout
      @out.rewind
      @out = @out.read
    end
 
    send_data @out unless @out.empty?
    send_data "=> #{@ret.inspect}" unless @ret == :exception
    send_data "\0\n>> \0"
  end
 
  # def send_data data
  # p ['server send', data]
  # super
  # end
 
  def scope
    @scope ||= instance_eval{ binding }
  end
 
  def handle_error
    $! = RuntimeError.new("unknown exception raised") unless $!
    print $!.class, ": ", $!, "\n"
 
    trace = []
    $!.backtrace.each do |line|
      trace << "\\tfrom \#{line}"
      break if line =~ /\(rirb\)/
    end
    
    puts trace
  end
 
  def self.start port = 7331
    EM.run{
      @server ||= EM.start_server '127.0.0.1', port, self
    }
  end
 
  def self.stop
    @server.close_connection if @server
    @server = nil
  end
end
 
module RIRB
  def connection_completed
    p 'connected to console'
  end
 
  def receive_data data
    # p ['receive', data]
    (@buffer ||= BufferedTokenizer.new("\0")).extract(data).each do |d|
      process(d)
    end
  end
 
  def process data
    if data.strip == '>>'
      while l = Readline.readline('>> ')
        unless l.nil? or l.strip.empty?
          Readline::HISTORY.push(l)
          send_data l
          break
        end
      end
    else
      puts data
    end
  end
 
  def unbind
    p 'disconnected'
    EM.stop_event_loop
  end
  
  def self.connect host = 'localhost', port = 7331
    require 'readline'
    EM.run{
      trap('INT'){ exit }
      @connection.close_connection if @connection
      @connection = EM.connect host, port, self do |c|
        c.instance_eval{ @host, @port = host, port }
      end
    }
  end
  attr_reader :host, :port
end
 
if __FILE__ == $0
  EM.run{
    if ARGV[0] == 'server'
      Console.start
    elsif ARGV[0] == 'client'
      RIRB.connect
    else
      puts "#{$0} <server|client>"
      EM.stop
    end
  }
end