class Rouge::Lexers::ConsoleLexer
Some more regular text.</pre>
“‘
$ cp foo bar
# This is a comment
“`console?comments=true
<pre>Here’s some regular text.
@example
as CGI-style parameters as in the example below.
This allows an end user to pass options to {ConsoleLexer} by passing them
pass the language string to Rouge as written in the original document.
Most Markdown lexers that recognise GitHub-Flavored Markdown syntax, will
the ‘#` character.
either not manually specified or, if manually specified, does not include
comment. Please note that this option will only work if the prompt is
The comments option, if enabled, will lex lines that begin with a `#` as a
error message
5. error: comma-separated list of strings that indicate the start of an
4. comments: whether to enable comments.
prompt (default: `$,#,>,;`);
3. prompt: comma-separated list of strings that indicate the end of a
2. output: the output language (default: `plaintext?token=Generic.Output`);
1. lang: the shell language to lex (default: `shell`);
The {ConsoleLexer} class accepts five options:
the shell (by default, the {Shell} lexer).
line before passing the remainder of the line to the language lexer for
{Shell} lexer, {ConsoleLexer} will try to parse out the prompt from each
text that would display in a console/terminal. As distinct from the
The {ConsoleLexer} class is intended to lex content that represents the
def allow_comments?
whether to allow comments. if manually specifying a prompt that isn't
def allow_comments? case @comments when :guess @prompt && !@prompt.empty? && !end_chars.include?('#') else @comments end end
def comment_regex
def comment_regex /\A\s*?#/ end
def end_chars
def end_chars @end_chars ||= if @prompt.any? @prompt.reject { |c| c.empty? } elsif allow_comments? %w($ > ;) else %w($ # > ;) end end
def error_regex
def error_regex @error_regex ||= if @error.any? /^(?:#{@error.map(&Regexp.method(:escape)).join('|')})/ end end
def initialize(*)
def initialize(*) super @prompt = list_option(:prompt) { nil } @lang = lexer_option(:lang) { 'shell' } @output = lexer_option(:output) { PlainText.new(token: Generic::Output) } @comments = bool_option(:comments) { :guess } @error = list_option(:error) { nil } end
def lang_lexer
def lang_lexer @lang_lexer ||= case @lang when Lexer @lang when nil Shell.new(options) when Class @lang.new(options) when String Lexer.find(@lang).new(options) end end
def line_regex
def line_regex /(.*?)(\n|$)/ end
def output_lexer
def output_lexer @output_lexer ||= case @output when nil PlainText.new(token: Generic::Output) when Lexer @output when Class @output.new(options) when String Lexer.find(@output).new(options) end end
def process_line(input, &output)
def process_line(input, &output) input.scan(line_regex) # As a nicety, support the use of elisions in input text. A user can # write a line with only `<...>` or one or more `.` characters and # Rouge will treat it as a comment. if input[0] =~ /\A\s*(?:<[.]+>|[.]+)\s*\z/ puts "console: matched snip #{input[0].inspect}" if @debug output_lexer.reset! lang_lexer.reset! yield Comment, input[0] elsif prompt_regex =~ input[0] puts "console: matched prompt #{input[0].inspect}" if @debug output_lexer.reset! yield Generic::Prompt, $& # make sure to take care of initial whitespace # before we pass to the lang lexer so it can determine where # the "real" beginning of the line is $' =~ /\A\s*/ yield Text::Whitespace, $& unless $&.empty? lang_lexer.continue_lex($', &output) elsif comment_regex =~ input[0].strip puts "console: matched comment #{input[0].inspect}" if @debug output_lexer.reset! lang_lexer.reset! yield Comment, input[0] elsif error_regex =~ input[0] puts "console: matched error #{input[0].inspect}" if @debug output_lexer.reset! lang_lexer.reset! yield Generic::Error, input[0] else puts "console: matched output #{input[0].inspect}" if @debug lang_lexer.reset! output_lexer.continue_lex(input[0], &output) end end
def prompt_prefix_regex
def prompt_prefix_regex if allow_comments? /[^<#]*?/m else /.*?/m end end
def prompt_regex
def prompt_regex @prompt_regex ||= begin /^#{prompt_prefix_regex}(?:#{end_chars.map(&Regexp.method(:escape)).join('|')})/ end end
def stream_tokens(input, &output)
def stream_tokens(input, &output) input = StringScanner.new(input) lang_lexer.reset! output_lexer.reset! process_line(input, &output) while !input.eos? end