Module: Repper::Format

Defined in:
lib/repper/format.rb,
lib/repper/format/plain.rb,
lib/repper/format/inline.rb,
lib/repper/format/extended.rb,
lib/repper/format/annotated.rb,
lib/repper/format/structured.rb,
lib/repper/format/tabulo_style.rb

Constant Summary collapse

Plain =

A no-op format, equivalent to the original Regexp#inspect.

->(tokens, *) do
  tokens.map(&:text).join
end
Inline =

A format that only adds color but does not change structure.

->(tokens, theme) do
  tokens.map { |tok| theme.colorize(tok.text, tok.type) }.join
end
Extended =

A lightly structured format that retains parsability and functional equivalence, for use in code.

->(tokens, theme) do
  run_types = i[escape literal nonposixclass nonproperty
                 posixclass property set type]
  forms_run = ->(el){ run_types.include?(el.type) || el.subtype == :dot }
  prev = nil

  tokens.each.with_object(''.dup) do |tok, acc|
    # drop existing x-mode whitespace, if any
    if tok.whitespace?
      next
    # keep some tokens in line:
    # - option switches and conditions for syntactic correctness
    # - quantifiers and codepoint runs for conciseness
    elsif tok.type == :quantifier ||
          tok.subtype == :options_switch && tok.text == ')' ||
          tok.subtype == :condition ||
          prev && forms_run.call(prev) && forms_run.call(tok)
      acc << theme.colorize(tok.inlined_text, tok.type)
    # keep comments in line, too, but with padding
    elsif tok.comment?
      acc << " #{theme.colorize(tok.inlined_text, tok.type)}"
    # render root start as wtokl as empty root end in same line
    elsif tok.subtype == :root && (prev.nil? || prev.subtype == :root)
      acc << theme.colorize(tok.text, tok.type)
    # tokse, if root is not empty, ensure x-flag is present at end
    elsif tok.subtype == :root
      acc << "\n#{theme.colorize(tok.text.sub(/x?\z/, 'x'), tok.type)}"
    # render other tokens on their own lines for an indented structure,
    # e.g. groups, alternations, anchors, assertions, ...
    else
      acc << "\n#{theme.colorize(tok.indented_text, tok.type)}"
    end
    prev = tok
  end
end
Annotated =

A structured and colorized format with annotations about token types.

->(tokens, theme) do
  table = Tabulo::Table.new(tokens.reject(&:whitespace?), **TABULO_STYLE)
  table.add_column(
    :indented_text,
    styler: ->(_, string, cell) { theme.colorize(string, cell.source.type) }
  )
  table.add_column(
    :annotation,
    styler: ->(_, string, cell) { theme.colorize(string, :annotation) }
  )
  table.pack.to_s
end
Structured =

A structured format with colorization.

->(tokens, theme) do
  table = Tabulo::Table.new(tokens.reject(&:whitespace?), **TABULO_STYLE)
  table.add_column(
    :indented_text,
    styler: ->(_, string, cell) { theme.colorize(string, cell.source.type) }
  )
  table.pack.to_s
end
TABULO_STYLE =
{
  border:               :blank,
  header_frequency:     nil, # i.e. omit column headers
  truncation_indicator: '…',
  wrap_body_cells_to:   1,
}

Class Method Summary collapse

Class Method Details

.cast(arg) ⇒ Object



3
4
5
6
7
8
9
10
# File 'lib/repper/format.rb', line 3

def self.cast(arg)
  case arg
  when ::Proc             then arg
  when :x                 then Format::Extended
  when ::Symbol, ::String then Format.const_get(arg.capitalize) rescue nil
  when false, nil         then Format::Inline
  end || raise(Repper::ArgumentError, "unknown format #{arg.inspect}")
end