rouge 3.20.0 → 3.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rouge.rb +1 -0
  3. data/lib/rouge/cli.rb +32 -2
  4. data/lib/rouge/demos/brightscript +6 -0
  5. data/lib/rouge/demos/email +11 -0
  6. data/lib/rouge/demos/j +12 -0
  7. data/lib/rouge/demos/janet +3 -0
  8. data/lib/rouge/demos/postscript +9 -0
  9. data/lib/rouge/demos/ssh +4 -0
  10. data/lib/rouge/demos/systemd +4 -0
  11. data/lib/rouge/formatters/html_line_highlighter.rb +24 -0
  12. data/lib/rouge/formatters/html_line_table.rb +1 -3
  13. data/lib/rouge/formatters/html_linewise.rb +2 -3
  14. data/lib/rouge/lexer.rb +38 -20
  15. data/lib/rouge/lexers/apex.rb +9 -7
  16. data/lib/rouge/lexers/batchfile.rb +3 -2
  17. data/lib/rouge/lexers/brightscript.rb +147 -0
  18. data/lib/rouge/lexers/cpp.rb +6 -5
  19. data/lib/rouge/lexers/css.rb +3 -1
  20. data/lib/rouge/lexers/docker.rb +2 -2
  21. data/lib/rouge/lexers/elm.rb +5 -5
  22. data/lib/rouge/lexers/email.rb +39 -0
  23. data/lib/rouge/lexers/ghc_core.rb +2 -1
  24. data/lib/rouge/lexers/graphql.rb +1 -1
  25. data/lib/rouge/lexers/hack.rb +1 -1
  26. data/lib/rouge/lexers/html.rb +6 -6
  27. data/lib/rouge/lexers/http.rb +8 -2
  28. data/lib/rouge/lexers/isbl.rb +2 -2
  29. data/lib/rouge/lexers/j.rb +244 -0
  30. data/lib/rouge/lexers/janet.rb +218 -0
  31. data/lib/rouge/lexers/javascript.rb +11 -3
  32. data/lib/rouge/lexers/jinja.rb +22 -7
  33. data/lib/rouge/lexers/jsl.rb +1 -1
  34. data/lib/rouge/lexers/jsonnet.rb +4 -3
  35. data/lib/rouge/lexers/jsp.rb +2 -3
  36. data/lib/rouge/lexers/julia.rb +4 -2
  37. data/lib/rouge/lexers/kotlin.rb +8 -4
  38. data/lib/rouge/lexers/opentype_feature_file.rb +0 -1
  39. data/lib/rouge/lexers/perl.rb +27 -7
  40. data/lib/rouge/lexers/php.rb +274 -128
  41. data/lib/rouge/lexers/postscript.rb +93 -0
  42. data/lib/rouge/lexers/powershell.rb +41 -29
  43. data/lib/rouge/lexers/q.rb +1 -1
  44. data/lib/rouge/lexers/rego.rb +27 -12
  45. data/lib/rouge/lexers/ruby.rb +1 -1
  46. data/lib/rouge/lexers/rust.rb +5 -3
  47. data/lib/rouge/lexers/sass/common.rb +1 -0
  48. data/lib/rouge/lexers/smarty.rb +1 -1
  49. data/lib/rouge/lexers/ssh.rb +33 -0
  50. data/lib/rouge/lexers/systemd.rb +34 -0
  51. data/lib/rouge/lexers/twig.rb +4 -4
  52. data/lib/rouge/lexers/velocity.rb +1 -1
  53. data/lib/rouge/lexers/wollok.rb +0 -1
  54. data/lib/rouge/lexers/xml.rb +5 -3
  55. data/lib/rouge/lexers/yaml.rb +5 -3
  56. data/lib/rouge/regex_lexer.rb +56 -1
  57. data/lib/rouge/version.rb +1 -1
  58. metadata +17 -2
@@ -63,7 +63,7 @@ module Rouge
63
63
  rule %r((#{dq}[.]#{dq}?|[.]#{dq})(e[+-]?#{dq}[lu]*)?)i, Num::Float
64
64
  rule %r(#{dq}e[+-]?#{dq}[lu]*)i, Num::Float
65
65
  rule %r/0x\h('?\h)*[lu]*/i, Num::Hex
66
- rule %r/0b[01]+(?:_[01]+)*/, Num::Bin
66
+ rule %r/0b[01]+('[01]+)*/, Num::Bin
67
67
  rule %r/0[0-7]('?[0-7])*[lu]*/i, Num::Oct
68
68
  rule %r/#{dq}[lu]*/i, Num::Integer
69
69
  rule %r/\bnullptr\b/, Name::Builtin
@@ -75,15 +75,16 @@ module Rouge
75
75
  rule id, Name::Class, :pop!
76
76
 
77
77
  # template specification
78
- rule %r/\s*(?=>)/m, Text, :pop!
79
- rule %r/[.]{3}/, Operator
80
78
  mixin :whitespace
79
+ rule %r/[.]{3}/, Operator
80
+ rule %r/,/, Punctuation, :pop!
81
+ rule(//) { pop! }
81
82
  end
82
83
 
83
84
  state :template do
84
- rule %r/>/, Punctuation, :pop!
85
+ rule %r/[>;]/, Punctuation, :pop!
85
86
  rule %r/typename\b/, Keyword, :classname
86
- mixin :root
87
+ mixin :statements
87
88
  end
88
89
 
89
90
  state :case do
@@ -11,7 +11,9 @@ module Rouge
11
11
  filenames '*.css'
12
12
  mimetypes 'text/css'
13
13
 
14
- identifier = /[a-zA-Z0-9_-]+/
14
+ # Documentation: https://www.w3.org/TR/CSS21/syndata.html#characters
15
+
16
+ identifier = /[\p{L}_-][\p{Word}\p{Cf}-]*/
15
17
  number = /-?(?:[0-9]+(\.[0-9]+)?|\.[0-9]+)/
16
18
 
17
19
  def self.attributes
@@ -7,8 +7,8 @@ module Rouge
7
7
  title "Docker"
8
8
  desc "Dockerfile syntax"
9
9
  tag 'docker'
10
- aliases 'dockerfile'
11
- filenames 'Dockerfile', '*.Dockerfile', '*.docker', 'Dockerfile_*'
10
+ aliases 'dockerfile', 'Dockerfile'
11
+ filenames 'Dockerfile', '*.Dockerfile', '*.docker'
12
12
  mimetypes 'text/x-dockerfile-config'
13
13
 
14
14
  KEYWORDS = %w(
@@ -78,13 +78,13 @@ module Rouge
78
78
  rule %r/"/, Str::Double, :pop!
79
79
  end
80
80
 
81
- # Multiple line string with tripple double quotes, e.g. """ multi """
81
+ # Multiple line string with triple double quotes, e.g. """ multi """
82
82
  state :multiline_string do
83
- rule %r/\s*"""/, Str, :pop!
84
- rule %r/.*/, Str
85
- rule %r/\s*/, Str
83
+ rule %r/\\"/, Str::Escape
84
+ rule %r/"""/, Str, :pop!
85
+ rule %r/[^"]+/, Str
86
+ rule %r/"/, Str
86
87
  end
87
-
88
88
  end
89
89
  end
90
90
  end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ class Email < RegexLexer
7
+ tag 'email'
8
+ aliases 'eml', 'e-mail'
9
+ filenames '*.eml'
10
+ mimetypes 'message/rfc822'
11
+
12
+ title "Email"
13
+ desc "An email message"
14
+
15
+ start do
16
+ push :fields
17
+ end
18
+
19
+ state :fields do
20
+ rule %r/[:]/, Operator, :field_body
21
+ rule %r/[^\n\r:]+/, Name::Tag
22
+ rule %r/[\n\r]/, Name::Tag
23
+ end
24
+
25
+ state :field_body do
26
+ rule(/(\r?\n){2}/) { token Text; pop!(2) }
27
+ rule %r/\r?\n(?![ \v\t\f])/, Text, :pop!
28
+ rule %r/[^\n\r]+/, Name::Attribute
29
+ rule %r/[\n\r]/, Name::Attribute
30
+ end
31
+
32
+ state :root do
33
+ rule %r/\n/, Text
34
+ rule %r/^>.*/, Comment
35
+ rule %r/.+/, Text
36
+ end
37
+ end
38
+ end
39
+ end
@@ -27,8 +27,9 @@ module Rouge
27
27
  mixin :function
28
28
 
29
29
  # rest is Text
30
+ # TODO: this is really inefficient
30
31
  rule %r/\s/m, Text
31
- rule %r/.*/, Text
32
+ rule %r/./, Text
32
33
  end
33
34
 
34
35
  state :expression do
@@ -20,7 +20,7 @@ module Rouge
20
20
  end
21
21
 
22
22
  rule %r/\bfragment\b/, Keyword, :fragment_definition
23
-
23
+
24
24
  rule %r/\bscalar\b/, Keyword, :value
25
25
 
26
26
  rule %r/\b(?:type|interface|enum)\b/, Keyword, :type_definition
@@ -32,7 +32,7 @@ module Rouge
32
32
  )
33
33
  end
34
34
 
35
- prepend :template do
35
+ prepend :root do
36
36
  rule %r/<\?hh(\s*\/\/\s*(strict|decl|partial))?$/, Comment::Preproc, :php
37
37
  end
38
38
 
@@ -47,13 +47,13 @@ module Rouge
47
47
  rule %r(</), Name::Tag, :tag_end
48
48
  rule %r/</, Name::Tag, :tag_start
49
49
 
50
- rule %r(<\s*[a-zA-Z0-9:-]+), Name::Tag, :tag # opening tags
51
- rule %r(<\s*/\s*[a-zA-Z0-9:-]+\s*>), Name::Tag # closing tags
50
+ rule %r(<\s*[\p{L}:_-][\p{Word}\p{Cf}:.·-]*), Name::Tag, :tag # opening tags
51
+ rule %r(<\s*/\s*[\p{L}:_-][\p{Word}\p{Cf}:.·-]*\s*>), Name::Tag # closing tags
52
52
  end
53
53
 
54
54
  state :tag_end do
55
55
  mixin :tag_end_end
56
- rule %r/[a-zA-Z0-9:-]+/ do
56
+ rule %r/[\p{L}:_-][\p{Word}\p{Cf}:.·-]*/ do
57
57
  token Name::Tag
58
58
  goto :tag_end_end
59
59
  end
@@ -67,7 +67,7 @@ module Rouge
67
67
  state :tag_start do
68
68
  rule %r/\s+/, Text
69
69
 
70
- rule %r/[a-zA-Z0-9:-]+/ do
70
+ rule %r/[\p{L}:_-][\p{Word}\p{Cf}:.·-]*/ do
71
71
  token Name::Tag
72
72
  goto :tag
73
73
  end
@@ -83,8 +83,8 @@ module Rouge
83
83
 
84
84
  state :tag do
85
85
  rule %r/\s+/m, Text
86
- rule %r/[a-zA-Z0-9_:\[\]()*.-]+\s*=\s*/m, Name::Attribute, :attr
87
- rule %r/[a-zA-Z0-9_:#*-]+/, Name::Attribute
86
+ rule %r/[\p{L}:_\[\]()*.-][\p{Word}\p{Cf}:.·\[\]()*-]*\s*=\s*/m, Name::Attribute, :attr
87
+ rule %r/[\p{L}:_*#-][\p{Word}\p{Cf}:.·*#-]*/, Name::Attribute
88
88
  rule %r(/?\s*>)m, Name::Tag, :pop!
89
89
  end
90
90
 
@@ -8,16 +8,22 @@ module Rouge
8
8
  title "HTTP"
9
9
  desc 'http requests and responses'
10
10
 
11
+ option :content, "the language for the content (default: auto-detect)"
12
+
11
13
  def self.http_methods
12
14
  @http_methods ||= %w(GET POST PUT DELETE HEAD OPTIONS TRACE PATCH)
13
15
  end
14
16
 
15
17
  def content_lexer
18
+ @content_lexer ||= (lexer_option(:content) || guess_content_lexer)
19
+ end
20
+
21
+ def guess_content_lexer
16
22
  return Lexers::PlainText unless @content_type
17
23
 
18
- @content_lexer ||= Lexer.guess_by_mimetype(@content_type)
24
+ Lexer.guess_by_mimetype(@content_type)
19
25
  rescue Lexer::AmbiguousGuess
20
- @content_lexer = Lexers::PlainText
26
+ Lexers::PlainText
21
27
  end
22
28
 
23
29
  start { @content_type = 'text/plain' }
@@ -41,7 +41,7 @@ module Rouge
41
41
 
42
42
  state :dotted do
43
43
  mixin :whitespace
44
- rule %r/[a-zа-яё_0-9]*/i do |m|
44
+ rule %r/[a-zа-яё_0-9]+/i do |m|
45
45
  name = m[0]
46
46
  if self.class.constants.include? name.downcase
47
47
  token Name::Builtin
@@ -56,7 +56,7 @@ module Rouge
56
56
 
57
57
  state :type do
58
58
  mixin :whitespace
59
- rule %r/[a-zа-яё_0-9]*/i do |m|
59
+ rule %r/[a-zа-яё_0-9]+/i do |m|
60
60
  name = m[0]
61
61
  if self.class.interfaces.include? name.downcase
62
62
  token Keyword::Type
@@ -0,0 +1,244 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Lexers
6
+ class J < RegexLexer
7
+ title 'J'
8
+ desc "The J programming language (jsoftware.com)"
9
+ tag 'j'
10
+ filenames '*.ijs', '*.ijt'
11
+
12
+ # For J-specific terms we use, see:
13
+ # https://code.jsoftware.com/wiki/Vocabulary/AET
14
+ # https://code.jsoftware.com/wiki/Vocabulary/Glossary
15
+
16
+ # https://code.jsoftware.com/wiki/Vocabulary/PartsOfSpeech
17
+ def self.token_map
18
+ @token_map ||= {
19
+ noun: Keyword::Constant,
20
+ verb: Name::Function,
21
+ modifier: Operator,
22
+ name: Name,
23
+ param: Name::Builtin::Pseudo,
24
+ other: Punctuation,
25
+ nil => Error,
26
+ }
27
+ end
28
+
29
+ # https://code.jsoftware.com/wiki/NuVoc
30
+ def self.inflection_list
31
+ @inflection_list ||= ['', '.', ':', '..', '.:', ':.', '::']
32
+ end
33
+
34
+ def self.primitive_table
35
+ @primitive_table ||= Hash.new([:name]).tap do |h|
36
+ {
37
+ '()' => [:other],
38
+ '=' => [:verb, :other, :other],
39
+ '<>+-*%$|,#' => [:verb, :verb, :verb],
40
+ '^' => [:verb, :verb, :modifier],
41
+ '~"' => [:modifier, :verb, :verb],
42
+ '.:@' => [:modifier, :modifier, :modifier],
43
+ ';' => [:verb, :modifier, :verb],
44
+ '!' => [:verb, :modifier, :modifier],
45
+ '/\\' => [:modifier, :modifier, :verb],
46
+ '[' => [:verb, nil, :verb],
47
+ ']' => [:verb],
48
+ '{' => [:verb, :verb, :verb, nil, nil, nil, :verb],
49
+ '}' => [:modifier, :verb, :verb, nil, nil, nil, :modifier],
50
+ '`' => [:modifier, nil, :modifier],
51
+ '&' => [:modifier, :modifier, :modifier, nil, :modifier],
52
+ '?' => [:verb, :verb],
53
+ 'a' => [:name, :noun, :noun],
54
+ 'ACeEIjorv' => [:name, :verb],
55
+ 'bdfHMT' => [:name, :modifier],
56
+ 'Dt' => [:name, :modifier, :modifier],
57
+ 'F' => [:name, :modifier, :modifier, :modifier, :modifier,
58
+ :modifier, :modifier],
59
+ 'iu' => [:name, :verb, :verb],
60
+ 'L' => [:name, :verb, :modifier],
61
+ 'mny' => [:param],
62
+ 'p' => [:name, :verb, :verb, :verb],
63
+ 'qsZ' => [:name, nil, :verb],
64
+ 'S' => [:name, nil, :modifier],
65
+ 'u' => [:param, :verb, :verb],
66
+ 'v' => [:param, :verb],
67
+ 'x' => [:param, nil, :verb],
68
+ }.each {|k, v| k.each_char {|c| h[c] = v } }
69
+ end
70
+ end
71
+
72
+ def self.primitive(char, inflection)
73
+ i = inflection_list.index(inflection) or return Error
74
+ token_map[primitive_table[char][i]]
75
+ end
76
+
77
+ def self.control_words
78
+ @control_words ||= Set.new %w(
79
+ assert break case catch catchd catcht continue do else elseif end
80
+ fcase for if return select throw try while whilst
81
+ )
82
+ end
83
+
84
+ def self.control_words_id
85
+ @control_words_id ||= Set.new %w(for goto label)
86
+ end
87
+
88
+ state :expr do
89
+ rule %r/\s+/, Text
90
+
91
+ rule %r'([!-&(-/:-@\[-^`{-~]|[A-Za-z]\b)([.:]*)' do |m|
92
+ token J.primitive(m[1], m[2])
93
+ end
94
+
95
+ rule %r/(?:\d|_\d?):([.:]*)/ do |m|
96
+ token m[1].empty? ? J.token_map[:verb] : Error
97
+ end
98
+
99
+ rule %r/[\d_][\w.]*([.:]*)/ do |m|
100
+ token m[1].empty? ? Num : Error
101
+ end
102
+
103
+ rule %r/'/, Str::Single, :str
104
+
105
+ rule %r/NB\.(?![.:]).*/, Comment::Single
106
+
107
+ rule %r/([A-Za-z]\w*)([.:]*)/ do |m|
108
+ if m[2] == '.'
109
+ word, sep, id = m[1].partition '_'
110
+ list = if sep.empty?
111
+ J.control_words
112
+ elsif not id.empty?
113
+ J.control_words_id
114
+ end
115
+ if list and list.include? word
116
+ token Keyword, word + sep
117
+ token((word == 'for' ? Name : Name::Label), id)
118
+ token Keyword, m[2]
119
+ else
120
+ token Error
121
+ end
122
+ else
123
+ token m[2].empty? ? Name : Error
124
+ end
125
+ end
126
+ end
127
+
128
+ state :str do
129
+ rule %r/''/, Str::Escape
130
+ rule %r/[^'\n]+/, Str::Single
131
+ rule %r/'|$/, Str::Single, :pop!
132
+ end
133
+
134
+ start do
135
+ @note_next = false
136
+ end
137
+
138
+ state :root do
139
+ rule %r/\n/ do
140
+ token Text
141
+ if @note_next
142
+ push :note
143
+ @note_next = false
144
+ end
145
+ end
146
+
147
+ # https://code.jsoftware.com/wiki/Vocabulary/com
148
+ # https://code.jsoftware.com/wiki/Vocabulary/NounExplicitDefinition
149
+ rule %r/
150
+ ([0-4]|13|adverb|conjunction|dyad|monad|noun|verb)([\ \t]+)
151
+ (def(?:ine)?\b|:)(?![.:])([\ \t]*)
152
+ /x do |m|
153
+ groups Keyword::Pseudo, Text, Keyword::Pseudo, Text
154
+ @def_body = (m[1] == '0' || m[1] == 'noun') ? :noun : :code
155
+ if m[3] == 'define'
156
+ # stack: [:root]
157
+ # or [:root, ..., :def_next]
158
+ pop! if stack.size > 1
159
+ push @def_body
160
+ push :def_next # [:root, ..., @def_body, :def_next]
161
+ else
162
+ push :expl_def
163
+ end
164
+ end
165
+
166
+ rule %r/^([ \t]*)(Note\b(?![.:]))([ \t\r]*)(?!=[.:]|$)/ do
167
+ groups Text, Name, Text
168
+ @note_next = true
169
+ end
170
+
171
+ rule %r/[mnuvxy]\b(?![.:])/, Name
172
+ mixin :expr
173
+ end
174
+
175
+ state :def_next do
176
+ rule %r/\n/, Text, :pop!
177
+ mixin :root
178
+ end
179
+
180
+ state :expl_def do
181
+ rule %r/0\b(?![.:])/ do
182
+ token Keyword::Pseudo
183
+ # stack: [:root, :expl_def]
184
+ # or [:root, ..., :def_next, :expl_def]
185
+ pop! if stack.size > 2
186
+ goto @def_body
187
+ push :def_next # [:root, ..., @def_body, :def_next]
188
+ end
189
+ rule %r/'/ do
190
+ if @def_body == :noun
191
+ token Str::Single
192
+ goto :str
193
+ else
194
+ token Punctuation
195
+ goto :q_expr
196
+ end
197
+ end
198
+ rule(//) { pop! }
199
+ end
200
+
201
+ # `q_expr` lexes the content of a string literal which is a part of an
202
+ # explicit definition.
203
+ # e.g. dyad def 'x + y'
204
+ state :q_expr do
205
+ rule %r/''/, Str::Single, :q_str
206
+ rule %r/'|$/, Punctuation, :pop!
207
+ rule %r/NB\.(?![.:])([^'\n]|'')*/, Comment::Single
208
+ mixin :expr
209
+ end
210
+
211
+ state :q_str do
212
+ rule %r/''''/, Str::Escape
213
+ rule %r/[^'\n]+/, Str::Single
214
+ rule %r/''/, Str::Single, :pop!
215
+ rule(/'|$/) { token Punctuation; pop! 2 }
216
+ end
217
+
218
+ state :note do
219
+ mixin :delimiter
220
+ rule %r/.+\n?/, Comment::Multiline
221
+ end
222
+
223
+ state :noun do
224
+ mixin :delimiter
225
+ rule %r/.+\n?/, Str::Heredoc
226
+ end
227
+
228
+ state :code do
229
+ mixin :delimiter
230
+ rule %r/^([ \t]*)(:)([ \t\r]*)$/ do
231
+ groups Text, Punctuation, Text
232
+ end
233
+ mixin :expr
234
+ end
235
+
236
+ state :delimiter do
237
+ rule %r/^([ \t]*)(\))([ \t\r]*$\n?)/ do
238
+ groups Text, Punctuation, Text
239
+ pop!
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end