arcadia 0.1.2.1 → 0.1.3

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,5 +1,5 @@
1
- name=event-log
2
- active=yes
3
- require=ext/ae-event-log/ae-event-log
4
- class=EventLog
5
-
1
+ name=event-log
2
+ active=no
3
+ require=ext/ae-event-log/ae-event-log
4
+ class=EventLog
5
+
@@ -127,10 +127,10 @@ class FileH < ArcadiaExt
127
127
  if _event.context.file
128
128
  self.add2history(_event.context.file)
129
129
  add_to_tree(_event.context.file)
130
- end
130
+ end
131
131
  when EditorContract::FILE_AFTER_CLOSE
132
132
  if _event.context.file
133
- end
133
+ end
134
134
  end
135
135
  end
136
136
 
@@ -0,0 +1,6 @@
1
+ name=flag
2
+ label=Flag
3
+ frame=0.0
4
+ active=no
5
+ require=ext/ae-flag/ae-flag
6
+ class=ArcadiaFlag
@@ -0,0 +1,12 @@
1
+
2
+
3
+ class ArcadiaFlag < ArcadiaExt
4
+ def build
5
+ @tkLabel3 = TkLabel.new(self.frame){
6
+ image TkPhotoImage.new('format'=>'GIF','data' =>A_LOGO_GIF)
7
+ background "#000000"
8
+ place('x'=> 0,'y' => 0, 'relwidth' =>'1', 'relheight'=>'1')
9
+ }
10
+
11
+ end
12
+ end
@@ -1,7 +1,7 @@
1
- name=objic
2
- label=Object Inspector
3
- frame=1.0
4
- active=yes
5
- require=ext/ae-inspector/ae-inspector
6
- class=ObjiController
7
-
1
+ name=objic
2
+ label=Object Inspector
3
+ frame=1.0
4
+ active=yes
5
+ require=ext/ae-inspector/ae-inspector
6
+ class=ObjiController
7
+
@@ -1,15 +1,15 @@
1
- name=output2
2
- label=Event Log
3
- frame=1.1
4
- active=yes
5
- require=ext/ae-output/ae-output
6
- class=Output
7
- MsgContract.channel=CH1
8
-
9
-
10
- font=courier 10
11
- font.bold=courier 10 bold
12
- freebsd::font=courier 10
13
- freebsd::font.bold=courier 12 bold
14
- win::font={Courier New} 9
15
- win::font.bold={Courier New} 9 bold
1
+ name=output2
2
+ label=Event Log
3
+ frame=1.1
4
+ active=no
5
+ require=ext/ae-output/ae-output
6
+ class=Output
7
+ MsgContract.channel=CH1
8
+
9
+
10
+ font=courier 10
11
+ font.bold=courier 10 bold
12
+ freebsd::font=courier 10
13
+ freebsd::font.bold=courier 12 bold
14
+ win::font={Courier New} 9
15
+ win::font.bold={Courier New} 9 bold
@@ -1,7 +1,7 @@
1
- name=palette
2
- label=Palette
3
- frame=0.0
4
- active=yes
5
- require=ext/ae-palette/ae-palette
6
- class=Palette
7
-
1
+ name=palette
2
+ label=Palette
3
+ frame=0.0
4
+ active=yes
5
+ require=ext/ae-palette/ae-palette
6
+ class=Palette
7
+
@@ -0,0 +1,20 @@
1
+ #==============================================================
2
+ name=ruby-debug
3
+ label=Ruby Debug
4
+ frame=1.0
5
+ active=yes
6
+ require=ext/ae-ruby-debug/ae-ruby-debug
7
+ class=RubyDebug
8
+ #==============================================================
9
+ server.host=localhost
10
+ server.port=8989
11
+ server.timeout=10
12
+ font=courier 10
13
+ font.bold=courier 10 bold
14
+ color.background=#ffffff
15
+ color.foreground=#000000
16
+ freebsd::font=courier 10
17
+ freebsd::font.bold=courier 10 bold
18
+ win::font={Courier New} 8
19
+ win::font.bold={Courier New} 8 bold
20
+
@@ -0,0 +1,1329 @@
1
+ #
2
+ # ae-ruby-debug.rb - Arcadia Ruby ide
3
+ # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
+ #
5
+
6
+ class RubyDebugView
7
+ def initialize(_frame, _controller)
8
+ @frame = _frame
9
+ @controller = _controller
10
+ self.build_ui
11
+ @controller.rdc.add_listener(self)
12
+ @nodes_to_open = Array.new
13
+ #@break_hash = Hash.new
14
+ end
15
+
16
+ def build_buttons_set
17
+ _relief = 'groove'
18
+ @debug_button_box.add(
19
+ 'name'=>'debug_over',
20
+ 'background' => 'white',
21
+ 'anchor' => 'nw',
22
+ 'command'=>proc{self.debug_send(:step_over)},
23
+ 'helptext'=>'step over',
24
+ 'image'=> TkPhotoImage.new('dat' => D_NEXT_GIF),
25
+ 'relief'=> _relief
26
+ )
27
+ @debug_button_box.add(
28
+ 'name'=>'debug_into',
29
+ 'background' => 'white',
30
+ 'anchor' => 'nw',
31
+ 'command'=>proc{self.debug_send(:step_into)},
32
+ 'helptext'=>'step into',
33
+ 'image'=> TkPhotoImage.new('dat' => D_STEP_INTO_GIF),
34
+ 'relief'=>_relief
35
+ )
36
+ @debug_button_box.add(
37
+ 'name'=>'debug_out',
38
+ 'background' => 'white',
39
+ 'anchor' => 'nw',
40
+ 'helptext'=>'step out',
41
+ 'command'=>proc{self.debug_send(:step_out)},
42
+ 'image'=> TkPhotoImage.new('dat' => D_STEP_OUT_GIF),
43
+ 'relief'=>_relief
44
+ )
45
+ @debug_button_box.add(
46
+ 'name'=>'debug_resume',
47
+ 'background' => 'white',
48
+ 'anchor' => 'nw',
49
+ 'helptext'=>'resume',
50
+ 'image'=> TkPhotoImage.new('dat' => D_RESUME_GIF),
51
+ 'command'=>proc{self.debug_send(:resume)},
52
+ 'relief'=>_relief
53
+ )
54
+
55
+ @debug_button_box.add(
56
+ 'name'=>'debug_quit',
57
+ 'background' => 'white',
58
+ 'anchor' => 'nw',
59
+ 'helptext'=>'quit',
60
+ 'image'=> TkPhotoImage.new('dat' => D_QUIT_GIF),
61
+ 'command'=>proc{self.debug_send(:quit)},
62
+ 'relief'=>_relief
63
+ )
64
+
65
+ end
66
+
67
+ def build_ui
68
+ _y = 22
69
+ @debug_button_box = Tk::BWidget::ButtonBox.new(@frame){
70
+ homogeneous true
71
+ state 'disabled'
72
+ #background '#3d7956'
73
+ }.place('height'=> _y)
74
+
75
+ @debug_frame = TkFrame.new(@frame){
76
+ border 2
77
+ place(
78
+ 'y'=>_y,
79
+ 'height'=> -_y,
80
+ 'relheight'=> 1,
81
+ 'relwidth'=> 1
82
+ )
83
+ }
84
+
85
+ self.build_buttons_set
86
+
87
+ sf = AGTkOSplittedFrames.new(@debug_frame,70)
88
+
89
+ #-------------------------------------------------
90
+ build_process_panel(sf.top_frame)
91
+ #-------------------------------------------------
92
+
93
+ @enb = Tk::BWidget::NoteBook.new(sf.bottom_frame){
94
+ tabbevelsize 0
95
+ internalborderwidth 2
96
+ activeforeground 'red'
97
+ activebackground 'yellow'
98
+ #background 'black'
99
+ borderwidth 1
100
+ side $arcadia['conf']['editor.tabs.side']
101
+ font $arcadia['conf']['editor.tabs.font']
102
+ place('relwidth' => 1,'relheight' => '1')
103
+ }
104
+ _tab_var = @enb.insert('end', 'vars' ,
105
+ 'text'=> 'Variables',
106
+ 'raisecmd'=>proc{}
107
+ )
108
+ _tab_breakpoint = @enb.insert('end', 'Breakpoint' ,
109
+ 'text'=> 'Breakpoints',
110
+ 'raisecmd'=>proc{}
111
+ )
112
+ # _tab_catchpoint = @enb.insert('end', 'catchpoint' ,
113
+ # 'text'=> 'catchpoint',
114
+ # 'raisecmd'=>proc{}
115
+ # )
116
+
117
+ build_var_panel(_tab_var)
118
+ build_break_panel(_tab_breakpoint)
119
+
120
+ @stack_nodes = Array.new
121
+ @enb.raise('vars')
122
+
123
+ end
124
+
125
+ def build_process_panel(_frame)
126
+ @tree_process = Tk::BWidget::Tree.new(_frame){
127
+ background '#FFFFFF'
128
+ relief 'flat'
129
+ showlines false
130
+ deltay 15
131
+ place('relwidth' => 1,'relheight' => '1')
132
+ }
133
+ @tree_process.textbind("Double-ButtonPress-1", proc{
134
+ _selected = @tree_process.selection_get[0]
135
+ if @tree_process.parent(_selected)=='client'
136
+ _text = @tree_process.itemcget(_selected, 'text')
137
+ pos = match_position_from_stack(_text)
138
+ if pos.length >0
139
+ EditorContract.instance.open_file(self, 'file'=>pos[0], 'line'=>pos[1])
140
+ end
141
+ end
142
+ })
143
+
144
+ end
145
+
146
+ def start_process(_filename)
147
+ @tree_process.insert('end', 'root' ,'server', {
148
+ 'text' => "Server => #{File.basename(_filename)} at #{@controller.conf('server.host')}:#{@controller.conf('server.port')}",
149
+ 'font' => @controller.conf('font.bold')
150
+ })
151
+ @tree_process.insert('end', 'server' ,'client', {
152
+ 'font' => @controller.conf('font.bold'),
153
+ 'text' => "Client"
154
+ })
155
+ @tree_process.open_tree('server',true)
156
+ end
157
+
158
+ def tree_var_free
159
+ @tree_var.delete(@tree_var.nodes('local_var'))
160
+ @tree_var.delete(@tree_var.nodes('instance_var'))
161
+ @tree_var.delete(@tree_var.nodes('global_var'))
162
+ @tree_var.delete(@tree_var.nodes('eval')) if @tree_var.exist?('eval')
163
+ end
164
+
165
+ def tree_process_free
166
+ @tree_process.delete(@tree_process.nodes('root'))
167
+ end
168
+
169
+
170
+ def build_var_panel(_frame)
171
+ _open_proc = proc do |_arg|
172
+ inspect_node(_arg) if @nodes_to_open.include?(_arg)
173
+ end
174
+
175
+ @tree_var = Tk::BWidget::Tree.new(_frame){
176
+ background '#FFFFFF'
177
+ relief 'flat'
178
+ showlines true
179
+ linesfill '#e7de8f'
180
+ deltay 15
181
+ opencmd _open_proc
182
+ # pack('fill'=>'both', :padx=>0, :pady=>0, :expand => 'yes')
183
+ }.place('relwidth' => 1,'relheight' => '1','bordermode' => 'inside')
184
+
185
+ _scrollcommand = proc{|*args| @tree_var.yview(*args)}
186
+ _scrollbar = TkScrollbar.new(_frame){|s|
187
+ width 8
188
+ command _scrollcommand
189
+ }.pack('side'=>'right', 'fill'=>'y')
190
+ @tree_var.yscrollcommand proc{|first,last| _scrollbar.set(first,last)}
191
+
192
+ @local_on = true
193
+ @instance_on = true
194
+ @global_on = false
195
+
196
+ _i_on = TkPhotoImage.new('dat' => ON_GIF)
197
+ _i_off = TkPhotoImage.new('dat' => OFF_GIF)
198
+
199
+ _b_relief = 'groove'
200
+ @b_local_onoff = TkButton.new(@tree_var){
201
+ image _i_on
202
+ relief _b_relief
203
+ state 'disabled'
204
+ anchor 'nw'
205
+ }.bind("1",proc{
206
+ @local_on = !@local_on
207
+ if @local_on
208
+ @b_local_onoff.image(_i_on)
209
+ command_enabled(false)
210
+ Thread.new{
211
+ update_variables('local_var', @controller.rdc.variables('local_variables')) #if @tree_var.open?('local_var')
212
+ command_enabled(true)
213
+ }
214
+ else
215
+ @b_local_onoff.image(_i_off)
216
+ @tree_var.delete(@tree_var.nodes('local_var'))
217
+ end
218
+ })
219
+
220
+ @tree_var.insert('end', 'root' ,'local_var', {
221
+ #'deltax' => 0,
222
+ #'padx'=>2,
223
+ 'fill'=>'#3f941b',
224
+ 'open'=>true,
225
+ 'anchor'=>'w',
226
+ 'font' => @controller.conf('font.bold'),
227
+ 'text' => "Local variables",
228
+ 'window' => @b_local_onoff
229
+ })
230
+
231
+ @b_instance_onoff = TkButton.new(@tree_var){
232
+ image _i_on
233
+ relief _b_relief
234
+ state 'disabled'
235
+ anchor 'nw'
236
+ }.bind("1",proc{
237
+ @instance_on = !@instance_on
238
+ if @instance_on
239
+ @b_instance_onoff.image(_i_on)
240
+ command_enabled(false)
241
+ Thread.new{
242
+ update_variables('instance_var', @controller.rdc.variables('instance_variables')) #if @tree_var.open?('local_var')
243
+ command_enabled(true)
244
+ }
245
+ else
246
+ @b_instance_onoff.image(_i_off)
247
+ @tree_var.delete(@tree_var.nodes('instance_var'))
248
+ end
249
+ })
250
+ @tree_var.insert('end', 'root' ,'instance_var', {
251
+ # 'deltax' => 0,
252
+ # 'padx'=>2,
253
+ 'fill'=>'#892541',
254
+ 'open'=>true,
255
+ 'anchor'=>'w',
256
+ 'font' => @controller.conf('font.bold'),
257
+ 'text' => "Instance variables",
258
+ 'window' => @b_instance_onoff
259
+ })
260
+
261
+ @b_global_onoff = TkButton.new(@tree_var){
262
+ image _i_off
263
+ relief _b_relief
264
+ state 'disabled'
265
+ anchor 'nw'
266
+ }.bind("1",proc{
267
+ @global_on = !@global_on
268
+ if @global_on
269
+ @b_global_onoff.image(_i_on)
270
+ command_enabled(false)
271
+ Thread.new{
272
+ update_variables('global_var', @controller.rdc.variables('global_variables')) #if @tree_var.open?('local_var')
273
+ command_enabled(true)
274
+ }
275
+ else
276
+ @b_global_onoff.image(_i_off)
277
+ @tree_var.delete(@tree_var.nodes('global_var'))
278
+ end
279
+ })
280
+ @tree_var.insert('end', 'root' ,'global_var', {
281
+ 'fill'=>'#f94867',
282
+ 'open'=>true,
283
+ 'anchor'=>'w',
284
+ 'font' => @controller.conf('font.bold'),
285
+ 'text' => "Global variables",
286
+ 'window' => @b_global_onoff
287
+ })
288
+
289
+
290
+
291
+ end
292
+
293
+ def build_break_panel(_tab_breakpoint)
294
+ @tree_break = Tk::BWidget::Tree.new(_tab_breakpoint){
295
+ background '#FFFFFF'
296
+ relief 'flat'
297
+ showlines true
298
+ linesfill '#e7de8f'
299
+ deltay 15
300
+ }.place('relwidth' => 1,'relheight' => '1')
301
+ end
302
+
303
+ def file2node_name(_file)
304
+ _s = ""
305
+ _file.gsub("/",_s).gsub(".",_s).gsub(":",_s).gsub("\\",_s).gsub("-",_s)
306
+ end
307
+
308
+ def line2node_name(_parent, _line)
309
+ "#{_parent}_#{_line.to_s}"
310
+ end
311
+
312
+ def break_list_add(_file, _line)
313
+ _file_node = file2node_name(_file)
314
+ _line_node = line2node_name(_file_node, _line)
315
+ if !@tree_break.exist?(_file_node)
316
+ @tree_break.insert('end', 'root' ,_file_node, {
317
+ 'fill'=>'#8080ff',
318
+ 'open'=>true,
319
+ 'anchor'=>'w',
320
+ 'font' => @controller.conf('font.bold'),
321
+ 'text' => _file
322
+ })
323
+ end
324
+
325
+ if !@tree_break.exist?(_line_node)
326
+ @tree_break.insert('end', _file_node ,_line_node, {
327
+ 'fill'=>'#f94867',
328
+ 'open'=>true,
329
+ 'anchor'=>'w',
330
+ 'font' => @controller.conf('font.bold'),
331
+ 'text' => "line: #{_line}"
332
+ })
333
+ end
334
+ end
335
+
336
+ def break_list_del(_file, _line)
337
+ _file_node = file2node_name(_file)
338
+ _line_node = line2node_name(_file_node, _line)
339
+ if @tree_break.exist?(_line_node)
340
+ @tree_break.delete(_line_node)
341
+ _bro = @tree_break.nodes(_file_node)
342
+ if _bro && _bro.length > 0
343
+ @tree_break.delete(_file_node)
344
+ end
345
+ end
346
+ end
347
+
348
+ def break_list_select(_file, _line)
349
+ _file_node = file2node_name(_file)
350
+ _line_node = line2node_name(_file_node, _line)
351
+ @tree_break.selection_clear
352
+ if @tree_break.exist?(_line_node)
353
+ @tree_break.selection_add(_line_node)
354
+ @tree_break.see(_line_node)
355
+ end
356
+ end
357
+
358
+
359
+ def break_list_free
360
+ @tree_break.delete(@tree_break.nodes('root'))
361
+ end
362
+
363
+ def clear
364
+ tree_var_free
365
+ tree_process_free
366
+ break_list_free
367
+ end
368
+
369
+
370
+ def rdebug_client_update(_command, _result)
371
+ #MsgContract.instance.out_debug(self,"on command #{_command}")
372
+ return if !@controller.rdc.is_debugging_ready?
373
+ begin
374
+ if _command == 'quit'
375
+ msg = "Really quit debug ? (y/n)"
376
+ ans = Tk.messageBox('icon' => 'question', 'type' => 'yesno',
377
+ 'title' => '(Arcadia) Debug', 'message' => msg)
378
+ if ans == 'yes'
379
+ debug_send(:quit_yes)
380
+ clear
381
+ else
382
+ debug_send(:quit_no)
383
+ end
384
+ elsif _command == 'quit_yes'
385
+ clear
386
+ elsif _command == 'quit_no'
387
+ command_enabled(true)
388
+ elsif _command != 'where' && _command != 'quit_yes'
389
+ begin
390
+ update_position
391
+ update_variables('local_var', @controller.rdc.variables('local_variables')) if @local_on
392
+ update_variables('instance_var', @controller.rdc.variables('instance_variables')) if @instance_on
393
+ #MsgContract.instance.out_debug(self,"on command #{_command}:global_variables")
394
+ update_variables('global_var', @controller.rdc.variables('global_variables')) if @global_on
395
+ ensure
396
+ command_enabled(true) if @controller.rdc.is_debugging_ready? && (!_command.include?('quit') || _command.include?('quit_no'))
397
+ end
398
+ end
399
+ rescue Exception => e
400
+ MsgContract.instance.out_debug(self,"on command #{_command}:#{e.inspect}")
401
+ end
402
+ end
403
+
404
+ def match_position_from_stack(_line)
405
+ ret = Array.new
406
+ _target = _line.sub("-->",'').strip
407
+ matchline = _target.match(/#[0-9]*.*:([0-9]*)/)
408
+ line_no = matchline[1].to_i if !matchline.nil? && matchline.length==2
409
+ matchfile = _target.match(/#[0-9]*.(.*):[0-9]*/)
410
+ filename = matchfile[1].to_s if !matchfile.nil? && matchfile.length==2
411
+ if filename && line_no
412
+ ret << filename << line_no
413
+ end
414
+ ret
415
+ end
416
+
417
+ def update_position
418
+ stack = @controller.rdc.where
419
+ #MsgContract.instance.out_debug(self,stack)
420
+ if !stack.nil?
421
+ stack = stack.split(/\n/)
422
+ line_no = -1
423
+ if !stack[0].nil?
424
+ pos = match_position_from_stack(stack[0])
425
+ #matchline = stack[0].match(/-->.#[0-9]*.*:([0-9]*)/)
426
+ ##matchline = stack[0].match(/.*:([0-9]*)/)
427
+ #line_no = matchline[1].to_i if !matchline.nil? && matchline.length==2
428
+
429
+ #matchfile = stack[0].match(/-->.#[0-9]*.(.*):[0-9]*/)
430
+ ##matchfile = stack[0].match(/.(.*):[0-9]*/)
431
+
432
+ #filename = matchfile[1].to_s if !matchfile.nil? && matchfile.length==2
433
+ end
434
+ if pos.length > 0
435
+ #MsgContract.instance.out_debug(self,"'file'=> #{pos[0]}, 'line'=>#{pos[1]}")
436
+ _file = File.expand_path(pos[0])
437
+ DebugContract.instance.debug_step(self, 'file'=> _file, 'line'=>pos[1])
438
+ break_list_select(_file, pos[1].to_s)
439
+ end
440
+ i = 0
441
+ @tree_process.delete(@stack_nodes)
442
+ stack.each do |line|
443
+ _node = "c#{i.to_s}"
444
+ @tree_process.insert('end', 'client' ,_node, {
445
+ # 'deltax' => 0,
446
+ # 'padx'=>2,
447
+ 'font' => @controller.conf('font'),
448
+ 'text' => line,
449
+ 'helptext' => line
450
+ })
451
+ @stack_nodes << _node
452
+ i = i+1
453
+ end
454
+ end
455
+ end
456
+
457
+ def is_simple_class?(_class)
458
+ ['Numeric','Fixnum','String','FalseClass','TrueClass','NilClass'].include?(_class)
459
+ # _class == Numeric || _class.superclass == Numeric ||
460
+ # _class == String || _class.superclass == String ||
461
+ # _class == FalseClass || _class.superclass == FalseClass||
462
+ # _class == TrueClass || _class.superclass == TrueClass||
463
+ # _class == NilClass || _class.superclass == NilClass
464
+ end
465
+
466
+ def show_expression(_exp, _hash)
467
+ if !@tree_var.exist?('eval')
468
+ @tree_var.insert('end', 'root' ,'eval', {
469
+ 'fill'=>'#4aadf7',
470
+ 'open'=>true,
471
+ 'anchor'=>'w',
472
+ 'font' => @controller.conf('font.bold'),
473
+ 'text' => "Eval selection"
474
+ })
475
+ end
476
+ update_variables('eval', _hash)
477
+ end
478
+
479
+ def inspect_node(_node)
480
+ command_enabled(false)
481
+ begin
482
+ _var = var_name(_node)
483
+ _o = @controller.rdc.debug_dump(_var)
484
+ #@tree_var.delete(@tree_var.nodes(_node))
485
+ var_deep(_node, _o)
486
+ ensure
487
+ command_enabled(true)
488
+ end
489
+ end
490
+
491
+ def var_deep(_var, _hash)
492
+ # _var_cla = _hash['__CLASS__']
493
+ # _var_len = _hash['__LENGTH__']
494
+ # @tree_var.itemconfigure(_var, 'text' => "#{_var_cla}:#{_var_len}")
495
+ return nil if _hash.nil?
496
+ return _hash.to_s if _hash.class != Hash
497
+ _hash.keys.sort.each{|k|
498
+ v = _hash[k]
499
+ next if k=='__CLASS__'
500
+ _complex = v.class == Hash
501
+ if _complex
502
+ _text = var_format(k,v['__CLASS__'])
503
+ elsif (k=='__LENGTH__') && v=='0'
504
+ _text = '{...}'
505
+ elsif (k=='__LENGTH__') && v!='0'
506
+ next
507
+ else
508
+ _text = var_format(k,nil,v)
509
+ end
510
+ _node = node_name(k, _var)
511
+ if @tree_var.exist?(_node)
512
+ @tree_var.itemconfigure(_node, 'text' => _text)
513
+ else
514
+ @tree_var.insert('end', _var ,_node, {
515
+ 'font' => @controller.conf('font'),
516
+ 'text' => _text,
517
+ 'helptext' => v,
518
+ 'anchor'=>'w'
519
+ })
520
+ end
521
+ var_deep(_node,v) if _complex
522
+ }
523
+ end
524
+
525
+ def var_format(_name, _class, _value=nil)
526
+ if !_value.nil? && !_class.nil?
527
+ return "#{_name.to_s.strip} => #{_value.to_s.strip} [#{_class.to_s.strip}]"
528
+ elsif _value.nil? && !_class.nil?
529
+ return "#{_name.to_s.strip} [#{_class.to_s.strip}]"
530
+ elsif !_value.nil? && _class.nil?
531
+ return "#{_name.to_s.strip} => #{_value.to_s.strip}"
532
+ elsif _value.nil? && _class.nil?
533
+ return "#{_name.to_s.strip} => {...}"
534
+ end
535
+ end
536
+
537
+ def node_name(_node, _parent)
538
+ return "#{_parent}@@@#{_node.gsub('$','__S__').gsub('&','__E__').gsub(':','__D__').gsub('!','__A__')}"
539
+ end
540
+
541
+ def var_name(_node)
542
+ #_parent = @tree_var.parent(_node)
543
+ #return _node.sub("#{_parent}_", '')
544
+ return _node.split('@@@')[-1].gsub('__S__','$').gsub('__E__','&').gsub('__D__',':').gsub('__A__','!')
545
+ end
546
+
547
+ def command_enabled(_value)
548
+ #MsgContract.instance.out_debug(self,"command_enabled= #{_value.to_s}")
549
+
550
+ @c_on = _value
551
+ _value ? _state = 'normal':_state = 'disabled'
552
+ @debug_button_box.configure(:state=>_state)
553
+ @b_local_onoff.configure(:state=>_state)
554
+ @b_instance_onoff.configure(:state=>_state)
555
+ @b_global_onoff.configure(:state=>_state)
556
+ Tk.update
557
+ end
558
+
559
+ def update_variables(_parent_node, _var)
560
+ if _var.keys.sort == @tree_var.nodes(_parent_node).collect! {|x| var_name(x).to_s}.sort
561
+ _var.each{|k,v|
562
+ _n = node_name(k, _parent_node)
563
+ if is_simple_class?(v.value_class)
564
+ _text = var_format(k,v.value_class,v.value)
565
+ else
566
+ _text = var_format(k,v.value_class)
567
+ end
568
+ _node = @tree_var.itemconfigure(_n, 'text' => _text)
569
+ }
570
+ else
571
+ @nodes_to_open.clear
572
+ @tree_var.delete(@tree_var.nodes(_parent_node))
573
+ #@nodes[_parent_node].clear
574
+ _var.each{|k,v|
575
+ _n = node_name(k, _parent_node)
576
+ if is_simple_class?(v.value_class)
577
+ #MsgContract.instance.out_simple(self,"#{k} : simple")
578
+ _text = var_format(k,v.value_class,v.value)
579
+ _drawcross = 'auto'
580
+ else
581
+ #MsgContract.instance.out_simple(self,"#{k} : complex")
582
+ _text = var_format(k,v.value_class)
583
+ _drawcross = 'always'
584
+ @nodes_to_open << _n
585
+ end
586
+ @tree_var.insert('end', _parent_node ,_n, {
587
+ 'font' => @controller.conf('font'),
588
+ 'text' => _text,
589
+ 'helptext' => v.value,
590
+ 'drawcross' => _drawcross,
591
+ 'anchor'=>'w'
592
+ # 'deltax' => 1
593
+ })
594
+ #@nodes[_parent_node] << k
595
+ }
596
+ end
597
+ Tk.update
598
+ end
599
+
600
+ def debug_send(_command)
601
+ if @controller.rdc
602
+ begin
603
+ command_enabled(false)
604
+ #@debug_button_box.configure(:state=>'disabled')
605
+ Thread.new{@controller.rdc.send(_command)}
606
+ #@controller.rdc.send(_command)
607
+ rescue Exception => e
608
+ MsgContract.instance.out_debug(self,"---> "+e.to_s)
609
+ end
610
+ end
611
+ end
612
+ end
613
+
614
+ class RubyDebugException < Exception
615
+ end
616
+
617
+ class RubyDebugServer
618
+ include Observable
619
+ RDS_QUIET = 'RDS_QUIET'
620
+ def initialize(_caller)
621
+ if _caller.respond_to? :rdebug_server_update
622
+ ObserverCallback.new(self,_caller,:rdebug_server_update)
623
+ end
624
+ end
625
+
626
+ def start_session(_filename, _host='localhost', _remote_port='8989')
627
+ if is_windows?
628
+ commandLine = "rdebug.cmd --port #{_remote_port} -sw #{_filename}"
629
+ else
630
+ commandLine = "rdebug --host #{_host} --port #{_remote_port} -sw #{_filename}"
631
+ end
632
+ #MsgContract.instance.out_debug(self,commandLine)
633
+ begin
634
+ if is_windows?
635
+ @tid = Thread.new {
636
+ Kernel.system(commandLine)
637
+ Kernel.system('y')
638
+ notify(RDS_QUIET)
639
+ }
640
+ else
641
+ @pid = Process.fork {
642
+ Kernel.system(commandLine)
643
+ Kernel.exit!
644
+ notify(RDS_QUIET)
645
+ }
646
+ end
647
+ rescue Exception => e
648
+ MsgContract.instance.out_debug(self,"Error on start_server : #{e.class}:#{e.message}")
649
+ end
650
+ end
651
+
652
+ def kill
653
+ begin
654
+ if is_windows?
655
+ @tid.join(2)
656
+ @tid.kill!
657
+ else
658
+ Process.kill('QUIT',@pid)
659
+ end
660
+ notify(RDS_QUIET)
661
+ rescue Exception => e
662
+ MsgContract.instance.out_debug(self,"Error on start_server : #{e.class}:#{e.message}")
663
+ end
664
+ end
665
+
666
+ def is_windows?
667
+ !(RUBY_PLATFORM =~ /(win|w)32$/).nil?
668
+ #RUBY_PLATFORM.include?('win')
669
+ end
670
+
671
+ def notify(_state)
672
+ changed
673
+ notify_observers(_state)
674
+ end
675
+
676
+ end
677
+
678
+ #Ruby-debug commands
679
+
680
+ # * b[reak]
681
+ # list breakpoints
682
+ # * b[reak] [file|class:]LINE|METHOD [if expr]
683
+ # * b[reak] [class.]LINE|METHOD [if expr]
684
+ # set breakpoint to some position, optionally if expr == true
685
+ # * cat[ch]
686
+ # show catchpoint
687
+ # * cat[ch] EXCEPTION
688
+ # set catchpoint to an exception
689
+ # * disp[lay] EXPRESSION add expression into display expression list
690
+ # * undisp[lay][ nnn]
691
+ # delete one particular or all display expressions if no expression number given
692
+ # * del[ete][ nnn]
693
+ # delete some or all breakpoints (get the number using “break”)
694
+ # * c[ont]
695
+ # run until program ends or hit breakpoint
696
+ # * r[un]
697
+ # alias for cont
698
+ # * s[tep][ nnn]
699
+ # step (into methods) one line or till line nnn
700
+ # * n[ext][ nnn]
701
+ # go over one line or till line nnn
702
+ # * w[here]
703
+ # displays stack
704
+ # * f[rame]
705
+ # alias for where
706
+ # * l[ist][ (-|nn-mm)]
707
+ # list program, - list backwards, nn-mm list given lines. No arguments keeps listing
708
+ # * up[ nn]
709
+ # move to higher frame
710
+ # * down[ nn]
711
+ # move to lower frame
712
+ # * fin[ish]
713
+ # return to outer frame
714
+ # * q[uit]
715
+ # exit from debugger
716
+ # * v[ar] g[lobal]
717
+ # show global variables
718
+ # * v[ar] l[ocal]
719
+ # show local variables
720
+ # * v[ar] i[nstance] OBJECT
721
+ # show instance variables of object
722
+ # * v[ar] c[onst] OBJECT
723
+ # show constants of object
724
+ # * m[ethod] i[nstance] OBJECT
725
+ # show methods of object
726
+ # * m[ethod] CLASS|MODULE
727
+ # show instance methods of class or module
728
+ # * th[read] l[ist]
729
+ # list all threads
730
+ # * th[read] c[ur[rent]]
731
+ # show current thread
732
+ # * th[read] [sw[itch]] nnn
733
+ # switch thread context to nnn
734
+ # * th[read] stop nnn
735
+ # stop thread nnn
736
+ # * th[read] resume nnn
737
+ # resume thread nnn
738
+ # * p EXPRESSION
739
+ # evaluate expression and print its value
740
+ # * pp EXPRESSSION
741
+ # evaluate expression and print its value
742
+ # * h[elp]
743
+ # print this help
744
+ # * RETURN KEY
745
+ # redo previous command. Convenient when using list, step, next, up, down,
746
+ # * EVERYHTING ELSE
747
+ # evaluate
748
+
749
+
750
+ class RubyDebugClient
751
+ require 'socket'
752
+ require 'yaml'
753
+ include Observable
754
+ Var = Struct.new("Var",
755
+ :value,
756
+ :value_class
757
+ )
758
+
759
+ def initialize(_server='localhost', _port=8989, _timeout=0)
760
+ @session = nil
761
+ @server = _server
762
+ @port = _port
763
+ @timeout = _timeout.to_i
764
+ @busy = false
765
+ @pend = false
766
+ end
767
+
768
+ def add_listener(_caller, _method=:rdebug_client_update)
769
+ if _caller.respond_to? :rdebug_client_update
770
+ ObserverCallback.new(self,_caller,:rdebug_client_update)
771
+ end
772
+ end
773
+
774
+ def notify(_command, _result=nil)
775
+ #MsgContract.instance.out_debug(self,"notify=>#{_command}")
776
+ @busy = false
777
+ changed
778
+ notify_observers(_command, _result)
779
+ _result
780
+ end
781
+
782
+ def is_debugging_ready?
783
+ is_alive? && !is_busy?
784
+ end
785
+
786
+ def is_busy?
787
+ @busy
788
+ end
789
+
790
+ def is_alive?
791
+ !@session.nil? && !@session.closed? && !@pend
792
+ end
793
+
794
+ def socket_session
795
+ if @session.nil?
796
+ begin
797
+ #sleep(2)
798
+ @session = TCPSocket.new(@server, @port)
799
+ @pend = false
800
+ rescue Errno::ECONNREFUSED => e
801
+ sleep(1)
802
+ @t = @t -1
803
+ if @t > 0
804
+ socket_session
805
+ else
806
+ MsgContract.instance.out_debug(self,"socket_session : #{e.inspect}")
807
+ end
808
+ end
809
+ end
810
+ #MsgContract.instance.out_debug(self,"session : #{@session.inspect}")
811
+ return @session
812
+ end
813
+
814
+ def kill
815
+ begin
816
+ @session.close if is_alive?
817
+ @session = nil
818
+ rescue Exception => e
819
+ MsgContract.instance.out_debug(self,"Error on close session : #{e.class}:#{e.message}")
820
+ end
821
+ end
822
+
823
+ def start_session
824
+ begin
825
+ @t = @timeout
826
+ if socket_session
827
+ #MsgContract.instance.out_debug(self,"session : #{@session.inspect}")
828
+ notify('start', read)
829
+ read("eval require 'yaml'")
830
+ end
831
+ return @session
832
+ rescue Exception => e
833
+ MsgContract.instance.out_debug(self,"Error on start_session : #{e.class}:#{e.message}")
834
+ end
835
+ end
836
+
837
+ def stop_session
838
+ begin
839
+ quit if is_debugging_ready?
840
+ @session.close if is_alive?
841
+ rescue Exception => e
842
+ MsgContract.instance.out_debug(self,"Error on stop_session : #{e.class}:#{e.inspect}")
843
+ end
844
+ end
845
+
846
+ # send a command to the debugger via socket
847
+ def command(_command)
848
+ #MsgContract.instance.out_debug(self,"command=>#{_command}")
849
+ begin
850
+ return false if @busy
851
+ if is_alive?
852
+ @busy = true
853
+ socket_session.puts(_command)
854
+ else
855
+ start_session if !@pend
856
+ end
857
+ true
858
+ rescue Errno::ECONNABORTED => e
859
+ #kill
860
+ notify("quit_yes")
861
+ DebugContract.instance.debug_end(self)
862
+ MsgContract.instance.out_debug(self,"Debugged has finished executing")
863
+ @session = nil
864
+ @pend = true
865
+ false
866
+ #raise RubyDebugException.new("Debugged has finished executing")
867
+ rescue Exception => e
868
+ MsgContract.instance.out_debug(self,"Error on command #{_command}: #{e.class}:#{e.inspect}")
869
+ false
870
+ end
871
+ end
872
+ private :command
873
+
874
+ def read(_command=nil)
875
+ return nil if _command && !command(_command)
876
+ socket_session.flush
877
+ result = ""
878
+ while _command !='y' && is_alive? && line = socket_session.gets
879
+ #MsgContract.instance.out_debug(self, "read: letta riga => #{line}")
880
+ break if line =~ /^PROMPT (.*)$/ || line =~ /.(y\/n)./
881
+ result << line
882
+ #break if _command =~ /^eval./
883
+ end
884
+ #MsgContract.instance.out_simple(self, "read(#{_command}): result => #{result}")
885
+ @busy = false
886
+ result
887
+
888
+ rescue Errno::ECONNABORTED
889
+ raise RubyDebugException.new("Debugged has finished executing")
890
+ rescue Errno::ECONNRESET
891
+ raise RubyDebugException.new("Debugged has finished executing")
892
+ rescue Exception => e
893
+ raise RubyDebugException.new("Error: on command '#{_command}' => #{e.class} : #{e.inspect}")
894
+ end
895
+ private :read
896
+
897
+
898
+ def step_over
899
+ notify("next", read("next"))
900
+ end
901
+
902
+ def step_into
903
+ notify("step", read("step"))
904
+ end
905
+
906
+ def step_out
907
+ notify("fin", read("fin"))
908
+ end
909
+
910
+ def resume
911
+ notify("cont", read("cont"))
912
+ end
913
+
914
+ def where
915
+ notify("where", read("where"))
916
+ end
917
+
918
+ def quit
919
+ notify("quit", read("q"))
920
+ end
921
+
922
+ def quit_yes
923
+ notify("quit_yes", read("y"))
924
+ DebugContract.instance.debug_end(self)
925
+ kill
926
+ end
927
+
928
+ def quit_no
929
+ notify("quit_no", read("n"))
930
+ end
931
+
932
+ # return the current stack trace
933
+ def stacktrace
934
+ notify("backtrace", read("backtrace"))
935
+ end
936
+
937
+
938
+ def yaml_pseudo_load(_obj)
939
+ #MsgContract.instance.out_simple(self,"_obj="+_obj.inspect)
940
+ just_present = @valuobjs.include?(_obj)
941
+ @valuobjs << _obj
942
+ if _obj.class == YAML::DomainType
943
+ #MsgContract.instance.out_simple(self,"_obj DomainType="+_obj.inspect)
944
+ return _obj.type_id if just_present
945
+ ret = Hash.new
946
+ ret['__CLASS__']=_obj.type_id
947
+ l = _obj.value.length
948
+ ret['__LENGTH__']= l.to_s
949
+ if l > 0
950
+ _obj.value.each{|k,v|
951
+ ret["@#{k}"]=yaml_pseudo_load(v)
952
+ }
953
+ end
954
+ ret
955
+ elsif _obj.class == Hash
956
+ #MsgContract.instance.out_simple(self,"_obj Hash="+_obj.inspect)
957
+ return 'Hash' if just_present
958
+ ret = Hash.new
959
+ ret['__CLASS__']= 'Hash'
960
+ l = _obj.length
961
+ ret['__LENGTH__']= l.to_s
962
+ if l > 0
963
+ _obj.each{|k,v|
964
+ ret[k]=yaml_pseudo_load(v)
965
+ }
966
+ end
967
+ ret
968
+ elsif _obj.class == Array
969
+ #MsgContract.instance.out_simple(self,"_obj Array="+_obj.inspect)
970
+ return 'Array' if just_present
971
+ ret = Hash.new
972
+ ret['__CLASS__']= 'Array'
973
+ l = _obj.length
974
+ ret['__LENGTH__']= l.to_s
975
+ if l > 0
976
+ _obj.each_with_index{|v,i|
977
+ ret[i.to_s]=yaml_pseudo_load(v)
978
+ }
979
+ end
980
+ ret
981
+ elsif _obj.class == Struct
982
+ #MsgContract.instance.out_simple(self,"_obj Array="+_obj.inspect)
983
+ return 'Struct' if just_present
984
+ ret = Hash.new
985
+ ret['__CLASS__']= 'Struct'
986
+ l = _obj.length
987
+ ret['__LENGTH__']= l.to_s
988
+ if l > 0
989
+
990
+ _obj.members.each{|m|
991
+ ret[m]=yaml_pseudo_load(_obj[m])
992
+ }
993
+ end
994
+ ret
995
+ else
996
+ #MsgContract.instance.out_simple(self,"_obj ="+_obj.inspect)
997
+
998
+ _obj
999
+ end
1000
+
1001
+ end
1002
+
1003
+
1004
+ def debug_dump(_exp)
1005
+ var = nil
1006
+ if @valuobjs.nil?
1007
+ @valuobjs = Array.new
1008
+ else
1009
+ @valuobjs.clear
1010
+ end
1011
+ begin
1012
+ _str = eval(read("eval YAML::dump(#{_exp})"))
1013
+ #MsgContract.instance.out_simple(self,"value passato 1 ="+_str.to_s)
1014
+ _str.gsub!('!ruby/object:', '!')
1015
+ #MsgContract.instance.out_simple(self,"value passato 2 ="+_str.to_s)
1016
+ _obj = YAML::load(_str)
1017
+ var = yaml_pseudo_load(_obj)
1018
+ rescue Exception => e
1019
+ MsgContract.instance.out_simple(self,"exception on eval #{_exp} :#{e.inspect}")
1020
+ var = nil
1021
+ end
1022
+ return var
1023
+ end
1024
+
1025
+
1026
+ # returns the instance variables and there values
1027
+ def instance_variables_new(_this='self')
1028
+ command("eval #{_this}.instance_variables")
1029
+ variables = []
1030
+ begin
1031
+ variables = eval(read)
1032
+ rescue Exception
1033
+ variables = []
1034
+ end
1035
+ @consider = Array.new
1036
+ variable_values = Hash.new
1037
+ variables.each do |var|
1038
+ #next if var != '@objs'
1039
+ # command("eval require 'pp'; #{var}.pretty_inspect() + '|||' + #{var}.class.to_s")
1040
+ command("eval YAML::dump(#{var})")
1041
+ _str = eval read
1042
+ #MsgContract.instance.out_simple(self,"value passato 1 ="+_str)
1043
+
1044
+ _str.gsub!('!ruby/object:', '!')
1045
+
1046
+ #MsgContract.instance.out_simple(self,"value passato 2 ="+_str)
1047
+
1048
+ _obj = YAML::load(_str)
1049
+
1050
+ _xvalue = yaml_pseudo_load(_obj)
1051
+ if _xvalue.class == Hash
1052
+ _xclass = _xvalue['__CLASS__']
1053
+ else
1054
+ _xclass = _xvalue.class.to_s
1055
+ end
1056
+ #_vvv = eval(_value)
1057
+
1058
+ #MsgContract.instance.out_simple(self,"vvv class="+_vvv.class.to_s)
1059
+
1060
+ #MsgContract.instance.out_simple(self,"value="+_xvalue.inspect)
1061
+ #MsgContract.instance.out_simple(self,"class="+_xclass)
1062
+ variable_values[var] = Var.new(_xvalue, _xclass)
1063
+ end
1064
+ return variable_values
1065
+ end
1066
+
1067
+ # returns the local variables and there values
1068
+ def variables(_type)
1069
+ begin
1070
+ #variables = read[1..-2].split(', ').collect!{|x| x[1..-2]}
1071
+ to_eval = read("eval #{_type}")
1072
+ #MsgContract.instance.out_simple(self,"to_eval="+to_eval.to_s)
1073
+ variables = eval(to_eval)
1074
+ #MsgContract.instance.out_simple(self,"variables="+variables.to_s)
1075
+ rescue Exception => e
1076
+ variables = []
1077
+ #p "on command eval #{_type}:#{e.inspect}"
1078
+ #MsgContract.instance.out_debug(self,"on command eval #{_type}:#{e.inspect}")
1079
+ end
1080
+ variables = [] if variables.nil?
1081
+ variable_values = Hash.new
1082
+ variables.each do |var|
1083
+ next if var=='$;'
1084
+ # command("eval #{var}.to_s + '|||' + #{var}.class.to_s")
1085
+ # _str = eval(read)
1086
+ # _value, _class = _str.split('|||')
1087
+ # variable_values[var] = Var.new(_value, _class)
1088
+ variable_values[var] = debug_eval(var)
1089
+ end
1090
+ return variable_values
1091
+ end
1092
+
1093
+ def debug_eval(_exp)
1094
+ command("eval #{res=_exp}.to_s + '|||' + #{res}.class.to_s")
1095
+ _str = eval(read)
1096
+ _value, _class = _str.split('|||')
1097
+ return Var.new(_value, _class)
1098
+ end
1099
+
1100
+ # returns the local variables and there values
1101
+ def local_variables
1102
+ command("eval local_variables")
1103
+ variables = []
1104
+ begin
1105
+ variables = eval(read)
1106
+ rescue Exception
1107
+ variables = []
1108
+ end
1109
+ variable_values = Hash.new
1110
+ variables.each do |var|
1111
+ command("eval #{var}.to_s + '|||' + #{var}.class.to_s")
1112
+ _str = eval(read)
1113
+ _value, _class = _str.split('|||')
1114
+ variable_values[var] = Var.new(_value, eval(_class))
1115
+ end
1116
+ return variable_values
1117
+ end
1118
+
1119
+
1120
+ # returns the global variables and there values
1121
+ def global_variables
1122
+ command("eval global_variables")
1123
+ variables = []
1124
+ begin
1125
+ variables = eval(read)
1126
+ rescue Exception
1127
+ variables = []
1128
+ end
1129
+ variable_values = Hash.new
1130
+ variables.each do |var|
1131
+ command("eval #{var}.to_s")
1132
+ variable_values[var] = read
1133
+ end
1134
+ return variable_values
1135
+ end
1136
+
1137
+
1138
+ def set_breakpoint(_file, _line)
1139
+ #_line = _line + 1
1140
+ text = read("break #{_file}:#{_line}")
1141
+ breakpoint_no = -1
1142
+ matches = text.match(/Set breakpoint ([0-9]*)?/)
1143
+ breakpoint_no = matches[1].to_i if (matches.length == 2)
1144
+ return breakpoint_no
1145
+ end
1146
+
1147
+ def unset_breakpoint(_id)
1148
+ read("delete #{_id}")
1149
+ end
1150
+ end
1151
+
1152
+ class RubyDebug < ArcadiaExt
1153
+ attr_reader :rds
1154
+ attr_reader :rdc
1155
+ def before_build
1156
+ ArcadiaContractListener.new(self, EditorContract, :do_editor_event)
1157
+ @breakpoints = Hash.new
1158
+ @static_breakpoints = Array.new
1159
+ end
1160
+
1161
+ def build
1162
+ end
1163
+
1164
+ def do_editor_event(_event)
1165
+ case _event.signature
1166
+ when EditorContract::BREAKPOINT_AFTER_CREATE
1167
+ self.breakpoint_add(File.expand_path(_event.context.file), _event.context.line)
1168
+ when EditorContract::BREAKPOINT_AFTER_DELETE
1169
+ self.breakpoint_del(File.expand_path(_event.context.file), _event.context.line)
1170
+ when EditorContract::BUFFER_AFTER_RAISE
1171
+ @raised_file=_event.context.file
1172
+ when EditorContract::EVAL_EXPRESSION
1173
+ eval_expression(_event.context.text)
1174
+ end
1175
+ end
1176
+
1177
+ def eval_expression(_exp)
1178
+ res = @rdc.debug_eval(_exp) if @rdc && @rdc.is_debugging_ready?
1179
+ hash = Hash.new
1180
+ hash[_exp]=res
1181
+ @rdv.show_expression(_exp, hash) if res
1182
+ end
1183
+
1184
+ def start_debug_server
1185
+ end
1186
+ private :start_debug_server
1187
+
1188
+ def start_debug_client
1189
+ end
1190
+ private :start_debug_client
1191
+
1192
+
1193
+ def breakpoint_suf(_file,_line)
1194
+ return _line.to_s + "-" + _file.to_s
1195
+ end
1196
+ private :breakpoint_suf
1197
+
1198
+ def break_name(_file,_line)
1199
+ "#{_file}:#{_line}"
1200
+ end
1201
+
1202
+ def breakpoint_add_live(_file,_line)
1203
+ if @rdc
1204
+ @breakpoints[breakpoint_suf(_file,_line)] = @rdc.set_breakpoint(_file, _line.to_i)
1205
+ @rdv.break_list_add(_file,_line) if @rdv
1206
+ end
1207
+ end
1208
+
1209
+ def breakpoint_del_live(_file,_line)
1210
+ if @rdc
1211
+ @rdc.unset_breakpoint(@breakpoints.delete(breakpoint_suf(_file,_line)))
1212
+ @rdv.break_list_del(_file,_line) if @rdv
1213
+ end
1214
+ end
1215
+
1216
+ def breakpoint_free_live
1217
+ @breakpoints.clear
1218
+ @rdv.break_list_free if @rdv
1219
+ end
1220
+
1221
+ def breakpoint_add(_file,_line)
1222
+ breakpoint_add_live(_file,_line)
1223
+ @static_breakpoints << {:file=>_file,:line=>_line}
1224
+ end
1225
+ #private :breakpoint_add
1226
+
1227
+ def breakpoint_del(_file,_line)
1228
+ breakpoint_del_live(_file,_line)
1229
+ @static_breakpoints.delete_if{|b| (b[:file]==_file && b[:line]==_line)}
1230
+ end
1231
+ #private :breakpoint_del
1232
+
1233
+
1234
+ def can_exit_query
1235
+ if @rdc
1236
+ query = (Tk.messageBox('icon' => 'question', 'type' => 'yesno',
1237
+ 'title' => '(Arcadia) Debug',
1238
+ 'message' => "Debug in course, do you want to exit?")=='yes')
1239
+ if query
1240
+ debug_quit
1241
+ return true
1242
+ else
1243
+ return false
1244
+ end
1245
+ else
1246
+ return true
1247
+ end
1248
+ end
1249
+
1250
+
1251
+
1252
+ def debug_begin
1253
+ breakpoint_free_live
1254
+ DebugContract.instance.debug_begin(self)
1255
+ end
1256
+
1257
+ def debug_last
1258
+ debug($arcadia['pers']['run.file.last'])
1259
+ end
1260
+
1261
+ def debug_current
1262
+ debug(@raised_file) if @raised_file!=nil
1263
+ end
1264
+ def debugging?
1265
+ !@rdc.nil? && @rdc.is_alive?
1266
+ end
1267
+ def debug(_filename=nil)
1268
+ if _filename && !debugging?
1269
+ begin
1270
+ self.debug_begin
1271
+ @arcadia['pers']['run.file.last']=_filename
1272
+ @rds = RubyDebugServer.new(self) if @rds.nil?
1273
+ @rds.start_session(_filename, conf('server.host'), conf('server.port'))
1274
+ #MsgContract.instance.out_simple(self,@rds.to_s)
1275
+ @rdc = RubyDebugClient.new(conf('server.host'), conf('server.port'), conf('server.timeout')) if @rdc.nil?
1276
+ @rdv = RubyDebugView.new(self.frame, self) if @rdv.nil?
1277
+ @rdv.start_process(_filename)
1278
+ if @rdc.start_session
1279
+ @static_breakpoints.each{|_b|
1280
+ #MsgContract.instance.out_simple(self," breakpoint_add #{_b[:file]}:#{_b[:line]}")
1281
+ breakpoint_add_live(_b[:file], _b[:line])
1282
+ }
1283
+ end
1284
+ #MsgContract.instance.out_simple(self,"\n<begin debug>")
1285
+
1286
+ rescue Exception => e
1287
+ MsgContract.instance.out_debug(self,"---> "+e.to_s)
1288
+ end
1289
+ end
1290
+ end
1291
+
1292
+
1293
+ def rdebug_server_update(_state)
1294
+ case _state
1295
+ when RubyDebugServer::_RDS_QUIT_
1296
+ debug_quit
1297
+ end
1298
+ p _state
1299
+ end
1300
+
1301
+ def debug_free
1302
+ self.frame_free
1303
+ @rdc = nil
1304
+ @rdv = nil
1305
+ end
1306
+
1307
+ def debug_quit
1308
+ if @rdc
1309
+ if @rdc.is_alive?
1310
+ Thread.new{
1311
+ Tk.messageBox('icon' => 'info',
1312
+ 'type' => 'ok',
1313
+ 'title' => '(Arcadia) Debug',
1314
+ 'message' => "Debug in course, stop it before exit")
1315
+ }
1316
+ else
1317
+ begin
1318
+ debug_free
1319
+ rescue Exception => e
1320
+ MsgContract.instance.out_debug(self, "debug_quit:---> "+e.to_s)
1321
+ #@arcadia['shell'].outln("debug_quit:---> "+e.to_s )
1322
+ end
1323
+ end
1324
+ end
1325
+ end
1326
+
1327
+
1328
+
1329
+ end