module Byebug
def self.settings
exception
:stack_on_error - shows full stack trace if eval command results in an
:fullpath - displays full paths when showing frame stack
:forcestep - stepping command always move to the new line
:frame_class_names - displays method's class name when showing frame stack
code
:autoreload - makes 'list' command always display up-to-date source
:autolist - automatically calls 'list' command on breakpoint
:autoirb - automatically calls 'irb' command on breakpoint
recognized as a byebug command
:autoeval - evaluates input in the current binding if it's not
byebug settings. These settings are available:
Use Byebug.settings[] and Byebug.settings[]= methods to query and set
Returns ths settings object.
#
def self.settings Command.settings end
def add_breakpoint(file, line, expr=nil)
-
expr(String) -- -
line(Fixnum) -- -
file(String) --
def add_breakpoint(file, line, expr=nil) breakpoint = Breakpoint.new(file, line, expr) breakpoints << breakpoint breakpoint end
def handle_post_mortem(exp)
def handle_post_mortem(exp) return if !exp || !exp.__bb_context || !exp.__bb_context.calced_stack_size orig_tracing = Byebug.tracing? Byebug.tracing = false Byebug.last_exception = exp handler.at_line(exp.__bb_context, exp.__bb_file, exp.__bb_line) ensure Byebug.tracing = orig_tracing end
def interface=(value)
def interface=(value) handler.interface = value end
def line_at(filename, line_number)
@return "\n" if there was a problem. Leaking blanks are stripped off.
Get line +line_number+ from file named +filename+.
def line_at(filename, line_number) source_reload return "\n" unless File.exist?(filename) line = Tracer::Single.get_line(filename, line_number) return "#{line.gsub(/^\s+/, '').chomp}" end
def post_mortem
...
offender
...
Byebug.post_mortem do
end
raise 'error'
def offender
e.g.
enable post-mortem mode by wrapping this block with Byebug.post_mortem,
If you know that a particular block of code raises an exception you can
== Local post-mortem mode
and enables post-mortem mode.
at_exit hook that intercepts any exception not handled by your script
By calling Byebug.post_mortem method without a block, you install an
== Global post-mortem mode
Activates the post-mortem mode. There are two ways of using it:
def post_mortem if block_given? old_post_mortem = self.post_mortem? begin self.post_mortem = true yield rescue Exception => exp handle_post_mortem(exp) raise ensure self.post_mortem = old_post_mortem end else return if self.post_mortem? self.post_mortem = true debug_at_exit do handle_post_mortem($!) if post_mortem? end end end
def remove_breakpoint(id)
-
breakpoint(integer) -- number
def remove_breakpoint(id) breakpoints.delete_at(id) end
def run_init_script(out = handler.interface)
program you are debugging, in the directory where you invoke byebug.
file, one generic in your home directory, and another, specific to the
different from your home directory. Thus, you can have more than one init
working directory. This is only done if the current directory is
Reads and executes the commands from init file (if any) in the current
Runs normal byebug initialization scripts.
def run_init_script(out = handler.interface) cwd_script = File.expand_path(File.join(".", INITFILE)) run_script(cwd_script, out) if File.exists?(cwd_script) home_script = File.expand_path(File.join(ENV['HOME'].to_s, INITFILE)) if File.exists?(home_script) and cwd_script != home_script run_script(home_script, out) end end
def run_script(file, out = handler.interface, verbose=false)
Runs a script file
def run_script(file, out = handler.interface, verbose=false) interface = ScriptInterface.new(File.expand_path(file), out) processor = ControlCommandProcessor.new(interface) processor.process_commands(verbose) end
def source_reload
def source_reload Object.send(:remove_const, 'SCRIPT_LINES__') if Object.const_defined?('SCRIPT_LINES__') Object.const_set('SCRIPT_LINES__', {}) end
def start(options={}, &block)
can't be unset.
uncaught exception. Once post-mortem debugging is set, it
:post_mortem - true if you want to enter post-mortem debugging on an
the (first) call.
saved, you should make sure it hasn't been changed before
is set to true the values will get set. Since ARGV is
make a byebug restart possible. Only the first time :init
:init - true if you want to save ARGV and some other variables to
+options+ is a hash used to set various debugging options.
many times as you called Byebug.start method.
Note that if you want to stop byebug, you must call Byebug.stop as
Byebug.start's have no effect and you can't use this inside byebug itself.
Also, byebug only allows one invocation of byebug at a time; nested
Byebug.start { byebug; foo } # Stop inside of foo
will probably want to have a call to Byebug.byebug. For example:
executed it stops byebug with Byebug.stop method. Inside the block you
If a block is given, it starts byebug and yields block. After the block is
already started.
If it's called without a block, it returns +true+ unless byebug was
Byebug.start(options) { ... } -> obj
Byebug.start(options) -> bool
def start(options={}, &block) options = Byebug::DEFAULT_START_SETTINGS.merge(options) if options[:init] Byebug.const_set('ARGV', ARGV.clone) unless defined? Byebug::ARGV Byebug.const_set('PROG_SCRIPT', $0) unless defined? Byebug::PROG_SCRIPT Byebug.const_set('INITIAL_DIR', Dir.pwd) unless defined? Byebug::INITIAL_DIR end Byebug.tracing = options[:tracing] unless options[:tracing].nil? retval = Byebug._start(&block) post_mortem if options[:post_mortem] return retval end
def start_client(host = 'localhost', port = PORT)
Connects to the remote byebug
def start_client(host = 'localhost', port = PORT) interface = Byebug::LocalInterface.new socket = TCPSocket.new(host, port) puts "Connected." catch(:exit) do while (line = socket.gets) case line when /^PROMPT (.*)$/ input = interface.read_command($1) throw :exit unless input socket.puts input when /^CONFIRM (.*)$/ input = interface.confirm($1) throw :exit unless input socket.puts input else print line end end end socket.close end
def start_server(host = nil, port = PORT)
Starts a remote byebug
def start_server(host = nil, port = PORT) return if @thread self.interface = nil start yield if block_given? mutex = Mutex.new proceed = ConditionVariable.new server = TCPServer.new(host, port) @thread = DebugThread.new do while (session = server.accept) self.interface = RemoteInterface.new(session) if wait_connection mutex.synchronize do proceed.signal end end end end if wait_connection mutex.synchronize do proceed.wait(mutex) end end end