class Rouge::Lexers::ConsoleLexer

The {ConsoleLexer} class is intended to lex content that represents the text that would display in a console/terminal. As distinct from the {Shell} lexer, {ConsoleLexer} will try to parse out the prompt from each line before passing the remainder of the line to the language lexer for the shell (by default, the {Shell} lexer).

The {ConsoleLexer} class accepts five options:

  1. lang: the shell language to lex (default: ‘shell`);

  2. output: the output language (default: ‘plaintext?token=Generic.Output`);

  3. prompt: comma-separated list of strings that indicate the end of a prompt (default: ‘$,#,>,;`);

  4. comments: whether to enable comments.

  5. error: comma-separated list of strings that indicate the start of an error message

The comments option, if enabled, will lex lines that begin with a ‘#` as a comment. Please note that this option will only work if the prompt is either not manually specified or, if manually specified, does not include the `#` character.

Most Markdown lexers that recognise GitHub-Flavored Markdown syntax, will pass the language string to Rouge as written in the original document. This allows an end user to pass options to {ConsoleLexer} by passing them as CGI-style parameters as in the example below.

@example <pre>Here’s some regular text.

“‘console?comments=true # This is a comment $ cp foo bar “`

Some more regular text.</pre>

Public Class Methods

new(*) click to toggle source
Calls superclass method Rouge::Lexer::new
# File lib/rouge/lexers/console.rb, line 51
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

Public Instance Methods

allow_comments?() click to toggle source

whether to allow comments. if manually specifying a prompt that isn’t simply “#”, we flag this to on

# File lib/rouge/lexers/console.rb, line 62
def allow_comments?
  case @comments
  when :guess
    @prompt && !@prompt.empty? && !end_chars.include?('#')
  else
    @comments
  end
end
comment_regex() click to toggle source
# File lib/rouge/lexers/console.rb, line 71
def comment_regex
  /\A\s*?#/
end
end_chars() click to toggle source
# File lib/rouge/lexers/console.rb, line 75
def end_chars
  @end_chars ||= if @prompt.any?
    @prompt.reject { |c| c.empty? }
  elsif allow_comments?
    %w($ > ;)
  else
    %w($ # > ;)
  end
end
error_regex() click to toggle source
# File lib/rouge/lexers/console.rb, line 85
def error_regex
  @error_regex ||= if @error.any?
    /^(?:#{@error.map(&Regexp.method(:escape)).join('|')})/
  end
end
lang_lexer() click to toggle source
# File lib/rouge/lexers/console.rb, line 91
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
line_regex() click to toggle source
# File lib/rouge/lexers/console.rb, line 104
def line_regex
  /(\\.|[^\\])*?(\n|$)/m
end
output_lexer() click to toggle source
# File lib/rouge/lexers/console.rb, line 108
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
process_line(input) { |Comment, input| ... } click to toggle source
# File lib/rouge/lexers/console.rb, line 121
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
prompt_prefix_regex() click to toggle source
# File lib/rouge/lexers/console.rb, line 166
def prompt_prefix_regex
  if allow_comments?
    /[^<#]*?/m
  else
    /.*?/m
  end
end
prompt_regex() click to toggle source
# File lib/rouge/lexers/console.rb, line 174
def prompt_regex
  @prompt_regex ||= begin
    /^#{prompt_prefix_regex}(?:#{end_chars.map(&Regexp.method(:escape)).join('|')})/
  end
end
stream_tokens(input, &output) click to toggle source
# File lib/rouge/lexers/console.rb, line 180
def stream_tokens(input, &output)
  input = StringScanner.new(input)
  lang_lexer.reset!
  output_lexer.reset!

  process_line(input, &output) while !input.eos?
end