rb8-trepanning 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGES +34 -0
  3. data/ChangeLog +875 -0
  4. data/README.textile +59 -0
  5. data/Rakefile +215 -0
  6. data/app/.gitignore +1 -0
  7. data/app/cmd_parse.kpeg +241 -0
  8. data/app/cmd_parse.rb +212 -0
  9. data/app/cmd_parser.rb +1948 -0
  10. data/app/complete.rb +79 -0
  11. data/app/default.rb +90 -0
  12. data/app/display.rb +148 -0
  13. data/app/eventbuffer.rb +147 -0
  14. data/app/frame.rb +166 -0
  15. data/app/irb.rb +114 -0
  16. data/app/options.rb +200 -0
  17. data/app/run.rb +74 -0
  18. data/app/util.rb +65 -0
  19. data/bin/.gitignore +1 -0
  20. data/bin/trepan8 +115 -0
  21. data/data/.gitignore +1 -0
  22. data/data/irbrc +41 -0
  23. data/interface/.gitignore +1 -0
  24. data/interface/base_intf.rb +109 -0
  25. data/interface/client.rb +82 -0
  26. data/interface/comcodes.rb +20 -0
  27. data/interface/script.rb +110 -0
  28. data/interface/server.rb +147 -0
  29. data/interface/user.rb +165 -0
  30. data/io/base_io.rb +148 -0
  31. data/io/input.rb +158 -0
  32. data/io/null_output.rb +46 -0
  33. data/io/string_array.rb +156 -0
  34. data/io/tcpclient.rb +129 -0
  35. data/io/tcpfns.rb +33 -0
  36. data/io/tcpserver.rb +141 -0
  37. data/lib/debugger.rb +8 -0
  38. data/lib/trepanning.rb +283 -0
  39. data/processor/.gitignore +1 -0
  40. data/processor/command-ruby-debug/breakpoints.rb +155 -0
  41. data/processor/command-ruby-debug/catchpoint.rb +55 -0
  42. data/processor/command-ruby-debug/condition.rb +49 -0
  43. data/processor/command-ruby-debug/control.rb +31 -0
  44. data/processor/command-ruby-debug/display.rb +120 -0
  45. data/processor/command-ruby-debug/enable.rb +202 -0
  46. data/processor/command-ruby-debug/frame.rb +199 -0
  47. data/processor/command-ruby-debug/help.rb +63 -0
  48. data/processor/command-ruby-debug/info.rb +359 -0
  49. data/processor/command-ruby-debug/method.rb +84 -0
  50. data/processor/command-ruby-debug/reload.rb +40 -0
  51. data/processor/command-ruby-debug/save.rb +90 -0
  52. data/processor/command-ruby-debug/set.rb +237 -0
  53. data/processor/command-ruby-debug/show.rb +251 -0
  54. data/processor/command-ruby-debug/source.rb +36 -0
  55. data/processor/command-ruby-debug/threads.rb +189 -0
  56. data/processor/command-ruby-debug/trace.rb +57 -0
  57. data/processor/command-ruby-debug/variables.rb +199 -0
  58. data/processor/command.rb +270 -0
  59. data/processor/command/.gitignore +1 -0
  60. data/processor/command/alias.rb +54 -0
  61. data/processor/command/backtrace.rb +123 -0
  62. data/processor/command/base/cmd.rb +177 -0
  63. data/processor/command/base/subcmd.rb +230 -0
  64. data/processor/command/base/submgr.rb +188 -0
  65. data/processor/command/base/subsubcmd.rb +128 -0
  66. data/processor/command/base/subsubmgr.rb +199 -0
  67. data/processor/command/break.rb +114 -0
  68. data/processor/command/catch.rb +71 -0
  69. data/processor/command/complete.rb +39 -0
  70. data/processor/command/continue.rb +57 -0
  71. data/processor/command/directory.rb +50 -0
  72. data/processor/command/disable.rb +85 -0
  73. data/processor/command/display.rb +78 -0
  74. data/processor/command/down.rb +54 -0
  75. data/processor/command/edit.rb +79 -0
  76. data/processor/command/enable.rb +48 -0
  77. data/processor/command/eval.rb +90 -0
  78. data/processor/command/exit.rb +66 -0
  79. data/processor/command/finish.rb +59 -0
  80. data/processor/command/frame.rb +97 -0
  81. data/processor/command/help.rb +230 -0
  82. data/processor/command/help/.gitignore +1 -0
  83. data/processor/command/help/README +10 -0
  84. data/processor/command/help/command.txt +58 -0
  85. data/processor/command/help/examples.txt +16 -0
  86. data/processor/command/help/filename.txt +40 -0
  87. data/processor/command/help/location.txt +37 -0
  88. data/processor/command/help/suffixes.txt +17 -0
  89. data/processor/command/info.rb +28 -0
  90. data/processor/command/info_subcmd/.gitignore +1 -0
  91. data/processor/command/info_subcmd/args.rb +39 -0
  92. data/processor/command/info_subcmd/breakpoints.rb +80 -0
  93. data/processor/command/info_subcmd/catch.rb +36 -0
  94. data/processor/command/info_subcmd/files.rb +39 -0
  95. data/processor/command/info_subcmd/globals.rb +64 -0
  96. data/processor/command/info_subcmd/line.rb +30 -0
  97. data/processor/command/info_subcmd/locals.rb +69 -0
  98. data/processor/command/info_subcmd/macro.rb +62 -0
  99. data/processor/command/info_subcmd/program.rb +51 -0
  100. data/processor/command/info_subcmd/ruby.rb +57 -0
  101. data/processor/command/info_subcmd/source.rb +74 -0
  102. data/processor/command/info_subcmd/stack.rb +25 -0
  103. data/processor/command/info_subcmd/threads.rb +75 -0
  104. data/processor/command/kill.rb +78 -0
  105. data/processor/command/list.rb +117 -0
  106. data/processor/command/macro.rb +68 -0
  107. data/processor/command/next.rb +79 -0
  108. data/processor/command/parsetree.rb +56 -0
  109. data/processor/command/pp.rb +40 -0
  110. data/processor/command/pr.rb +37 -0
  111. data/processor/command/ps.rb +40 -0
  112. data/processor/command/restart.rb +86 -0
  113. data/processor/command/save.rb +58 -0
  114. data/processor/command/set.rb +47 -0
  115. data/processor/command/set_subcmd/.gitignore +1 -0
  116. data/processor/command/set_subcmd/abbrev.rb +25 -0
  117. data/processor/command/set_subcmd/auto.rb +27 -0
  118. data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
  119. data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
  120. data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
  121. data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
  122. data/processor/command/set_subcmd/basename.rb +25 -0
  123. data/processor/command/set_subcmd/callstyle.rb +46 -0
  124. data/processor/command/set_subcmd/confirm.rb +24 -0
  125. data/processor/command/set_subcmd/debug.rb +47 -0
  126. data/processor/command/set_subcmd/different.rb +61 -0
  127. data/processor/command/set_subcmd/highlight.rb +43 -0
  128. data/processor/command/set_subcmd/max.rb +26 -0
  129. data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
  130. data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
  131. data/processor/command/set_subcmd/max_subcmd/string.rb +76 -0
  132. data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
  133. data/processor/command/set_subcmd/reload.rb +42 -0
  134. data/processor/command/set_subcmd/timer.rb +58 -0
  135. data/processor/command/set_subcmd/trace.rb +37 -0
  136. data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
  137. data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
  138. data/processor/command/shell.rb +139 -0
  139. data/processor/command/show.rb +39 -0
  140. data/processor/command/show_subcmd/.gitignore +1 -0
  141. data/processor/command/show_subcmd/abbrev.rb +20 -0
  142. data/processor/command/show_subcmd/alias.rb +46 -0
  143. data/processor/command/show_subcmd/args.rb +34 -0
  144. data/processor/command/show_subcmd/auto.rb +28 -0
  145. data/processor/command/show_subcmd/auto_subcmd/eval.rb +27 -0
  146. data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
  147. data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
  148. data/processor/command/show_subcmd/basename.rb +20 -0
  149. data/processor/command/show_subcmd/callstyle.rb +22 -0
  150. data/processor/command/show_subcmd/confirm.rb +18 -0
  151. data/processor/command/show_subcmd/debug.rb +26 -0
  152. data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
  153. data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
  154. data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
  155. data/processor/command/show_subcmd/different.rb +26 -0
  156. data/processor/command/show_subcmd/directories.rb +22 -0
  157. data/processor/command/show_subcmd/highlight.rb +24 -0
  158. data/processor/command/show_subcmd/max.rb +27 -0
  159. data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
  160. data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
  161. data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
  162. data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
  163. data/processor/command/show_subcmd/reload.rb +18 -0
  164. data/processor/command/show_subcmd/timer.rb +18 -0
  165. data/processor/command/show_subcmd/trace.rb +29 -0
  166. data/processor/command/show_subcmd/trace_subcmd/buffer.rb +65 -0
  167. data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
  168. data/processor/command/show_subcmd/version.rb +23 -0
  169. data/processor/command/source.rb +134 -0
  170. data/processor/command/step.rb +81 -0
  171. data/processor/command/tbreak.rb +19 -0
  172. data/processor/command/unalias.rb +44 -0
  173. data/processor/command/undisplay.rb +59 -0
  174. data/processor/command/up.rb +72 -0
  175. data/processor/default.rb +56 -0
  176. data/processor/display.rb +17 -0
  177. data/processor/eval.rb +113 -0
  178. data/processor/eventbuf.rb +105 -0
  179. data/processor/frame.rb +172 -0
  180. data/processor/help.rb +92 -0
  181. data/processor/helper.rb +76 -0
  182. data/processor/hook.rb +134 -0
  183. data/processor/load_cmds.rb +258 -0
  184. data/processor/location.rb +174 -0
  185. data/processor/main.rb +455 -0
  186. data/processor/mock.rb +136 -0
  187. data/processor/msg.rb +61 -0
  188. data/processor/processor.rb +674 -0
  189. data/processor/running.rb +168 -0
  190. data/processor/stepping.rb +18 -0
  191. data/processor/subcmd.rb +161 -0
  192. data/processor/validate.rb +355 -0
  193. data/processor/virtual.rb +34 -0
  194. data/test/data/.gitignore +1 -0
  195. data/test/data/break_bad.cmd +19 -0
  196. data/test/data/break_bad.right +29 -0
  197. data/test/data/break_loop_bug.cmd +5 -0
  198. data/test/data/break_loop_bug.right +15 -0
  199. data/test/data/dollar-0.right +2 -0
  200. data/test/data/dollar-0a.right +2 -0
  201. data/test/data/dollar-0b.right +2 -0
  202. data/test/data/edit.cmd +14 -0
  203. data/test/data/edit.right +24 -0
  204. data/test/data/file-with-space.cmd +6 -0
  205. data/test/data/file-with-space.right +4 -0
  206. data/test/data/printvar.cmd +17 -0
  207. data/test/data/printvar.right +31 -0
  208. data/test/data/raise.cmd +11 -0
  209. data/test/data/raise.right +19 -0
  210. data/test/data/source.cmd +5 -0
  211. data/test/data/source.right +18 -0
  212. data/test/data/stepping-1.9.right +50 -0
  213. data/test/data/stepping.cmd +21 -0
  214. data/test/data/stepping.right +48 -0
  215. data/test/data/trepan8-save.1 +6 -0
  216. data/test/example/bp_loop_issue.rb +3 -0
  217. data/test/example/break-bug.rb +7 -0
  218. data/test/example/brkpt-class-bug.rb +8 -0
  219. data/test/example/classes.rb +11 -0
  220. data/test/example/dollar-0.rb +5 -0
  221. data/test/example/except-bug1.rb +4 -0
  222. data/test/example/except-bug2.rb +7 -0
  223. data/test/example/file with space.rb +1 -0
  224. data/test/example/gcd.rb +18 -0
  225. data/test/example/info-var-bug.rb +47 -0
  226. data/test/example/info-var-bug2.rb +2 -0
  227. data/test/example/null.rb +1 -0
  228. data/test/example/pm-bug.rb +3 -0
  229. data/test/example/pm.rb +11 -0
  230. data/test/example/raise.rb +3 -0
  231. data/test/integration/.gitignore +4 -0
  232. data/test/integration/config.yaml +8 -0
  233. data/test/integration/helper.rb +154 -0
  234. data/test/integration/test-break_bad.rb +26 -0
  235. data/test/integration/test-dollar-0.rb +31 -0
  236. data/test/integration/test-edit.rb +17 -0
  237. data/test/integration/test-file-with-space.rb +26 -0
  238. data/test/integration/test-printvar.rb +17 -0
  239. data/test/integration/test-raise.rb +21 -0
  240. data/test/integration/test-source.rb +16 -0
  241. data/test/integration/test-stepping.rb +24 -0
  242. data/test/unit/.gitignore +1 -0
  243. data/test/unit/cmd-helper.rb +52 -0
  244. data/test/unit/mock-helper.rb +12 -0
  245. data/test/unit/test-app-cmd_parse.rb +97 -0
  246. data/test/unit/test-app-cmd_parser.rb +23 -0
  247. data/test/unit/test-app-complete.rb +39 -0
  248. data/test/unit/test-app-frame.rb +32 -0
  249. data/test/unit/test-app-options.rb +92 -0
  250. data/test/unit/test-app-run.rb +14 -0
  251. data/test/unit/test-app-util.rb +44 -0
  252. data/test/unit/test-base-cmd.rb +45 -0
  253. data/test/unit/test-base-subcmd.rb +57 -0
  254. data/test/unit/test-base-submgr.rb +23 -0
  255. data/test/unit/test-base-subsubcmd.rb +17 -0
  256. data/test/unit/test-cmd-alias.rb +48 -0
  257. data/test/unit/test-cmd-exit.rb +27 -0
  258. data/test/unit/test-cmd-help.rb +104 -0
  259. data/test/unit/test-cmd-kill.rb +46 -0
  260. data/test/unit/test-cmd-source.rb +34 -0
  261. data/test/unit/test-completion.rb +42 -0
  262. data/test/unit/test-intf-user.rb +46 -0
  263. data/test/unit/test-io-input.rb +27 -0
  264. data/test/unit/test-io-tcp.rb +33 -0
  265. data/test/unit/test-io-tcpclient.rb +54 -0
  266. data/test/unit/test-io-tcpfns.rb +17 -0
  267. data/test/unit/test-io-tcpserver.rb +50 -0
  268. data/test/unit/test-proc-eval.rb +36 -0
  269. data/test/unit/test-proc-hook.rb +30 -0
  270. data/test/unit/test-proc-load_cmds.rb +50 -0
  271. data/test/unit/test-proc-location.rb +79 -0
  272. data/test/unit/test-subcmd-help.rb +44 -0
  273. data/trepan8.gemspec +52 -0
  274. metadata +391 -0
@@ -0,0 +1,188 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'rubygems'; require 'require_relative'
4
+ require_relative 'cmd'
5
+ require_relative '../../subcmd'
6
+ require_relative '../../help'
7
+ require_relative '../../../app/complete'
8
+
9
+ class Trepan::SubcommandMgr < Trepan::Command
10
+
11
+ include Trepan::Help
12
+
13
+ unless defined?(CATEGORY)
14
+ CATEGORY = 'status'
15
+ MIN_ARGS = 0
16
+ MAX_ARGS = nil
17
+ NAME = '?' # FIXME: Need to define this, but should
18
+ # pick this up from class/file name.
19
+ NEED_STACK = false
20
+ end
21
+
22
+ attr_accessor :subcmds # Trepan::Subcmd
23
+ attr_reader :name # Name of command
24
+ attr_reader :last_args # Last arguments seen
25
+
26
+ # Initialize show subcommands. Note: instance variable name
27
+ # has to be setcmds ('set' + 'cmds') for subcommand completion
28
+ # to work.
29
+ def initialize(proc)
30
+ @name = obj_const(self, :NAME)
31
+ @subcmds = Trepan::Subcmd.new(self)
32
+ @proc = proc
33
+ @intf = proc.interfaces[-1]
34
+ load_debugger_subcommands(self)
35
+ end
36
+
37
+ # Create an instance of each of the debugger subcommands. Commands
38
+ # are found by importing files in the directory 'name' + '_sub'. Some
39
+ # files are excluded via an array set in initialize. For each of
40
+ # the remaining files, we import them and scan for class names
41
+ # inside those files and for each class name, we will create an
42
+ # instance of that class. The set of TrepanCommand class instances
43
+ # form set of possible debugger commands.
44
+ def load_debugger_subcommands(parent)
45
+
46
+ # Initialization
47
+ cmd_names = []
48
+ subcmd_names = []
49
+ cmd_dir = File.dirname(__FILE__)
50
+ subcmd_dir = File.join(cmd_dir, '..', name + '_subcmd')
51
+ files = Dir.glob(File.join(subcmd_dir, '*.rb'))
52
+ files.each do |rb|
53
+ basename = File.basename(rb, '.rb')
54
+ if File.directory?(File.join(File.dirname(rb), basename + '_subcmd'))
55
+ subcmd_names << name.capitalize + basename.capitalize
56
+ else
57
+ cmd_names << name.capitalize + basename.capitalize
58
+ end
59
+ require rb
60
+ end if File.directory?(subcmd_dir)
61
+
62
+ subcommands = {}
63
+ cmd_names.each do |name|
64
+ next unless Trepan::Subcommand.constants.member?(name) or
65
+ Trepan::Subcommand.constants.member?(name.to_sym)
66
+ klass = Trepan::Subcommand.const_get(name)
67
+ cmd = klass.send(:new, self)
68
+ @subcmds.add(cmd)
69
+ end
70
+ subcmd_names.each do |name|
71
+ next unless Trepan::SubSubcommand.constants.member?(name) or
72
+ Trepan::SubSubcommand.constants.member?(name.to_sym)
73
+ subcmd_class = Trepan::SubSubcommand.const_get(name)
74
+ begin
75
+ cmd = subcmd_class.send(:new, self, parent)
76
+ rescue Exception => exc
77
+ puts "Subcmd #{name} in #{parent.name.inspect} is bad: #{exc}"
78
+ end
79
+ @subcmds.add(cmd)
80
+ end
81
+ end
82
+
83
+ # Give help for a command which has subcommands. This can be
84
+ # called in several ways:
85
+ # help cmd
86
+ # help cmd subcmd
87
+ # help cmd commands
88
+ #
89
+ # Our shtick is to give help for the overall command only if
90
+ # subcommand or 'commands' is not given. If a subcommand is given and
91
+ # found, then specific help for that is given. If 'commands' is given
92
+ # we will list the all the subcommands.
93
+ def help(args)
94
+ if args.size <= 2
95
+ # "help cmd". Give the general help for the command part.
96
+ doc = my_const(:HELP)
97
+ if doc
98
+ return doc
99
+ else
100
+ errmsg('Sorry - author mess up. ' +
101
+ 'No help registered for command' +
102
+ @name)
103
+ return nil
104
+ end
105
+ end
106
+
107
+ subcmd_name = args[2]
108
+
109
+ if '*' == subcmd_name
110
+ help_text = ["List of subcommands for command '%s':" % @name]
111
+ help_text << columnize_commands(@subcmds.list)
112
+ return help_text
113
+ end
114
+
115
+ # "help cmd subcmd". Give help specific for that subcommand.
116
+ cmd = @subcmds.lookup(subcmd_name, false)
117
+ if cmd
118
+ if cmd.respond_to?(:help)
119
+ return cmd.help(args)
120
+ else
121
+ doc = obj_const(cmd, :HELP)
122
+ if doc
123
+ return doc
124
+ else
125
+ errmsg('Sorry - author mess up. ' +
126
+ 'No help registered for subcommand: ' +
127
+ subcmd_name + ', of command: ' +
128
+ @name)
129
+ return nil
130
+ end
131
+ end
132
+ else
133
+ matches = @subcmds.list.grep(/^#{subcmd_name}/).sort
134
+ if matches.empty?
135
+ errmsg("No #{name} subcommands found matching /^#{subcmd_name}/. Try \"help\" #{@name}.")
136
+ return nil
137
+ elsif 1 == matches.size
138
+ args[-1] = matches[0].to_s
139
+ help(args)
140
+ else
141
+ help_text = ["Subcommands of \"#{@name}\" matching /^#{subcmd_name}/:"]
142
+ help_text << columnize_commands(matches.sort)
143
+ return help_text
144
+ end
145
+ end
146
+ end
147
+
148
+ # Return an Array of subcommands that can start with +arg+. If none
149
+ # found we just return +arg+.
150
+ # FIXME: Not used any more?
151
+ def complete(prefix)
152
+ Trepan::Complete.complete_token(@subcmds.subcmds.keys, prefix)
153
+ end
154
+
155
+ def complete_token_with_next(prefix)
156
+ Trepan::Complete.complete_token_with_next(@subcmds.subcmds, prefix)
157
+ end
158
+
159
+ def run(args) # nodoc
160
+ @last_args = args
161
+ if args.size < 2 || args.size == 2 && args[-1] == '*'
162
+ summary_list(obj_const(self, :NAME), @subcmds)
163
+ return false
164
+ end
165
+
166
+ subcmd_prefix = args[1]
167
+ # We were given: cmd subcmd ...
168
+ # Run that.
169
+ subcmd = @subcmds.lookup(subcmd_prefix)
170
+ if subcmd
171
+ if @proc.ok_for_running(subcmd, subcmd.class.const_get('CMD'),
172
+ args.size-2)
173
+ subcmd.run(args)
174
+ end
175
+ else
176
+ undefined_subcmd(@name, subcmd_prefix)
177
+ end
178
+ end
179
+ end
180
+
181
+ if __FILE__ == $0
182
+ # Demo it.
183
+ require_relative '../../mock'
184
+ dbgr, cmd = MockDebugger::setup('show')
185
+ ## p cmd.complete('d')
186
+ ## p cmd.subcmds.lookup('ar').prefix
187
+ ## p cmd.subcmds.lookup('a')
188
+ end
@@ -0,0 +1,128 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
+ # A base class for debugger subcommands of subcommands.
4
+ #
5
+ # Note: don't end classname with Command (capital C as in SubCommand),
6
+ # since main will think this a command name like QuitCommand
7
+ # ^
8
+
9
+ # Base Class for Trepan subcommands. We pull in some helper
10
+ # functions for command from module cmdfns.
11
+
12
+ require 'rubygems'; require 'require_relative'
13
+ require_relative 'cmd'
14
+ require_relative 'subcmd'
15
+
16
+ module Trepan
17
+
18
+ class SubSubcommand < Subcommand
19
+ def initialize(cmd, parent, name)
20
+ @cmd = cmd
21
+ @name = name
22
+ @parent = parent
23
+ @proc = parent.proc
24
+ end
25
+
26
+ def settings
27
+ @parent.settings
28
+ end
29
+
30
+ def string_in_show
31
+ help_constant_sym =
32
+ if (self.class.constants.member?('SHORT_HELP') ||
33
+ self.class.constants.member?(:SHORT_HELP))
34
+ :SHORT_HELP
35
+ else
36
+ :HELP
37
+ end
38
+ str = my_const(help_constant_sym)
39
+ %w(Show Set).each do |word|
40
+ if 0 == str.index(word)
41
+ str = str[word.size+1 ..-1].capitalize
42
+ break
43
+ end
44
+ end
45
+ str
46
+ end
47
+
48
+ # Set a Boolean-valued debugger setting.
49
+ def run_set_bool(args, default=true)
50
+ set_val = args.size < 2 ? 'on' : args[1]
51
+ setting = @name.gsub(/^(set|show)/,'')
52
+ begin
53
+ settings[setting.to_sym] = @proc.get_onoff(set_val)
54
+ run_show_bool(string_in_show)
55
+ rescue NameError, TypeError
56
+ end
57
+ end
58
+
59
+ def run_show_bool(what=nil)
60
+ setting = @name.gsub(/^(set|show)/,'')
61
+ val = show_onoff(settings[setting.to_sym])
62
+ what = setting unless what
63
+ msg('%s is %s.' % [what.chomp, val])
64
+ end
65
+
66
+ end
67
+
68
+ class SetBoolSubSubcommand < SubSubcommand
69
+ completion %w(on off)
70
+ def run(args)
71
+ run_set_bool(args)
72
+ end
73
+
74
+ def save_command
75
+ val = settings[subcmd_setting_key] ? 'on' : 'off'
76
+ ["#{subcmd_prefix_string} #{val}"]
77
+ end
78
+ end
79
+
80
+ class ShowBoolSubSubcommand < SubSubcommand
81
+ def run(args)
82
+ run_show_bool(string_in_show)
83
+ end
84
+ end
85
+
86
+ class ShowIntSubSubcommand < SubSubcommand
87
+ def run(args)
88
+ run_show_int
89
+ end
90
+ end
91
+ end
92
+
93
+ module Trepanning
94
+ module SubSubcommand
95
+ module_function
96
+ def set_name_prefix(__file__, klass)
97
+ full_dirname = File.dirname(File.expand_path(__file__))
98
+ full_parent_dirname = File.expand_path(File.join(full_dirname, '..'))
99
+ dirname = File.basename(full_dirname)
100
+ parent_dirname = File.basename(full_parent_dirname)
101
+ name = File.basename(__file__, '.rb')
102
+ klass.const_set(:NAME, name)
103
+
104
+ short_dirname = dirname[0...-'_subcmd'.size]
105
+ short_parent_dirname = parent_dirname[0...-'_subcmd'.size]
106
+ prefix = klass.const_set(:PREFIX, %W(#{short_parent_dirname}
107
+ #{short_dirname} #{name}))
108
+ klass.const_set(:CMD, prefix.join(' '))
109
+ end
110
+ end
111
+ end
112
+
113
+
114
+ if __FILE__ == $0
115
+ # Demo it.
116
+ require_relative '../../mock'
117
+ require_relative '../../subcmd'
118
+ name = File.basename(__FILE__, '.rb')
119
+
120
+ # FIXME: DRY the below code
121
+ dbgr, info_cmd = MockDebugger::setup('info', false)
122
+ testcmdMgr = Trepan::Subcmd.new(info_cmd)
123
+ cmd_name = 'testing'
124
+ ## infox_cmd = Trepan::SubSubcommand.new(info_cmd.proc,
125
+ ## info_cmd,
126
+ ## cmd_name)
127
+ ## infox_cmd.settings
128
+ end
@@ -0,0 +1,199 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
3
+ require 'rubygems'; require 'require_relative'
4
+ require_relative 'subcmd'
5
+ require_relative '../../subcmd'
6
+ require_relative '../../help'
7
+
8
+ class Trepan::SubSubcommandMgr < Trepan::Subcommand
9
+
10
+ include Trepan::Help
11
+
12
+ unless defined?(CATEGORY)
13
+ CATEGORY = 'status'
14
+ MIN_ARGS = 0
15
+ MAX_ARGS = nil
16
+ NAME = '?' # FIXME: Need to define this, but should
17
+ # pick this up from class/file name.
18
+ NEED_STACK = false
19
+ end
20
+
21
+ attr_accessor :pname
22
+ attr_accessor :subcmds # Array of instantiated Trepan::Subcommand objects
23
+
24
+ # Initialize show subcommands. Note: instance variable name
25
+ # has to be setcmds ('set' + 'cmds') for subcommand completion
26
+ # to work.
27
+ # FIXME: do we need proc still?
28
+ def initialize(proc, parent)
29
+ name = obj_const(self, :NAME)
30
+ @name = name.to_sym
31
+ @subcmds = Trepan::Subcmd.new(self)
32
+ @parent = parent
33
+ @pname = parent.name
34
+ @proc = parent.proc
35
+
36
+ # Set class constant SHORT_HELP to be the first line of HELP
37
+ # unless it has been defined in the class already.
38
+ # The below was the simplest way I could find to do this since
39
+ # we are the super class but want to set the subclass's constant.
40
+ # defined? didn't seem to work here.
41
+ c = self.class.constants
42
+ self.class.const_set(:SHORT_HELP,
43
+ self.class.const_get('HELP') ||
44
+ self.class.const_get(:HELP)) if
45
+ (c.member?('HELP') || c.member?(:HELP)) and
46
+ !(c.member?('SHORT_HELP') || c.member?(:SHORT_HELP))
47
+
48
+ load_debugger_subsubcommands(name, self)
49
+ end
50
+
51
+ # Create an instance of each of the debugger subcommands. Commands
52
+ # are found by importing files in the directory 'name' + 'sub'. Some
53
+ # files are excluded via an array set in initialize. For each of
54
+ # the remaining files, we import them and scan for class names
55
+ # inside those files and for each class name, we will create an
56
+ # instance of that class. The set of TrepanCommand class instances
57
+ # form set of possible debugger commands.
58
+ def load_debugger_subsubcommands(name, obj)
59
+
60
+ # Initialization
61
+ cmd_names = []
62
+ cmd_dir = File.dirname(__FILE__)
63
+ subcmd_dir = File.join(cmd_dir, '..', @pname + '_subcmd', name + '_subcmd')
64
+ files = Dir.glob(File.join(subcmd_dir, '*.rb'))
65
+ files.each do |rb|
66
+ cmd_names << name.capitalize + File.basename(rb, '.rb').capitalize
67
+ require rb
68
+ end if File.directory?(subcmd_dir)
69
+
70
+ subcommands = {}
71
+ cmd_names.each do |subname|
72
+ cmd_name = "#{pname}#{subname.downcase}"
73
+ subclass_name = "#{@pname.capitalize}#{subname}"
74
+ next if
75
+ not (Trepan::SubSubcommand.constants.member?(subclass_name) or
76
+ Trepan::SubSubcommand.constants.member?(subclass_name.to_sym))
77
+ cmd = self.instance_eval("Trepan::SubSubcommand::" + subclass_name +
78
+ ".new(self, @parent, '#{cmd_name}')")
79
+ @subcmds.add(cmd, cmd_name)
80
+ end
81
+ end
82
+
83
+ # Give help for a command which has subcommands. This can be
84
+ # called in several ways:
85
+ # help cmd
86
+ # help cmd subcmd
87
+ # help cmd commands
88
+ #
89
+ # Our shtick is to give help for the overall command only if
90
+ # subcommand or 'commands' is not given. If a subcommand is given and
91
+ # found, then specific help for that is given. If 'commands' is given
92
+ # we will list the all the subcommands.
93
+ def help(args)
94
+ if args.size <= 3
95
+ # "help cmd". Give the general help for the command part.
96
+ doc = self.class.const_get(:HELP)
97
+ if doc
98
+ return doc
99
+ else
100
+ errmsg('Sorry - author mess up. ' +
101
+ 'No help registered for command' +
102
+ @name)
103
+ return nil
104
+ end
105
+ end
106
+
107
+ prefix = my_const(:PREFIX)
108
+ subcmd_name = args[prefix.size+1]
109
+ prefix_str = prefix.join(' ')
110
+
111
+ if '*' == subcmd_name
112
+ help_text = ["List of subcommands for '%s':" % prefix_str]
113
+ cmd_names = @subcmds.list.map{|c| c[prefix_str.size-1..-1]}
114
+ help_text << columnize_commands(cmd_names)
115
+ return help_text
116
+ end
117
+
118
+ # "help cmd subcmd". Give help specific for that subcommand if
119
+ # the command matches uniquely, or show a list of matching
120
+ # subcommands
121
+ keyprefix_str = prefix.join('')
122
+ key_str = keyprefix_str + subcmd_name
123
+ cmd = @subcmds.lookup(key_str, false)
124
+ if cmd
125
+ doc = obj_const(cmd, :HELP)
126
+ if doc
127
+ return doc
128
+ else
129
+ errmsg('Sorry - author mess up. ' +
130
+ 'No help registered for subcommand: ' +
131
+ subcmd_name + ', of command: ' +
132
+ @name)
133
+ return nil
134
+ end
135
+ else
136
+ matches = @subcmds.list.grep(/^#{key_str}/).sort
137
+ if matches.empty?
138
+ errmsg("No #{name} subcommands found matching /^#{subcmd_name}/. Try \"help #{@name}\".")
139
+ return nil
140
+ elsif 1 == matches.size
141
+ args[-1] = matches[0].to_s[keyprefix_str.size..-1]
142
+ help(args)
143
+ else
144
+ help_text = ["Subcommands of \"#{@name}\" matching /^#{subcmd_name}/:"]
145
+ help_text << columnize_commands(matches.sort)
146
+ return help_text
147
+ end
148
+ end
149
+ end
150
+
151
+ # Return an Array of subcommands that can start with +arg+. If none
152
+ # found we just return +arg+.
153
+ def complete(prefix)
154
+ prior = self.prefix.join('').size
155
+ last_args = @subcmds.list.map{|str| str[prior..-1]}
156
+ Trepan::Complete.complete_token(last_args, prefix)
157
+ end
158
+
159
+ def complete_token_with_next(prefix)
160
+ Trepan::Complete.complete_token_with_next(@subcmds.subcmds, prefix,
161
+ self.prefix.join(''))
162
+ end
163
+
164
+ def run(args)
165
+ args = @parent.last_args if args.size == 0
166
+ if args.size < 3 || args.size == 3 && args[-1] == '*'
167
+ summary_list(obj_const(self, :NAME), @subcmds)
168
+ return false
169
+ end
170
+
171
+ subcmd_prefix = args[0..2].join('')
172
+ # We were given: cmd subcmd ...
173
+ # Run that.
174
+ subcmd = @subcmds.lookup(subcmd_prefix)
175
+ if subcmd
176
+ subcmd.run(args[2..-1])
177
+ else
178
+ undefined_subcmd(obj_const(self, :PREFIX).join(' '), args[-1])
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+ if __FILE__ == $0
185
+ # Demo it.
186
+ require_relative '../../mock'
187
+ dbgr = MockDebugger::MockDebugger.new
188
+ # cmds = dbgr.core.processor.commands
189
+ # cmd = cmds['info']
190
+ # Trepan::SubSubcommandMgr.new(dbgr.core.processor, cmd)
191
+ # puts cmd.help(%w(help info registers))
192
+ # puts '=' * 40
193
+ # puts cmd.help(%w(help info registers *))
194
+ # puts '=' * 40
195
+ # FIXME
196
+ # require_relative '../../lib/trepanning'
197
+ # Trepan.debugger
198
+ # puts cmd.help(%w(help info registers p.*))
199
+ end