Refactor IRB color dispatch

The reason why we were checking lexer state in addition to token was
that we do not want to colorize local variable, method call, etc., while
they share the :on_ident token with a name of method definition which
should be colored as blue.

It means that we're concerned about the lexer state only for :on_ident.
Thus we can skip checking lexer state for non-:on_ident tokens. This
refactoring is based on that idea.

Also, now we manage Ripper's lexer state as Integer (use `|` if you
need to check multiple states). It should be faster than using Array of
Integer because #any? block call is not needed.
This commit is contained in:
Takashi Kokubun 2019-05-26 10:29:20 -07:00
parent e73a68ebc3
commit 897901283c
No known key found for this signature in database
GPG Key ID: 6FFC433B12EE23DD
2 changed files with 32 additions and 30 deletions

View File

@ -18,40 +18,44 @@ module IRB # :nodoc:
on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__'], on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__'],
on_const: ['ENV'], on_const: ['ENV'],
} }
private_constant :TOKEN_KEYWORDS
begin begin
# Following pry's colors where possible, but sometimes having a compromise like making # Following pry's colors where possible, but sometimes having a compromise like making
# backtick and regexp as red (string's color, because they're sharing tokens). # backtick and regexp as red (string's color, because they're sharing tokens).
TOKEN_SEQ_EXPRS = { TOKEN_SEQ_EXPRS = {
on_CHAR: [[BLUE, BOLD], [Ripper::EXPR_END]], on_CHAR: [[BLUE, BOLD], :all],
on_backtick: [[RED], [Ripper::EXPR_BEG]], on_backtick: [[RED], :all],
on_const: [[BLUE, BOLD, UNDERLINE], [Ripper::EXPR_ARG, Ripper::EXPR_CMDARG, Ripper::EXPR_ENDFN]], on_const: [[BLUE, BOLD, UNDERLINE], :all],
on_embexpr_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_CMDARG, Ripper::EXPR_FNAME, Ripper::EXPR_ARG]], on_comment: [[BLUE, BOLD], :all],
on_embexpr_end: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_CMDARG, Ripper::EXPR_ENDFN, Ripper::EXPR_ARG]], on_embexpr_beg: [[RED], :all],
on_embvar: [[RED], [Ripper::EXPR_BEG]], on_embexpr_end: [[RED], :all],
on_float: [[MAGENTA, BOLD], [Ripper::EXPR_END]], on_embvar: [[RED], :all],
on_heredoc_beg: [[RED], [Ripper::EXPR_BEG]], on_float: [[MAGENTA, BOLD], :all],
on_heredoc_end: [[RED], [Ripper::EXPR_BEG]], on_heredoc_beg: [[RED], :all],
on_ident: [[BLUE, BOLD], [Ripper::EXPR_ENDFN]], on_heredoc_end: [[RED], :all],
on_imaginary: [[BLUE, BOLD], [Ripper::EXPR_END]], on_ident: [[BLUE, BOLD], Ripper::EXPR_ENDFN],
on_int: [[BLUE, BOLD], [Ripper::EXPR_END]], on_imaginary: [[BLUE, BOLD], :all],
on_kw: [[GREEN], [Ripper::EXPR_ARG, Ripper::EXPR_CLASS, Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_FNAME, Ripper::EXPR_MID]], on_int: [[BLUE, BOLD], :all],
on_label: [[MAGENTA], [Ripper::EXPR_LABELED]], on_kw: [[GREEN], :all],
on_label_end: [[RED], [Ripper::EXPR_BEG]], on_label: [[MAGENTA], :all],
on_qsymbols_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_CMDARG]], on_label_end: [[RED], :all],
on_qwords_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_CMDARG]], on_qsymbols_beg: [[RED], :all],
on_rational: [[BLUE, BOLD], [Ripper::EXPR_END]], on_qwords_beg: [[RED], :all],
on_regexp_beg: [[RED, BOLD], [Ripper::EXPR_BEG]], on_rational: [[BLUE, BOLD], :all],
on_regexp_end: [[RED, BOLD], [Ripper::EXPR_BEG]], on_regexp_beg: [[RED, BOLD], :all],
on_symbeg: [[YELLOW], [Ripper::EXPR_FNAME]], on_regexp_end: [[RED, BOLD], :all],
on_tstring_beg: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG]], on_symbeg: [[YELLOW], :all],
on_tstring_content: [[RED], [Ripper::EXPR_BEG, Ripper::EXPR_END, Ripper::EXPR_ARG, Ripper::EXPR_CMDARG, Ripper::EXPR_FNAME]], on_tstring_beg: [[RED], :all],
on_tstring_end: [[RED], [Ripper::EXPR_END]], on_tstring_content: [[RED], :all],
on_words_beg: [[RED], [Ripper::EXPR_BEG]], on_tstring_end: [[RED], :all],
on_words_beg: [[RED], :all],
} }
rescue NameError rescue NameError
# Give up highlighting Ripper-incompatible older Ruby
TOKEN_SEQ_EXPRS = {} TOKEN_SEQ_EXPRS = {}
end end
private_constant :TOKEN_SEQ_EXPRS
class << self class << self
def colorable? def colorable?
@ -113,13 +117,11 @@ module IRB # :nodoc:
private private
def dispatch_seq(token, expr, str, in_symbol:) def dispatch_seq(token, expr, str, in_symbol:)
if token == :on_comment if in_symbol
[BLUE, BOLD]
elsif in_symbol
[YELLOW] [YELLOW]
elsif TOKEN_KEYWORDS.fetch(token, []).include?(str) elsif TOKEN_KEYWORDS.fetch(token, []).include?(str)
[CYAN, BOLD] [CYAN, BOLD]
elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; exprs&.any? { |e| (expr & e) != 0 }) elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; exprs == :all || (exprs != nil && (expr & exprs) != 0))
seq seq
else else
nil nil

View File

@ -30,7 +30,7 @@ module TestIRB
"['foo', :bar]" => "[#{RED}'#{CLEAR}#{RED}foo#{CLEAR}#{RED}'#{CLEAR}, #{YELLOW}:#{CLEAR}#{YELLOW}bar#{CLEAR}]", "['foo', :bar]" => "[#{RED}'#{CLEAR}#{RED}foo#{CLEAR}#{RED}'#{CLEAR}, #{YELLOW}:#{CLEAR}#{YELLOW}bar#{CLEAR}]",
"class A; end" => "#{GREEN}class#{CLEAR} #{BLUE}#{BOLD}#{UNDERLINE}A#{CLEAR}; #{GREEN}end#{CLEAR}", "class A; end" => "#{GREEN}class#{CLEAR} #{BLUE}#{BOLD}#{UNDERLINE}A#{CLEAR}; #{GREEN}end#{CLEAR}",
"def self.foo; bar; end" => "#{GREEN}def#{CLEAR} #{CYAN}#{BOLD}self#{CLEAR}.#{BLUE}#{BOLD}foo#{CLEAR}; bar; #{GREEN}end#{CLEAR}", "def self.foo; bar; end" => "#{GREEN}def#{CLEAR} #{CYAN}#{BOLD}self#{CLEAR}.#{BLUE}#{BOLD}foo#{CLEAR}; bar; #{GREEN}end#{CLEAR}",
'ERB.new("a#{nil}b", trim_mode: "-")' => "#{BLUE}#{BOLD}#{UNDERLINE}ERB#{CLEAR}.new(#{RED}\"#{CLEAR}#{RED}a#{CLEAR}#{RED}\#{#{CLEAR}#{CYAN}#{BOLD}nil#{CLEAR}#{RED}}#{CLEAR}#{RED}b#{CLEAR}#{RED}\"#{CLEAR}, #{MAGENTA}trim_mode:#{CLEAR} #{RED}\"#{CLEAR}#{RED}-#{CLEAR}#{RED}\"#{CLEAR})", 'erb = ERB.new("a#{nil}b", trim_mode: "-")' => "erb = #{BLUE}#{BOLD}#{UNDERLINE}ERB#{CLEAR}.new(#{RED}\"#{CLEAR}#{RED}a#{CLEAR}#{RED}\#{#{CLEAR}#{CYAN}#{BOLD}nil#{CLEAR}#{RED}}#{CLEAR}#{RED}b#{CLEAR}#{RED}\"#{CLEAR}, #{MAGENTA}trim_mode:#{CLEAR} #{RED}\"#{CLEAR}#{RED}-#{CLEAR}#{RED}\"#{CLEAR})",
"# comment" => "#{BLUE}#{BOLD}# comment#{CLEAR}", "# comment" => "#{BLUE}#{BOLD}# comment#{CLEAR}",
"yield(hello)" => "#{GREEN}yield#{CLEAR}(hello)", "yield(hello)" => "#{GREEN}yield#{CLEAR}(hello)",
'"##@var]"' => "#{RED}\"#{CLEAR}#{RED}##{CLEAR}#{RED}##{CLEAR}@var#{RED}]#{CLEAR}#{RED}\"#{CLEAR}", '"##@var]"' => "#{RED}\"#{CLEAR}#{RED}##{CLEAR}#{RED}##{CLEAR}@var#{RED}]#{CLEAR}#{RED}\"#{CLEAR}",