Class: Byebug::InfoCommand

Inherits:
Command
  • Object
show all
Includes:
Columnize
Defined in:
lib/byebug/commands/info.rb

Overview

Implements byebug “info” command.

Constant Summary collapse

Subcommands =
[
   ['args', 1, 'Argument variables of current stack frame'],
   ['breakpoints', 1, 'Status of user-settable breakpoints',
    'Without argument, list info about all breakpoints. With an integer ' \
    'argument, list info on that breakpoint.'],
   ['catch', 3,
    'Exceptions that can be caught in the current stack frame'],
   ['display', 2, 'Expressions to display when program stops'],
   ['file', 4, 'Info about a particular file read in',
    'After the file name is supplied, you can list file attributes that ' \
    'you wish to see. Attributes include: "all", "basic", "breakpoint", ' \
    '"lines", "mtime", "path" and "sha1".'],
   ['files', 5, 'File names and timestamps of files read in'],
   ['global_variables', 2, 'Global variables'],
   ['instance_variables', 2,
    'Instance variables of the current stack frame'],
   ['line', 2,
    'Line number and file name of current position in source file'],
   ['locals', 2, 'Local variables of the current stack frame'],
   ['program', 2, 'Execution status of the program'],
   ['stack', 2, 'Backtrace of the stack'],
   ['variables', 1,
    'Local and instance variables of the current stack frame']
  ].map do |name, min, short_help, long_help|
  SubcmdStruct.new(name, min, short_help, long_help)
end
InfoFileSubcommands =
[
   ['all', 1, 'All file information available - breakpoints, lines, ' \
    'mtime, path and sha1'],
   ['basic', 2, 'basic information - path, number of lines'],
   ['breakpoints', 2, 'Show trace line numbers',
    'These are the line number where a breakpoint can be set.'],
   ['lines', 1, 'Show number of lines in the file'],
   ['mtime', 1, 'Show modification time of file'],
   ['path', 4, 'Show full file path name for file'],
   ['sha1', 1, 'Show SHA1 hash of contents of the file']
  ].map do |name, min, short_help, long_help|
  SubcmdStruct.new(name, min, short_help, long_help)
end

Constants inherited from Command

Command::DEF_OPTIONS

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Command

commands, find, format_subcmd, format_subcmds, inherited, #initialize, load_commands, #match, method_missing, options, register_setting_get, register_setting_set, register_setting_var, settings, settings_map

Constructor Details

This class inherits a constructor from Byebug::Command

Class Method Details

.descriptionObject



311
312
313
314
315
# File 'lib/byebug/commands/info.rb', line 311

def description
  %{info[ subcommand]

    Generic command for showing things about the program being debugged.}
end

.help(args) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/byebug/commands/info.rb', line 317

def help(args)
  return description + format_subcmds unless args and args[1]

  return format_subcmd(args[1]) unless 'file' == args[1] and args[2]

  str = subcmd.short_help + '.'
  subsubcmd = Command.find(InfoFileSubcommands, args[2])
  if subsubcmd
    str += "\nInvalid \"file\" attribute \"#{args[2]}\"."
  else
    str += "\n" + subsubcmd.short_help + '.'
  end

  return str
end

.namesObject



307
308
309
# File 'lib/byebug/commands/info.rb', line 307

def names
  %w(info)
end

Instance Method Details

#executeObject



69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/byebug/commands/info.rb', line 69

def execute
  return print InfoCommand.help(nil) unless @match[1]

  args = @match[1].split(/[ \t]+/)
  param = args.shift
  subcmd = Command.find(Subcommands, param)
  if subcmd
    send("info_#{subcmd.name}", *args)
  else
    errmsg "Unknown info command #{param}\n"
  end
end

#info_args(*args) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/byebug/commands/info.rb', line 82

def info_args(*args)
  return errmsg "No frame selected.\n" unless @state.context

  locals = @state.context.frame_locals
  args = @state.context.frame_args

  args.each do |name|
    s = "#{name} = #{locals[name].inspect}"
    pad_with_dots(s)
    print "#{s}\n"
  end
end

#info_breakpoints(*args) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/byebug/commands/info.rb', line 107

def info_breakpoints(*args)
  return errmsg "\"info breakpoints\" not available here.\n" unless
    @state.context

  return print "No breakpoints.\n" if Byebug.breakpoints.empty?

  brkpts = Byebug.breakpoints.sort_by{|b| b.id}
  unless args.empty?
    indices = args.map{|a| a.to_i}
    brkpts = brkpts.select{|b| indices.member?(b.id)}
    return errmsg "No breakpoints found among list given.\n" if
      brkpts.empty?
  end
  print "Num Enb What\n"
  brkpts.each { |b| info_breakpoint(b) }
end

#info_display(*args) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/byebug/commands/info.rb', line 124

def info_display(*args)
  return errmsg "\"info display\" not available here.\n" unless
    @state.context

  return print "There are no auto-display expressions now.\n" unless
    @state.display.find{|d| d[0]}

  print "Auto-display expressions now in effect:\n" \
        "Num Enb Expression\n"
  n = 1
  for d in @state.display
    print "%3d: %s  %s\n" % [n, (d[0] ? 'y' : 'n'), d[1]]
    n += 1
  end
end

#info_file(*args) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/byebug/commands/info.rb', line 172

def info_file(*args)
  return info_files unless args[0]

  param =  args[1] || 'basic'

  subcmd = Command.find(InfoFileSubcommands, param)
  return errmsg "Invalid parameter #{param}\n" unless subcmd

  unless LineCache::cached?(args[0])
    unless LineCache::cached_script?(args[0])
      return print "File #{args[0]} is not cached\n"
    end
    LineCache::cache(args[0], Command.settings[:autoreload])
  end

  print "File #{args[0]}"
  info_file_path(args[0]) if %w(all basic path).member?(subcmd.name)
  print "\n"

  info_file_lines(args[0]) if %w(all basic lines).member?(subcmd.name)
  info_file_breakpoints(args[0]) if %w(all breakpoints).member?(subcmd.name)
  info_file_mtime(args[0]) if %w(all mtime).member?(subcmd.name)
  info_file_sha1(args[0]) if %w(all sha1).member?(subcmd.name)
end

#info_files(*args) ⇒ Object



197
198
199
200
201
202
203
204
205
206
# File 'lib/byebug/commands/info.rb', line 197

def info_files(*args)
  files = LineCache::cached_files
  files += SCRIPT_LINES__.keys unless 'stat' == args[0]
  files.uniq.sort.each do |file|
    print "File #{file}"
    info_file_path(file)
    print "\n"
    info_file_mtime(file)
  end
end

#info_global_variables(*args) ⇒ Object



274
275
276
277
278
279
# File 'lib/byebug/commands/info.rb', line 274

def info_global_variables(*args)
  return errmsg "\"info global_variables\" not available here.\n" unless
    @state.context

  var_global
end

#info_instance_variables(*args) ⇒ Object



208
209
210
211
212
213
214
# File 'lib/byebug/commands/info.rb', line 208

def info_instance_variables(*args)
  return errmsg "\"info instance_variables\" not available here.\n" unless
    @state.context

  obj = debug_eval('self')
  var_list(obj.instance_variables)
end

#info_line(*args) ⇒ Object



216
217
218
219
# File 'lib/byebug/commands/info.rb', line 216

def info_line(*args)
  return errmsg "\"info line\" not available here.\n" unless @state.context
  print "Line #{@state.line} of \"#{@state.file}\"\n"
end

#info_locals(*args) ⇒ Object



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/byebug/commands/info.rb', line 221

def info_locals(*args)
  return errmsg "\"info locals\" not available here.\n" unless
    @state.context

  locals = @state.context.frame_locals
  locals.keys.sort.each do |name|
    ### FIXME: make a common routine
    begin
      s = "#{name} = #{locals[name].inspect}"
    rescue
      begin
      s = "#{name} = #{locals[name].to_s}"
      rescue
        s = "*Error in evaluation*"
      end
    end
    pad_with_dots(s)
    print "#{s}\n"
  end
end

#info_program(*args) ⇒ Object



256
257
258
259
260
261
262
263
264
265
266
# File 'lib/byebug/commands/info.rb', line 256

def info_program(*args)
  return errmsg "The program being debugged is not being run.\n" unless
    @state.context

  return print "The program crashed.\n" + Byebug.last_exception ?
               "Exception: #{Byebug.last_exception.inspect}" : "" + "\n" if
    @state.context.dead?

  print "Program stopped. "
  info_stop_reason @state.context.stop_reason
end

#info_stack(*args) ⇒ Object



268
269
270
271
272
# File 'lib/byebug/commands/info.rb', line 268

def info_stack(*args)
  return errmsg "\"info stack\" not available here.\n" unless @state.context

  print_backtrace
end

#info_variables(*args) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/byebug/commands/info.rb', line 281

def info_variables(*args)
  return errmsg "\"info variables\" not available here.\n" unless
    @state.context

  obj = debug_eval('self')
  locals = @state.context.frame_locals
  locals[:self] = @state.context.frame_self(@state.frame_pos)
  locals.keys.sort.each do |name|
    ### FIXME: make a common routine
    begin
      s = "#{name} = #{locals[name].inspect}"
    rescue
      begin
        s = "#{name} = #{locals[name].to_s}"
      rescue
        s = "#{name} = *Error in evaluation*"
      end
    end
    pad_with_dots(s)
    print "#{s}\n"
  end
  var_list(obj.instance_variables, obj.instance_eval{binding()})
  var_class_self
end

#regexpObject



65
66
67
# File 'lib/byebug/commands/info.rb', line 65

def regexp
  /^\s* i(?:nfo)? (?:\s+(.*))?$/ix
end