123456789_123456789_123456789_123456789_123456789_

Module: IRB::Color

Relationships & Source Files
Namespace Children
Classes:
Defined in: lib/irb/color.rb

Constant Summary

Class Attribute Summary

Class Method Summary

Class Attribute Details

.colorable?Boolean (readonly)

[ GitHub ]

  
# File 'lib/irb/color.rb', line 117

def colorable?
  supported = $stdout.tty? && (/mswin|mingw/.match?(RUBY_PLATFORM) || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))

  # because ruby/debug also uses irb's color module selectively,
  # irb won't be activated in that case.
  if IRB.respond_to?(:conf)
    supported && !!IRB.conf.fetch(:USE_COLORIZE, true)
  else
    supported
  end
end

Class Method Details

.clear(colorable: colorable?) )

[ GitHub ]

  
# File 'lib/irb/color.rb', line 150

def clear(colorable: colorable?)
  colorable ? CLEAR_SEQ : ''
end

.colorize(text, seq, colorable: colorable?) )

[ GitHub ]

  
# File 'lib/irb/color.rb', line 154

def colorize(text, seq, colorable: colorable?)
  return text unless colorable
  seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('')
  "#{seq}#{text}#{CLEAR_SEQ}"
end

.colorize_code(code, complete: true, ignore_error: false, colorable: colorable?, , local_variables: [])

If complete is false (code is incomplete), this does not warn compile_error. This option is needed to avoid warning a user when the compile_error is happening because the input is not wrong but just incomplete.

[ GitHub ]

  
# File 'lib/irb/color.rb', line 163

def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?, local_variables: [])
  return code unless colorable

  result = Prism.parse_lex(code, scopes: [local_variables])

  # IRB::ColorPrinter skips colorizing syntax invalid fragments
  return Reline::Unicode.escape_for_print(code) if ignore_error && !result.success?

  errors = result.errors
  unless complete
    errors = errors.reject { |error| error.message =~ /\Aexpected a|unexpected end-of-input|unterminated/ }
  end

  prism_node, prism_tokens = result.value
  visitor = ColorizeVisitor.new
  prism_node.accept(visitor)

  error_tokens = errors.map { |e| [e.location.start_line, e.location.start_column, 0, e.location.end_line, e.location.end_column, :error, e.location.slice] }
  error_tokens.reject! { |t| t.last.match?(/\A\s*\z/) }
  tokens = prism_tokens.map { |t,| [t.location.start_line, t.location.start_column, 2, t.location.end_line, t.location.end_column, t.type, t.value] }
  tokens.pop if tokens.last&.[](5) == :EOF

  colored = +''
  line_index = 0
  col = 0
  lines = code.lines
  flush = -> next_line_index, next_col {
    return if next_line_index == line_index && next_col == col
    (line_index...[next_line_index, lines.size].min).each do |ln|
      colored << Reline::Unicode.escape_for_print(lines[line_index].byteslice(col..))
      line_index = ln + 1
      col = 0
    end
    unless col == next_col
      colored << Reline::Unicode.escape_for_print(lines[next_line_index].byteslice(col..next_col - 1))
    end
  }

  (visitor.tokens + tokens + error_tokens).sort.each do |start_line, start_column, _priority, end_line, end_column, type, value|
    next if start_line - 1 < line_index || (start_line - 1 == line_index && start_column < col)

    flush.call(start_line - 1, start_column)
    if type == :CONSTANT && value == 'ENV'
      color = TOKEN_SEQS[:const_env]
    elsif type == :__END__
      color = TOKEN_SEQS[type]
      end_line = start_line
      value = '__END__'
      end_column = start_column + 7
    else
      color = TOKEN_SEQS[type]
    end
    if color
      value.split(/(\n)/).each do |s|
        colored << (s == "\n" ? s : "#{color}#{Reline::Unicode.escape_for_print(s)}#{CLEAR_SEQ}")
      end
    else
      colored << value
    end
    line_index = end_line - 1
    col = end_column
  end
  flush.call lines.size, 0
  colored
end

.inspect_colorable?(obj, seen: {}.compare_by_identity) ⇒ Boolean

[ GitHub ]

  
# File 'lib/irb/color.rb', line 129

def inspect_colorable?(obj, seen: {}.compare_by_identity)
  case obj
  when String, Symbol, Regexp, Integer, Float, FalseClass, TrueClass, NilClass
    true
  when Hash
    without_circular_ref(obj, seen: seen) do
      obj.all? { |k, v| inspect_colorable?(k, seen: seen) && inspect_colorable?(v, seen: seen) }
    end
  when Array
    without_circular_ref(obj, seen: seen) do
      obj.all? { |o| inspect_colorable?(o, seen: seen) }
    end
  when Range
    inspect_colorable?(obj.begin, seen: seen) && inspect_colorable?(obj.end, seen: seen)
  when Module
    !obj.name.nil?
  else
    false
  end
end

.without_circular_ref(obj, seen:, &block) (private)

[ GitHub ]

  
# File 'lib/irb/color.rb', line 285

def without_circular_ref(obj, seen:, &block)
  return false if seen.key?(obj)
  seen[obj] = true
  block.call
ensure
  seen.delete(obj)
end