class DEBUGGER__::Tracer

def colorize(str, color)

def colorize(str, color)
  # don't colorize trace sent into a file
  if @into
    str
  else
    super
  end
end

def description

def description
  nil
end

def disable

def disable
  @tracer.disable
end

def enable

def enable
  @tracer.enable
end

def enabled?

def enabled?
  @tracer.enabled?
end

def header depth

def header depth
  "DEBUGGER (trace/#{@type}) \#th:#{Thread.current.instance_variable_get(:@__thread_client_id)} \#depth:#{'%-2d'%depth}"
end

def initialize ui, pattern: nil, into: nil

def initialize ui, pattern: nil, into: nil
  if /\ADEBUGGER__::(([A-Z][a-z]+?)[A-Z][a-z]+)/ =~ self.class.name
    @name = $1
    @type = $2.downcase
  end
  setup
  if pattern
    @pattern = Regexp.compile(pattern)
  else
    @pattern = nil
  end
  if @into = into
    @output = File.open(into, 'w')
    @output.puts "PID:#{Process.pid} #{self}"
  else
    @output = ui
  end
  @key = [@type, @pattern, @into].freeze
  enable
end

def minfo tp

def minfo tp
  return "block{}" if tp.event == :b_call
  klass = tp.defined_class
  if klass.singleton_class?
    "#{tp.self}.#{tp.method_id}"
  else
    "#{klass}\##{tp.method_id}"
  end
end

def out tp, msg = nil, depth = caller.size - 1

def out tp, msg = nil, depth = caller.size - 1
  location_str = colorize("#{FrameInfo.pretty_path(tp.path)}:#{tp.lineno}", [:GREEN])
  buff = "#{header(depth)}#{msg} at #{location_str}"
  if false # TODO: Ractor.main?
    ThreadClient.current.on_trace self.object_id, buff
  else
    @output.puts buff
    @output.flush
  end
end

def skip? tp

def skip? tp
  ThreadClient.current.management? || skip_path?(tp.path) || skip_with_pattern?(tp)
end

def skip_with_pattern?(tp)

def skip_with_pattern?(tp)
  @pattern && !tp.path.match?(@pattern)
end

def to_s

def to_s
  s = "#{@name}#{description} (#{@tracer.enabled? ? 'enabled' : 'disabled'})"
  s += " with pattern #{@pattern.inspect}" if @pattern
  s += " into: #{@into}" if @into
  s
end