2019-04-25 15:16:21 +03:00
|
|
|
# frozen_string_literal: true
|
|
|
|
require 'ripper'
|
|
|
|
|
|
|
|
module IRB # :nodoc:
|
|
|
|
module Color
|
|
|
|
CLEAR = 0
|
|
|
|
BOLD = 1
|
|
|
|
UNDERLINE = 4
|
|
|
|
RED = 31
|
|
|
|
GREEN = 32
|
|
|
|
BLUE = 34
|
|
|
|
MAGENTA = 35
|
|
|
|
CYAN = 36
|
|
|
|
|
|
|
|
TOKEN_KEYWORDS = {
|
|
|
|
on_kw: ['nil', 'self', 'true', 'false'],
|
|
|
|
on_const: ['ENV'],
|
|
|
|
}
|
|
|
|
|
2019-04-26 12:28:54 +03:00
|
|
|
begin
|
|
|
|
TOKEN_SEQ_EXPRS = {
|
|
|
|
on_CHAR: [[BLUE, BOLD], [Ripper::EXPR_END]],
|
|
|
|
on_const: [[BLUE, BOLD, UNDERLINE], [Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
|
|
|
on_embexpr_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END]],
|
2019-04-28 14:18:44 +03:00
|
|
|
on_embexpr_end: [[RED], [Ripper::EXPR_END, Ripper::EXPR_ENDFN, Ripper::EXPR_CMDARG]],
|
|
|
|
on_embvar: [[RED], [Ripper::EXPR_BEG]],
|
2019-04-26 12:28:54 +03:00
|
|
|
on_ident: [[BLUE, BOLD], [Ripper::EXPR_ENDFN]],
|
|
|
|
on_int: [[BLUE, BOLD], [Ripper::EXPR_END]],
|
|
|
|
on_float: [[MAGENTA, BOLD], [Ripper::EXPR_END]],
|
|
|
|
on_kw: [[GREEN], [Ripper::EXPR_ARG, Ripper::EXPR_CLASS, Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_FNAME]],
|
|
|
|
on_label: [[MAGENTA], [Ripper::EXPR_LABELED]],
|
|
|
|
on_qwords_beg: [[RED], [Ripper::EXPR_BEG]],
|
|
|
|
on_regexp_beg: [[RED, BOLD], [Ripper::EXPR_BEG]],
|
|
|
|
on_regexp_end: [[RED, BOLD], [Ripper::EXPR_BEG]],
|
|
|
|
on_symbeg: [[BLUE, BOLD], [Ripper::EXPR_FNAME]],
|
|
|
|
on_tstring_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
2019-04-28 14:18:44 +03:00
|
|
|
on_tstring_content: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]],
|
2019-04-26 12:28:54 +03:00
|
|
|
on_tstring_end: [[RED], [Ripper::EXPR_END]],
|
|
|
|
}
|
|
|
|
rescue NameError
|
|
|
|
TOKEN_SEQ_EXPRS = {}
|
|
|
|
end
|
2019-04-25 15:16:21 +03:00
|
|
|
|
|
|
|
class << self
|
|
|
|
def colorable?
|
2019-05-23 09:33:40 +03:00
|
|
|
$stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
|
2019-04-25 15:16:21 +03:00
|
|
|
end
|
|
|
|
|
2019-04-25 15:36:48 +03:00
|
|
|
def inspect_colorable?(obj)
|
|
|
|
case obj
|
2019-04-28 15:51:35 +03:00
|
|
|
when String, Symbol, Regexp, Integer, Float, FalseClass, TrueClass, NilClass
|
|
|
|
true
|
2019-04-25 15:36:48 +03:00
|
|
|
when Hash
|
|
|
|
obj.all? { |k, v| inspect_colorable?(k) && inspect_colorable?(v) }
|
|
|
|
when Array
|
|
|
|
obj.all? { |o| inspect_colorable?(o) }
|
2019-04-28 15:51:35 +03:00
|
|
|
when Range
|
|
|
|
inspect_colorable?(obj.begin) && inspect_colorable?(obj.end)
|
|
|
|
when Module
|
|
|
|
!obj.name.nil?
|
2019-04-25 15:36:48 +03:00
|
|
|
else
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-04-25 15:16:21 +03:00
|
|
|
def clear
|
|
|
|
return '' unless colorable?
|
|
|
|
"\e[#{CLEAR}m"
|
|
|
|
end
|
|
|
|
|
|
|
|
def colorize(text, seq)
|
|
|
|
return text unless colorable?
|
|
|
|
"#{seq.map { |s| "\e[#{const_get(s)}m" }.join('')}#{text}#{clear}"
|
|
|
|
end
|
|
|
|
|
|
|
|
def colorize_code(code)
|
|
|
|
return code unless colorable?
|
|
|
|
|
|
|
|
colored = +''
|
2019-05-25 07:21:22 +03:00
|
|
|
length = 0
|
2019-04-25 15:16:21 +03:00
|
|
|
Ripper.lex(code).each do |(_line, _col), token, str, expr|
|
|
|
|
if seq = dispatch_seq(token, expr, str)
|
2019-05-25 07:21:22 +03:00
|
|
|
str.each_line do |line|
|
|
|
|
colored << "#{seq.map { |s| "\e[#{s}m" }.join('')}#{line}#{clear}"
|
|
|
|
end
|
2019-04-25 15:16:21 +03:00
|
|
|
else
|
|
|
|
colored << str
|
|
|
|
end
|
2019-05-25 07:21:22 +03:00
|
|
|
length += str.length
|
2019-04-25 15:16:21 +03:00
|
|
|
end
|
2019-05-25 07:21:22 +03:00
|
|
|
|
|
|
|
# give up colorizing incomplete Ripper tokens
|
|
|
|
return code if length != code.length
|
|
|
|
|
2019-04-25 15:16:21 +03:00
|
|
|
colored
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def dispatch_seq(token, expr, str)
|
|
|
|
if token == :on_comment
|
|
|
|
[BLUE, BOLD]
|
|
|
|
elsif TOKEN_KEYWORDS.fetch(token, []).include?(str)
|
|
|
|
[CYAN, BOLD]
|
2019-04-26 12:28:54 +03:00
|
|
|
elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; exprs&.any? { |e| (expr & e) != 0 })
|
2019-04-25 15:16:21 +03:00
|
|
|
seq
|
|
|
|
else
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|