1#!/usr/bin/env ruby
2#
3#  irbtkw.rb : IRB console with Ruby/Tk
4#
5#                                 by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
6#
7release = '2008/03/08'
8
9require 'tk'
10begin
11  require 'tktextio'
12rescue LoadError
13  require File.join(File.dirname(File.expand_path(__FILE__)), 'tktextio.rb')
14end
15
16require 'irb'
17
18if TkCore::WITH_ENCODING
19else
20  # $KCODE setup
21  case Tk.encoding
22  when 'shiftjis', 'cp932'
23    $KCODE='SJIS'
24  when 'euc-jp'
25    $KCODE='EUC'
26  when 'utf-8', 'unicode'
27    $KCODE='UTF8'
28  else
29    # unknown
30  end
31end
32
33# console setup
34top = TkToplevel.new(:title=>'IRB console')
35top.protocol(:WM_DELETE_WINDOW){ Tk.exit }
36
37case (Tk.windowingsystem)
38when 'win32'
39  fnt = ['MS Gothic', '-12']
40else
41  fnt = ['courier', '-12']
42end
43
44console = TkTextIO.new(top, :mode=>:console,
45                       :width=>80).pack(:side=>:left,
46                                        :expand=>true, :fill=>:both)
47console.yscrollbar(TkScrollbar.new(top, :width=>10).pack(:before=>console,
48                                                         :side=>:right,
49                                                         :expand=>false,
50                                                         :fill=>:y))
51
52# save original I/O
53out = $stdout
54err = $stderr
55
56irb_thread = nil
57ev_loop = Thread.new{
58  begin
59    Tk.mainloop
60  ensure
61    $stdout = out
62    $stderr = err
63    irb_thread.kill if irb_thread
64  end
65}
66
67# window position control
68root = Tk.root
69
70r_x = root.winfo_rootx
71r_y = root.winfo_rooty
72r_w = root.winfo_width
73
74t_x = top.winfo_rootx
75t_y = top.winfo_rooty
76t_w = top.winfo_width
77
78delta = 10
79
80ratio = 0.8
81s_w = (ratio * root.winfo_screenwidth).to_i
82
83if r_x < t_x
84  r_x, t_x = t_x, r_x
85end
86if t_x + t_w + r_w + delta < s_w
87  r_x = t_x + t_w + delta
88elsif t_w + r_w + delta < s_w
89  r_x = s_w - r_w
90  t_x = r_x - t_w
91else
92  r_x = s_w - r_w
93  t_x = 0
94end
95
96root.geometry("+#{r_x}+#{r_y}")
97top.geometry("+#{t_x}+#{t_y}")
98
99root.raise
100console.focus
101
102# I/O setup
103$stdin  = console
104$stdout = console
105$stderr = console
106
107# dummy for rubyw.exe on Windows
108def STDIN.tty?
109  true
110end
111
112# IRB setup
113IRB.init_config(nil)
114IRB.conf[:USE_READLINE] = false
115IRB.init_error
116irb = IRB::Irb.new
117IRB.conf[:MAIN_CONTEXT] = irb.context
118
119class IRB::StdioInputMethod
120  def gets
121    prompt = "\n" << @prompt
122    $stdin.instance_eval{
123      flush
124      @prompt = prompt
125      _set_console_line
126      @prompt = nil
127      _see_pos
128    }
129
130    @line[@line_no += 1] = $stdin.gets
131  end
132end
133
134# IRB start
135$stdout.print("*** IRB console on Ruby/Tk (#{release})  ")
136irb_thread = Thread.new{
137  catch(:IRB_EXIT){
138    loop {
139      begin
140        irb.eval_input
141      rescue Exception
142      end
143    }
144  }
145}
146
147console.bind('Control-c'){
148  console.insert('end', "^C\n")
149  irb_thread.raise RubyLex::TerminateLineInput
150}
151
152irb_thread.join
153
154# exit
155ev_loop.kill
156Tk.exit
157