lib/byebug/core.rb
require 'byebug/byebug' require 'byebug/version' require 'byebug/context' require 'byebug/breakpoint' require 'byebug/interface' require 'byebug/processor' require 'byebug/remote' require 'byebug/printers/plain' module Byebug extend self class NoScript < StandardError end class NonExistentScript < StandardError end # # Configuration file used for startup commands. Default value is .byebugrc # INIT_FILE = '.byebugrc' unless defined?(INIT_FILE) # # Main debugger's processor # attr_accessor :handler self.handler = CommandProcessor.new # # Main debugger's printer # attr_accessor :printer self.printer = Printers::Plain.new extend Forwardable def_delegators :handler, :errmsg, :puts # # Running mode of the debugger. Can be either: # # * :attached => Attached to a running program through the `byebug` method. # * :standalone => Started through `bin/byebug` script. # attr_accessor :mode # # Runs normal byebug initialization scripts. # # Reads and executes the commands from init file (if any) in the current # working directory. This is only done if the current directory is different # from your home directory. Thus, you can have more than one init file, one # generic in your home directory, and another, specific to the program you # are debugging, in the directory where you invoke byebug. # def run_init_script home_rc = File.expand_path(File.join(ENV['HOME'].to_s, INIT_FILE)) run_script(home_rc) if File.exist?(home_rc) cwd_rc = File.expand_path(File.join('.', INIT_FILE)) run_script(cwd_rc) if File.exist?(cwd_rc) && cwd_rc != home_rc end # # Extracts debugged program from command line args # def setup_cmd_line_args unless $PROGRAM_NAME.include?('bin/byebug') self.mode = :attached return end self.mode = :standalone fail(NoScript, 'You must specify a program to debug...') if $ARGV.empty? program = which($ARGV.shift) program = which($ARGV.shift) if program == which('ruby') fail(NonExistentScript, "The script doesn't exist") unless program $PROGRAM_NAME = program end private # # Runs a script file # def run_script(file, verbose = false) interface = ScriptInterface.new(file, verbose) processor = ControlCommandProcessor.new(interface) processor.process_commands end # # Cross-platform way of finding an executable in the $PATH. # Borrowed from: http://stackoverflow.com/questions/2108727 # def which(cmd) return File.expand_path(cmd) if File.exist?(cmd) exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| exts.each do |ext| exe = File.join(path, "#{cmd}#{ext}") return exe if File.executable?(exe) && !File.directory?(exe) end end nil end end # # Extends the extension class to be able to pass information about the # debugging environment from the c-extension to the user. # class Exception attr_reader :__bb_file, :__bb_line, :__bb_binding, :__bb_context end