This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
# -*- 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
|
||||
Reference in New Issue
Block a user