Re-enable spec/library for full CI runs.
[rbx.git] / lib / debugger / command.rb
blob19dac55610016521eaab9c759140a2c2139e7c65
1 class Debugger
2   # Base class for debugger commands. Each subclass *must* implement the
3   # following methods:
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
8   # the command_regexp.
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.
12   #
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
16   # required in.
17   # However, this should be done *before* the Debugger is instantiated.
18   #
19   # TODO: Add a command to load extension commands after debugger is
20   # instantiated
21   class Command
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 #)
31     # 3. The method name
32     MODULE_METHOD_RE = '(?:' + MODULE_RE + '([.#]))?' + METHOD_RE
34     @@commands = []
36     def self.available_commands
37       @@commands
38     end
40     # Registers a command name
41     def self.command(name, details={})
42       @@commands << self
43       
44       define_method :name do
45         name
46       end
48       unless re = details[:regexp] and re.kind_of? Regexp
49         raise ArgumentError, "A regex representing the command syntax must be specified"
50       end
51       define_method :command_regexp do
52         details[:regexp]
53       end
55       define_method :syntax do
56         details[:syntax]
57       end
59       define_method :description do
60         details[:description].gsub(/\s\s+/,' ').strip
61       end
62     end
64     # Registers a command setting
65     def self.setting(name, default, options={})
66       @settings ||= {}
67       @settings[name] = [default, options]
68     end
69     
70     # Returns the settings that can be used with this command.
71     def settings
72       self.class.instance_variable_get("@settings") || {}
73     end
74     
75     def initialize
76       if settings = self.class.instance_variable_get("@settings")
77         settings.each do |key, val|
78           instance_variable_set "@#{key.to_s}", val.first
79         end
80       end
81     end
82     
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.
86     def multiline?
87       false
88     end
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.
93     def <=>(other)
94       if other.kind_of? Command
95         order = 0
96         if other.public_methods(false).include? '<=>'
97           order = (other <=> self) * -1
98         end
99         if order == 0
100           order = (syntax <=> other.syntax)
101         end
102         return order
103       else
104         return nil
105       end
106     end
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)
112     # - the method name
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)
116       clazz = MAIN.class
117       unless mod.nil?
118         clazz = Module.const_lookup(mod.to_sym)
119       end
120       if mthd_type.nil? || mthd_type == '#'
121         cm = clazz.instance_method(mthd.to_sym)
122       else
123         cm = clazz.method(mthd.to_sym)
124       end
125     end
126   end
129 # Include the standard debugger commands
130 require 'debugger/standard_commands'
131 require 'debugger/vm_commands'