Skip to content
This repository has been archived by the owner on Sep 8, 2023. It is now read-only.

Commit

Permalink
Add Lexer#with and Lexer.lookup_fancy (rouge-ruby#1565)
Browse files Browse the repository at this point in the history
* add Lexer#with, for specifying options after initialization

* split out Lexer.lookup_fancy from Lexer.find_fancy

* rename additional_options -> default_options

These are overridden by any options set in the query parameters.

* provide a comment for Lexer#with

Co-authored-by: http://jneen.net/ <[email protected]>
  • Loading branch information
2 people authored and mattt committed May 19, 2021
1 parent 4f0c17c commit c9e7762
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 20 deletions.
58 changes: 38 additions & 20 deletions lib/rouge/lexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,15 @@ def find(name)
registry[name.to_s]
end

# Find a lexer, with fancy shiny features.
#
# * The string you pass can include CGI-style options
#
# Lexer.find_fancy('erb?parent=tex')
#
# * You can pass the special name 'guess' so we guess for you,
# and you can pass a second argument of the code to guess by
#
# Lexer.find_fancy('guess', "#!/bin/bash\necho Hello, world")
# Same as ::find_fancy, except instead of returning an instantiated
# lexer, returns a pair of [lexer_class, options], so that you can
# modify or provide additional options to the lexer.
#
# If the code matches more than one lexer then Guesser::Ambiguous
# is raised.
#
# This is used in the Redcarpet plugin as well as Rouge's own
# markdown lexer for highlighting internal code blocks.
#
def find_fancy(str, code=nil, additional_options={})

# Please note: the lexer class might be nil!
def lookup_fancy(str, code=nil, default_options={})
if str && !str.include?('?') && str != 'guess'
lexer_class = find(str)
return lexer_class && lexer_class.new(additional_options)
return [lexer_class, default_options]
end

name, opts = str ? str.split('?', 2) : [nil, '']
Expand All @@ -75,7 +62,7 @@ def find_fancy(str, code=nil, additional_options={})
[ k.to_s, val ]
end

opts = additional_options.merge(Hash[opts])
opts = default_options.merge(Hash[opts])

lexer_class = case name
when 'guess', nil
Expand All @@ -84,6 +71,29 @@ def find_fancy(str, code=nil, additional_options={})
self.find(name)
end

[lexer_class, opts]
end

# Find a lexer, with fancy shiny features.
#
# * The string you pass can include CGI-style options
#
# Lexer.find_fancy('erb?parent=tex')
#
# * You can pass the special name 'guess' so we guess for you,
# and you can pass a second argument of the code to guess by
#
# Lexer.find_fancy('guess', "#!/bin/bash\necho Hello, world")
#
# If the code matches more than one lexer then Guesser::Ambiguous
# is raised.
#
# This is used in the Redcarpet plugin as well as Rouge's own
# markdown lexer for highlighting internal code blocks.
#
def find_fancy(str, code=nil, default_options={})
lexer_class, opts = lookup_fancy(str, code, default_options)

lexer_class && lexer_class.new(opts)
end

Expand Down Expand Up @@ -317,6 +327,14 @@ def initialize(opts={})
@debug = Lexer.debug_enabled? && bool_option('debug')
end

# Returns a new lexer with the given options set. Useful for e.g. setting
# debug flags post hoc, or providing global overrides for certain options
def with(opts={})
new_options = @options.dup
opts.each { |k, v| new_options[k.to_s] = v }
self.class.new(new_options)
end

def as_bool(val)
case val
when nil, false, 0, '0', 'false', 'off'
Expand Down
12 changes: 12 additions & 0 deletions spec/lexer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,16 @@ def initialize(*)
assert_equal false, option_lexer.new({bool_opt: 'false'}).instance_variable_get(:@bool_opt)
assert_equal false, option_lexer.new({bool_opt: 'off'}).instance_variable_get(:@bool_opt)
end

it 'extends options with #with' do
php = Rouge::Lexers::PHP.new

assert { php.instance_variable_get(:@start_inline) == :guess }

inline_php = php.with(start_inline: true)
assert { inline_php.is_a?(Rouge::Lexers::PHP) }
assert { inline_php != php }
assert { php.instance_variable_get(:@start_inline) == :guess }
assert { inline_php.instance_variable_get(:@start_inline) == true }
end
end

0 comments on commit c9e7762

Please sign in to comment.