fxri 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,165 +1,165 @@
1
- # Copyright (c) 2005 Martin Ankerl
2
- class Search_Engine
3
- def initialize(gui, data)
4
- @gui = gui
5
- @data = data
6
- @search_thread = nil
7
- end
8
-
9
- # Executed whenever a search criteria changes to update the packet list.
10
- def on_search
11
- # restart current search
12
- @end_time = Time.now + $cfg.search_delay
13
- @restart_search = true
14
- @gui.search_label.enabled = false
15
- return if @search_thread && @search_thread.status
16
-
17
- @search_thread = Thread.new(@search_thread) do
18
- begin
19
- @gui.search_label.enabled = false
20
- # wait untill deadline
21
- while (t = (@end_time - Time.now)) > 0
22
- sleep(t)
23
- end
24
-
25
- @data.gui_mutex.synchronize do
26
- # the thread has to use the gui mutex inside
27
- @restart_search = false
28
-
29
- match_data = get_match_data
30
-
31
- # remove all items
32
- @gui.packet_list.dirty_clear
33
-
34
- # add all items that match the search criteria
35
- status_text_deadline = Time.now + $cfg.status_line_update_interval
36
- @data.items.each do |item|
37
- #item.parent = @gui.packet_list if match?(item, match_data)
38
- if match?(item, match_data)
39
- item.show
40
- now = Time.now
41
- if now > status_text_deadline
42
- update_search_status_text
43
- status_text_deadline = now + $cfg.status_line_update_interval
44
- end
45
- end
46
- break if @restart_search
47
- end
48
- update_search_status_text
49
-
50
- if (@gui.packet_list.numItems > 0)
51
- @gui.packet_list.setCurrentItem(0)
52
- @gui.packet_list.selectItem(0)
53
- @gui.main.show_info(@gui.packet_list.getItem(0).packet_item.data)
54
- end
55
- @gui.search_label.enabled = true
56
-
57
- end # synchronize
58
- end while @restart_search# || match_data != @gui.search_field.text.downcase.split
59
- end #thread.new
60
- end
61
-
62
- def get_match_data
63
- str_to_match_data(@gui.search_field.text)
64
- end
65
-
66
- # Converts a string into a match_data representation.
67
- def str_to_match_data(str, index=0)
68
- words = [ ]
69
- exclude = [ ]
70
- is_exclude = false
71
-
72
- while str[index]
73
- case str[index]
74
- when ?", ?'
75
- word, index = get_word(str, index+1, str[index])
76
- unless word.empty?
77
- if is_exclude
78
- exclude.push word
79
- is_exclude = false
80
- else
81
- words.push word
82
- end
83
- end
84
-
85
- when 32 # space
86
- is_exclude = false
87
-
88
- =begin
89
- when ?>
90
- min, index = get_word(str, index+1)
91
- min = @gui.logic.size_to_nr(min)
92
-
93
- when ?<
94
- max, index = get_word(str, index+1)
95
- max = @gui.logic.size_to_nr(max)
96
- =end
97
- when ?-
98
- is_exclude = true
99
-
100
- else
101
- word, index = get_word(str, index)
102
- if is_exclude
103
- exclude.push word
104
- is_exclude = false
105
- else
106
- words.push word
107
- end
108
- end
109
-
110
- index += 1
111
- end
112
-
113
- # check if word has upcase letters
114
- words.collect! do |w|
115
- [w, /[A-Z]/.match(w)!=nil]
116
- end
117
- exclude.collect! do |w|
118
- [w, /[A-Z]/.match(w)!=nil]
119
- end
120
- [words, exclude]
121
- end
122
-
123
- def get_word(str, index, delim=32) # 32==space
124
- word = ""
125
- c = str[index]
126
- while (c && c != delim)
127
- word += c.chr
128
- index += 1
129
- c = str[index]
130
- end
131
- [word, index]
132
- end
133
-
134
- # Update the text for the number of displayed packs.
135
- def update_search_status_text
136
- @gui.search_label.text = sprintf($cfg.text.search, @gui.packet_list.numItems, @data.items.size)
137
- end
138
-
139
- # Find out if item is matched by current search criteria.
140
- def match?(item, match_data)
141
- words, exclude, min, max = match_data
142
-
143
- # check text that has to be there
144
- searchable, sortable_downcase, sortable_normal = item.sortable(0)
145
- words.each do |match_str, is_sensitive|
146
- if is_sensitive
147
- return false unless sortable_normal.include?(match_str)
148
- else
149
- return false unless sortable_downcase.include?(match_str)
150
- end
151
- end
152
-
153
- # check text not allowed to be there
154
- exclude.each do |match_str, is_sensitive|
155
- if is_sensitive
156
- return false if sortable_normal.include?(match_str)
157
- else
158
- return false if sortable_downcase.include?(match_str)
159
- end
160
- end
161
-
162
- # each check ok
163
- true
164
- end
165
- end
1
+ # Copyright (c) 2005 Martin Ankerl
2
+ class Search_Engine
3
+ def initialize(gui, data)
4
+ @gui = gui
5
+ @data = data
6
+ @search_thread = nil
7
+ end
8
+
9
+ # Executed whenever a search criteria changes to update the packet list.
10
+ def on_search
11
+ # restart current search
12
+ @end_time = Time.now + $cfg.search_delay
13
+ @restart_search = true
14
+ @gui.search_label.enabled = false
15
+ return if @search_thread && @search_thread.status
16
+
17
+ @search_thread = Thread.new(@search_thread) do
18
+ begin
19
+ @gui.search_label.enabled = false
20
+ # wait untill deadline
21
+ while (t = (@end_time - Time.now)) > 0
22
+ sleep(t)
23
+ end
24
+
25
+ @data.gui_mutex.synchronize do
26
+ # the thread has to use the gui mutex inside
27
+ @restart_search = false
28
+
29
+ match_data = get_match_data
30
+
31
+ # remove all items
32
+ @gui.packet_list.dirty_clear
33
+
34
+ # add all items that match the search criteria
35
+ status_text_deadline = Time.now + $cfg.status_line_update_interval
36
+ @data.items.each do |item|
37
+ #item.parent = @gui.packet_list if match?(item, match_data)
38
+ if match?(item, match_data)
39
+ item.show
40
+ now = Time.now
41
+ if now > status_text_deadline
42
+ update_search_status_text
43
+ status_text_deadline = now + $cfg.status_line_update_interval
44
+ end
45
+ end
46
+ break if @restart_search
47
+ end
48
+ update_search_status_text
49
+
50
+ if (@gui.packet_list.numItems > 0)
51
+ @gui.packet_list.setCurrentItem(0)
52
+ @gui.packet_list.selectItem(0)
53
+ @gui.main.show_info(@gui.packet_list.getItem(0).packet_item.data)
54
+ end
55
+ @gui.search_label.enabled = true
56
+
57
+ end # synchronize
58
+ end while @restart_search# || match_data != @gui.search_field.text.downcase.split
59
+ end #thread.new
60
+ end
61
+
62
+ def get_match_data
63
+ str_to_match_data(@gui.search_field.text)
64
+ end
65
+
66
+ # Converts a string into a match_data representation.
67
+ def str_to_match_data(str, index=0)
68
+ words = [ ]
69
+ exclude = [ ]
70
+ is_exclude = false
71
+
72
+ while str[index]
73
+ case str[index]
74
+ when ?", ?'
75
+ word, index = get_word(str, index+1, str[index])
76
+ unless word.empty?
77
+ if is_exclude
78
+ exclude.push word
79
+ is_exclude = false
80
+ else
81
+ words.push word
82
+ end
83
+ end
84
+
85
+ when 32 # space
86
+ is_exclude = false
87
+
88
+ =begin
89
+ when ?>
90
+ min, index = get_word(str, index+1)
91
+ min = @gui.logic.size_to_nr(min)
92
+
93
+ when ?<
94
+ max, index = get_word(str, index+1)
95
+ max = @gui.logic.size_to_nr(max)
96
+ =end
97
+ when ?-
98
+ is_exclude = true
99
+
100
+ else
101
+ word, index = get_word(str, index)
102
+ if is_exclude
103
+ exclude.push word
104
+ is_exclude = false
105
+ else
106
+ words.push word
107
+ end
108
+ end
109
+
110
+ index += 1
111
+ end
112
+
113
+ # check if word has upcase letters
114
+ words.collect! do |w|
115
+ [w, /[A-Z]/.match(w)!=nil]
116
+ end
117
+ exclude.collect! do |w|
118
+ [w, /[A-Z]/.match(w)!=nil]
119
+ end
120
+ [words, exclude]
121
+ end
122
+
123
+ def get_word(str, index, delim=32) # 32==space
124
+ word = ""
125
+ c = str[index]
126
+ while (c && c != delim)
127
+ word += c.chr
128
+ index += 1
129
+ c = str[index]
130
+ end
131
+ [word, index]
132
+ end
133
+
134
+ # Update the text for the number of displayed packs.
135
+ def update_search_status_text
136
+ @gui.search_label.text = sprintf($cfg.text.search, @gui.packet_list.numItems, @data.items.size)
137
+ end
138
+
139
+ # Find out if item is matched by current search criteria.
140
+ def match?(item, match_data)
141
+ words, exclude, min, max = match_data
142
+
143
+ # check text that has to be there
144
+ searchable, sortable_downcase, sortable_normal = item.sortable(0)
145
+ words.each do |match_str, is_sensitive|
146
+ if is_sensitive
147
+ return false unless sortable_normal.include?(match_str)
148
+ else
149
+ return false unless sortable_downcase.include?(match_str)
150
+ end
151
+ end
152
+
153
+ # check text not allowed to be there
154
+ exclude.each do |match_str, is_sensitive|
155
+ if is_sensitive
156
+ return false if sortable_normal.include?(match_str)
157
+ else
158
+ return false if sortable_downcase.include?(match_str)
159
+ end
160
+ end
161
+
162
+ # each check ok
163
+ true
164
+ end
165
+ end
@@ -1,400 +1,401 @@
1
- #! /usr/bin/env ruby
2
-
3
- # TODO
4
- # - handle user input redirection
5
- # - readline
6
-
7
- # Credits:
8
- # - Initial linux version: Gilles Filippini
9
- # - Initial windows port : Marco Frailis
10
- # - Currently maintained and developed by
11
- # Martin DeMello <martindemello@gmail.com>
12
-
13
- require "fox16"
14
- require "irb"
15
- require "singleton"
16
- require "English"
17
-
18
- include Fox
19
-
20
- STDOUT.sync = true
21
-
22
- class FXIRBInputMethod < IRB::StdioInputMethod
23
-
24
- attr_accessor :print_prompt, :gets_mode
25
-
26
- def initialize
27
- super
28
- @history = 1
29
- @begin = nil
30
- @print_prompt = true
31
- @end = nil
32
- @continued_from = nil
33
- @gets_mode = false
34
- end
35
-
36
- def gets
37
- if @gets_mode
38
- return FXIrb.instance.get_line
39
- end
40
-
41
- if (a = @prompt.match(/(\d+)[>*]/))
42
- level = a[1].to_i
43
- else
44
- level = 0
45
- end
46
-
47
- if level > 0
48
- @continued_from ||= @line_no
49
- elsif @continued_from
50
- merge_last(@line_no-@continued_from+1)
51
- @continued_from = nil
52
- end
53
-
54
- if @print_prompt
55
- print @prompt
56
-
57
- #indentation
58
- print " "*level
59
- end
60
-
61
- str = FXIrb.instance.get_line
62
-
63
- @line_no += 1
64
- @history = @line_no + 1
65
- @line[@line_no] = str
66
-
67
- str
68
- end
69
-
70
- # merge a block spanning several lines into one \n-separated line
71
- def merge_last(i)
72
- return unless i > 1
73
- range = -i..-1
74
- @line[range] = @line[range].map {|l| l.chomp}.join("\n")
75
- @line_no -= (i-1)
76
- @history -= (i-1)
77
- end
78
-
79
- def prevCmd
80
- return "" if @gets_mode
81
-
82
- if @line_no > 0
83
- @history -= 1 unless @history <= 1
84
- return line(@history)
85
- end
86
- return ""
87
- end
88
-
89
- def nextCmd
90
- return "" if @gets_mode
91
-
92
- if (@line_no > 0) && (@history < @line_no)
93
- @history += 1
94
- return line(@history)
95
- end
96
- return ""
97
- end
98
-
99
- end
100
-
101
- module IRB
102
-
103
- def IRB.start_in_fxirb(im)
104
- if RUBY_VERSION < "1.7.3"
105
- IRB.initialize(nil)
106
- IRB.parse_opts
107
- IRB.load_modules
108
- else
109
- IRB.setup(nil)
110
- end
111
-
112
- irb = Irb.new(nil, im)
113
-
114
- @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
115
- @CONF[:MAIN_CONTEXT] = irb.context
116
- trap("SIGINT") do
117
- irb.signal_handle
118
- end
119
-
120
- class << irb.context.workspace.main
121
- def gets
122
- inp = IRB.conf[:MAIN_CONTEXT].io
123
- inp.gets_mode = true
124
- retval = IRB.conf[:MAIN_CONTEXT].io.gets
125
- inp.gets_mode = false
126
- retval
127
- end
128
- end
129
-
130
- catch(:IRB_EXIT) do
131
- irb.eval_input
132
- end
133
- print "\n"
134
-
135
- end
136
-
137
- end
138
-
139
-
140
- class FXIrb < FXText
141
- include Singleton
142
- include Responder
143
-
144
- attr_reader :input
145
-
146
- def FXIrb.init(p, tgt, sel, opts)
147
- unless @__instance__
148
- Thread.critical = true
149
- begin
150
- @__instance__ ||= new(p, tgt, sel, opts)
151
- ensure
152
- Thread.critical = false
153
- end
154
- end
155
- return @__instance__
156
- end
157
-
158
- def initialize(p, tgt, sel, opts)
159
- FXMAPFUNC(SEL_KEYRELEASE, 0, "onKeyRelease")
160
- FXMAPFUNC(SEL_KEYPRESS, 0, "onKeyPress")
161
- FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,"onLeftBtnPress")
162
- FXMAPFUNC(SEL_MIDDLEBUTTONPRESS,0,"onMiddleBtnPress")
163
- FXMAPFUNC(SEL_LEFTBUTTONRELEASE,0,"onLeftBtnRelease")
164
-
165
- super
166
- setFont(FXFont.new(FXApp.instance, "lucida console", 9))
167
- @anchor = 0
168
- end
169
-
170
- def create
171
- super
172
- setFocus
173
- # IRB initialization
174
- @inputAdded = 0
175
- @input = IO.pipe
176
- $DEFAULT_OUTPUT = self
177
-
178
- @im = FXIRBInputMethod.new
179
- @irb = Thread.new {
180
- IRB.start_in_fxirb(@im)
181
- self.crash
182
- }
183
-
184
-
185
- @multiline = false
186
-
187
- @exit_proc = lambda {exit}
188
- end
189
-
190
- def on_exit(&block)
191
- @exit_proc = block
192
- end
193
-
194
- def crash
195
- instance_eval(&@exit_proc)
196
- end
197
-
198
- def onKeyRelease(sender, sel, event)
199
- case event.code
200
- when Fox::KEY_Return, Fox::KEY_KP_Enter
201
- newLineEntered
202
- end
203
- return 1
204
- end
205
-
206
- def onKeyPress(sender,sel,event)
207
- case event.code
208
- when Fox::KEY_Return, Fox::KEY_KP_Enter
209
- setCursorPos(getLength)
210
- super
211
- when Fox::KEY_Up,Fox::KEY_KP_Up
212
- str = extractText(@anchor, getCursorPos-@anchor)
213
- if str =~ /\n/
214
- @multiline = true
215
- super
216
- setCursorPos(@anchor+1) if getCursorPos < @anchor
217
- else
218
- history(:prev) unless @multiline
219
- end
220
- when Fox::KEY_Down,Fox::KEY_KP_Down
221
- str = extractText(getCursorPos, getLength - getCursorPos)
222
- if str =~ /\n/
223
- @multiline = true
224
- super
225
- else
226
- history(:next) unless @multiline
227
- end
228
- when Fox::KEY_Left,Fox::KEY_KP_Left
229
- if getCursorPos > @anchor
230
- super
231
- end
232
- when Fox::KEY_Delete,Fox::KEY_KP_Delete,Fox::KEY_BackSpace
233
- if getCursorPos > @anchor
234
- super
235
- end
236
- when Fox::KEY_Home, Fox::KEY_KP_Home
237
- setCursorPos(@anchor)
238
- when Fox::KEY_End, Fox::KEY_KP_End
239
- setCursorPos(getLength)
240
- when Fox::KEY_Page_Up, Fox::KEY_KP_Page_Up
241
- history(:prev)
242
- when Fox::KEY_Page_Down, Fox::KEY_KP_Page_Down
243
- history(:next)
244
- when Fox::KEY_bracketright
245
- #auto-dedent if the } or ] is on a line by itself
246
- if (emptyline? or (getline == "en")) and indented?
247
- dedent
248
- end
249
- super
250
- when Fox::KEY_u
251
- if (event.state & CONTROLMASK) != 0
252
- str = extractText(getCursorPos, getLength - getCursorPos)
253
- rmline
254
- appendText(str)
255
- setCursorPos(@anchor)
256
- end
257
- super
258
- when Fox::KEY_k
259
- if (event.state & CONTROLMASK) != 0
260
- str = extractText(@anchor, getCursorPos-@anchor)
261
- rmline
262
- appendText(str)
263
- setCursorPos(getLength)
264
- end
265
- super
266
- when Fox::KEY_d
267
- if (event.state & CONTROLMASK) != 0
268
- #Ctrl - D
269
- rmline
270
- appendText("exit")
271
- newLineEntered
272
- else
273
- # test for 'end' so we can dedent
274
- if (getline == "en") and indented?
275
- dedent
276
- end
277
- end
278
- super
279
- else
280
- super
281
- end
282
- end
283
-
284
- def dedent
285
- str = getline
286
- @anchor -= 2
287
- rmline
288
- appendText(str)
289
- setCursorPos(getLength)
290
- end
291
-
292
- def history(dir)
293
- str = (dir == :prev) ? @im.prevCmd.chomp : @im.nextCmd.chomp
294
- if str != ""
295
- removeText(@anchor, getLength-@anchor)
296
- write(str)
297
- end
298
- end
299
-
300
- def getline
301
- extractText(@anchor, getLength-@anchor)
302
- end
303
-
304
- def rmline
305
- str = getline
306
- removeText(@anchor, getLength-@anchor)
307
- str
308
- end
309
-
310
- def emptyline?
311
- getline == ""
312
- end
313
-
314
- def indented?
315
- extractText(@anchor-2, 2) == " "
316
- end
317
-
318
- def onLeftBtnPress(sender,sel,event)
319
- @store_anchor = @anchor
320
- setFocus
321
- super
322
- end
323
-
324
- def onLeftBtnRelease(sender,sel,event)
325
- super
326
- @anchor = @store_anchor
327
- setCursorPos(@anchor)
328
- setCursorPos(getLength)
329
- end
330
-
331
- def onMiddleBtnPress(sender,sel,event)
332
- pos=getPosAt(event.win_x,event.win_y)
333
- if pos >= @anchor
334
- super
335
- end
336
- end
337
-
338
- def newLineEntered
339
- if getLength-@anchor > 0
340
- processCommandLine(extractText(@anchor, getLength-@anchor))
341
- else
342
- # Probably wrong, but might work
343
- processCommandLine(extractText(@anchor, getLength))
344
- end
345
- end
346
-
347
- def processCommandLine(cmd)
348
- @multiline = false
349
- lines = cmd.split(/\n/)
350
- lines.each {|i|
351
- @input[1].puts i
352
- @inputAdded += 1
353
- }
354
- @im.print_prompt = false
355
- while (@inputAdded > 0) do
356
- @irb.run
357
- end
358
- @im.merge_last(lines.length)
359
- @im.print_prompt = true
360
- end
361
-
362
- def sendCommand(cmd)
363
- setCursorPos(getLength)
364
- makePositionVisible(getLength) unless isPosVisible(getLength)
365
- cmd += "\n"
366
- appendText(cmd)
367
- processCommandLine(cmd)
368
- end
369
-
370
- def write(obj)
371
- str = obj.to_s
372
- appendText(str)
373
- setCursorPos(getLength)
374
- makePositionVisible(getLength) unless isPosVisible(getLength)
375
- return str.length
376
- end
377
-
378
- def get_line
379
- @anchor = getLength
380
- if @inputAdded == 0
381
- Thread.stop
382
- end
383
- @inputAdded -= 1
384
- return @input[0].gets
385
- end
386
- end
387
-
388
- # Stand alone run
389
- if __FILE__ == $0
390
- application = FXApp.new("FXIrb", "ruby")
391
- application.threadsEnabled = true
392
- Thread.abort_on_exception = true
393
- application.init(ARGV)
394
- window = FXMainWindow.new(application, "FXIrb", nil, nil, DECOR_ALL, 0, 0, 580, 500)
395
- fxirb = FXIrb.init(window, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP|TEXT_SHOWACTIVE)
396
- application.create
397
- window.show(PLACEMENT_SCREEN)
398
- fxirb.on_exit {exit}
399
- application.run
400
- end
1
+ #! /usr/bin/env ruby
2
+
3
+ # TODO
4
+ # - handle user input redirection
5
+ # - readline
6
+
7
+ # Credits:
8
+ # - Initial linux version: Gilles Filippini
9
+ # - Initial windows port : Marco Frailis
10
+ # - Currently maintained and developed by
11
+ # Martin DeMello <martindemello@gmail.com>
12
+
13
+ # Not needed; fxri already does that
14
+ #require "fox16"
15
+ require "irb"
16
+ require "singleton"
17
+ require "English"
18
+
19
+ include Fox
20
+
21
+ STDOUT.sync = true
22
+
23
+ class FXIRBInputMethod < IRB::StdioInputMethod
24
+
25
+ attr_accessor :print_prompt, :gets_mode
26
+
27
+ def initialize
28
+ super
29
+ @history = 1
30
+ @begin = nil
31
+ @print_prompt = true
32
+ @end = nil
33
+ @continued_from = nil
34
+ @gets_mode = false
35
+ end
36
+
37
+ def gets
38
+ if @gets_mode
39
+ return FXIrb.instance.get_line
40
+ end
41
+
42
+ if (a = @prompt.match(/(\d+)[>*]/))
43
+ level = a[1].to_i
44
+ else
45
+ level = 0
46
+ end
47
+
48
+ if level > 0
49
+ @continued_from ||= @line_no
50
+ elsif @continued_from
51
+ merge_last(@line_no-@continued_from+1)
52
+ @continued_from = nil
53
+ end
54
+
55
+ if @print_prompt
56
+ print @prompt
57
+
58
+ #indentation
59
+ print " "*level
60
+ end
61
+
62
+ str = FXIrb.instance.get_line
63
+
64
+ @line_no += 1
65
+ @history = @line_no + 1
66
+ @line[@line_no] = str
67
+
68
+ str
69
+ end
70
+
71
+ # merge a block spanning several lines into one \n-separated line
72
+ def merge_last(i)
73
+ return unless i > 1
74
+ range = -i..-1
75
+ @line[range] = @line[range].map {|l| l.chomp}.join("\n")
76
+ @line_no -= (i-1)
77
+ @history -= (i-1)
78
+ end
79
+
80
+ def prevCmd
81
+ return "" if @gets_mode
82
+
83
+ if @line_no > 0
84
+ @history -= 1 unless @history <= 1
85
+ return line(@history)
86
+ end
87
+ return ""
88
+ end
89
+
90
+ def nextCmd
91
+ return "" if @gets_mode
92
+
93
+ if (@line_no > 0) && (@history < @line_no)
94
+ @history += 1
95
+ return line(@history)
96
+ end
97
+ return ""
98
+ end
99
+
100
+ end
101
+
102
+ module IRB
103
+
104
+ def IRB.start_in_fxirb(im)
105
+ if RUBY_VERSION < "1.7.3"
106
+ IRB.initialize(nil)
107
+ IRB.parse_opts
108
+ IRB.load_modules
109
+ else
110
+ IRB.setup(nil)
111
+ end
112
+
113
+ irb = Irb.new(nil, im)
114
+
115
+ @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
116
+ @CONF[:MAIN_CONTEXT] = irb.context
117
+ trap("SIGINT") do
118
+ irb.signal_handle
119
+ end
120
+
121
+ class << irb.context.workspace.main
122
+ def gets
123
+ inp = IRB.conf[:MAIN_CONTEXT].io
124
+ inp.gets_mode = true
125
+ retval = IRB.conf[:MAIN_CONTEXT].io.gets
126
+ inp.gets_mode = false
127
+ retval
128
+ end
129
+ end
130
+
131
+ catch(:IRB_EXIT) do
132
+ irb.eval_input
133
+ end
134
+ print "\n"
135
+
136
+ end
137
+
138
+ end
139
+
140
+
141
+ class FXIrb < FXText
142
+ include Singleton
143
+ include Responder
144
+
145
+ attr_reader :input
146
+
147
+ def FXIrb.init(p, tgt, sel, opts)
148
+ unless @__instance__
149
+ Thread.critical = true
150
+ begin
151
+ @__instance__ ||= new(p, tgt, sel, opts)
152
+ ensure
153
+ Thread.critical = false
154
+ end
155
+ end
156
+ return @__instance__
157
+ end
158
+
159
+ def initialize(p, tgt, sel, opts)
160
+ FXMAPFUNC(SEL_KEYRELEASE, 0, "onKeyRelease")
161
+ FXMAPFUNC(SEL_KEYPRESS, 0, "onKeyPress")
162
+ FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,"onLeftBtnPress")
163
+ FXMAPFUNC(SEL_MIDDLEBUTTONPRESS,0,"onMiddleBtnPress")
164
+ FXMAPFUNC(SEL_LEFTBUTTONRELEASE,0,"onLeftBtnRelease")
165
+
166
+ super
167
+ setFont(FXFont.new(FXApp.instance, "lucida console", 9))
168
+ @anchor = 0
169
+ end
170
+
171
+ def create
172
+ super
173
+ setFocus
174
+ # IRB initialization
175
+ @inputAdded = 0
176
+ @input = IO.pipe
177
+ $DEFAULT_OUTPUT = self
178
+
179
+ @im = FXIRBInputMethod.new
180
+ @irb = Thread.new {
181
+ IRB.start_in_fxirb(@im)
182
+ self.crash
183
+ }
184
+
185
+
186
+ @multiline = false
187
+
188
+ @exit_proc = lambda {exit}
189
+ end
190
+
191
+ def on_exit(&block)
192
+ @exit_proc = block
193
+ end
194
+
195
+ def crash
196
+ instance_eval(&@exit_proc)
197
+ end
198
+
199
+ def onKeyRelease(sender, sel, event)
200
+ case event.code
201
+ when Fox::KEY_Return, Fox::KEY_KP_Enter
202
+ newLineEntered
203
+ end
204
+ return 1
205
+ end
206
+
207
+ def onKeyPress(sender,sel,event)
208
+ case event.code
209
+ when Fox::KEY_Return, Fox::KEY_KP_Enter
210
+ setCursorPos(getLength)
211
+ super
212
+ when Fox::KEY_Up,Fox::KEY_KP_Up
213
+ str = extractText(@anchor, getCursorPos-@anchor)
214
+ if str =~ /\n/
215
+ @multiline = true
216
+ super
217
+ setCursorPos(@anchor+1) if getCursorPos < @anchor
218
+ else
219
+ history(:prev) unless @multiline
220
+ end
221
+ when Fox::KEY_Down,Fox::KEY_KP_Down
222
+ str = extractText(getCursorPos, getLength - getCursorPos)
223
+ if str =~ /\n/
224
+ @multiline = true
225
+ super
226
+ else
227
+ history(:next) unless @multiline
228
+ end
229
+ when Fox::KEY_Left,Fox::KEY_KP_Left
230
+ if getCursorPos > @anchor
231
+ super
232
+ end
233
+ when Fox::KEY_Delete,Fox::KEY_KP_Delete,Fox::KEY_BackSpace
234
+ if getCursorPos > @anchor
235
+ super
236
+ end
237
+ when Fox::KEY_Home, Fox::KEY_KP_Home
238
+ setCursorPos(@anchor)
239
+ when Fox::KEY_End, Fox::KEY_KP_End
240
+ setCursorPos(getLength)
241
+ when Fox::KEY_Page_Up, Fox::KEY_KP_Page_Up
242
+ history(:prev)
243
+ when Fox::KEY_Page_Down, Fox::KEY_KP_Page_Down
244
+ history(:next)
245
+ when Fox::KEY_bracketright
246
+ #auto-dedent if the } or ] is on a line by itself
247
+ if (emptyline? or (getline == "en")) and indented?
248
+ dedent
249
+ end
250
+ super
251
+ when Fox::KEY_u
252
+ if (event.state & CONTROLMASK) != 0
253
+ str = extractText(getCursorPos, getLength - getCursorPos)
254
+ rmline
255
+ appendText(str)
256
+ setCursorPos(@anchor)
257
+ end
258
+ super
259
+ when Fox::KEY_k
260
+ if (event.state & CONTROLMASK) != 0
261
+ str = extractText(@anchor, getCursorPos-@anchor)
262
+ rmline
263
+ appendText(str)
264
+ setCursorPos(getLength)
265
+ end
266
+ super
267
+ when Fox::KEY_d
268
+ if (event.state & CONTROLMASK) != 0
269
+ #Ctrl - D
270
+ rmline
271
+ appendText("exit")
272
+ newLineEntered
273
+ else
274
+ # test for 'end' so we can dedent
275
+ if (getline == "en") and indented?
276
+ dedent
277
+ end
278
+ end
279
+ super
280
+ else
281
+ super
282
+ end
283
+ end
284
+
285
+ def dedent
286
+ str = getline
287
+ @anchor -= 2
288
+ rmline
289
+ appendText(str)
290
+ setCursorPos(getLength)
291
+ end
292
+
293
+ def history(dir)
294
+ str = (dir == :prev) ? @im.prevCmd.chomp : @im.nextCmd.chomp
295
+ if str != ""
296
+ removeText(@anchor, getLength-@anchor)
297
+ write(str)
298
+ end
299
+ end
300
+
301
+ def getline
302
+ extractText(@anchor, getLength-@anchor)
303
+ end
304
+
305
+ def rmline
306
+ str = getline
307
+ removeText(@anchor, getLength-@anchor)
308
+ str
309
+ end
310
+
311
+ def emptyline?
312
+ getline == ""
313
+ end
314
+
315
+ def indented?
316
+ extractText(@anchor-2, 2) == " "
317
+ end
318
+
319
+ def onLeftBtnPress(sender,sel,event)
320
+ @store_anchor = @anchor
321
+ setFocus
322
+ super
323
+ end
324
+
325
+ def onLeftBtnRelease(sender,sel,event)
326
+ super
327
+ @anchor = @store_anchor
328
+ setCursorPos(@anchor)
329
+ setCursorPos(getLength)
330
+ end
331
+
332
+ def onMiddleBtnPress(sender,sel,event)
333
+ pos=getPosAt(event.win_x,event.win_y)
334
+ if pos >= @anchor
335
+ super
336
+ end
337
+ end
338
+
339
+ def newLineEntered
340
+ if getLength-@anchor > 0
341
+ processCommandLine(extractText(@anchor, getLength-@anchor))
342
+ else
343
+ # Probably wrong, but might work
344
+ processCommandLine(extractText(@anchor, getLength))
345
+ end
346
+ end
347
+
348
+ def processCommandLine(cmd)
349
+ @multiline = false
350
+ lines = cmd.split(/\n/)
351
+ lines.each {|i|
352
+ @input[1].puts i
353
+ @inputAdded += 1
354
+ }
355
+ @im.print_prompt = false
356
+ while (@inputAdded > 0) do
357
+ @irb.run
358
+ end
359
+ @im.merge_last(lines.length)
360
+ @im.print_prompt = true
361
+ end
362
+
363
+ def sendCommand(cmd)
364
+ setCursorPos(getLength)
365
+ makePositionVisible(getLength) unless isPosVisible(getLength)
366
+ cmd += "\n"
367
+ appendText(cmd)
368
+ processCommandLine(cmd)
369
+ end
370
+
371
+ def write(obj)
372
+ str = obj.to_s
373
+ appendText(str)
374
+ setCursorPos(getLength)
375
+ makePositionVisible(getLength) unless isPosVisible(getLength)
376
+ return str.length
377
+ end
378
+
379
+ def get_line
380
+ @anchor = getLength
381
+ if @inputAdded == 0
382
+ Thread.stop
383
+ end
384
+ @inputAdded -= 1
385
+ return @input[0].gets
386
+ end
387
+ end
388
+
389
+ # Stand alone run
390
+ if __FILE__ == $0
391
+ application = FXApp.new("FXIrb", "ruby")
392
+ application.threadsEnabled = true
393
+ Thread.abort_on_exception = true
394
+ application.init(ARGV)
395
+ window = FXMainWindow.new(application, "FXIrb", nil, nil, DECOR_ALL, 0, 0, 580, 500)
396
+ fxirb = FXIrb.init(window, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP|TEXT_SHOWACTIVE)
397
+ application.create
398
+ window.show(PLACEMENT_SCREEN)
399
+ fxirb.on_exit {exit}
400
+ application.run
401
+ end