2 # Base class for debugger commands. Each subclass *must* implement the
4 # - command_regexp, which returns a Regexp instance used to determine when the
5 # user is executing the corresponding command.
6 # - execute, which takes two parameters: the instance of the +Debugger+, and a
7 # +MatchData+ object containing the results of the user input matched against
9 # Additionally, subclasses should also implement help, which should return two
10 # strings: a specification of the command syntax, and a short bit of text
11 # describing what the command does.
13 # Debugger::Command subclasses are registered with the Debugger::Command
14 # superclass via an +inherited+ hook. Standard commands are defined in this
15 # file, but additional debugger commands can be defined elsewhere and
17 # However, this should be done *before* the Debugger is instantiated.
19 # TODO: Add a command to load extension commands after debugger is
22 # Regular expression for matching a Ruby module or class name
23 MODULE_RE = '((?:(?:[A-Z]\w*)(?:::)?)*(?:[A-Z]\w*))'
25 # Regular expression for matching a Ruby method name
26 METHOD_RE = '((?:[a-zA-Z0-9_]+[!?]?=?)|[+\-*\/%\^<>]|\*\*|\[\]=?|==|===|>=|<=|<=>|!=|<<|>>|&&|\|\|)'
28 # Regular expression for matching a module and method name; defines three groups:
29 # 1. The module/class (optional)
30 # 2. The separator (a . or #)
32 MODULE_METHOD_RE = '(?:' + MODULE_RE + '([.#]))?' + METHOD_RE
36 def self.available_commands
40 # Registers a command name
41 def self.command(name, details={})
44 define_method :name do
48 unless re = details[:regexp] and re.kind_of? Regexp
49 raise ArgumentError, "A regex representing the command syntax must be specified"
51 define_method :command_regexp do
55 define_method :syntax do
59 define_method :description do
60 details[:description].gsub(/\s\s+/,' ').strip
64 # Registers a command setting
65 def self.setting(name, default, options={})
67 @settings[name] = [default, options]
70 # Returns the settings that can be used with this command.
72 self.class.instance_variable_get("@settings") || {}
76 if settings = self.class.instance_variable_get("@settings")
77 settings.each do |key, val|
78 instance_variable_set "@#{key.to_s}", val.first
83 # Indicates whether command may take (require) multiple lines of input.
84 # If this is true, a command must indicate to the debugger when additional
85 # input is required, by calling the Debugger#more_input! method.
90 # By default commands are processed in alphabetic order of the first item of
91 # the help string. By overriding this method, commands can order themselves
92 # in relation to other commands they need to precede or follow.
94 if other.kind_of? Command
96 if other.public_methods(false).include? '<=>'
97 order = (other <=> self) * -1
100 order = (syntax <=> other.syntax)
108 # Returns a Method or UnboundMethod object, given strings that identify:
109 # - the class/module (optional, defaults to MAIN if not specified)
110 # - the method type (# for an instance method, . for a class method)
111 # (optional, default is to assume instance method)
113 # Note: The three strings can be obtained from user input via the use of the
114 # MODULE_METHOD_RE constant defined on this class.
115 def get_method(mod, mthd_type, mthd)
118 clazz = Module.const_lookup(mod.to_sym)
120 if mthd_type.nil? || mthd_type == '#'
121 cm = clazz.instance_method(mthd.to_sym)
123 cm = clazz.method(mthd.to_sym)
129 # Include the standard debugger commands
130 require 'debugger/standard_commands'
131 require 'debugger/vm_commands'