arcadia 0.3.1 → 0.4.0

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.
Files changed (179) hide show
  1. data/README +9 -5
  2. data/bin/arcadia +13 -13
  3. data/bin/arcadia.bat +1 -0
  4. data/conf/arcadia.conf +6 -5
  5. data/conf/arcadia.init.rb +34 -34
  6. data/conf/arcadia.res.rb +6 -0
  7. data/ext/ae-breakpoints/ae-breakpoints.conf +10 -0
  8. data/ext/ae-breakpoints/ae-breakpoints.rb +349 -0
  9. data/ext/ae-complete-code/ae-complete-code.conf +0 -0
  10. data/ext/ae-complete-code/ae-complete-code.rb +74 -76
  11. data/ext/ae-doc-code/ae-doc-code.conf +15 -15
  12. data/ext/ae-doc-code/ae-doc-code.rb +300 -295
  13. data/ext/ae-editor/ae-editor.conf +4 -4
  14. data/ext/ae-editor/ae-editor.rb +450 -140
  15. data/ext/ae-editor/langs/conf.lang +0 -0
  16. data/ext/ae-editor/langs/lang.lang.bind +0 -0
  17. data/ext/ae-editor/langs/rb.lang +0 -0
  18. data/ext/ae-editor/langs/rbw.lang.bind +0 -0
  19. data/ext/ae-event-log/ae-event-log.conf +0 -0
  20. data/ext/ae-event-log/ae-event-log.rb +0 -0
  21. data/ext/ae-file-history/ae-file-history.conf +0 -0
  22. data/ext/ae-file-history/ae-file-history.rb +437 -373
  23. data/ext/ae-flag/ae-flag.conf +0 -0
  24. data/ext/ae-flag/ae-flag.rb +0 -0
  25. data/ext/ae-output-event/ae-output-event.conf +0 -0
  26. data/ext/ae-output/ae-output.conf +0 -0
  27. data/ext/ae-output/ae-output.rb +0 -0
  28. data/ext/ae-rad/ae-rad-inspector.rb +0 -0
  29. data/ext/ae-rad/ae-rad-libs.rb +0 -0
  30. data/ext/ae-rad/ae-rad-palette.rb +0 -0
  31. data/ext/ae-rad/ae-rad.conf +0 -0
  32. data/ext/ae-rad/ae-rad.rb +0 -0
  33. data/ext/ae-rad/lib/tk/al-tk.rb +4 -4
  34. data/ext/ae-rad/lib/tk/al-tk.res.rb +0 -0
  35. data/ext/ae-rad/lib/tk/al-tkarcadia.rb +25 -26
  36. data/ext/ae-rad/lib/tk/al-tkcustom.rb +0 -0
  37. data/ext/ae-rad/lib/tkext/al-bwidget.rb +0 -0
  38. data/ext/ae-rad/lib/tkext/al-iwidgets.rb +0 -0
  39. data/ext/ae-rad/lib/tkext/al-tile.rb +0 -0
  40. data/ext/ae-rad/lib/tkext/al-tktable.rb +0 -0
  41. data/ext/ae-ruby-debug/ae-ruby-debug.conf +0 -0
  42. data/ext/ae-ruby-debug/ae-ruby-debug.rb +1589 -1566
  43. data/ext/ae-search-in-files/ae-search-in-files.conf +0 -0
  44. data/ext/ae-search-in-files/ae-search-in-files.rb +0 -0
  45. data/ext/ae-shell/ae-shell.conf +0 -0
  46. data/ext/ae-shell/ae-shell.rb +0 -0
  47. data/ext/ae-shell/sh.rb +0 -0
  48. data/lib/a-commons.rb +27 -8
  49. data/lib/a-contracts.rb +3 -1
  50. data/lib/a-core.rb +33 -12
  51. data/lib/a-tkcommons.rb +17 -1
  52. data/tcl/BWidget-1.8.0/BWman/ArrowButton.html +0 -0
  53. data/tcl/BWidget-1.8.0/BWman/BWidget.html +0 -0
  54. data/tcl/BWidget-1.8.0/BWman/Button.html +0 -0
  55. data/tcl/BWidget-1.8.0/BWman/ButtonBox.html +0 -0
  56. data/tcl/BWidget-1.8.0/BWman/ComboBox.html +0 -0
  57. data/tcl/BWidget-1.8.0/BWman/Dialog.html +0 -0
  58. data/tcl/BWidget-1.8.0/BWman/DragSite.html +0 -0
  59. data/tcl/BWidget-1.8.0/BWman/DropSite.html +0 -0
  60. data/tcl/BWidget-1.8.0/BWman/DynamicHelp.html +0 -0
  61. data/tcl/BWidget-1.8.0/BWman/Entry.html +0 -0
  62. data/tcl/BWidget-1.8.0/BWman/Label.html +0 -0
  63. data/tcl/BWidget-1.8.0/BWman/LabelEntry.html +0 -0
  64. data/tcl/BWidget-1.8.0/BWman/LabelFrame.html +0 -0
  65. data/tcl/BWidget-1.8.0/BWman/ListBox.html +0 -0
  66. data/tcl/BWidget-1.8.0/BWman/MainFrame.html +0 -0
  67. data/tcl/BWidget-1.8.0/BWman/MessageDlg.html +0 -0
  68. data/tcl/BWidget-1.8.0/BWman/NoteBook.html +0 -0
  69. data/tcl/BWidget-1.8.0/BWman/PagesManager.html +0 -0
  70. data/tcl/BWidget-1.8.0/BWman/PanedWindow.html +0 -0
  71. data/tcl/BWidget-1.8.0/BWman/PanelFrame.html +0 -0
  72. data/tcl/BWidget-1.8.0/BWman/PasswdDlg.html +0 -0
  73. data/tcl/BWidget-1.8.0/BWman/ProgressBar.html +0 -0
  74. data/tcl/BWidget-1.8.0/BWman/ProgressDlg.html +0 -0
  75. data/tcl/BWidget-1.8.0/BWman/ScrollView.html +0 -0
  76. data/tcl/BWidget-1.8.0/BWman/ScrollableFrame.html +0 -0
  77. data/tcl/BWidget-1.8.0/BWman/ScrolledWindow.html +0 -0
  78. data/tcl/BWidget-1.8.0/BWman/SelectColor.html +0 -0
  79. data/tcl/BWidget-1.8.0/BWman/SelectFont.html +0 -0
  80. data/tcl/BWidget-1.8.0/BWman/Separator.html +0 -0
  81. data/tcl/BWidget-1.8.0/BWman/SpinBox.html +0 -0
  82. data/tcl/BWidget-1.8.0/BWman/StatusBar.html +0 -0
  83. data/tcl/BWidget-1.8.0/BWman/TitleFrame.html +0 -0
  84. data/tcl/BWidget-1.8.0/BWman/Tree.html +0 -0
  85. data/tcl/BWidget-1.8.0/BWman/Widget.html +0 -0
  86. data/tcl/BWidget-1.8.0/BWman/contents.html +0 -0
  87. data/tcl/BWidget-1.8.0/BWman/index.html +0 -0
  88. data/tcl/BWidget-1.8.0/BWman/navtree.html +0 -0
  89. data/tcl/BWidget-1.8.0/BWman/options.htm +0 -0
  90. data/tcl/BWidget-1.8.0/CHANGES.txt +0 -0
  91. data/tcl/BWidget-1.8.0/ChangeLog +0 -0
  92. data/tcl/BWidget-1.8.0/LICENSE.txt +0 -0
  93. data/tcl/BWidget-1.8.0/README.txt +0 -0
  94. data/tcl/BWidget-1.8.0/arrow.tcl +0 -0
  95. data/tcl/BWidget-1.8.0/bitmap.tcl +0 -0
  96. data/tcl/BWidget-1.8.0/button.tcl +0 -0
  97. data/tcl/BWidget-1.8.0/buttonbox.tcl +0 -0
  98. data/tcl/BWidget-1.8.0/color.tcl +0 -0
  99. data/tcl/BWidget-1.8.0/combobox.tcl +0 -0
  100. data/tcl/BWidget-1.8.0/demo/basic.tcl +0 -0
  101. data/tcl/BWidget-1.8.0/demo/bwidget.xbm +0 -0
  102. data/tcl/BWidget-1.8.0/demo/demo.tcl +0 -0
  103. data/tcl/BWidget-1.8.0/demo/dnd.tcl +0 -0
  104. data/tcl/BWidget-1.8.0/demo/manager.tcl +0 -0
  105. data/tcl/BWidget-1.8.0/demo/select.tcl +0 -0
  106. data/tcl/BWidget-1.8.0/demo/tmpldlg.tcl +0 -0
  107. data/tcl/BWidget-1.8.0/demo/tree.tcl +0 -0
  108. data/tcl/BWidget-1.8.0/demo/x1.xbm +0 -0
  109. data/tcl/BWidget-1.8.0/dialog.tcl +0 -0
  110. data/tcl/BWidget-1.8.0/dragsite.tcl +0 -0
  111. data/tcl/BWidget-1.8.0/dropsite.tcl +0 -0
  112. data/tcl/BWidget-1.8.0/dynhelp.tcl +0 -0
  113. data/tcl/BWidget-1.8.0/entry.tcl +0 -0
  114. data/tcl/BWidget-1.8.0/font.tcl +0 -0
  115. data/tcl/BWidget-1.8.0/images/bold.gif +0 -0
  116. data/tcl/BWidget-1.8.0/images/copy.gif +0 -0
  117. data/tcl/BWidget-1.8.0/images/cut.gif +0 -0
  118. data/tcl/BWidget-1.8.0/images/dragfile.gif +0 -0
  119. data/tcl/BWidget-1.8.0/images/dragicon.gif +0 -0
  120. data/tcl/BWidget-1.8.0/images/error.gif +0 -0
  121. data/tcl/BWidget-1.8.0/images/file.gif +0 -0
  122. data/tcl/BWidget-1.8.0/images/folder.gif +0 -0
  123. data/tcl/BWidget-1.8.0/images/hourglass.gif +0 -0
  124. data/tcl/BWidget-1.8.0/images/info.gif +0 -0
  125. data/tcl/BWidget-1.8.0/images/italic.gif +0 -0
  126. data/tcl/BWidget-1.8.0/images/minus.xbm +0 -0
  127. data/tcl/BWidget-1.8.0/images/new.gif +0 -0
  128. data/tcl/BWidget-1.8.0/images/opcopy.xbm +0 -0
  129. data/tcl/BWidget-1.8.0/images/open.gif +0 -0
  130. data/tcl/BWidget-1.8.0/images/openfold.gif +0 -0
  131. data/tcl/BWidget-1.8.0/images/oplink.xbm +0 -0
  132. data/tcl/BWidget-1.8.0/images/opmove.xbm +0 -0
  133. data/tcl/BWidget-1.8.0/images/overstrike.gif +0 -0
  134. data/tcl/BWidget-1.8.0/images/palette.gif +0 -0
  135. data/tcl/BWidget-1.8.0/images/passwd.gif +0 -0
  136. data/tcl/BWidget-1.8.0/images/paste.gif +0 -0
  137. data/tcl/BWidget-1.8.0/images/plus.xbm +0 -0
  138. data/tcl/BWidget-1.8.0/images/print.gif +0 -0
  139. data/tcl/BWidget-1.8.0/images/question.gif +0 -0
  140. data/tcl/BWidget-1.8.0/images/redo.gif +0 -0
  141. data/tcl/BWidget-1.8.0/images/save.gif +0 -0
  142. data/tcl/BWidget-1.8.0/images/target.xbm +0 -0
  143. data/tcl/BWidget-1.8.0/images/underline.gif +0 -0
  144. data/tcl/BWidget-1.8.0/images/undo.gif +0 -0
  145. data/tcl/BWidget-1.8.0/images/warning.gif +0 -0
  146. data/tcl/BWidget-1.8.0/init.tcl +0 -0
  147. data/tcl/BWidget-1.8.0/label.tcl +0 -0
  148. data/tcl/BWidget-1.8.0/labelentry.tcl +0 -0
  149. data/tcl/BWidget-1.8.0/labelframe.tcl +0 -0
  150. data/tcl/BWidget-1.8.0/lang/da.rc +0 -0
  151. data/tcl/BWidget-1.8.0/lang/de.rc +0 -0
  152. data/tcl/BWidget-1.8.0/lang/en.rc +0 -0
  153. data/tcl/BWidget-1.8.0/lang/es.rc +0 -0
  154. data/tcl/BWidget-1.8.0/lang/fr.rc +0 -0
  155. data/tcl/BWidget-1.8.0/listbox.tcl +0 -0
  156. data/tcl/BWidget-1.8.0/mainframe.tcl +0 -0
  157. data/tcl/BWidget-1.8.0/messagedlg.tcl +0 -0
  158. data/tcl/BWidget-1.8.0/notebook.tcl +0 -0
  159. data/tcl/BWidget-1.8.0/pagesmgr.tcl +0 -0
  160. data/tcl/BWidget-1.8.0/panedw.tcl +0 -0
  161. data/tcl/BWidget-1.8.0/panelframe.tcl +0 -0
  162. data/tcl/BWidget-1.8.0/passwddlg.tcl +0 -0
  163. data/tcl/BWidget-1.8.0/pkgIndex.tcl +0 -0
  164. data/tcl/BWidget-1.8.0/progressbar.tcl +0 -0
  165. data/tcl/BWidget-1.8.0/progressdlg.tcl +0 -0
  166. data/tcl/BWidget-1.8.0/scrollframe.tcl +0 -0
  167. data/tcl/BWidget-1.8.0/scrollview.tcl +0 -0
  168. data/tcl/BWidget-1.8.0/scrollw.tcl +0 -0
  169. data/tcl/BWidget-1.8.0/separator.tcl +0 -0
  170. data/tcl/BWidget-1.8.0/spinbox.tcl +0 -0
  171. data/tcl/BWidget-1.8.0/statusbar.tcl +0 -0
  172. data/tcl/BWidget-1.8.0/tests/entry.test +0 -0
  173. data/tcl/BWidget-1.8.0/titleframe.tcl +0 -0
  174. data/tcl/BWidget-1.8.0/tree.tcl +0 -0
  175. data/tcl/BWidget-1.8.0/utils.tcl +0 -0
  176. data/tcl/BWidget-1.8.0/widget.tcl +0 -0
  177. data/tcl/BWidget-1.8.0/wizard.tcl +0 -0
  178. data/tcl/BWidget-1.8.0/xpm2image.tcl +0 -0
  179. metadata +158 -154
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -108,7 +108,7 @@ class AGTkPlaceManager
108
108
  def initialize(_agobj, _active=false)
109
109
  #Tk.messageBox('message'=>_active.to_s)
110
110
  unless defined? _agobj.ag_parent
111
- break
111
+ return
112
112
  end
113
113
  @agobj = _agobj
114
114
  if !defined? @@place_managers
@@ -561,7 +561,7 @@ class AGTkPackManager
561
561
 
562
562
  def initialize(_agobj, _active)
563
563
  unless defined? _agobj.ag_parent
564
- break
564
+ return
565
565
  end
566
566
  @agobj = _agobj
567
567
  if !defined? @@packs_managers
@@ -602,7 +602,7 @@ class AGTkGridManager
602
602
 
603
603
  def initialize(_agobj, _active)
604
604
  unless defined? _agobj.ag_parent
605
- break
605
+ return
606
606
  end
607
607
  @agobj = _agobj
608
608
  if !defined? @@grids_managers
@@ -627,7 +627,7 @@ class AGTkLManager
627
627
 
628
628
  def initialize(_agobj, _activate)
629
629
  unless defined? _agobj.ag_parent
630
- break
630
+ return
631
631
  end
632
632
  @@place_managers = Array.new if !defined? @@place_managers
633
633
  @@pack_managers = Array.new if !defined? @@pack_managers
File without changes
@@ -1,26 +1,25 @@
1
- #
2
- # al-tkarcadia.rb - Arcadia Ruby ide
3
- # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
- #
5
-
6
- require 'ext/ae-rad/lib/tk/al-tk'
7
- require 'lib/a-tkcommons'
8
-
9
- class WAGTkVSplittedFrames < AGTkFrame
10
- def WAGTkVSplittedFrames.class_wrapped
11
- AGTkVSplittedFrames
12
- end
13
- def new_object
14
- @obj = AGTkVSplittedFrames.new(@ag_parent.obj)
15
- end
16
-
17
- def properties
18
- super()
19
- end
20
- end
21
-
22
- class ArcadiaLibArcadiaTk < ArcadiaLib
23
- def register_classes
24
- self.add_class(WAGTkVSplittedFrames)
25
- end
26
- end
1
+ #
2
+ # al-tkarcadia.rb - Arcadia Ruby ide
3
+ # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
+ #
5
+ require 'ext/ae-rad/lib/tk/al-tk'
6
+ require 'lib/a-tkcommons'
7
+
8
+ class WAGTkVSplittedFrames < AGTkFrame
9
+ def WAGTkVSplittedFrames.class_wrapped
10
+ AGTkVSplittedFrames
11
+ end
12
+ def new_object
13
+ @obj = AGTkVSplittedFrames.new(@ag_parent.obj)
14
+ end
15
+
16
+ def properties
17
+ super()
18
+ end
19
+ end
20
+
21
+ class ArcadiaLibArcadiaTk < ArcadiaLib
22
+ def register_classes
23
+ self.add_class(WAGTkVSplittedFrames)
24
+ end
25
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,1566 +1,1589 @@
1
- #
2
- # ae-ruby-debug.rb - Arcadia Ruby ide
3
- # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
- #
5
-
6
-
7
- class RubyDebugView
8
- include TkUtil
9
- B_STATE_ON = '+'
10
- B_STATE_OFF = '-'
11
- B_STATE_FREEZE = '='
12
- def initialize(_frame, _controller)
13
- @frame = _frame
14
- @controller = _controller
15
- self.build_ui
16
- @controller.rdc.add_listener(self)
17
- @nodes_to_open = Array.new
18
- #@break_hash = Hash.new
19
- end
20
-
21
- def build_buttons_set
22
- _relief = 'groove'
23
- # @debug_button_box.add(Arcadia.style('toolbarbutton').update({
24
- # 'name'=>'debug_over',
25
- # 'anchor' => 'nw',
26
- # 'command'=>proc{self.debug_send(:step_over)},
27
- # 'helptext'=>'step over',
28
- # 'image'=> TkPhotoImage.new('dat' => D_NEXT_GIF)})
29
- # )
30
- @debug_button_box.add(
31
- 'name'=>'debug_over',
32
- 'background' => 'white',
33
- 'anchor' => 'nw',
34
- 'command'=>proc{self.debug_send(:step_over)},
35
- 'helptext'=>'step over',
36
- 'image'=> TkPhotoImage.new('dat' => D_NEXT_GIF),
37
- 'relief'=> _relief
38
- )
39
- @debug_button_box.add(
40
- 'name'=>'debug_into',
41
- 'background' => 'white',
42
- 'anchor' => 'nw',
43
- 'command'=>proc{self.debug_send(:step_into)},
44
- 'helptext'=>'step into',
45
- 'image'=> TkPhotoImage.new('dat' => D_STEP_INTO_GIF),
46
- 'relief'=>_relief
47
- )
48
- @debug_button_box.add(
49
- 'name'=>'debug_out',
50
- 'background' => 'white',
51
- 'anchor' => 'nw',
52
- 'helptext'=>'step out',
53
- 'command'=>proc{self.debug_send(:step_out)},
54
- 'image'=> TkPhotoImage.new('dat' => D_STEP_OUT_GIF),
55
- 'relief'=>_relief
56
- )
57
- @debug_button_box.add(
58
- 'name'=>'debug_resume',
59
- 'background' => 'white',
60
- 'anchor' => 'nw',
61
- 'helptext'=>'resume',
62
- 'image'=> TkPhotoImage.new('dat' => D_RESUME_GIF),
63
- 'command'=>proc{self.debug_send(:resume)},
64
- 'relief'=>_relief
65
- )
66
-
67
- @debug_button_box.add(
68
- 'name'=>'debug_quit',
69
- 'background' => 'white',
70
- 'anchor' => 'nw',
71
- 'helptext'=>'quit',
72
- 'image'=> TkPhotoImage.new('dat' => D_QUIT_GIF),
73
- 'command'=>proc{self.debug_send(:quit)},
74
- 'relief'=>_relief
75
- )
76
-
77
- end
78
-
79
- def build_ui
80
- _y = 22
81
- @debug_button_box = Tk::BWidget::ButtonBox.new(@frame){
82
- homogeneous true
83
- state 'disabled'
84
- background Arcadia.conf('panel.background')
85
- }.place('height'=> _y)
86
-
87
- @debug_frame = TkFrame.new(@frame, Arcadia.style('panel')){
88
- border 2
89
- place(
90
- 'y'=>_y,
91
- 'height'=> -_y,
92
- 'relheight'=> 1,
93
- 'relwidth'=> 1
94
- )
95
- }
96
-
97
- self.build_buttons_set
98
-
99
- sf = AGTkOSplittedFrames.new(@debug_frame,70)
100
-
101
- #-------------------------------------------------
102
- build_process_panel(sf.top_frame)
103
- #-------------------------------------------------
104
-
105
- @enb = Tk::BWidget::NoteBook.new(sf.bottom_frame, Arcadia.style('tabpanel')){
106
- tabbevelsize 0
107
- internalborderwidth 2
108
- place('relwidth' => 1,'relheight' => '1')
109
- }
110
- _tab_var = @enb.insert('end', 'vars' ,
111
- 'text'=> 'Variables',
112
- 'raisecmd'=>proc{}
113
- )
114
- _tab_breakpoint = @enb.insert('end', 'Breakpoint' ,
115
- 'text'=> 'Breakpoints',
116
- 'raisecmd'=>proc{}
117
- )
118
- # _tab_catchpoint = @enb.insert('end', 'catchpoint' ,
119
- # 'text'=> 'catchpoint',
120
- # 'raisecmd'=>proc{}
121
- # )
122
-
123
- build_var_panel(_tab_var)
124
- build_break_panel(_tab_breakpoint)
125
- @stack_nodes = Array.new
126
- @enb.raise('vars')
127
-
128
- end
129
-
130
- def build_process_panel(_frame)
131
- @tree_process = Tk::BWidget::Tree.new(_frame, Arcadia.style('treepanel')){
132
- showlines false
133
- deltay 15
134
- place('relwidth' => 1,'relheight' => '1')
135
- }
136
- @tree_process.textbind("Double-ButtonPress-1", proc{
137
- _selected = @tree_process.selection_get[0]
138
- if @tree_process.parent(_selected)=='client'
139
- _text = @tree_process.itemcget(_selected, 'text')
140
- pos = match_position_from_stack(_text)
141
- if pos.length >0
142
- Arcadia.process_event(OpenBufferEvent.new(self,'file'=>pos[0], 'row'=>pos[1]))
143
- #EditorContract.instance.open_file(self, 'file'=>pos[0], 'line'=>pos[1])
144
- end
145
- end
146
- })
147
-
148
- end
149
-
150
- def start_process(_filename)
151
- @tree_process.insert('end', 'root' ,'server', {
152
- 'text' => "Server => #{File.basename(_filename)} at #{@controller.conf('server.host')}:#{@controller.conf('server.port')}"
153
- }.update(Arcadia.style('treeitem')))
154
- @tree_process.insert('end', 'server' ,'client', {
155
- 'text' => "Client"
156
- }.update(Arcadia.style('treeitem')))
157
- @tree_process.open_tree('server',true)
158
- end
159
-
160
- def tree_var_free
161
- @tree_var.delete(@tree_var.nodes('local_var'))
162
- @tree_var.delete(@tree_var.nodes('instance_var'))
163
- @tree_var.delete(@tree_var.nodes('global_var'))
164
- @tree_var.delete(@tree_var.nodes('class_var'))
165
- @tree_var.delete(@tree_var.nodes('eval')) if @tree_var.exist?('eval')
166
- end
167
-
168
- def tree_process_free
169
- @tree_process.delete(@tree_process.nodes('root'))
170
- end
171
-
172
- def bnext_state(_state)
173
- if _state == B_STATE_ON
174
- return B_STATE_FREEZE
175
- elsif _state == B_STATE_FREEZE
176
- return B_STATE_OFF
177
- elsif _state == B_STATE_OFF
178
- return B_STATE_ON
179
- end
180
- end
181
-
182
- def build_var_panel(_frame)
183
- _open_proc = proc do |_arg|
184
- inspect_node(_arg) if @nodes_to_open.include?(_arg)
185
- end
186
-
187
- @tree_var = Tk::BWidget::Tree.new(_frame, Arcadia.style('treepanel')){
188
- showlines true
189
- deltay 15
190
- opencmd _open_proc
191
- }.place('relwidth' => 1,'relheight' => '1','bordermode' => 'inside')
192
-
193
- _scrollcommand = proc{|*args| @tree_var.yview(*args)}
194
- _scrollbar = TkScrollbar.new(_frame, Arcadia.style('scrollbar')){|s|
195
- width 8
196
- command _scrollcommand
197
- }.pack('side'=>'right', 'fill'=>'y')
198
- @tree_var.yscrollcommand proc{|first,last| _scrollbar.set(first,last)}
199
-
200
- @local_state = B_STATE_ON
201
- @instance_state = B_STATE_ON
202
- @class_state = B_STATE_ON
203
- @global_state = B_STATE_OFF
204
-
205
- _i_on = TkPhotoImage.new('dat' => ON_GIF)
206
- _i_off = TkPhotoImage.new('dat' => OFF_GIF)
207
- _i_freeze = TkPhotoImage.new('dat' => FREEZE_GIF)
208
-
209
- _b_relief = 'groove'
210
- #------------------ loacal variables -------------------
211
- _loc_var_text = "Local variables"
212
- @b_local_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
213
- image _i_on
214
- state 'disabled'
215
- anchor 'nw'
216
- }.bind("1",proc{
217
- @local_state = bnext_state(@local_state)
218
- if @local_state == B_STATE_ON
219
- @tree_var.itemconfigure('local_var',
220
- 'text'=>"#{_loc_var_text}",
221
- 'helptext'=>""
222
- )
223
- @b_local_onoff.image(_i_on)
224
- command_enabled(false)
225
- Thread.new{
226
- update_variables('local_var', @controller.rdc.variables('local_variables')) #if @tree_var.open?('local_var')
227
- command_enabled(true)
228
- }
229
- elsif @local_state == B_STATE_FREEZE
230
- @b_local_onoff.image(_i_freeze)
231
- @tree_var.itemconfigure('local_var',
232
- 'text'=>"#{_loc_var_text} freeze at #{@last_position_string}",
233
- 'helptext'=>"#{_loc_var_text} freeze at #{@last_position_string}"
234
- )
235
- elsif @local_state == B_STATE_OFF
236
- @b_local_onoff.image(_i_off)
237
- @tree_var.delete(@tree_var.nodes('local_var'))
238
- @tree_var.itemconfigure('local_var',
239
- 'text'=>"#{_loc_var_text}",
240
- 'helptext'=>""
241
- )
242
- end
243
- })
244
-
245
- @tree_var.insert('end', 'root' ,'local_var', Arcadia.style('treeitem').update({
246
- 'fill'=>Arcadia.conf('hightlight.8.foreground'),
247
- 'open'=>true,
248
- 'anchor'=>'w',
249
- 'text' => _loc_var_text,
250
- 'window' => @b_local_onoff
251
- }))
252
-
253
- #------------------ instance variables -------------------
254
- _instance_var_text="Instance variables"
255
- @b_instance_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
256
- image _i_on
257
- #relief _b_relief
258
- state 'disabled'
259
- anchor 'nw'
260
- }.bind("1",proc{
261
- @instance_state = bnext_state(@instance_state)
262
- if @instance_state == B_STATE_ON
263
- @tree_var.itemconfigure('instance_var',
264
- 'text'=>"#{_instance_var_text}",
265
- 'helptext'=>""
266
- )
267
- @b_instance_onoff.image(_i_on)
268
- command_enabled(false)
269
- Thread.new{
270
- update_variables('instance_var', @controller.rdc.variables('instance_variables')) #if @tree_var.open?('local_var')
271
- command_enabled(true)
272
- }
273
- elsif @instance_state == B_STATE_FREEZE
274
- @b_instance_onoff.image(_i_freeze)
275
- @tree_var.itemconfigure('instance_var',
276
- 'text'=>"#{_instance_var_text} freeze at #{@last_position_string}",
277
- 'helptext'=>"#{_instance_var_text} freeze at #{@last_position_string}"
278
- )
279
- elsif @instance_state == B_STATE_OFF
280
- @b_instance_onoff.image(_i_off)
281
- @tree_var.delete(@tree_var.nodes('instance_var'))
282
- @tree_var.itemconfigure('instance_var',
283
- 'text'=>"#{_instance_var_text}",
284
- 'helptext'=>""
285
- )
286
- end
287
- })
288
- @tree_var.insert('end', 'root' ,'instance_var', Arcadia.style('treeitem').update({
289
- 'fill'=>Arcadia.conf('hightlight.9.foreground'),
290
- 'open'=>true,
291
- 'anchor'=>'w',
292
- 'text' => _instance_var_text,
293
- 'window' => @b_instance_onoff
294
- }))
295
-
296
- #------------------ class variables -------------------
297
- _class_var_text="Class variables"
298
- @b_class_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
299
- image _i_on
300
- #relief _b_relief
301
- state 'disabled'
302
- anchor 'nw'
303
- }.bind("1",proc{
304
- @class_state = bnext_state(@class_state)
305
- if @class_state == B_STATE_ON
306
- @tree_var.itemconfigure('class_var',
307
- 'text'=>"#{_class_var_text}",
308
- 'helptext'=>""
309
- )
310
- @b_class_onoff.image(_i_on)
311
- command_enabled(false)
312
- Thread.new{
313
- update_variables('class_var', @controller.rdc.variables('self.class.class_variables')) #if @tree_var.open?('local_var')
314
- command_enabled(true)
315
- }
316
- elsif @class_state == B_STATE_FREEZE
317
- @b_class_onoff.image(_i_freeze)
318
- @tree_var.itemconfigure('class_var',
319
- 'text'=>"#{_class_var_text} freeze at #{@last_position_string}",
320
- 'helptext'=>"#{_class_var_text} freeze at #{@last_position_string}"
321
- )
322
- elsif @class_state == B_STATE_OFF
323
- @b_class_onoff.image(_i_off)
324
- @tree_var.delete(@tree_var.nodes('class_var'))
325
- @tree_var.itemconfigure('class_var',
326
- 'text'=>"#{_class_var_text}",
327
- 'helptext'=>""
328
- )
329
- end
330
- })
331
- @tree_var.insert('end', 'root' ,'class_var', Arcadia.style('treeitem').update({
332
- 'fill'=>Arcadia.conf('hightlight.10.foreground'),
333
- 'open'=>true,
334
- 'anchor'=>'w',
335
- 'text' => _class_var_text,
336
- 'window' => @b_class_onoff
337
- }))
338
-
339
-
340
- #------------------ global variables -------------------
341
- _global_var_text="Global variables"
342
- @b_global_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
343
- image _i_off
344
- #relief _b_relief
345
- state 'disabled'
346
- anchor 'nw'
347
- }.bind("1",proc{
348
- @global_state = bnext_state(@global_state)
349
- if @global_state == B_STATE_ON
350
- @tree_var.itemconfigure('global_var',
351
- 'text'=>"#{_global_var_text}",
352
- 'helptext'=>""
353
- )
354
- @b_global_onoff.image(_i_on)
355
- command_enabled(false)
356
- Thread.new{
357
- update_variables('global_var', @controller.rdc.variables('global_variables')) #if @tree_var.open?('local_var')
358
- command_enabled(true)
359
- }
360
- elsif @global_state == B_STATE_FREEZE
361
- @b_global_onoff.image(_i_freeze)
362
- @tree_var.itemconfigure('global_var',
363
- 'text'=>"#{_global_var_text} freeze at #{@last_position_string}",
364
- 'helptext'=>"#{_global_var_text} freeze at #{@last_position_string}"
365
- )
366
- elsif @global_state == B_STATE_OFF
367
- @b_global_onoff.image(_i_off)
368
- @tree_var.delete(@tree_var.nodes('global_var'))
369
- @tree_var.itemconfigure('global_var',
370
- 'text'=>"#{_global_var_text}",
371
- 'helptext'=>""
372
- )
373
- end
374
- })
375
- @tree_var.insert('end', 'root' ,'global_var', Arcadia.style('treeitem').update({
376
- 'fill'=>Arcadia.conf('hightlight.11.foreground'),
377
- 'open'=>true,
378
- 'anchor'=>'w',
379
- 'text' => _global_var_text,
380
- 'window' => @b_global_onoff
381
- }))
382
- end
383
-
384
- def build_break_panel(_tab_breakpoint)
385
- @tree_break = Tk::BWidget::Tree.new(_tab_breakpoint, Arcadia.style('treepanel')){
386
- showlines true
387
- deltay 15
388
- }.place('relwidth' => 1,'relheight' => '1')
389
- end
390
-
391
- def file2node_name(_file)
392
- _s = ""
393
- _file.gsub("/",_s).gsub(".",_s).gsub(":",_s).gsub("\\",_s).gsub("-",_s)
394
- end
395
-
396
- def line2node_name(_parent, _line)
397
- "#{_parent}_#{_line.to_s}"
398
- end
399
-
400
- def break_list_add(_file, _line)
401
- _file_node = file2node_name(_file)
402
- _line_node = line2node_name(_file_node, _line)
403
- if !@tree_break.exist?(_file_node)
404
- @tree_break.insert('end', 'root' ,_file_node, {
405
- 'open'=>true,
406
- 'anchor'=>'w',
407
- 'text' => _file
408
- }.update(Arcadia.style('treeitem')))
409
- end
410
-
411
- if !@tree_break.exist?(_line_node)
412
- @tree_break.insert('end', _file_node ,_line_node, {
413
- 'open'=>true,
414
- 'anchor'=>'w',
415
- 'text' => "line: #{_line}"
416
- }.update(Arcadia.style('treeitem')))
417
- end
418
- end
419
-
420
- def break_list_del(_file, _line)
421
- _file_node = file2node_name(_file)
422
- _line_node = line2node_name(_file_node, _line)
423
- if @tree_break.exist?(_line_node)
424
- @tree_break.delete(_line_node)
425
- _bro = @tree_break.nodes(_file_node)
426
- if _bro && _bro.length > 0
427
- @tree_break.delete(_file_node)
428
- end
429
- end
430
- end
431
-
432
- def break_list_select(_file, _line)
433
- _file_node = file2node_name(_file)
434
- _line_node = line2node_name(_file_node, _line)
435
- @tree_break.selection_clear
436
- if @tree_break.exist?(_line_node)
437
- @tree_break.selection_add(_line_node)
438
- @tree_break.see(_line_node)
439
- end
440
- end
441
-
442
-
443
- def break_list_free
444
- @tree_break.delete(@tree_break.nodes('root'))
445
- end
446
-
447
- def clear
448
- tree_var_free
449
- tree_process_free
450
- break_list_free
451
- end
452
-
453
-
454
- def rdebug_client_update(_command, _result)
455
- #Arcadia.console(self,'msg'=>"on command #{_command} => #{_result}", 'level'=>'debug')
456
- return if @controller.rdc.nil? || !@controller.rdc.is_debugging_ready? || !@controller.rds.is_alive?
457
- begin
458
- if _command == 'quit'
459
- msg = "Really quit debug ? (y/n)"
460
- ans = Tk.messageBox('icon' => 'question', 'type' => 'yesno',
461
- 'title' => '(Arcadia) Debug', 'message' => msg)
462
- if ans == 'yes'
463
- debug_send(:quit_yes)
464
- clear
465
- else
466
- debug_send(:quit_no)
467
- end
468
- elsif _command == 'quit_yes'
469
- clear
470
- elsif _command == 'quit_no'
471
- command_enabled(true)
472
- elsif _command == 'cont' && !_result.downcase.include?('breakpoint')
473
- @controller.rdc.kill
474
- clear
475
- elsif _command != 'where' && _command != 'quit_yes'
476
- begin
477
- update_position
478
- update_variables('local_var', @controller.rdc.variables('local_variables')) if @local_state == B_STATE_ON
479
- update_variables('instance_var', @controller.rdc.variables('instance_variables')) if @instance_state == B_STATE_ON
480
- update_variables('class_var', @controller.rdc.variables('self.class.class_variables')) if @class_state == B_STATE_ON
481
- #Arcadia.new_debug_msg(self,"on command #{_command}:global_variables")
482
- update_variables('global_var', @controller.rdc.variables('global_variables')) if @global_state == B_STATE_ON
483
- ensure
484
- command_enabled(true) if !@controller.rdc.nil? && @controller.rdc.is_debugging_ready? && (!_command.include?('quit') || _command.include?('quit_no'))
485
- end
486
- end
487
- rescue Exception => e
488
- Arcadia.console(self, 'msg'=>"on command #{_command}:#{e.inspect}", 'level'=>'debug')
489
- #Arcadia.new_debug_msg(self,"on command #{_command}:#{e.inspect}")
490
- end
491
- end
492
-
493
- def match_position_from_stack(_line)
494
- #Arcadia.new_error_msg(self, "match on #{_line}")
495
- ret = Array.new
496
- matchline = _line.match(/#*([0-9]*)[\s\w\W]*\s(.*):([0-9]*)(.*)/)
497
- if !matchline.nil? && matchline.length==5
498
- #Arcadia.new_error_msg(self, "matchline[2]=#{matchline[2]}")
499
- #Arcadia.new_error_msg(self, "matchline[3]=#{matchline[3]}")
500
- filename = matchline[2].to_s.strip
501
- line_no = matchline[3].to_i
502
- if filename && line_no
503
- ret << filename << line_no
504
- end
505
- end
506
- ret
507
- end
508
-
509
- def update_position
510
- stack = @controller.rdc.where
511
- #Arcadia.new_debug_msg(self,stack)
512
- if !stack.nil?
513
- stack = stack.split(/\n/)
514
- line_no = -1
515
- if stack.length > 1 && stack[1].strip[0..0]!='#'
516
- pos = match_position_from_stack(stack[1].strip)
517
- elsif !stack[0].nil?
518
- pos = match_position_from_stack(stack[0])
519
- end
520
- if pos.length > 0
521
- _file = pos[0]
522
- #p "_file=#{_file}"
523
- _file = File.expand_path(pos[0]) if !File.exist?(_file)
524
- Arcadia.broadcast_event(DebugStepInfoEvent.new(self,'file'=> _file, 'row'=>pos[1]))
525
- #DebugContract.instance.debug_step(self, 'file'=> _file, 'line'=>pos[1])
526
- break_list_select(_file, pos[1].to_s)
527
- @last_position_string = "#{pos[0]}:#{pos[1]}"
528
- end
529
- i = 0
530
- @tree_process.delete(@stack_nodes)
531
- stack.each do |line|
532
- _node = "c#{i.to_s}"
533
- @tree_process.insert('end', 'client' ,_node, {
534
- 'text' => line,
535
- 'helptext' => line
536
- }.update(Arcadia.style('treeitem')))
537
- #Arcadia.console(self, 'msg'=>"inserted line #{line}")
538
- @stack_nodes << _node
539
- i = i+1
540
- end
541
- end
542
- end
543
-
544
- def is_simple_class?(_var)
545
- ['Numeric','Fixnum','String','FalseClass','TrueClass','NilClass'].include?(_var.value_class) && !_var.value.to_s.strip.include?("\n")
546
- end
547
-
548
- def show_expression(_exp, _hash)
549
- if !@tree_var.exist?('eval')
550
- @tree_var.insert('end', 'root' ,'eval', Arcadia.style('treeitem').update({
551
- 'fill'=>Arcadia.conf('hightlight.13.foreground'),
552
- 'open'=>true,
553
- 'anchor'=>'w',
554
- 'text' => "Eval selection"
555
- }))
556
- end
557
- update_variables('eval', _hash)
558
- end
559
-
560
- def inspect_node(_node)
561
- command_enabled(false)
562
- begin
563
- _var = var_name(_node)
564
- _o = @controller.rdc.debug_dump(_var)
565
- if _o.class == Hash
566
- var_deep(_node, _o)
567
- else
568
- var_deep_string(_node, _o)
569
- end
570
- ensure
571
- command_enabled(true)
572
- end
573
- end
574
-
575
- def var_deep(_var, _hash)
576
- # _var_cla = _hash['__CLASS__']
577
- # _var_len = _hash['__LENGTH__']
578
- # @tree_var.itemconfigure(_var, 'text' => "#{_var_cla}:#{_var_len}")
579
- return nil if _hash.nil?
580
- return _hash.to_s if _hash.class != Hash
581
- if _hash['__CLASS__']=='Array'
582
- _sorted_keys = _hash.keys.collect!{|x| x.to_i}.sort.collect!{|x| x.to_s}
583
- else
584
- _sorted_keys = _hash.keys.sort
585
- end
586
- _sorted_keys.each{|k|
587
- #_hash.keys.sort.each{|k|
588
- v = _hash[k]
589
- next if k=='__CLASS__'
590
- _complex = v.class == Hash
591
- if _complex
592
- _text = var_format(k,v['__CLASS__'])
593
- elsif (k=='__LENGTH__') && v=='0'
594
- _text = '{}'
595
- elsif (k=='__LENGTH__') && v!='0'
596
- next
597
- else
598
- _text = var_format(k,nil,v)
599
- end
600
- _node = node_name(k, _var)
601
- if @tree_var.exist?(_node)
602
- @tree_var.itemconfigure(_node, 'text' => _text)
603
- else
604
- @tree_var.insert('end', _var ,_node, Arcadia.style('treeitem').update({
605
- 'text' => _text,
606
- 'helptext' => v,
607
- 'anchor'=>'w'
608
- }))
609
- end
610
- var_deep(_node,v) if _complex
611
- }
612
- end
613
-
614
- def var_deep_string(_var, _str)
615
- @tree_var.delete(@tree_var.nodes(_var))
616
- return nil if _str.nil?
617
- _str = _str.to_s if !_str.kind_of?(String)
618
- a_str = _str.split("\n")
619
- a_str.each_with_index{|v,i|
620
- _node = node_name(i.to_s, _var)
621
- @tree_var.insert('end', _var ,_node, Arcadia.style('treeitem').update({
622
- 'text' => v,
623
- 'fill' => Arcadia.conf('hightlight.12.foreground'),
624
- 'anchor'=>'w'
625
- }))
626
- }
627
- end
628
-
629
-
630
- def var_format(_name, _class, _value=nil)
631
- if !_value.nil? && !_class.nil?
632
- return "#{_name.to_s.strip} => #{_value.to_s.strip} [#{_class.to_s.strip}]"
633
- elsif _value.nil? && !_class.nil?
634
- return "#{_name.to_s.strip} [#{_class.to_s.strip}]"
635
- elsif !_value.nil? && _class.nil?
636
- return "#{_name.to_s.strip} => #{_value.to_s.strip}"
637
- elsif _value.nil? && _class.nil?
638
- return "#{_name.to_s.strip} => {}"
639
- end
640
- end
641
-
642
- def node_name(_node, _parent)
643
- return "#{_parent}@@@#{_node.gsub('$','__S__').gsub('&','__E__').gsub(':','__D__').gsub('!','__A__')}"
644
- end
645
-
646
- def var_name(_node)
647
- #_parent = @tree_var.parent(_node)
648
- #return _node.sub("#{_parent}_", '')
649
- return _node.split('@@@')[-1].gsub('__S__','$').gsub('__E__','&').gsub('__D__',':').gsub('__A__','!')
650
- end
651
-
652
- def command_enabled(_value)
653
- #Arcadia.new_debug_msg(self,"command_enabled= #{_value.to_s}")
654
- @c_on = _value
655
- _value ? _state = 'normal':_state = 'disabled'
656
- @debug_button_box.configure(:state=>_state)
657
- @b_local_onoff.configure(:state=>_state)
658
- @b_instance_onoff.configure(:state=>_state)
659
- @b_class_onoff.configure(:state=>_state)
660
- @b_global_onoff.configure(:state=>_state)
661
- Tk.update
662
- end
663
-
664
- def update_variables(_parent_node, _var)
665
- #Arcadia.console(self, 'msg'=>"---update_variables =>#{_var} figlio di #{_parent_node}")
666
- if _var.keys.sort == @tree_var.nodes(_parent_node).collect! {|x| var_name(x).to_s}.sort
667
- _var.each{|k,v|
668
- #Arcadia.console(self, 'msg'=>"node_name of #{k}")
669
- _n = node_name(k, _parent_node)
670
- if is_simple_class?(v)
671
- _text = var_format(k,v.value_class,v.value)
672
- _drawcross = 'auto'
673
- else
674
- _text = var_format(k,v.value_class)
675
- _drawcross = 'always'
676
- @nodes_to_open << _n if !@nodes_to_open.include?(_n)
677
- inspect_node(_n) if bool(@tree_var.itemcget(@tree_var.tagid(_n), 'open'))
678
- end
679
- #Arcadia.console(self, 'msg'=>"_n=#{_n} text=#{_text}")
680
- _node = @tree_var.itemconfigure(_n,
681
- 'text' => _text,
682
- 'helptext' => v.value,
683
- 'drawcross' => _drawcross
684
- )
685
- }
686
- else
687
- @nodes_to_open.clear
688
- @tree_var.delete(@tree_var.nodes(_parent_node))
689
- #@nodes[_parent_node].clear
690
- _var.keys.sort.each{|k|
691
- v = _var[k]
692
- _n = node_name(k, _parent_node)
693
- if is_simple_class?(v)
694
- _text = var_format(k,v.value_class,v.value)
695
- _drawcross = 'auto'
696
- else
697
- _text = var_format(k,v.value_class)
698
- _drawcross = 'always'
699
- @nodes_to_open << _n
700
- end
701
- @tree_var.insert('end', _parent_node ,_n, Arcadia.style('treeitem').update({
702
- 'text' => _text,
703
- 'helptext' => v.value,
704
- 'drawcross' => _drawcross,
705
- 'anchor'=>'w'
706
- }))
707
- }
708
- end
709
- Tk.update
710
- end
711
-
712
- def debug_send(_command)
713
- if @controller.rdc
714
- begin
715
- command_enabled(false)
716
- #@debug_button_box.configure(:state=>'disabled')
717
- Thread.new do
718
- Arcadia.process_event(StepDebugEvent.new(self, 'command'=>_command))
719
- #@controller.rdc.send(_command)
720
- end
721
- #@controller.rdc.send(_command)
722
- rescue Exception => e
723
- Arcadia.console(self, 'msg'=>"---> "+e.to_s, 'level'=>'debug')
724
- #Arcadia.new_debug_msg(self,"---> "+e.to_s)
725
- end
726
- end
727
- end
728
- end
729
-
730
- class RubyDebugException < Exception
731
- end
732
-
733
- class RubyDebugServer
734
- include Observable
735
- attr_accessor :quit_confirm_request
736
- RDS_QUIET = 'RDS_QUIET'
737
- def initialize(_caller, _arcadia=nil)
738
- if _caller.respond_to? :rdebug_server_update
739
- ObserverCallback.new(self,_caller,:rdebug_server_update)
740
- end
741
- @arcadia = _arcadia
742
- @quit_confirm_request = false
743
- @alive = false
744
- end
745
-
746
- def start_session_new(_filename, _host='localhost', _remote_port='8989')
747
- if is_windows?
748
- commandLine = "rdebug.cmd --host #{_host} --port #{_remote_port} -sw #{_filename}"
749
- else
750
- commandLine = "rdebug --host #{_host} --port #{_remote_port} -sw #{_filename}"
751
- end
752
- Arcadia.process_event(SystemExecEvent.new(self, 'command'=>commandLine))
753
- end
754
-
755
- def is_alive?
756
- @alive
757
- end
758
-
759
- def set_alive(_value=false)
760
- @alive = _value
761
- end
762
-
763
- def start_session(_filename, _host='localhost', _remote_port='8989')
764
- if is_windows?
765
- commandLine = "rdebug.cmd --port #{_remote_port} -sw #{_filename}"
766
- else
767
- commandLine = "rdebug --host #{_host} --port #{_remote_port} -sw #{_filename}"
768
- end
769
- begin
770
- @alive = true
771
- if is_windows?
772
- @tid = Thread.new do
773
- if Kernel.system(commandLine)
774
- Kernel.system('y')
775
- else
776
- if @quit_confirm_request
777
- Arcadia.console(self, 'msg'=>"#{$?.inspect}")
778
- #Arcadia.new_msg(self,"#{$?.inspect}")
779
- else
780
- _event = Arcadia.process_event(RunRubyFileEvent.new(self, 'file'=>_filename))
781
- Arcadia.console(self, 'msg'=>"#{_event.results[0].output}", 'level'=>'debug')
782
- #Arcadia.new_debug_msg(self,"#{_event.results[0].output}")
783
- end
784
- end
785
- set_alive(false)
786
- notify(RDS_QUIET)
787
- end
788
- else
789
- @pid = Process.fork do
790
- if Kernel.system(commandLine)
791
- set_alive(false)
792
- #p "alive=#{is_alive?}"
793
- notify(RDS_QUIET)
794
- Kernel.system('y')
795
- Kernel.exit!
796
- else
797
- Kernel.exit!
798
- Arcadia.console(self, 'msg'=>"#{$?.inspect}", 'level'=>'debug')
799
- #Arcadia.new_debug_msg(self,"#{$?.inspect}")
800
- end
801
- #p "@alive=#{@alive}"
802
- #notify(RDS_QUIET)
803
- #Process.wait
804
- end
805
- end
806
- rescue Exception => e
807
- Arcadia.console(self, 'msg'=>"Error on start_server : #{e.class}:#{e.message}", 'level'=>'debug')
808
- #Arcadia.new_debug_msg(self,"Error on start_server : #{e.class}:#{e.message}")
809
- end
810
- end
811
-
812
- def kill
813
- begin
814
- if is_windows?
815
- @tid.join(2)
816
- @tid.kill!
817
- else
818
- Process.kill('QUIT',@pid)
819
- end
820
- notify(RDS_QUIET)
821
- rescue Exception => e
822
- Arcadia.console(self, 'msg'=>"Error on kill : #{e.class}:#{e.message}", 'level'=>'debug')
823
- #Arcadia.new_debug_msg(self,"Error on start_server : #{e.class}:#{e.message}")
824
- end
825
- end
826
-
827
- def is_windows?
828
- !(RUBY_PLATFORM =~ /(win|w)32$/).nil?
829
- end
830
-
831
- def notify(_state)
832
- #p "----- notify ----- #{_state}"
833
- changed
834
- notify_observers(_state)
835
- end
836
-
837
- end
838
-
839
- #Ruby-debug commands
840
-
841
- # * b[reak]
842
- # list breakpoints
843
- # * b[reak] [file|class:]LINE|METHOD [if expr]
844
- # * b[reak] [class.]LINE|METHOD [if expr]
845
- # set breakpoint to some position, optionally if expr == true
846
- # * cat[ch]
847
- # show catchpoint
848
- # * cat[ch] EXCEPTION
849
- # set catchpoint to an exception
850
- # * disp[lay] EXPRESSION add expression into display expression list
851
- # * undisp[lay][ nnn]
852
- # delete one particular or all display expressions if no expression number given
853
- # * del[ete][ nnn]
854
- # delete some or all breakpoints (get the number using “break”)
855
- # * c[ont]
856
- # run until program ends or hit breakpoint
857
- # * r[un]
858
- # alias for cont
859
- # * s[tep][ nnn]
860
- # step (into methods) one line or till line nnn
861
- # * n[ext][ nnn]
862
- # go over one line or till line nnn
863
- # * w[here]
864
- # displays stack
865
- # * f[rame]
866
- # alias for where
867
- # * l[ist][ (-|nn-mm)]
868
- # list program, - list backwards, nn-mm list given lines. No arguments keeps listing
869
- # * up[ nn]
870
- # move to higher frame
871
- # * down[ nn]
872
- # move to lower frame
873
- # * fin[ish]
874
- # return to outer frame
875
- # * q[uit]
876
- # exit from debugger
877
- # * v[ar] g[lobal]
878
- # show global variables
879
- # * v[ar] l[ocal]
880
- # show local variables
881
- # * v[ar] i[nstance] OBJECT
882
- # show instance variables of object
883
- # * v[ar] c[onst] OBJECT
884
- # show constants of object
885
- # * m[ethod] i[nstance] OBJECT
886
- # show methods of object
887
- # * m[ethod] CLASS|MODULE
888
- # show instance methods of class or module
889
- # * th[read] l[ist]
890
- # list all threads
891
- # * th[read] c[ur[rent]]
892
- # show current thread
893
- # * th[read] [sw[itch]] nnn
894
- # switch thread context to nnn
895
- # * th[read] stop nnn
896
- # stop thread nnn
897
- # * th[read] resume nnn
898
- # resume thread nnn
899
- # * p EXPRESSION
900
- # evaluate expression and print its value
901
- # * pp EXPRESSSION
902
- # evaluate expression and print its value
903
- # * h[elp]
904
- # print this help
905
- # * RETURN KEY
906
- # redo previous command. Convenient when using list, step, next, up, down,
907
- # * EVERYHTING ELSE
908
- # evaluate
909
-
910
-
911
- class RubyDebugClient
912
- require 'socket'
913
- require 'yaml'
914
- include Observable
915
- Var = Struct.new("Var",
916
- :value,
917
- :value_class
918
- )
919
-
920
- def initialize(_controller, _server='localhost', _port=8989, _timeout=0)
921
- @controller = _controller
922
- @session = nil
923
- @server = _server
924
- @port = _port
925
- @timeout = _timeout.to_i
926
- @busy = false
927
- @pend = false
928
- end
929
-
930
- def add_listener(_caller, _method=:rdebug_client_update)
931
- if _caller.respond_to? :rdebug_client_update
932
- ObserverCallback.new(self,_caller,:rdebug_client_update)
933
- end
934
- end
935
-
936
- def notify(_command, _result=nil)
937
- #Arcadia.new_debug_msg(self,"notify=>#{_command}")
938
- @busy = false
939
- changed
940
- notify_observers(_command, _result)
941
- _result
942
- end
943
-
944
- def is_debugging_ready?
945
- is_alive? && !is_busy?
946
- end
947
-
948
- def is_busy?
949
- @busy
950
- end
951
-
952
- def is_alive?
953
- #p "===>@session=#{@session}"
954
- #p "===>@session.closed?=#{@session.closed?}" if @session
955
- #p "===>@pend=#{@pend}"
956
- !(@session.nil? || @session.closed? || @pend)
957
- #(!@session.nil? && !@session.closed? && !@pend)
958
- end
959
-
960
- def socket_session
961
- #p "====>socket_session"
962
- #Arcadia.new_debug_msg(self,"socket_session : passo")
963
- if @session.nil? && @controller.rds.is_alive?
964
- begin
965
- #sleep(2)
966
- @session = TCPSocket.new(@server, @port)
967
- @pend = false
968
- rescue Errno::ECONNREFUSED,Errno::EBADF => e
969
- sleep(1)
970
- @t = @t -1
971
- if @t > 0
972
- socket_session
973
- else
974
- Arcadia.console(self, 'msg'=>"socket_session : #{e.inspect}", 'level'=>'debug')
975
- #Arcadia.new_debug_msg(self,"socket_session : #{e.inspect}")
976
- end
977
- rescue Exception => e
978
- @session = nil
979
- Arcadia.console(self, 'msg'=>"Error on socket_session : #{e.class}:#{e.message}", 'level'=>'debug')
980
- #Arcadia.new_debug_msg(self,"Error on socket_session : #{e.class}:#{e.message}")
981
- end
982
- elsif !@controller.rds.is_alive?
983
- @session = nil
984
- end
985
- #Arcadia.new_debug_msg(self,"session : #{@session.inspect}")
986
- #p "@session=>#{@session}"
987
- return @session
988
- end
989
-
990
- def kill
991
- begin
992
- @session.close if is_alive?
993
- @session=nil
994
- rescue Exception => e
995
- Arcadia.console(self, 'msg'=>"Error on close session : #{e.class}:#{e.message}", 'level'=>'debug')
996
- #Arcadia.new_debug_msg(self,"Error on close session : #{e.class}:#{e.message}")
997
- end
998
- end
999
-
1000
- def start_session
1001
- begin
1002
- #p "======>start session"
1003
- @t = @timeout
1004
- if socket_session
1005
- #Arcadia.new_debug_msg(self,"session : #{@session.inspect}")
1006
- notify('start', read)
1007
- read("eval require 'yaml'")
1008
- end
1009
- return @session
1010
- rescue Exception => e
1011
- Arcadia.console(self, 'msg'=>"Error on start_session : #{e.class}:#{e.message}", 'level'=>'debug')
1012
- #Arcadia.new_debug_msg(self,"Error on start_session : #{e.class}:#{e.message}")
1013
- end
1014
- end
1015
-
1016
- def stop_session
1017
- begin
1018
- quit if is_debugging_ready?
1019
- @session.close if is_alive?
1020
- rescue Exception => e
1021
- Arcadia.console(self, 'msg'=>"Error on stop_session : #{e.class}:#{e.inspect}", 'level'=>'debug')
1022
- #Arcadia.new_debug_msg(self,"Error on stop_session : #{e.class}:#{e.inspect}")
1023
- end
1024
- end
1025
-
1026
- # send a command to the debugger via socket
1027
- def command(_command)
1028
- #Arcadia.new_debug_msg(self,"command=>#{_command}")
1029
- begin
1030
- return false if @busy
1031
- if is_alive?
1032
- @busy = true
1033
- @session.puts(_command) if socket_session
1034
- else
1035
- start_session if !@pend
1036
- end
1037
- #_command !="cont"
1038
- true
1039
- rescue Errno::ECONNABORTED => e
1040
- notify("quit_yes")
1041
- #DebugContract.instance.debug_end(self)
1042
- Arcadia.console(self, 'msg'=>"Debugger has finished executing:\n #{e.class}:#{e.inspect}", 'level'=>'debug')
1043
- #Arcadia.new_debug_msg(self,"Debugger has finished executing:\n #{e.class}:#{e.inspect}")
1044
- @session = nil
1045
- @pend = true
1046
- false
1047
- #raise RubyDebugException.new("Debugged has finished executing")
1048
- rescue Exception => e
1049
- Arcadia.console(self, 'msg'=>"Error on command #{_command}: #{e.class}:#{e.inspect}", 'level'=>'debug')
1050
- #Arcadia.new_debug_msg(self,"Error on command #{_command}: #{e.class}:#{e.inspect}")
1051
- false
1052
- end
1053
- end
1054
- private :command
1055
-
1056
- def read(_command=nil)
1057
- return nil if _command && !command(_command)
1058
- result = ""
1059
- if socket_session
1060
- @session.flush
1061
- while _command !='y' && is_alive? && line = @session.gets
1062
- break if line =~ /^PROMPT (.*)$/ || line =~ /.(y\/n)./
1063
- result << line
1064
- #break if _command =~ /^eval./
1065
- end
1066
- #Arcadia.new_debug_msg(self, "read: letta per '#{_command}' result => #{result}")
1067
- end
1068
- @busy = false
1069
- result
1070
-
1071
- rescue Errno::ECONNABORTED
1072
- raise RubyDebugException.new("Debugged has finished executing")
1073
- rescue Errno::ECONNRESET
1074
- raise RubyDebugException.new("Debugged has finished executing")
1075
- rescue Exception => e
1076
- raise RubyDebugException.new("Error: on command '#{_command}' => #{e.class} : #{e.inspect}")
1077
- end
1078
- private :read
1079
-
1080
-
1081
- def step_over
1082
- notify("next", read("next"))
1083
- end
1084
-
1085
- def step_into
1086
- notify("step", read("step"))
1087
- end
1088
-
1089
- def step_out
1090
- notify("fin", read("fin"))
1091
- end
1092
-
1093
- def resume
1094
- notify("cont", read("cont"))
1095
- end
1096
-
1097
- def where
1098
- notify("where", read("where"))
1099
- end
1100
-
1101
- def quit
1102
- notify("quit", read("q"))
1103
- end
1104
-
1105
- def quit_yes
1106
- notify("quit_yes", read("y"))
1107
- #DebugContract.instance.debug_end(self)
1108
- kill
1109
- end
1110
-
1111
- def quit_no
1112
- notify("quit_no", read("n"))
1113
- end
1114
-
1115
- # return the current stack trace
1116
- def stacktrace
1117
- notify("backtrace", read("backtrace"))
1118
- end
1119
-
1120
-
1121
- def yaml_pseudo_load(_obj)
1122
- just_present = @valuobjs.include?(_obj)
1123
- @valuobjs << _obj
1124
- if _obj.class == YAML::DomainType
1125
- return _obj.type_id if just_present
1126
- ret = Hash.new
1127
- ret['__CLASS__']=_obj.type_id
1128
- l = _obj.value.length
1129
- ret['__LENGTH__']= l.to_s
1130
- if l > 0
1131
- _obj.value.each{|k,v|
1132
- ret["@#{k}"]=yaml_pseudo_load(v)
1133
- }
1134
- end
1135
- ret
1136
- elsif _obj.class == Hash
1137
- #Arcadia.new_msg(self,"_obj Hash="+_obj.inspect)
1138
- return 'Hash' if just_present
1139
- ret = Hash.new
1140
- ret['__CLASS__']= 'Hash'
1141
- l = _obj.length
1142
- ret['__LENGTH__']= l.to_s
1143
- if l > 0
1144
- _obj.each{|k,v|
1145
- ret[k]=yaml_pseudo_load(v)
1146
- }
1147
- end
1148
- ret
1149
- elsif _obj.class == Array
1150
- #Arcadia.new_msg(self,"_obj Array="+_obj.inspect)
1151
- return 'Array' if just_present
1152
- ret = Hash.new
1153
- ret['__CLASS__']= 'Array'
1154
- l = _obj.length
1155
- ret['__LENGTH__']= l.to_s
1156
- if l > 0
1157
- _obj.each_with_index{|v,i|
1158
- ret[i.to_s]=yaml_pseudo_load(v)
1159
- }
1160
- end
1161
- ret
1162
- elsif _obj.class == Struct
1163
- #Arcadia.new_msg(self,"_obj Array="+_obj.inspect)
1164
- return 'Struct' if just_present
1165
- ret = Hash.new
1166
- ret['__CLASS__']= 'Struct'
1167
- l = _obj.length
1168
- ret['__LENGTH__']= l.to_s
1169
- if l > 0
1170
-
1171
- _obj.members.each{|m|
1172
- ret[m]=yaml_pseudo_load(_obj[m])
1173
- }
1174
- end
1175
- ret
1176
- else
1177
- #Arcadia.new_msg(self,"_obj ="+_obj.inspect)
1178
-
1179
- _obj
1180
- end
1181
-
1182
- end
1183
-
1184
-
1185
- def debug_dump(_exp)
1186
- var = nil
1187
- if @valuobjs.nil?
1188
- @valuobjs = Array.new
1189
- else
1190
- @valuobjs.clear
1191
- end
1192
- begin
1193
- _to_eval = read("eval YAML::dump(#{_exp})")
1194
- if _to_eval.include?('Exception:')
1195
- _to_eval = read("eval require 'pp';eval #{_exp}.pretty_inspect")
1196
- var = eval(_to_eval)
1197
- #var = "?"
1198
- else
1199
- _str = eval(_to_eval)
1200
- _str.gsub!('!ruby/object:', '!')
1201
- _obj = YAML::load(_str)
1202
- var = yaml_pseudo_load(_obj)
1203
- end
1204
- rescue Exception => e
1205
- Arcadia.console(self, 'msg'=>"exception on eval #{_exp} :#{e.inspect}")
1206
- #Arcadia.new_msg(self,"exception on eval #{_exp} :#{e.inspect}")
1207
- var = nil
1208
- end
1209
- return var
1210
- end
1211
-
1212
-
1213
- # returns the instance variables and there values
1214
- def instance_variables_new(_this='self')
1215
- command("eval #{_this}.instance_variables")
1216
- variables = []
1217
- begin
1218
- variables = eval(read)
1219
- rescue Exception
1220
- variables = []
1221
- end
1222
- @consider = Array.new
1223
- variable_values = Hash.new
1224
- variables.each do |var|
1225
- #next if var != '@objs'
1226
- # command("eval require 'pp'; #{var}.pretty_inspect() + '|||' + #{var}.class.to_s")
1227
- command("eval YAML::dump(#{var})")
1228
- _str = eval read
1229
- #Arcadia.new_msg(self,"value passato 1 ="+_str)
1230
-
1231
- _str.gsub!('!ruby/object:', '!')
1232
-
1233
- #Arcadia.new_msg(self,"value passato 2 ="+_str)
1234
-
1235
- _obj = YAML::load(_str)
1236
-
1237
- _xvalue = yaml_pseudo_load(_obj)
1238
- if _xvalue.class == Hash
1239
- _xclass = _xvalue['__CLASS__']
1240
- else
1241
- _xclass = _xvalue.class.to_s
1242
- end
1243
- #_vvv = eval(_value)
1244
-
1245
- #Arcadia.new_msg(self,"vvv class="+_vvv.class.to_s)
1246
-
1247
- #Arcadia.new_msg(self,"value="+_xvalue.inspect)
1248
- #Arcadia.new_msg(self,"class="+_xclass)
1249
- variable_values[var] = Var.new(_xvalue, _xclass)
1250
- end
1251
- return variable_values
1252
- end
1253
-
1254
- # returns the local variables and there values
1255
- def variables(_type)
1256
- begin
1257
- #variables = read[1..-2].split(', ').collect!{|x| x[1..-2]}
1258
- to_eval = read("eval #{_type}")
1259
- #Arcadia.new_msg(self,"to_eval="+to_eval.to_s)
1260
- variables = eval(to_eval)
1261
- #Arcadia.new_msg(self,"variables="+variables.to_s)
1262
- rescue Exception => e
1263
- variables = []
1264
- #p "on command eval #{_type}:#{e.inspect}"
1265
- #Arcadia.new_debug_msg(self,"on command eval #{_type}:#{e.inspect}")
1266
- end
1267
- variables = [] if variables.nil?
1268
- variable_values = Hash.new
1269
- variables.each do |var|
1270
- next if var=='$;'
1271
- # command("eval #{var}.to_s + '|||' + #{var}.class.to_s")
1272
- # _str = eval(read)
1273
- # _value, _class = _str.split('|||')
1274
- # variable_values[var] = Var.new(_value, _class)
1275
- variable_values[var] = debug_eval(var)
1276
- end
1277
- return variable_values
1278
- end
1279
-
1280
- def debug_eval(_exp)
1281
- command("eval #{res=_exp}.to_s + '|||' + #{res}.class.to_s")
1282
- _str = eval(read)
1283
- _value, _class = _str.split('|||')
1284
- return Var.new(_value, _class)
1285
- end
1286
-
1287
- # returns the local variables and there values
1288
- def local_variables
1289
- command("eval local_variables")
1290
- variables = []
1291
- begin
1292
- variables = eval(read)
1293
- rescue Exception
1294
- variables = []
1295
- end
1296
- variable_values = Hash.new
1297
- variables.each do |var|
1298
- command("eval #{var}.to_s + '|||' + #{var}.class.to_s")
1299
- _str = eval(read)
1300
- _value, _class = _str.split('|||')
1301
- variable_values[var] = Var.new(_value, eval(_class))
1302
- end
1303
- return variable_values
1304
- end
1305
-
1306
-
1307
- # returns the global variables and there values
1308
- def global_variables
1309
- command("eval global_variables")
1310
- variables = []
1311
- begin
1312
- variables = eval(read)
1313
- rescue Exception
1314
- variables = []
1315
- end
1316
- variable_values = Hash.new
1317
- variables.each do |var|
1318
- command("eval #{var}.to_s")
1319
- variable_values[var] = read
1320
- end
1321
- return variable_values
1322
- end
1323
-
1324
-
1325
- def set_breakpoint(_file, _line)
1326
- #_line = _line + 1
1327
- text = read("break #{_file}:#{_line}")
1328
- breakpoint_no = -1
1329
- #matches = text.match(/Set breakpoint ([0-9]*)?/)
1330
- matches = text.downcase.match(/breakpoint ([0-9]*)?/)
1331
- #Arcadia.new_error_msg(self, "text=#{text}")
1332
- #Arcadia.new_error_msg(self, "matches[1]=#{matches[1]}")
1333
- breakpoint_no = matches[1].to_i if (matches.length == 2)
1334
- return breakpoint_no
1335
- end
1336
-
1337
- def unset_breakpoint(_id)
1338
- read("delete #{_id}")
1339
- end
1340
- end
1341
-
1342
- class RubyDebug < ArcadiaExt
1343
- include Autils
1344
- attr_reader :rds
1345
- attr_reader :rdc
1346
- def on_before_build(_event)
1347
- if !full_in_path_command('rdebug').nil?
1348
- #ArcadiaContractListener.new(self, EditorContract, :do_editor_event)
1349
- Arcadia.attach_listener(self, BufferEvent)
1350
- @breakpoints = Hash.new
1351
- @static_breakpoints = Array.new
1352
- else
1353
- Arcadia.console(self, 'msg'=>"Warning: Extension ae-ruby-debug depend upon rdebug command (install it or update system path!)", 'level'=>'error')
1354
- #Arcadia.new_error_msg(self, "Warning: Extension ae-ruby-debug depend upon rdebug command (install it or update system path!)")
1355
- end
1356
- end
1357
-
1358
- def on_build(_event)
1359
- Arcadia.attach_listener(self, DebugEvent)
1360
- end
1361
-
1362
- def on_buffer(_event)
1363
- case _event
1364
- when BufferRaisedEvent
1365
- @raised_file=_event.file
1366
- end
1367
- end
1368
-
1369
- def on_debug(_event)
1370
- case _event
1371
- when StartDebugEvent
1372
- _filename = _event.file
1373
- _filename = @arcadia['pers']['run.file.last'] if _filename == "*LAST"
1374
- debug(_filename)
1375
- when StepDebugEvent
1376
- if (_event.command == :quit_yes)
1377
- @rds.quit_confirm_request = true
1378
- end
1379
- @rdc.send(_event.command) if @rdc.is_alive?
1380
-
1381
- #p "on_debug -> Thread.current=#{Thread.current}"
1382
-
1383
- #p "on_debug --> @rdc.is_alive?=#{@rdc.is_alive?}"
1384
- #p "on_debug --> @rds.is_alive?=#{@rds.is_alive?}"
1385
- when SetBreakpointEvent
1386
- self.breakpoint_add(File.expand_path(_event.file), _event.row)
1387
- when UnsetBreakpointEvent
1388
- self.breakpoint_del(File.expand_path(_event.file), _event.row)
1389
- when EvalExpressionEvent
1390
- eval_expression(_event.expression)
1391
- when StopDebugEvent
1392
- self.debug_quit
1393
- end
1394
- end
1395
-
1396
-
1397
- # def do_editor_event(_event)
1398
- # case _event.signature
1399
- # when EditorContract::BREAKPOINT_AFTER_CREATE
1400
- # self.breakpoint_add(File.expand_path(_event.context.file), _event.context.line)
1401
- # when EditorContract::BREAKPOINT_AFTER_DELETE
1402
- # self.breakpoint_del(File.expand_path(_event.context.file), _event.context.line)
1403
- # when EditorContract::BUFFER_AFTER_RAISE
1404
- # @raised_file=_event.context.file
1405
- # when EditorContract::EVAL_EXPRESSION
1406
- # eval_expression(_event.context.text)
1407
- # end
1408
- # end
1409
-
1410
- def eval_expression(_exp)
1411
- res = @rdc.debug_eval(_exp) if @rdc && @rdc.is_debugging_ready?
1412
- hash = Hash.new
1413
- hash[_exp]=res
1414
- @rdv.show_expression(_exp, hash) if res
1415
- end
1416
-
1417
- def start_debug_server
1418
- end
1419
- private :start_debug_server
1420
-
1421
- def start_debug_client
1422
- end
1423
- private :start_debug_client
1424
-
1425
-
1426
- def breakpoint_suf(_file,_line)
1427
- return _line.to_s + "-" + _file.to_s
1428
- end
1429
- private :breakpoint_suf
1430
-
1431
- def break_name(_file,_line)
1432
- "#{_file}:#{_line}"
1433
- end
1434
-
1435
- def breakpoint_add_live(_file,_line)
1436
- if @rdc && @rdc.is_alive?
1437
- @breakpoints[breakpoint_suf(_file,_line)] = @rdc.set_breakpoint(_file, _line.to_i)
1438
- @rdv.break_list_add(_file,_line) if @rdv
1439
- end
1440
- end
1441
-
1442
- def breakpoint_del_live(_file,_line)
1443
- if @rdc && @rdc.is_alive?
1444
- @rdc.unset_breakpoint(@breakpoints.delete(breakpoint_suf(_file,_line)))
1445
- @rdv.break_list_del(_file,_line) if @rdv
1446
- end
1447
- end
1448
-
1449
- def breakpoint_free_live
1450
- @breakpoints.clear
1451
- @rdv.break_list_free if @rdv
1452
- end
1453
-
1454
- def breakpoint_add(_file,_line)
1455
- breakpoint_add_live(_file,_line)
1456
- @static_breakpoints << {:file=>_file,:line=>_line}
1457
- end
1458
- #private :breakpoint_add
1459
-
1460
- def breakpoint_del(_file,_line)
1461
- breakpoint_del_live(_file,_line)
1462
- @static_breakpoints.delete_if{|b| (b[:file]==_file && b[:line]==_line)}
1463
- end
1464
- #private :breakpoint_del
1465
-
1466
-
1467
- def on_exit_query(_event)
1468
- if @rdc && @rdc.is_alive?
1469
- query = (Tk.messageBox('icon' => 'question', 'type' => 'yesno',
1470
- 'title' => '(Arcadia) Debug',
1471
- 'message' => "Debug in course, do you want to exit?")=='yes')
1472
- if query
1473
- debug_quit
1474
- _event.can_exit=true
1475
- else
1476
- _event.can_exit=false
1477
- end
1478
- else
1479
- _event.can_exit=true
1480
- end
1481
- end
1482
-
1483
- def debug_last
1484
- Arcadia.process_event(StartDebugEvent.new(self, 'file'=>$arcadia['pers']['run.file.last']))
1485
- #debug($arcadia['pers']['run.file.last'])
1486
- end
1487
-
1488
- def debug_current
1489
- Arcadia.process_event(StartDebugEvent.new(self, 'file'=>@raised_file)) if @raised_file!=nil
1490
- #debug(@raised_file) if @raised_file!=nil
1491
- end
1492
- def debugging?
1493
- !@rdc.nil? && @rdc.is_alive?
1494
- end
1495
-
1496
- def debug_begin
1497
- breakpoint_free_live
1498
- #DebugContract.instance.debug_begin(self)
1499
- end
1500
-
1501
- def debug(_filename=nil)
1502
- if _filename && !debugging?
1503
- begin
1504
- self.debug_begin
1505
- @arcadia['pers']['run.file.last']=_filename
1506
- @rds = RubyDebugServer.new(self,@arcadia) if @rds.nil?
1507
- @rds.start_session(_filename, conf('server.host'), conf('server.port'))
1508
- #Arcadia.new_msg(self,@rds.to_s)
1509
-
1510
- @rdc = RubyDebugClient.new(self, conf('server.host'), conf('server.port'), conf('server.timeout')) if @rdc.nil?
1511
- @rdv = RubyDebugView.new(self.frame.hinner_frame, self) if @rdv.nil?
1512
- @rdv.start_process(_filename)
1513
- if @rdc.start_session
1514
- @static_breakpoints.each{|_b|
1515
- #Arcadia.console(self,'msg'=>" breakpoint_add #{_b[:file]}:#{_b[:line]}")
1516
- breakpoint_add_live(_b[:file], _b[:line])
1517
- }
1518
- end
1519
- rescue Exception => e
1520
- Arcadia.console(self, 'msg'=>"---> "+e.to_s, 'level'=>'debug')
1521
- end
1522
- end
1523
- end
1524
-
1525
- def rdebug_server_update(_state)
1526
- case _state
1527
- when RubyDebugServer::RDS_QUIET
1528
- @rdc.kill if @rdc
1529
- #p "@rdc.is_alive?=#{@rdc.is_alive?}"
1530
- #p "rdebug_server_update -> Thread.current=#{Thread.current}"
1531
- #@rdv.command_enabled(false)
1532
- #debug_free
1533
- end
1534
- end
1535
-
1536
- def debug_free
1537
- self.frame.free
1538
- @rdc = nil
1539
- @rdv = nil
1540
- end
1541
-
1542
- def debug_quit
1543
- #p "in debug quit @rdc.is_alive?=#{@rdc.is_alive?}"
1544
- if @rdc
1545
- if @rdc.is_alive?
1546
- Thread.new{
1547
- Tk.messageBox('icon' => 'info',
1548
- 'type' => 'ok',
1549
- 'title' => '(Arcadia) Debug',
1550
- 'message' => "Debug in course, stop it before exit")
1551
- }
1552
- else
1553
- begin
1554
- debug_free
1555
- rescue Exception => e
1556
- Arcadia.console(self, 'msg'=>"debug_quit:---> "+e.to_s, 'level'=>'debug')
1557
- #Arcadia.new_debug_msg(self, "debug_quit:---> "+e.to_s)
1558
- #@arcadia['shell'].outln("debug_quit:---> "+e.to_s )
1559
- end
1560
- end
1561
- end
1562
- end
1563
-
1564
-
1565
-
1566
- end
1
+ #
2
+ # ae-ruby-debug.rb - Arcadia Ruby ide
3
+ # by Antonio Galeone <antonio-galeone@rubyforge.org>
4
+ #
5
+
6
+
7
+ class RubyDebugView
8
+ include TkUtil
9
+ B_STATE_ON = '+'
10
+ B_STATE_OFF = '-'
11
+ B_STATE_FREEZE = '='
12
+ def initialize(_frame, _controller)
13
+ @frame = _frame
14
+ @controller = _controller
15
+ self.build_ui
16
+ @controller.rdc.add_listener(self)
17
+ @nodes_to_open = Array.new
18
+ #@break_hash = Hash.new
19
+ end
20
+
21
+ def build_buttons_set
22
+ _relief = 'groove'
23
+ # @debug_button_box.add(Arcadia.style('toolbarbutton').update({
24
+ # 'name'=>'debug_over',
25
+ # 'anchor' => 'nw',
26
+ # 'command'=>proc{self.debug_send(:step_over)},
27
+ # 'helptext'=>'step over',
28
+ # 'image'=> TkPhotoImage.new('dat' => D_NEXT_GIF)})
29
+ # )
30
+ @debug_button_box.add(
31
+ 'name'=>'debug_over',
32
+ 'background' => 'white',
33
+ 'anchor' => 'nw',
34
+ 'command'=>proc{self.debug_send(:step_over)},
35
+ 'helptext'=>'step over',
36
+ 'image'=> TkPhotoImage.new('dat' => D_NEXT_GIF),
37
+ 'relief'=> _relief
38
+ )
39
+ @debug_button_box.add(
40
+ 'name'=>'debug_into',
41
+ 'background' => 'white',
42
+ 'anchor' => 'nw',
43
+ 'command'=>proc{self.debug_send(:step_into)},
44
+ 'helptext'=>'step into',
45
+ 'image'=> TkPhotoImage.new('dat' => D_STEP_INTO_GIF),
46
+ 'relief'=>_relief
47
+ )
48
+ @debug_button_box.add(
49
+ 'name'=>'debug_out',
50
+ 'background' => 'white',
51
+ 'anchor' => 'nw',
52
+ 'helptext'=>'step out',
53
+ 'command'=>proc{self.debug_send(:step_out)},
54
+ 'image'=> TkPhotoImage.new('dat' => D_STEP_OUT_GIF),
55
+ 'relief'=>_relief
56
+ )
57
+ @debug_button_box.add(
58
+ 'name'=>'debug_resume',
59
+ 'background' => 'white',
60
+ 'anchor' => 'nw',
61
+ 'helptext'=>'resume',
62
+ 'image'=> TkPhotoImage.new('dat' => D_RESUME_GIF),
63
+ 'command'=>proc{self.debug_send(:resume)},
64
+ 'relief'=>_relief
65
+ )
66
+
67
+ @debug_button_box.add(
68
+ 'name'=>'debug_quit',
69
+ 'background' => 'white',
70
+ 'anchor' => 'nw',
71
+ 'helptext'=>'quit',
72
+ 'image'=> TkPhotoImage.new('dat' => D_QUIT_GIF),
73
+ 'command'=>proc{self.debug_send(:quit)},
74
+ 'relief'=>_relief
75
+ )
76
+
77
+ # @debug_button_box.bind_append("KeyPress"){|e|
78
+ # case e.keysym
79
+ # when 'F5'
80
+ # self.debug_send(:step_over)
81
+ # end
82
+ #
83
+ # }
84
+ end
85
+
86
+ def build_ui
87
+ _y = 22
88
+ @debug_button_box = Tk::BWidget::ButtonBox.new(@frame){
89
+ homogeneous true
90
+ state 'disabled'
91
+ background Arcadia.conf('panel.background')
92
+ }.place('height'=> _y)
93
+
94
+ @debug_frame = TkFrame.new(@frame, Arcadia.style('panel')){
95
+ border 2
96
+ place(
97
+ 'y'=>_y,
98
+ 'height'=> -_y,
99
+ 'relheight'=> 1,
100
+ 'relwidth'=> 1
101
+ )
102
+ }
103
+
104
+ self.build_buttons_set
105
+
106
+ sf = AGTkOSplittedFrames.new(@debug_frame,70)
107
+
108
+ #-------------------------------------------------
109
+ build_process_panel(sf.top_frame)
110
+ #-------------------------------------------------
111
+
112
+ @enb = Tk::BWidget::NoteBook.new(sf.bottom_frame, Arcadia.style('tabpanel')){
113
+ tabbevelsize 0
114
+ internalborderwidth 2
115
+ place('relwidth' => 1,'relheight' => '1')
116
+ }
117
+ _tab_var = @enb.insert('end', 'vars' ,
118
+ 'text'=> 'Variables',
119
+ 'raisecmd'=>proc{}
120
+ )
121
+ # _tab_breakpoint = @enb.insert('end', 'Breakpoint' ,
122
+ # 'text'=> 'Breakpoints',
123
+ # 'raisecmd'=>proc{}
124
+ # )
125
+
126
+ # _tab_catchpoint = @enb.insert('end', 'catchpoint' ,
127
+ # 'text'=> 'catchpoint',
128
+ # 'raisecmd'=>proc{}
129
+ # )
130
+
131
+ build_var_panel(_tab_var)
132
+ #build_break_panel(_tab_breakpoint)
133
+ @stack_nodes = Array.new
134
+ @enb.raise('vars')
135
+
136
+ end
137
+
138
+ def build_process_panel(_frame)
139
+ @tree_process = Tk::BWidget::Tree.new(_frame, Arcadia.style('treepanel')){
140
+ showlines false
141
+ deltay 15
142
+ place('relwidth' => 1,'relheight' => '1')
143
+ }
144
+ @tree_process.textbind("Double-ButtonPress-1", proc{
145
+ _selected = @tree_process.selection_get[0]
146
+ if @tree_process.parent(_selected)=='client'
147
+ _text = @tree_process.itemcget(_selected, 'text')
148
+ pos = match_position_from_stack(_text)
149
+ if pos.length >0
150
+ Arcadia.process_event(OpenBufferEvent.new(self,'file'=>pos[0], 'row'=>pos[1]))
151
+ #EditorContract.instance.open_file(self, 'file'=>pos[0], 'line'=>pos[1])
152
+ end
153
+ end
154
+ })
155
+
156
+ end
157
+
158
+ def start_process(_filename)
159
+ @tree_process.insert('end', 'root' ,'server', {
160
+ 'text' => "Server => #{File.basename(_filename)} at #{@controller.conf('server.host')}:#{@controller.conf('server.port')}"
161
+ }.update(Arcadia.style('treeitem')))
162
+ @tree_process.insert('end', 'server' ,'client', {
163
+ 'text' => "Client"
164
+ }.update(Arcadia.style('treeitem')))
165
+ @tree_process.open_tree('server',true)
166
+ end
167
+
168
+ def tree_var_free
169
+ @tree_var.delete(@tree_var.nodes('local_var'))
170
+ @tree_var.delete(@tree_var.nodes('instance_var'))
171
+ @tree_var.delete(@tree_var.nodes('global_var'))
172
+ @tree_var.delete(@tree_var.nodes('class_var'))
173
+ @tree_var.delete(@tree_var.nodes('eval')) if @tree_var.exist?('eval')
174
+ end
175
+
176
+ def tree_process_free
177
+ @tree_process.delete(@tree_process.nodes('root'))
178
+ end
179
+
180
+ def bnext_state(_state)
181
+ if _state == B_STATE_ON
182
+ return B_STATE_FREEZE
183
+ elsif _state == B_STATE_FREEZE
184
+ return B_STATE_OFF
185
+ elsif _state == B_STATE_OFF
186
+ return B_STATE_ON
187
+ end
188
+ end
189
+
190
+ def build_var_panel(_frame)
191
+ _open_proc = proc do |_arg|
192
+ inspect_node(_arg) if @nodes_to_open.include?(_arg)
193
+ end
194
+
195
+ @tree_var = Tk::BWidget::Tree.new(_frame, Arcadia.style('treepanel')){
196
+ showlines true
197
+ deltay 15
198
+ opencmd _open_proc
199
+ }.place('relwidth' => 1,'relheight' => '1','bordermode' => 'inside')
200
+
201
+ _scrollcommand = proc{|*args| @tree_var.yview(*args)}
202
+ _scrollbar = TkScrollbar.new(_frame, Arcadia.style('scrollbar')){|s|
203
+ width 8
204
+ command _scrollcommand
205
+ }.pack('side'=>'right', 'fill'=>'y')
206
+ @tree_var.yscrollcommand proc{|first,last| _scrollbar.set(first,last)}
207
+
208
+ @tree_var.textbind("Double-ButtonPress-1", proc{
209
+ _selected = @tree_var.selection_get[0]
210
+ _msg = @tree_var.itemcget(_selected, 'text')
211
+ Arcadia.dialog(self, 'type'=>'ok','title' => 'Value', 'msg' => _msg, 'level'=>'info')
212
+ })
213
+
214
+
215
+ @local_state = B_STATE_ON
216
+ @instance_state = B_STATE_ON
217
+ @class_state = B_STATE_ON
218
+ @global_state = B_STATE_OFF
219
+
220
+ _i_on = TkPhotoImage.new('dat' => ON_GIF)
221
+ _i_off = TkPhotoImage.new('dat' => OFF_GIF)
222
+ _i_freeze = TkPhotoImage.new('dat' => FREEZE_GIF)
223
+
224
+ _b_relief = 'groove'
225
+ #------------------ loacal variables -------------------
226
+ _loc_var_text = "Local variables"
227
+ @b_local_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
228
+ image _i_on
229
+ state 'disabled'
230
+ anchor 'nw'
231
+ }.bind("1",proc{
232
+ @local_state = bnext_state(@local_state)
233
+ if @local_state == B_STATE_ON
234
+ @tree_var.itemconfigure('local_var',
235
+ 'text'=>"#{_loc_var_text}",
236
+ 'helptext'=>""
237
+ )
238
+ @b_local_onoff.image(_i_on)
239
+ command_enabled(false)
240
+ Thread.new{
241
+ update_variables('local_var', @controller.rdc.variables('local_variables')) #if @tree_var.open?('local_var')
242
+ command_enabled(true)
243
+ }
244
+ elsif @local_state == B_STATE_FREEZE
245
+ @b_local_onoff.image(_i_freeze)
246
+ @tree_var.itemconfigure('local_var',
247
+ 'text'=>"#{_loc_var_text} freeze at #{@last_position_string}",
248
+ 'helptext'=>"#{_loc_var_text} freeze at #{@last_position_string}"
249
+ )
250
+ elsif @local_state == B_STATE_OFF
251
+ @b_local_onoff.image(_i_off)
252
+ @tree_var.delete(@tree_var.nodes('local_var'))
253
+ @tree_var.itemconfigure('local_var',
254
+ 'text'=>"#{_loc_var_text}",
255
+ 'helptext'=>""
256
+ )
257
+ end
258
+ })
259
+
260
+ @tree_var.insert('end', 'root' ,'local_var', Arcadia.style('treeitem').update({
261
+ 'fill'=>Arcadia.conf('hightlight.8.foreground'),
262
+ 'open'=>true,
263
+ 'anchor'=>'w',
264
+ 'text' => _loc_var_text,
265
+ 'window' => @b_local_onoff
266
+ }))
267
+
268
+ #------------------ instance variables -------------------
269
+ _instance_var_text="Instance variables"
270
+ @b_instance_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
271
+ image _i_on
272
+ #relief _b_relief
273
+ state 'disabled'
274
+ anchor 'nw'
275
+ }.bind("1",proc{
276
+ @instance_state = bnext_state(@instance_state)
277
+ if @instance_state == B_STATE_ON
278
+ @tree_var.itemconfigure('instance_var',
279
+ 'text'=>"#{_instance_var_text}",
280
+ 'helptext'=>""
281
+ )
282
+ @b_instance_onoff.image(_i_on)
283
+ command_enabled(false)
284
+ Thread.new{
285
+ update_variables('instance_var', @controller.rdc.variables('instance_variables')) #if @tree_var.open?('local_var')
286
+ command_enabled(true)
287
+ }
288
+ elsif @instance_state == B_STATE_FREEZE
289
+ @b_instance_onoff.image(_i_freeze)
290
+ @tree_var.itemconfigure('instance_var',
291
+ 'text'=>"#{_instance_var_text} freeze at #{@last_position_string}",
292
+ 'helptext'=>"#{_instance_var_text} freeze at #{@last_position_string}"
293
+ )
294
+ elsif @instance_state == B_STATE_OFF
295
+ @b_instance_onoff.image(_i_off)
296
+ @tree_var.delete(@tree_var.nodes('instance_var'))
297
+ @tree_var.itemconfigure('instance_var',
298
+ 'text'=>"#{_instance_var_text}",
299
+ 'helptext'=>""
300
+ )
301
+ end
302
+ })
303
+ @tree_var.insert('end', 'root' ,'instance_var', Arcadia.style('treeitem').update({
304
+ 'fill'=>Arcadia.conf('hightlight.9.foreground'),
305
+ 'open'=>true,
306
+ 'anchor'=>'w',
307
+ 'text' => _instance_var_text,
308
+ 'window' => @b_instance_onoff
309
+ }))
310
+
311
+ #------------------ class variables -------------------
312
+ _class_var_text="Class variables"
313
+ @b_class_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
314
+ image _i_on
315
+ #relief _b_relief
316
+ state 'disabled'
317
+ anchor 'nw'
318
+ }.bind("1",proc{
319
+ @class_state = bnext_state(@class_state)
320
+ if @class_state == B_STATE_ON
321
+ @tree_var.itemconfigure('class_var',
322
+ 'text'=>"#{_class_var_text}",
323
+ 'helptext'=>""
324
+ )
325
+ @b_class_onoff.image(_i_on)
326
+ command_enabled(false)
327
+ Thread.new{
328
+ update_variables('class_var', @controller.rdc.variables('self.class.class_variables')) #if @tree_var.open?('local_var')
329
+ command_enabled(true)
330
+ }
331
+ elsif @class_state == B_STATE_FREEZE
332
+ @b_class_onoff.image(_i_freeze)
333
+ @tree_var.itemconfigure('class_var',
334
+ 'text'=>"#{_class_var_text} freeze at #{@last_position_string}",
335
+ 'helptext'=>"#{_class_var_text} freeze at #{@last_position_string}"
336
+ )
337
+ elsif @class_state == B_STATE_OFF
338
+ @b_class_onoff.image(_i_off)
339
+ @tree_var.delete(@tree_var.nodes('class_var'))
340
+ @tree_var.itemconfigure('class_var',
341
+ 'text'=>"#{_class_var_text}",
342
+ 'helptext'=>""
343
+ )
344
+ end
345
+ })
346
+ @tree_var.insert('end', 'root' ,'class_var', Arcadia.style('treeitem').update({
347
+ 'fill'=>Arcadia.conf('hightlight.10.foreground'),
348
+ 'open'=>true,
349
+ 'anchor'=>'w',
350
+ 'text' => _class_var_text,
351
+ 'window' => @b_class_onoff
352
+ }))
353
+
354
+
355
+ #------------------ global variables -------------------
356
+ _global_var_text="Global variables"
357
+ @b_global_onoff = TkButton.new(@tree_var, Arcadia.style('button')){
358
+ image _i_off
359
+ #relief _b_relief
360
+ state 'disabled'
361
+ anchor 'nw'
362
+ }.bind("1",proc{
363
+ @global_state = bnext_state(@global_state)
364
+ if @global_state == B_STATE_ON
365
+ @tree_var.itemconfigure('global_var',
366
+ 'text'=>"#{_global_var_text}",
367
+ 'helptext'=>""
368
+ )
369
+ @b_global_onoff.image(_i_on)
370
+ command_enabled(false)
371
+ Thread.new{
372
+ update_variables('global_var', @controller.rdc.variables('global_variables')) #if @tree_var.open?('local_var')
373
+ command_enabled(true)
374
+ }
375
+ elsif @global_state == B_STATE_FREEZE
376
+ @b_global_onoff.image(_i_freeze)
377
+ @tree_var.itemconfigure('global_var',
378
+ 'text'=>"#{_global_var_text} freeze at #{@last_position_string}",
379
+ 'helptext'=>"#{_global_var_text} freeze at #{@last_position_string}"
380
+ )
381
+ elsif @global_state == B_STATE_OFF
382
+ @b_global_onoff.image(_i_off)
383
+ @tree_var.delete(@tree_var.nodes('global_var'))
384
+ @tree_var.itemconfigure('global_var',
385
+ 'text'=>"#{_global_var_text}",
386
+ 'helptext'=>""
387
+ )
388
+ end
389
+ })
390
+ @tree_var.insert('end', 'root' ,'global_var', Arcadia.style('treeitem').update({
391
+ 'fill'=>Arcadia.conf('hightlight.11.foreground'),
392
+ 'open'=>true,
393
+ 'anchor'=>'w',
394
+ 'text' => _global_var_text,
395
+ 'window' => @b_global_onoff
396
+ }))
397
+ end
398
+
399
+ # def build_break_panel(_tab_breakpoint)
400
+ # @tree_break = Tk::BWidget::Tree.new(_tab_breakpoint, Arcadia.style('treepanel')){
401
+ # showlines true
402
+ # deltay 15
403
+ # }.place('relwidth' => 1,'relheight' => '1')
404
+ # end
405
+
406
+ def file2node_name(_file)
407
+ _s = ""
408
+ _file.gsub("/",_s).gsub(".",_s).gsub(":",_s).gsub("\\",_s).gsub("-",_s)
409
+ end
410
+
411
+ def line2node_name(_parent, _line)
412
+ "#{_parent}_#{_line.to_s}"
413
+ end
414
+
415
+ # def break_list_add(_file, _line)
416
+ # _file_node = file2node_name(_file)
417
+ # _line_node = line2node_name(_file_node, _line)
418
+ # if !@tree_break.exist?(_file_node)
419
+ # @tree_break.insert('end', 'root' ,_file_node, {
420
+ # 'open'=>true,
421
+ # 'anchor'=>'w',
422
+ # 'text' => _file
423
+ # }.update(Arcadia.style('treeitem')))
424
+ # end
425
+ #
426
+ # if !@tree_break.exist?(_line_node)
427
+ # @tree_break.insert('end', _file_node ,_line_node, {
428
+ # 'open'=>true,
429
+ # 'anchor'=>'w',
430
+ # 'text' => "line: #{_line}"
431
+ # }.update(Arcadia.style('treeitem')))
432
+ # end
433
+ # end
434
+
435
+ # def break_list_del(_file, _line)
436
+ # _file_node = file2node_name(_file)
437
+ # _line_node = line2node_name(_file_node, _line)
438
+ # if @tree_break.exist?(_line_node)
439
+ # @tree_break.delete(_line_node)
440
+ # _bro = @tree_break.nodes(_file_node)
441
+ # if _bro && _bro.length > 0
442
+ # @tree_break.delete(_file_node)
443
+ # end
444
+ # end
445
+ # end
446
+
447
+ # def break_list_select(_file, _line)
448
+ # _file_node = file2node_name(_file)
449
+ # _line_node = line2node_name(_file_node, _line)
450
+ # @tree_break.selection_clear
451
+ # if @tree_break.exist?(_line_node)
452
+ # @tree_break.selection_add(_line_node)
453
+ # @tree_break.see(_line_node)
454
+ # end
455
+ # end
456
+
457
+
458
+ # def break_list_free
459
+ # @tree_break.delete(@tree_break.nodes('root'))
460
+ # end
461
+
462
+ def clear
463
+ tree_var_free
464
+ tree_process_free
465
+ #break_list_free
466
+ end
467
+
468
+
469
+ def rdebug_client_update(_command, _result)
470
+ #Arcadia.console(self,'msg'=>"on command #{_command} => #{_result}", 'level'=>'debug')
471
+ return if @controller.rdc.nil? || !@controller.rdc.is_debugging_ready? || !@controller.rds.is_alive?
472
+ begin
473
+ if _command == 'quit'
474
+ msg = "Really quit debug ? (y/n)"
475
+ ans = Tk.messageBox('icon' => 'question', 'type' => 'yesno',
476
+ 'title' => '(Arcadia) Debug', 'message' => msg)
477
+ if ans == 'yes'
478
+ debug_send(:quit_yes)
479
+ clear
480
+ else
481
+ debug_send(:quit_no)
482
+ end
483
+ elsif _command == 'quit_yes'
484
+ clear
485
+ elsif _command == 'quit_no'
486
+ command_enabled(true)
487
+ elsif _command == 'cont' && !_result.downcase.include?('breakpoint')
488
+ @controller.rdc.kill
489
+ clear
490
+ elsif _command != 'where' && _command != 'quit_yes'
491
+ begin
492
+ update_position
493
+ update_variables('local_var', @controller.rdc.variables('local_variables')) if @local_state == B_STATE_ON
494
+ update_variables('instance_var', @controller.rdc.variables('instance_variables')) if @instance_state == B_STATE_ON
495
+ update_variables('class_var', @controller.rdc.variables('self.class.class_variables')) if @class_state == B_STATE_ON
496
+ #Arcadia.new_debug_msg(self,"on command #{_command}:global_variables")
497
+ update_variables('global_var', @controller.rdc.variables('global_variables')) if @global_state == B_STATE_ON
498
+ ensure
499
+ command_enabled(true) if !@controller.rdc.nil? && @controller.rdc.is_debugging_ready? && (!_command.include?('quit') || _command.include?('quit_no'))
500
+ end
501
+ end
502
+ rescue Exception => e
503
+ Arcadia.console(self, 'msg'=>"on command #{_command}:#{e.inspect}", 'level'=>'debug')
504
+ #Arcadia.new_debug_msg(self,"on command #{_command}:#{e.inspect}")
505
+ end
506
+ end
507
+
508
+ def match_position_from_stack(_line)
509
+ #Arcadia.new_error_msg(self, "match on #{_line}")
510
+ ret = Array.new
511
+ matchline = _line.match(/#*([0-9]*)[\s\w\W]*\s(.*):([0-9]*)(.*)/)
512
+ if !matchline.nil? && matchline.length==5
513
+ #Arcadia.new_error_msg(self, "matchline[2]=#{matchline[2]}")
514
+ #Arcadia.new_error_msg(self, "matchline[3]=#{matchline[3]}")
515
+ filename = matchline[2].to_s.strip
516
+ line_no = matchline[3].to_i
517
+ if filename && line_no
518
+ ret << filename << line_no
519
+ end
520
+ end
521
+ ret
522
+ end
523
+
524
+ def update_position
525
+ stack = @controller.rdc.where
526
+ #Arcadia.new_debug_msg(self,stack)
527
+ if !stack.nil?
528
+ stack = stack.split(/\n/)
529
+ line_no = -1
530
+ if stack.length > 1 && stack[1].strip[0..0]!='#'
531
+ pos = match_position_from_stack(stack[1].strip)
532
+ elsif !stack[0].nil?
533
+ pos = match_position_from_stack(stack[0])
534
+ end
535
+ if pos.length > 0
536
+ _file = pos[0]
537
+ #p "_file=#{_file}"
538
+ _file = File.expand_path(pos[0]) if !File.exist?(_file)
539
+ Arcadia.broadcast_event(DebugStepInfoEvent.new(self,'file'=> _file, 'row'=>pos[1]))
540
+ #DebugContract.instance.debug_step(self, 'file'=> _file, 'line'=>pos[1])
541
+ #break_list_select(_file, pos[1].to_s)
542
+ @last_position_string = "#{pos[0]}:#{pos[1]}"
543
+ end
544
+ i = 0
545
+ @tree_process.delete(@stack_nodes)
546
+ stack.each do |line|
547
+ _node = "c#{i.to_s}"
548
+ @tree_process.insert('end', 'client' ,_node, {
549
+ 'text' => line,
550
+ 'helptext' => line
551
+ }.update(Arcadia.style('treeitem')))
552
+ #Arcadia.console(self, 'msg'=>"inserted line #{line}")
553
+ @stack_nodes << _node
554
+ i = i+1
555
+ end
556
+ end
557
+ end
558
+
559
+ def is_simple_class?(_var)
560
+ ['Numeric','Fixnum','String','FalseClass','TrueClass','NilClass'].include?(_var.value_class) && !_var.value.to_s.strip.include?("\n")
561
+ end
562
+
563
+ def show_expression(_exp, _hash)
564
+ if !@tree_var.exist?('eval')
565
+ @tree_var.insert('end', 'root' ,'eval', Arcadia.style('treeitem').update({
566
+ 'fill'=>Arcadia.conf('hightlight.13.foreground'),
567
+ 'open'=>true,
568
+ 'anchor'=>'w',
569
+ 'text' => "Eval selection"
570
+ }))
571
+ end
572
+ update_variables('eval', _hash)
573
+ end
574
+
575
+ def inspect_node(_node)
576
+ command_enabled(false)
577
+ begin
578
+ _var = var_name(_node)
579
+ _o = @controller.rdc.debug_dump(_var)
580
+ if _o.class == Hash
581
+ var_deep(_node, _o)
582
+ else
583
+ var_deep_string(_node, _o)
584
+ end
585
+ ensure
586
+ command_enabled(true)
587
+ end
588
+ end
589
+
590
+ def var_deep(_var, _hash)
591
+ # _var_cla = _hash['__CLASS__']
592
+ # _var_len = _hash['__LENGTH__']
593
+ # @tree_var.itemconfigure(_var, 'text' => "#{_var_cla}:#{_var_len}")
594
+ return nil if _hash.nil?
595
+ return _hash.to_s if _hash.class != Hash
596
+ if _hash['__CLASS__']=='Array'
597
+ _sorted_keys = _hash.keys.collect!{|x| x.to_i}.sort.collect!{|x| x.to_s}
598
+ else
599
+ _sorted_keys = _hash.keys.sort
600
+ end
601
+ _sorted_keys.each{|k|
602
+ #_hash.keys.sort.each{|k|
603
+ v = _hash[k]
604
+ next if k=='__CLASS__'
605
+ _complex = v.class == Hash
606
+ if _complex
607
+ _text = var_format(k,v['__CLASS__'])
608
+ elsif (k=='__LENGTH__') && v=='0'
609
+ _text = '{}'
610
+ elsif (k=='__LENGTH__') && v!='0'
611
+ next
612
+ elsif _hash['__CLASS__']=='Array'
613
+ _text = var_format(k.rjust(_hash['__LENGTH__'].length),nil,v,false)
614
+ else
615
+ _text = var_format(k,nil,v)
616
+ end
617
+ _node = node_name(k, _var)
618
+ if @tree_var.exist?(_node)
619
+ @tree_var.itemconfigure(_node, 'text' => _text)
620
+ else
621
+ @tree_var.insert('end', _var ,_node, Arcadia.style('treeitem').update({
622
+ 'text' => _text,
623
+ 'helptext' => v,
624
+ 'anchor'=>'w'
625
+ }))
626
+ end
627
+ var_deep(_node,v) if _complex
628
+ }
629
+ end
630
+
631
+ def var_deep_string(_var, _str)
632
+ @tree_var.delete(@tree_var.nodes(_var))
633
+ return nil if _str.nil?
634
+ _str = _str.to_s if !_str.kind_of?(String)
635
+ a_str = _str.split("\n")
636
+ a_str.each_with_index{|v,i|
637
+ _node = node_name(i.to_s, _var)
638
+ @tree_var.insert('end', _var ,_node, Arcadia.style('treeitem').update({
639
+ 'text' => v,
640
+ 'fill' => Arcadia.conf('hightlight.12.foreground'),
641
+ 'anchor'=>'w'
642
+ }))
643
+ }
644
+ end
645
+
646
+
647
+ def var_format(_name, _class, _value=nil, _strip_name=true)
648
+ if _strip_name
649
+ _name = _name.to_s.strip
650
+ else
651
+ _name = _name.to_s
652
+ end
653
+ if !_value.nil? && !_class.nil?
654
+ return "#{_name} => #{_value.to_s.strip} [#{_class.to_s.strip}]"
655
+ elsif _value.nil? && !_class.nil?
656
+ return "#{_name} [#{_class.to_s.strip}]"
657
+ elsif !_value.nil? && _class.nil?
658
+ return "#{_name} => #{_value.to_s.strip}"
659
+ elsif _value.nil? && _class.nil?
660
+ return "#{_name} => {}"
661
+ end
662
+ end
663
+
664
+ def node_name(_node, _parent)
665
+ return "#{_parent}@@@#{_node.gsub('$','__S__').gsub('&','__E__').gsub(':','__D__').gsub('!','__A__')}"
666
+ end
667
+
668
+ def var_name(_node)
669
+ #_parent = @tree_var.parent(_node)
670
+ #return _node.sub("#{_parent}_", '')
671
+ return _node.split('@@@')[-1].gsub('__S__','$').gsub('__E__','&').gsub('__D__',':').gsub('__A__','!')
672
+ end
673
+
674
+ def command_enabled(_value)
675
+ #Arcadia.new_debug_msg(self,"command_enabled= #{_value.to_s}")
676
+ @c_on = _value
677
+ _value ? _state = 'normal':_state = 'disabled'
678
+ @debug_button_box.configure(:state=>_state)
679
+ @b_local_onoff.configure(:state=>_state)
680
+ @b_instance_onoff.configure(:state=>_state)
681
+ @b_class_onoff.configure(:state=>_state)
682
+ @b_global_onoff.configure(:state=>_state)
683
+ Tk.update
684
+ end
685
+
686
+ def update_variables(_parent_node, _var)
687
+ #Arcadia.console(self, 'msg'=>"---update_variables =>#{_var} figlio di #{_parent_node}")
688
+ if _var.keys.sort == @tree_var.nodes(_parent_node).collect! {|x| var_name(x).to_s}.sort
689
+ _var.each{|k,v|
690
+ #Arcadia.console(self, 'msg'=>"node_name of #{k}")
691
+ _n = node_name(k, _parent_node)
692
+ if is_simple_class?(v)
693
+ _text = var_format(k,v.value_class,v.value)
694
+ _drawcross = 'auto'
695
+ else
696
+ _text = var_format(k,v.value_class)
697
+ _drawcross = 'always'
698
+ @nodes_to_open << _n if !@nodes_to_open.include?(_n)
699
+ inspect_node(_n) if bool(@tree_var.itemcget(@tree_var.tagid(_n), 'open'))
700
+ end
701
+ #Arcadia.console(self, 'msg'=>"_n=#{_n} text=#{_text}")
702
+ _node = @tree_var.itemconfigure(_n,
703
+ 'text' => _text,
704
+ 'helptext' => v.value,
705
+ 'drawcross' => _drawcross
706
+ )
707
+ }
708
+ else
709
+ @nodes_to_open.clear
710
+ @tree_var.delete(@tree_var.nodes(_parent_node))
711
+ #@nodes[_parent_node].clear
712
+ _var.keys.sort.each{|k|
713
+ v = _var[k]
714
+ _n = node_name(k, _parent_node)
715
+ if is_simple_class?(v)
716
+ _text = var_format(k,v.value_class,v.value)
717
+ _drawcross = 'auto'
718
+ else
719
+ _text = var_format(k,v.value_class)
720
+ _drawcross = 'always'
721
+ @nodes_to_open << _n
722
+ end
723
+ @tree_var.insert('end', _parent_node ,_n, Arcadia.style('treeitem').update({
724
+ 'text' => _text,
725
+ 'helptext' => v.value,
726
+ 'drawcross' => _drawcross,
727
+ 'anchor'=>'w'
728
+ }))
729
+ }
730
+ end
731
+ Tk.update
732
+ end
733
+
734
+ def debug_send(_command)
735
+ if @controller.rdc
736
+ begin
737
+ command_enabled(false)
738
+ #@debug_button_box.configure(:state=>'disabled')
739
+ Thread.new do
740
+ Arcadia.process_event(StepDebugEvent.new(self, 'command'=>_command))
741
+ #@controller.rdc.send(_command)
742
+ end
743
+ #@controller.rdc.send(_command)
744
+ rescue Exception => e
745
+ Arcadia.console(self, 'msg'=>"---> "+e.to_s, 'level'=>'debug')
746
+ #Arcadia.new_debug_msg(self,"---> "+e.to_s)
747
+ end
748
+ end
749
+ end
750
+ end
751
+
752
+ class RubyDebugException < Exception
753
+ end
754
+
755
+ class RubyDebugServer
756
+ include Observable
757
+ attr_accessor :quit_confirm_request
758
+ RDS_QUIET = 'RDS_QUIET'
759
+ def initialize(_caller, _arcadia=nil)
760
+ if _caller.respond_to? :rdebug_server_update
761
+ ObserverCallback.new(self,_caller,:rdebug_server_update)
762
+ end
763
+ @arcadia = _arcadia
764
+ @quit_confirm_request = false
765
+ @alive = false
766
+ end
767
+
768
+ def start_session_new(_filename, _host='localhost', _remote_port='8989')
769
+ if is_windows?
770
+ commandLine = "rdebug.cmd --host #{_host} --port #{_remote_port} -sw #{_filename}"
771
+ else
772
+ commandLine = "rdebug --host #{_host} --port #{_remote_port} -sw #{_filename}"
773
+ end
774
+ Arcadia.process_event(SystemExecEvent.new(self, 'command'=>commandLine))
775
+ end
776
+
777
+ def is_alive?
778
+ @alive
779
+ end
780
+
781
+ def set_alive(_value=false)
782
+ @alive = _value
783
+ end
784
+
785
+ def start_session(_filename, _host='localhost', _remote_port='8989')
786
+ if is_windows?
787
+ commandLine = "rdebug.cmd --port #{_remote_port} -sw #{_filename}"
788
+ else
789
+ commandLine = "rdebug --host #{_host} --port #{_remote_port} -sw #{_filename}"
790
+ end
791
+ begin
792
+ @alive = true
793
+ if is_windows?
794
+ @tid = Thread.new do
795
+ if Kernel.system(commandLine)
796
+ Kernel.system('y')
797
+ else
798
+ if @quit_confirm_request
799
+ Arcadia.console(self, 'msg'=>"#{$?.inspect}")
800
+ #Arcadia.new_msg(self,"#{$?.inspect}")
801
+ else
802
+ _event = Arcadia.process_event(RunRubyFileEvent.new(self, 'file'=>_filename))
803
+ Arcadia.console(self, 'msg'=>"#{_event.results[0].output}", 'level'=>'debug')
804
+ #Arcadia.new_debug_msg(self,"#{_event.results[0].output}")
805
+ end
806
+ end
807
+ set_alive(false)
808
+ notify(RDS_QUIET)
809
+ end
810
+ else
811
+ @pid = Process.fork do
812
+ if Kernel.system(commandLine)
813
+ set_alive(false)
814
+ #p "alive=#{is_alive?}"
815
+ notify(RDS_QUIET)
816
+ Kernel.system('y')
817
+ Kernel.exit!
818
+ else
819
+ Kernel.exit!
820
+ Arcadia.console(self, 'msg'=>"#{$?.inspect}", 'level'=>'debug')
821
+ #Arcadia.new_debug_msg(self,"#{$?.inspect}")
822
+ end
823
+ #p "@alive=#{@alive}"
824
+ #notify(RDS_QUIET)
825
+ #Process.wait
826
+ end
827
+ end
828
+ rescue Exception => e
829
+ Arcadia.console(self, 'msg'=>"Error on start_server : #{e.class}:#{e.message}", 'level'=>'debug')
830
+ #Arcadia.new_debug_msg(self,"Error on start_server : #{e.class}:#{e.message}")
831
+ end
832
+ end
833
+
834
+ def kill
835
+ begin
836
+ if is_windows?
837
+ @tid.join(2)
838
+ @tid.kill!
839
+ else
840
+ Process.kill('QUIT',@pid)
841
+ end
842
+ notify(RDS_QUIET)
843
+ rescue Exception => e
844
+ Arcadia.console(self, 'msg'=>"Error on kill : #{e.class}:#{e.message}", 'level'=>'debug')
845
+ #Arcadia.new_debug_msg(self,"Error on start_server : #{e.class}:#{e.message}")
846
+ end
847
+ end
848
+
849
+ def is_windows?
850
+ !(RUBY_PLATFORM =~ /(win|w)32$/).nil?
851
+ end
852
+
853
+ def notify(_state)
854
+ #p "----- notify ----- #{_state}"
855
+ changed
856
+ notify_observers(_state)
857
+ end
858
+
859
+ end
860
+
861
+ #Ruby-debug commands
862
+
863
+ # * b[reak]
864
+ # list breakpoints
865
+ # * b[reak] [file|class:]LINE|METHOD [if expr]
866
+ # * b[reak] [class.]LINE|METHOD [if expr]
867
+ # set breakpoint to some position, optionally if expr == true
868
+ # * cat[ch]
869
+ # show catchpoint
870
+ # * cat[ch] EXCEPTION
871
+ # set catchpoint to an exception
872
+ # * disp[lay] EXPRESSION add expression into display expression list
873
+ # * undisp[lay][ nnn]
874
+ # delete one particular or all display expressions if no expression number given
875
+ # * del[ete][ nnn]
876
+ # delete some or all breakpoints (get the number using “break”)
877
+ # * c[ont]
878
+ # run until program ends or hit breakpoint
879
+ # * r[un]
880
+ # alias for cont
881
+ # * s[tep][ nnn]
882
+ # step (into methods) one line or till line nnn
883
+ # * n[ext][ nnn]
884
+ # go over one line or till line nnn
885
+ # * w[here]
886
+ # displays stack
887
+ # * f[rame]
888
+ # alias for where
889
+ # * l[ist][ (-|nn-mm)]
890
+ # list program, - list backwards, nn-mm list given lines. No arguments keeps listing
891
+ # * up[ nn]
892
+ # move to higher frame
893
+ # * down[ nn]
894
+ # move to lower frame
895
+ # * fin[ish]
896
+ # return to outer frame
897
+ # * q[uit]
898
+ # exit from debugger
899
+ # * v[ar] g[lobal]
900
+ # show global variables
901
+ # * v[ar] l[ocal]
902
+ # show local variables
903
+ # * v[ar] i[nstance] OBJECT
904
+ # show instance variables of object
905
+ # * v[ar] c[onst] OBJECT
906
+ # show constants of object
907
+ # * m[ethod] i[nstance] OBJECT
908
+ # show methods of object
909
+ # * m[ethod] CLASS|MODULE
910
+ # show instance methods of class or module
911
+ # * th[read] l[ist]
912
+ # list all threads
913
+ # * th[read] c[ur[rent]]
914
+ # show current thread
915
+ # * th[read] [sw[itch]] nnn
916
+ # switch thread context to nnn
917
+ # * th[read] stop nnn
918
+ # stop thread nnn
919
+ # * th[read] resume nnn
920
+ # resume thread nnn
921
+ # * p EXPRESSION
922
+ # evaluate expression and print its value
923
+ # * pp EXPRESSSION
924
+ # evaluate expression and print its value
925
+ # * h[elp]
926
+ # print this help
927
+ # * RETURN KEY
928
+ # redo previous command. Convenient when using list, step, next, up, down,
929
+ # * EVERYHTING ELSE
930
+ # evaluate
931
+
932
+
933
+ class RubyDebugClient
934
+ require 'socket'
935
+ require 'yaml'
936
+ include Observable
937
+ Var = Struct.new("Var",
938
+ :value,
939
+ :value_class
940
+ )
941
+
942
+ def initialize(_controller, _server='localhost', _port=8989, _timeout=0)
943
+ @controller = _controller
944
+ @session = nil
945
+ @server = _server
946
+ @port = _port
947
+ @timeout = _timeout.to_i
948
+ @busy = false
949
+ @pend = false
950
+ end
951
+
952
+ def add_listener(_caller, _method=:rdebug_client_update)
953
+ if _caller.respond_to? :rdebug_client_update
954
+ ObserverCallback.new(self,_caller,:rdebug_client_update)
955
+ end
956
+ end
957
+
958
+ def notify(_command, _result=nil)
959
+ #Arcadia.new_debug_msg(self,"notify=>#{_command}")
960
+ @busy = false
961
+ changed
962
+ notify_observers(_command, _result)
963
+ _result
964
+ end
965
+
966
+ def is_debugging_ready?
967
+ is_alive? && !is_busy?
968
+ end
969
+
970
+ def is_busy?
971
+ @busy
972
+ end
973
+
974
+ def is_alive?
975
+ #p "===>@session=#{@session}"
976
+ #p "===>@session.closed?=#{@session.closed?}" if @session
977
+ #p "===>@pend=#{@pend}"
978
+ !(@session.nil? || @session.closed? || @pend)
979
+ #(!@session.nil? && !@session.closed? && !@pend)
980
+ end
981
+
982
+ def socket_session
983
+ #p "====>socket_session"
984
+ #Arcadia.new_debug_msg(self,"socket_session : passo")
985
+ if @session.nil? && @controller.rds.is_alive?
986
+ begin
987
+ #sleep(2)
988
+ @session = TCPSocket.new(@server, @port)
989
+ @pend = false
990
+ rescue Errno::ECONNREFUSED,Errno::EBADF => e
991
+ sleep(1)
992
+ @t = @t -1
993
+ if @t > 0
994
+ socket_session
995
+ else
996
+ Arcadia.console(self, 'msg'=>"socket_session : #{e.inspect}", 'level'=>'debug')
997
+ #Arcadia.new_debug_msg(self,"socket_session : #{e.inspect}")
998
+ end
999
+ rescue Exception => e
1000
+ @session = nil
1001
+ Arcadia.console(self, 'msg'=>"Error on socket_session : #{e.class}:#{e.message}", 'level'=>'debug')
1002
+ #Arcadia.new_debug_msg(self,"Error on socket_session : #{e.class}:#{e.message}")
1003
+ end
1004
+ elsif !@controller.rds.is_alive?
1005
+ @session = nil
1006
+ end
1007
+ #Arcadia.new_debug_msg(self,"session : #{@session.inspect}")
1008
+ #p "@session=>#{@session}"
1009
+ return @session
1010
+ end
1011
+
1012
+ def kill
1013
+ begin
1014
+ @session.close if is_alive?
1015
+ @session=nil
1016
+ rescue Exception => e
1017
+ Arcadia.console(self, 'msg'=>"Error on close session : #{e.class}:#{e.message}", 'level'=>'debug')
1018
+ #Arcadia.new_debug_msg(self,"Error on close session : #{e.class}:#{e.message}")
1019
+ end
1020
+ end
1021
+
1022
+ def start_session
1023
+ begin
1024
+ #p "======>start session"
1025
+ @t = @timeout
1026
+ if socket_session
1027
+ #Arcadia.new_debug_msg(self,"session : #{@session.inspect}")
1028
+ notify('start', read)
1029
+ read("eval require 'yaml'")
1030
+ end
1031
+ return @session
1032
+ rescue Exception => e
1033
+ Arcadia.console(self, 'msg'=>"Error on start_session : #{e.class}:#{e.message}", 'level'=>'debug')
1034
+ #Arcadia.new_debug_msg(self,"Error on start_session : #{e.class}:#{e.message}")
1035
+ end
1036
+ end
1037
+
1038
+ def stop_session
1039
+ begin
1040
+ quit if is_debugging_ready?
1041
+ @session.close if is_alive?
1042
+ rescue Exception => e
1043
+ Arcadia.console(self, 'msg'=>"Error on stop_session : #{e.class}:#{e.inspect}", 'level'=>'debug')
1044
+ #Arcadia.new_debug_msg(self,"Error on stop_session : #{e.class}:#{e.inspect}")
1045
+ end
1046
+ end
1047
+
1048
+ # send a command to the debugger via socket
1049
+ def command(_command)
1050
+ #Arcadia.new_debug_msg(self,"command=>#{_command}")
1051
+ begin
1052
+ return false if @busy
1053
+ if is_alive?
1054
+ @busy = true
1055
+ @session.puts(_command) if socket_session
1056
+ else
1057
+ start_session if !@pend
1058
+ end
1059
+ #_command !="cont"
1060
+ true
1061
+ rescue Errno::ECONNABORTED => e
1062
+ notify("quit_yes")
1063
+ #DebugContract.instance.debug_end(self)
1064
+ Arcadia.console(self, 'msg'=>"Debugger has finished executing:\n #{e.class}:#{e.inspect}", 'level'=>'debug')
1065
+ #Arcadia.new_debug_msg(self,"Debugger has finished executing:\n #{e.class}:#{e.inspect}")
1066
+ @session = nil
1067
+ @pend = true
1068
+ false
1069
+ #raise RubyDebugException.new("Debugged has finished executing")
1070
+ rescue Exception => e
1071
+ Arcadia.console(self, 'msg'=>"Error on command #{_command}: #{e.class}:#{e.inspect}", 'level'=>'debug')
1072
+ #Arcadia.new_debug_msg(self,"Error on command #{_command}: #{e.class}:#{e.inspect}")
1073
+ false
1074
+ end
1075
+ end
1076
+ private :command
1077
+
1078
+ def read(_command=nil)
1079
+ return nil if _command && !command(_command)
1080
+ result = ""
1081
+ if socket_session
1082
+ @session.flush
1083
+ while _command !='y' && is_alive? && line = @session.gets
1084
+ break if line =~ /^PROMPT (.*)$/ || line =~ /.(y\/n)./
1085
+ result << line
1086
+ #break if _command =~ /^eval./
1087
+ end
1088
+ #Arcadia.new_debug_msg(self, "read: letta per '#{_command}' result => #{result}")
1089
+ end
1090
+ @busy = false
1091
+ result
1092
+
1093
+ rescue Errno::ECONNABORTED
1094
+ raise RubyDebugException.new("Debugged has finished executing")
1095
+ rescue Errno::ECONNRESET
1096
+ raise RubyDebugException.new("Debugged has finished executing")
1097
+ rescue Exception => e
1098
+ raise RubyDebugException.new("Error: on command '#{_command}' => #{e.class} : #{e.inspect}")
1099
+ end
1100
+ private :read
1101
+
1102
+
1103
+ def step_over
1104
+ notify("next", read("next"))
1105
+ end
1106
+
1107
+ def step_into
1108
+ notify("step", read("step"))
1109
+ end
1110
+
1111
+ def step_out
1112
+ notify("fin", read("fin"))
1113
+ end
1114
+
1115
+ def resume
1116
+ notify("cont", read("cont"))
1117
+ end
1118
+
1119
+ def where
1120
+ notify("where", read("where"))
1121
+ end
1122
+
1123
+ def quit
1124
+ notify("quit", read("q"))
1125
+ end
1126
+
1127
+ def quit_yes
1128
+ notify("quit_yes", read("y"))
1129
+ #DebugContract.instance.debug_end(self)
1130
+ kill
1131
+ end
1132
+
1133
+ def quit_no
1134
+ notify("quit_no", read("n"))
1135
+ end
1136
+
1137
+ # return the current stack trace
1138
+ def stacktrace
1139
+ notify("backtrace", read("backtrace"))
1140
+ end
1141
+
1142
+
1143
+ def yaml_pseudo_load(_obj)
1144
+ just_present = @valuobjs.include?(_obj)
1145
+ @valuobjs << _obj
1146
+ if _obj.class == YAML::DomainType
1147
+ return _obj.type_id if just_present
1148
+ ret = Hash.new
1149
+ ret['__CLASS__']=_obj.type_id
1150
+ l = _obj.value.length
1151
+ ret['__LENGTH__']= l.to_s
1152
+ if l > 0
1153
+ _obj.value.each{|k,v|
1154
+ ret["@#{k}"]=yaml_pseudo_load(v)
1155
+ }
1156
+ end
1157
+ ret
1158
+ elsif _obj.class == Hash
1159
+ #Arcadia.new_msg(self,"_obj Hash="+_obj.inspect)
1160
+ return 'Hash' if just_present
1161
+ ret = Hash.new
1162
+ ret['__CLASS__']= 'Hash'
1163
+ l = _obj.length
1164
+ ret['__LENGTH__']= l.to_s
1165
+ if l > 0
1166
+ _obj.each{|k,v|
1167
+ ret[k]=yaml_pseudo_load(v)
1168
+ }
1169
+ end
1170
+ ret
1171
+ elsif _obj.class == Array
1172
+ #Arcadia.new_msg(self,"_obj Array="+_obj.inspect)
1173
+ return 'Array' if just_present
1174
+ ret = Hash.new
1175
+ ret['__CLASS__']= 'Array'
1176
+ l = _obj.length
1177
+ ret['__LENGTH__']= l.to_s
1178
+ if l > 0
1179
+ _obj.each_with_index{|v,i|
1180
+ ret[i.to_s]=yaml_pseudo_load(v)
1181
+ }
1182
+ end
1183
+ ret
1184
+ elsif _obj.class == Struct
1185
+ #Arcadia.new_msg(self,"_obj Array="+_obj.inspect)
1186
+ return 'Struct' if just_present
1187
+ ret = Hash.new
1188
+ ret['__CLASS__']= 'Struct'
1189
+ l = _obj.length
1190
+ ret['__LENGTH__']= l.to_s
1191
+ if l > 0
1192
+
1193
+ _obj.members.each{|m|
1194
+ ret[m]=yaml_pseudo_load(_obj[m])
1195
+ }
1196
+ end
1197
+ ret
1198
+ else
1199
+ #Arcadia.new_msg(self,"_obj ="+_obj.inspect)
1200
+
1201
+ _obj
1202
+ end
1203
+
1204
+ end
1205
+
1206
+
1207
+ def debug_dump(_exp)
1208
+ var = nil
1209
+ if @valuobjs.nil?
1210
+ @valuobjs = Array.new
1211
+ else
1212
+ @valuobjs.clear
1213
+ end
1214
+ begin
1215
+ _to_eval = read("eval YAML::dump(#{_exp})")
1216
+ if _to_eval.include?('Exception:')
1217
+ _to_eval = read("eval require 'pp';eval #{_exp}.pretty_inspect")
1218
+ var = eval(_to_eval)
1219
+ #var = "?"
1220
+ else
1221
+ _str = eval(_to_eval)
1222
+ _str.gsub!('!ruby/object:', '!')
1223
+ _obj = YAML::load(_str)
1224
+ var = yaml_pseudo_load(_obj)
1225
+ end
1226
+ rescue Exception => e
1227
+ Arcadia.console(self, 'msg'=>"exception on eval #{_exp} :#{e.inspect}")
1228
+ #Arcadia.new_msg(self,"exception on eval #{_exp} :#{e.inspect}")
1229
+ var = nil
1230
+ end
1231
+ return var
1232
+ end
1233
+
1234
+
1235
+ # returns the instance variables and there values
1236
+ def instance_variables_new(_this='self')
1237
+ command("eval #{_this}.instance_variables")
1238
+ variables = []
1239
+ begin
1240
+ variables = eval(read)
1241
+ rescue Exception
1242
+ variables = []
1243
+ end
1244
+ @consider = Array.new
1245
+ variable_values = Hash.new
1246
+ variables.each do |var|
1247
+ #next if var != '@objs'
1248
+ # command("eval require 'pp'; #{var}.pretty_inspect() + '|||' + #{var}.class.to_s")
1249
+ command("eval YAML::dump(#{var})")
1250
+ _str = eval read
1251
+ #Arcadia.new_msg(self,"value passato 1 ="+_str)
1252
+
1253
+ _str.gsub!('!ruby/object:', '!')
1254
+
1255
+ #Arcadia.new_msg(self,"value passato 2 ="+_str)
1256
+
1257
+ _obj = YAML::load(_str)
1258
+
1259
+ _xvalue = yaml_pseudo_load(_obj)
1260
+ if _xvalue.class == Hash
1261
+ _xclass = _xvalue['__CLASS__']
1262
+ else
1263
+ _xclass = _xvalue.class.to_s
1264
+ end
1265
+ #_vvv = eval(_value)
1266
+
1267
+ #Arcadia.new_msg(self,"vvv class="+_vvv.class.to_s)
1268
+
1269
+ #Arcadia.new_msg(self,"value="+_xvalue.inspect)
1270
+ #Arcadia.new_msg(self,"class="+_xclass)
1271
+ variable_values[var] = Var.new(_xvalue, _xclass)
1272
+ end
1273
+ return variable_values
1274
+ end
1275
+
1276
+ # returns the local variables and there values
1277
+ def variables(_type)
1278
+ begin
1279
+ #variables = read[1..-2].split(', ').collect!{|x| x[1..-2]}
1280
+ to_eval = read("eval #{_type}")
1281
+ #Arcadia.new_msg(self,"to_eval="+to_eval.to_s)
1282
+ variables = eval(to_eval)
1283
+ #Arcadia.new_msg(self,"variables="+variables.to_s)
1284
+ rescue Exception => e
1285
+ variables = []
1286
+ #p "on command eval #{_type}:#{e.inspect}"
1287
+ #Arcadia.new_debug_msg(self,"on command eval #{_type}:#{e.inspect}")
1288
+ end
1289
+ variables = [] if variables.nil?
1290
+ variable_values = Hash.new
1291
+ variables.each do |var|
1292
+ next if var=='$;'
1293
+ # command("eval #{var}.to_s + '|||' + #{var}.class.to_s")
1294
+ # _str = eval(read)
1295
+ # _value, _class = _str.split('|||')
1296
+ # variable_values[var] = Var.new(_value, _class)
1297
+ variable_values[var] = debug_eval(var)
1298
+ end
1299
+ return variable_values
1300
+ end
1301
+
1302
+ def debug_eval(_exp)
1303
+ command("eval #{res=_exp}.to_s + '|||' + #{res}.class.to_s")
1304
+ _str = eval(read)
1305
+ _value, _class = _str.split('|||')
1306
+ return Var.new(_value, _class)
1307
+ end
1308
+
1309
+ # returns the local variables and there values
1310
+ def local_variables
1311
+ command("eval local_variables")
1312
+ variables = []
1313
+ begin
1314
+ variables = eval(read)
1315
+ rescue Exception
1316
+ variables = []
1317
+ end
1318
+ variable_values = Hash.new
1319
+ variables.each do |var|
1320
+ command("eval #{var}.to_s + '|||' + #{var}.class.to_s")
1321
+ _str = eval(read)
1322
+ _value, _class = _str.split('|||')
1323
+ variable_values[var] = Var.new(_value, eval(_class))
1324
+ end
1325
+ return variable_values
1326
+ end
1327
+
1328
+
1329
+ # returns the global variables and there values
1330
+ def global_variables
1331
+ command("eval global_variables")
1332
+ variables = []
1333
+ begin
1334
+ variables = eval(read)
1335
+ rescue Exception
1336
+ variables = []
1337
+ end
1338
+ variable_values = Hash.new
1339
+ variables.each do |var|
1340
+ command("eval #{var}.to_s")
1341
+ variable_values[var] = read
1342
+ end
1343
+ return variable_values
1344
+ end
1345
+
1346
+
1347
+ def set_breakpoint(_file, _line)
1348
+ #_line = _line + 1
1349
+ text = read("break #{_file}:#{_line}")
1350
+ breakpoint_no = -1
1351
+ #matches = text.match(/Set breakpoint ([0-9]*)?/)
1352
+ matches = text.downcase.match(/breakpoint ([0-9]*)?/)
1353
+ #Arcadia.new_error_msg(self, "text=#{text}")
1354
+ #Arcadia.new_error_msg(self, "matches[1]=#{matches[1]}")
1355
+ breakpoint_no = matches[1].to_i if (matches.length == 2)
1356
+ return breakpoint_no
1357
+ end
1358
+
1359
+ def unset_breakpoint(_id)
1360
+ read("delete #{_id}")
1361
+ end
1362
+ end
1363
+
1364
+ class RubyDebug < ArcadiaExt
1365
+ include Autils
1366
+ attr_reader :rds
1367
+ attr_reader :rdc
1368
+ def on_before_build(_event)
1369
+ if !full_in_path_command('rdebug').nil?
1370
+ #ArcadiaContractListener.new(self, EditorContract, :do_editor_event)
1371
+ Arcadia.attach_listener(self, BufferEvent)
1372
+ @breakpoints = Hash.new
1373
+ @static_breakpoints = Array.new
1374
+ else
1375
+ Arcadia.console(self, 'msg'=>"Warning: Extension ae-ruby-debug depend upon rdebug command (install it or update system path!)", 'level'=>'error')
1376
+ #Arcadia.new_error_msg(self, "Warning: Extension ae-ruby-debug depend upon rdebug command (install it or update system path!)")
1377
+ end
1378
+ Arcadia.attach_listener(self, DebugEvent)
1379
+ end
1380
+
1381
+ def on_build(_event)
1382
+ #Arcadia.attach_listener(self, DebugEvent)
1383
+ end
1384
+
1385
+ def on_buffer(_event)
1386
+ case _event
1387
+ when BufferRaisedEvent
1388
+ @raised_file=_event.file
1389
+ end
1390
+ end
1391
+
1392
+ def on_debug(_event)
1393
+ case _event
1394
+ when StartDebugEvent
1395
+ _filename = _event.file
1396
+ _filename = @arcadia['pers']['run.file.last'] if _filename == "*LAST"
1397
+ debug(_filename)
1398
+ when StepDebugEvent
1399
+ if (_event.command == :quit_yes)
1400
+ @rds.quit_confirm_request = true
1401
+ end
1402
+ @rdc.send(_event.command) if @rdc.is_alive?
1403
+
1404
+ #p "on_debug -> Thread.current=#{Thread.current}"
1405
+
1406
+ #p "on_debug --> @rdc.is_alive?=#{@rdc.is_alive?}"
1407
+ #p "on_debug --> @rds.is_alive?=#{@rds.is_alive?}"
1408
+ when SetBreakpointEvent
1409
+ self.breakpoint_add(File.expand_path(_event.file), _event.row)
1410
+ when UnsetBreakpointEvent
1411
+ self.breakpoint_del(File.expand_path(_event.file), _event.row)
1412
+ when EvalExpressionEvent
1413
+ eval_expression(_event.expression)
1414
+ when StopDebugEvent
1415
+ self.debug_quit
1416
+ end
1417
+ end
1418
+
1419
+
1420
+ # def do_editor_event(_event)
1421
+ # case _event.signature
1422
+ # when EditorContract::BREAKPOINT_AFTER_CREATE
1423
+ # self.breakpoint_add(File.expand_path(_event.context.file), _event.context.line)
1424
+ # when EditorContract::BREAKPOINT_AFTER_DELETE
1425
+ # self.breakpoint_del(File.expand_path(_event.context.file), _event.context.line)
1426
+ # when EditorContract::BUFFER_AFTER_RAISE
1427
+ # @raised_file=_event.context.file
1428
+ # when EditorContract::EVAL_EXPRESSION
1429
+ # eval_expression(_event.context.text)
1430
+ # end
1431
+ # end
1432
+
1433
+ def eval_expression(_exp)
1434
+ res = @rdc.debug_eval(_exp) if @rdc && @rdc.is_debugging_ready?
1435
+ hash = Hash.new
1436
+ hash[_exp]=res
1437
+ @rdv.show_expression(_exp, hash) if res
1438
+ end
1439
+
1440
+ def start_debug_server
1441
+ end
1442
+ private :start_debug_server
1443
+
1444
+ def start_debug_client
1445
+ end
1446
+ private :start_debug_client
1447
+
1448
+
1449
+ def breakpoint_suf(_file,_line)
1450
+ return _line.to_s + "-" + _file.to_s
1451
+ end
1452
+ private :breakpoint_suf
1453
+
1454
+ def break_name(_file,_line)
1455
+ "#{_file}:#{_line}"
1456
+ end
1457
+
1458
+ def breakpoint_add_live(_file,_line)
1459
+ if @rdc && @rdc.is_alive?
1460
+ @breakpoints[breakpoint_suf(_file,_line)] = @rdc.set_breakpoint(_file, _line.to_i)
1461
+ #@rdv.break_list_add(_file,_line) if @rdv
1462
+ end
1463
+ end
1464
+
1465
+ def breakpoint_del_live(_file,_line)
1466
+ if @rdc && @rdc.is_alive?
1467
+ @rdc.unset_breakpoint(@breakpoints.delete(breakpoint_suf(_file,_line)))
1468
+ #@rdv.break_list_del(_file,_line) if @rdv
1469
+ end
1470
+ end
1471
+
1472
+ def breakpoint_free_live
1473
+ @breakpoints.clear
1474
+ #@rdv.break_list_free if @rdv
1475
+ end
1476
+
1477
+ def breakpoint_add(_file,_line)
1478
+ breakpoint_add_live(_file,_line)
1479
+ @static_breakpoints << {:file=>_file,:line=>_line}
1480
+ end
1481
+ #private :breakpoint_add
1482
+
1483
+ def breakpoint_del(_file,_line)
1484
+ breakpoint_del_live(_file,_line)
1485
+ @static_breakpoints.delete_if{|b| (b[:file]==_file && b[:line]==_line)}
1486
+ end
1487
+ #private :breakpoint_del
1488
+
1489
+
1490
+ def on_exit_query(_event)
1491
+ if @rdc && @rdc.is_alive?
1492
+ query = (Tk.messageBox('icon' => 'question', 'type' => 'yesno',
1493
+ 'title' => '(Arcadia) Debug',
1494
+ 'message' => "Debug in course, do you want to exit?")=='yes')
1495
+ if query
1496
+ debug_quit
1497
+ _event.can_exit=true
1498
+ else
1499
+ _event.can_exit=false
1500
+ end
1501
+ else
1502
+ _event.can_exit=true
1503
+ end
1504
+ end
1505
+
1506
+ def debug_last
1507
+ Arcadia.process_event(StartDebugEvent.new(self, 'file'=>$arcadia['pers']['run.file.last']))
1508
+ #debug($arcadia['pers']['run.file.last'])
1509
+ end
1510
+
1511
+ def debug_current
1512
+ Arcadia.process_event(StartDebugEvent.new(self, 'file'=>@raised_file)) if @raised_file!=nil
1513
+ #debug(@raised_file) if @raised_file!=nil
1514
+ end
1515
+ def debugging?
1516
+ !@rdc.nil? && @rdc.is_alive?
1517
+ end
1518
+
1519
+ def debug_begin
1520
+ breakpoint_free_live
1521
+ #DebugContract.instance.debug_begin(self)
1522
+ end
1523
+
1524
+ def debug(_filename=nil)
1525
+ if _filename && !debugging?
1526
+ begin
1527
+ self.debug_begin
1528
+ @arcadia['pers']['run.file.last']=_filename
1529
+ @rds = RubyDebugServer.new(self,@arcadia) if @rds.nil?
1530
+ @rds.start_session(_filename, conf('server.host'), conf('server.port'))
1531
+ #Arcadia.new_msg(self,@rds.to_s)
1532
+
1533
+ @rdc = RubyDebugClient.new(self, conf('server.host'), conf('server.port'), conf('server.timeout')) if @rdc.nil?
1534
+ @rdv = RubyDebugView.new(self.frame.hinner_frame, self) if @rdv.nil?
1535
+ @rdv.start_process(_filename)
1536
+ if @rdc.start_session
1537
+ @static_breakpoints.each{|_b|
1538
+ #Arcadia.console(self,'msg'=>" breakpoint_add #{_b[:file]}:#{_b[:line]}")
1539
+ breakpoint_add_live(_b[:file], _b[:line])
1540
+ }
1541
+ end
1542
+ rescue Exception => e
1543
+ Arcadia.console(self, 'msg'=>"---> "+e.to_s, 'level'=>'debug')
1544
+ end
1545
+ end
1546
+ end
1547
+
1548
+ def rdebug_server_update(_state)
1549
+ case _state
1550
+ when RubyDebugServer::RDS_QUIET
1551
+ @rdc.kill if @rdc
1552
+ #p "@rdc.is_alive?=#{@rdc.is_alive?}"
1553
+ #p "rdebug_server_update -> Thread.current=#{Thread.current}"
1554
+ #@rdv.command_enabled(false)
1555
+ #debug_free
1556
+ end
1557
+ end
1558
+
1559
+ def debug_free
1560
+ self.frame.free
1561
+ @rdc = nil
1562
+ @rdv = nil
1563
+ end
1564
+
1565
+ def debug_quit
1566
+ #p "in debug quit @rdc.is_alive?=#{@rdc.is_alive?}"
1567
+ if @rdc
1568
+ if @rdc.is_alive?
1569
+ Thread.new{
1570
+ Tk.messageBox('icon' => 'info',
1571
+ 'type' => 'ok',
1572
+ 'title' => '(Arcadia) Debug',
1573
+ 'message' => "Debug in course, stop it before exit")
1574
+ }
1575
+ else
1576
+ begin
1577
+ debug_free
1578
+ rescue Exception => e
1579
+ Arcadia.console(self, 'msg'=>"debug_quit:---> "+e.to_s, 'level'=>'debug')
1580
+ #Arcadia.new_debug_msg(self, "debug_quit:---> "+e.to_s)
1581
+ #@arcadia['shell'].outln("debug_quit:---> "+e.to_s )
1582
+ end
1583
+ end
1584
+ end
1585
+ end
1586
+
1587
+
1588
+
1589
+ end