module Byebug

def self.attach(steps_out, before)


events occur. Before entering byebug the init script is read.
Enters byebug right before (or right after if _before_ is false) return
def self.attach(steps_out, before)
  setup_cmd_line_args
  start
  run_init_script
  current_context.step_out(steps_out, before)
end

def self.handle_post_mortem


prompt back to the user before program termination.
Saves information about the unhandled exception and gives a byebug
def self.handle_post_mortem
  return unless Byebug.raised_exception
  context = Byebug.raised_exception.__bb_context
  file = Byebug.raised_exception.__bb_file
  line = Byebug.raised_exception.__bb_line
  Byebug.handler.at_line(context, file, line)
end

def interrupt


Interrupts the current thread
def interrupt
  current_context.interrupt
end

def parse_host_and_port(host_port_spec)

def parse_host_and_port(host_port_spec)
  location = host_port_spec.split(':')
  location[1] ? [location[0], location[1].to_i] : ['localhost', location[0]]
end

def run_init_script


are debugging, in the directory where you invoke byebug.
generic in your home directory, and another, specific to the program you
from your home directory. Thus, you can have more than one init file, one
working directory. This is only done if the current directory is different
Reads and executes the commands from init file (if any) in the current

Runs normal byebug initialization scripts.
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

def run_script(file, verbose = false)


Runs a script file
def run_script(file, verbose = false)
  interface = ScriptInterface.new(file, verbose)
  processor = ControlCommandProcessor.new(interface)
  processor.process_commands
end

def setup_cmd_line_args


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

def start_client(host = 'localhost', port = PORT)


Connects to the remote byebug
def start_client(host = 'localhost', port = PORT)
  handler.interface = LocalInterface.new
  puts 'Connecting to byebug server...'
  socket = TCPSocket.new(host, port)
  puts 'Connected.'
  catch(:exit) do
    while (line = socket.gets)
      case line
      when /^PROMPT (.*)$/
        input = handler.interface.read_command(Regexp.last_match[1])
        throw :exit unless input
        socket.puts input
      when /^CONFIRM (.*)$/
        input = handler.interface.confirm(Regexp.last_match[1])
        throw :exit unless input
        socket.puts input
      else
        puts line
      end
    end
  end
  socket.close
end

def start_control(host = nil, ctrl_port = PORT + 1)

def start_control(host = nil, ctrl_port = PORT + 1)
  return @actual_control_port if @control_thread
  server = TCPServer.new(host, ctrl_port)
  @actual_control_port = server.addr[1]
  @control_thread = DebugThread.new do
    while (session = server.accept)
      handler.interface = RemoteInterface.new(session)
      ControlCommandProcessor.new(handler.interface).process_commands
    end
  end
  @actual_control_port
end

def start_server(host = nil, port = PORT)


Starts a remote byebug
def start_server(host = nil, port = PORT)
  return if @thread
  handler.interface = nil
  start
  start_control(host, port == 0 ? 0 : port + 1)
  yield if block_given?
  mutex = Mutex.new
  proceed = ConditionVariable.new
  server = TCPServer.new(host, port)
  self.actual_port = server.addr[1]
  @thread = DebugThread.new do
    while (session = server.accept)
      handler.interface = RemoteInterface.new(session)
      mutex.synchronize { proceed.signal } if wait_connection
    end
  end
  mutex.synchronize { proceed.wait(mutex) } if wait_connection
end

def which(cmd)


Borrowed from: http://stackoverflow.com/questions/2108727
Cross-platform way of finding an executable in the $PATH.
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