require'byebug/byebug'require'byebug/version'require'byebug/context'require'byebug/processor'require'byebug/command_processor'require'byebug/control_command_processor'require'byebug/remote'require'stringio'require'tracer'require'linecache19'moduleByebug# List of files byebug will ignore while debuggingIGNORED_FILES=Dir.glob(File.expand_path('../**/*.rb',__FILE__))# Default options to Byebug.startDEFAULT_START_SETTINGS={init: true,# Set $0 and save ARGV?post_mortem: false,# post-mortem debugging on uncaught exception?tracing: nil# Byebug.tracing? value. true/false resets}unlessdefined?(DEFAULT_START_SETTINGS)# Configuration file used for startup commands. Default value is .byebugrcINITFILE='.byebugrc'unlessdefined?(INITFILE)class<<self# processor modules provide +handler+ objectattr_accessor:handlerByebug.handler=CommandProcessor.newattr_accessor:last_exceptionByebug.last_exception=nildefsource_reloadObject.send(:remove_const,'SCRIPT_LINES__')ifObject.const_defined?('SCRIPT_LINES__')Object.const_set('SCRIPT_LINES__',{})end## Get line +line_number+ from file named +filename+.## @return "\n" if there was a problem. Leaking blanks are stripped off.#defline_at(filename,line_number)source_reloadreturn"\n"unlessFile.exist?(filename)line=Tracer::Single.get_line(filename,line_number)return"#{line.gsub(/^\s+/,'').chomp}"end## Add a new breakpoint## @param [String] file# @param [Fixnum] line# @param [String] expr#defadd_breakpoint(file,line,expr=nil)breakpoint=Breakpoint.new(file,line,expr)breakpoints<<breakpointbreakpointend## Remove a breakpoint## @param [integer] breakpoint number#defremove_breakpoint(id)breakpoints.reject!{|b|b.id==id}enddefinterface=(value)handler.interface=valueendextendForwardabledef_delegators:"handler.interface",:print## Byebug.start(options) -> bool# Byebug.start(options) { ... } -> obj## If it's called without a block, it returns +true+ unless byebug was# already started.## If a block is given, it starts byebug and yields block. After the block is# executed it stops byebug with Byebug.stop method. Inside the block you# will probably want to have a call to Byebug.byebug. For example:## Byebug.start { byebug; foo } # Stop inside of foo## Also, byebug only allows one invocation of byebug at a time; nested# Byebug.start's have no effect and you can't use this inside byebug itself.## <i>Note that if you want to stop byebug, you must call Byebug.stop as# many times as you called Byebug.start method.</i>## +options+ is a hash used to set various debugging options.# :init - true if you want to save ARGV and some other variables to# make a byebug restart possible. Only the first time :init# is set to true the values will get set. Since ARGV is# saved, you should make sure it hasn't been changed before# the (first) call.# :post_mortem - true if you want to enter post-mortem debugging on an# uncaught exception. Once post-mortem debugging is set, it# can't be unset.#defstart(options={},&block)options=Byebug::DEFAULT_START_SETTINGS.merge(options)ifoptions[:init]Byebug.const_set('ARGV',ARGV.clone)unlessdefined?Byebug::ARGVByebug.const_set('PROG_SCRIPT',$0)unlessdefined?Byebug::PROG_SCRIPTByebug.const_set('INITIAL_DIR',Dir.pwd)unlessdefined?Byebug::INITIAL_DIRendByebug.tracing=options[:tracing]unlessoptions[:tracing].nil?retval=Byebug._start(&block)post_mortemifoptions[:post_mortem]returnretvalend## 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.#defrun_init_script(out=handler.interface)cwd_script=File.expand_path(File.join(".",INITFILE))run_script(cwd_script,out)ifFile.exist?(cwd_script)home_script=File.expand_path(File.join(ENV['HOME'].to_s,INITFILE))ifFile.exist?(home_script)andcwd_script!=home_scriptrun_script(home_script,out)endend## Runs a script file#defrun_script(file,out=handler.interface,verbose=false)interface=ScriptInterface.new(File.expand_path(file),out)processor=ControlCommandProcessor.new(interface)processor.process_commands(verbose)end## Activates the post-mortem mode.## By calling Byebug.post_mortem method, you install an at_exit hook that# intercepts any exception not handled by your script and enables# post-mortem mode.#defpost_mortemreturnifself.post_mortem?at_exit{handle_post_mortem($!)ifpost_mortem?}self.post_mortem=trueenddefhandle_post_mortem(exp)returnif!expByebug.last_exception=expreturnif!exp.__bb_context||!exp.__bb_context.calced_stack_sizeorig_tracing=Byebug.tracing?Byebug.tracing=falsehandler.at_line(exp.__bb_context,exp.__bb_file,exp.__bb_line)ensureByebug.tracing=orig_tracingendprivate:handle_post_mortemendendclassExceptionattr_reader:__bb_file,:__bb_line,:__bb_binding,:__bb_contextendmoduleKernel## Enters byebug after _steps_into_ line events and _steps_out_ return events# occur. Before entering byebug startup, the init script is read.#defbyebug(steps_into=1,steps_out=2)Byebug.startByebug.run_init_script(StringIO.new)ifByebug.current_context.calced_stack_size>2Byebug.current_context.stop_returnsteps_outifsteps_out>=1endByebug.current_context.step_intosteps_intoifsteps_into>=0endalias_method:debugger,:byebugend