lib/rouge/lexers/robot_framework.rb
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
module Rouge
module Lexers
class RobotFramework < RegexLexer
tag 'robot_framework'
aliases 'robot', 'robot-framework'
title "Robot Framework"
desc 'Robot Framework is a generic open source automation testing framework (robotframework.org)'
filenames '*.robot'
mimetypes 'text/x-robot'
def initialize(opts = {})
super(opts)
@col = 0
@next = nil
@is_template = false
end
def self.settings_with_keywords
@settings_with_keywords ||= Set.new [
"library", "resource", "setup", "teardown", "template", "suite setup",
"suite teardown", "task setup", "task teardown", "task template",
"test setup", "test teardown", "test template", "variables"
]
end
def self.settings_with_args
@settings_with_args ||= Set.new [
"arguments", "default tags", "documentation", "force tags",
"metadata", "return", "tags", "timeout", "task timeout",
"test timeout"
]
end
id = %r/(?:\\|[^|$@&% \t\n])+(?: (?:\\.|[^|$@&% \t\n])+)*/
bdd = %r/(?:Given|When|Then|And|But) /i
sep = %r/ +\| +|[ ]{2,}|\t+/
start do
push :prior_text
end
state :prior_text do
rule %r/^[^*].*/, Text
rule(//) { pop! }
end
# Mixins
state :whitespace do
rule %r/\s+/, Text::Whitespace
end
state :section_include do
mixin :end_section
mixin :sep
mixin :newline
end
state :end_section do
rule(/(?=^(?:\| )?\*)/) { pop! }
end
state :return do
rule(//) { pop! }
end
state :sep do
rule %r/\| /, Text::Whitespace
rule sep do
token Text::Whitespace
@col = @col + 1
if @next
push @next
elsif @is_template
push :args
elsif @col == 1
@next = :keyword
push :keyword
else
push :args
end
push :cell_start
end
rule %r/\.\.\. */ do
token Text::Whitespace
@col = @col + 1
push :args
end
rule %r/ ?\|/, Text::Whitespace
end
state :newline do
rule %r/\n/ do
token Text::Whitespace
@col = 0
@next = nil
push :cell_start
end
end
# States
state :root do
mixin :whitespace
rule %r/^(?:\| )?\*[* ]*([A-Z]+(?: [A-Z]+)?).*/i do |m|
token Generic::Heading, m[0]
case m[1].chomp("s").downcase
when "setting" then push :section_settings
when "test case" then push :section_tests
when "task" then push :section_tasks
when "keyword" then push :section_keywords
when "variable" then push :section_variables
end
end
end
state :section_settings do
mixin :section_include
rule %r/([A-Z]+(?: [A-Z]+)?)(:?)/i do |m|
match = m[1].downcase
@next = if self.class.settings_with_keywords.include? match
:keyword
elsif self.class.settings_with_args.include? match
:args
end
groups Name::Builtin::Pseudo, Punctuation
end
end
state :section_tests do
mixin :section_include
rule %r/[$@&%{}]+/, Name::Label
rule %r/( )(?![ |])/, Name::Label
rule id do
@is_template = false
token Name::Label
end
end
state :section_tasks do
mixin :section_tests
end
state :section_keywords do
mixin :section_include
rule %r/[$@&%]\{/ do
token Name::Variable
push :var
end
rule %r/[$@&%{}]+/, Name::Label
rule %r/( )(?![ |])/, Name::Label
rule id, Name::Label
end
state :section_variables do
mixin :section_include
rule %r/[$@&%]\{/ do
token Name::Variable
@next = :args
push :var
end
end
state :cell_start do
rule %r/#.*/, Comment
mixin :return
end
state :keyword do
rule %r/(\[)([A-Z]+(?: [A-Z]+)?)(\])/i do |m|
groups Punctuation, Name::Builtin::Pseudo, Punctuation
match = m[2].downcase
@is_template = true if match == "template"
if self.class.settings_with_keywords.include? match
@next = :keyword
elsif self.class.settings_with_args.include? match
@next = :args
end
pop!
end
rule %r/[$@&%]\{/ do
token Name::Variable
@next = :keyword unless @next.nil?
push :var
end
rule %r/FOR/i do
token Name::Function
@next = :keyword unless @next.nil?
end
rule %r/( )(?![ |])/, Name::Function
rule bdd, Name::Builtin
rule id do
token Name::Function
@next = nil
end
mixin :return
end
state :args do
rule %r/[$@&%]\{/ do
token Name::Variable
@next = :keyword unless @next.nil?
push :var
end
rule %r/[$@&%]+/, Str
rule %r/( )(?![ |])/, Str
rule id, Str
mixin :return
end
state :var do
rule %r/(\})( )(=)/ do
groups Name::Variable, Text::Whitespace, Punctuation
pop!
end
rule %r/[$@&%]\{/, Name::Variable, :var
rule %r/[{\[]/, Name::Variable, :var
rule %r/[}\]]/, Name::Variable, :pop!
rule %r/[^$@&%{}\[\]]+/, Name::Variable
rule %r/\}\[/, Name::Variable
end
end
end
end