rouge 3.3.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +15 -3
  3. data/lib/rouge.rb +49 -41
  4. data/lib/rouge/cli.rb +64 -15
  5. data/lib/rouge/demos/ada +26 -0
  6. data/lib/rouge/demos/armasm +12 -0
  7. data/lib/rouge/demos/batchfile +3 -0
  8. data/lib/rouge/demos/bbcbasic +6 -0
  9. data/lib/rouge/demos/bpf +7 -0
  10. data/lib/rouge/demos/brainfuck +5 -0
  11. data/lib/rouge/demos/cmhg +8 -0
  12. data/lib/rouge/demos/cuda +11 -0
  13. data/lib/rouge/demos/cython +6 -0
  14. data/lib/rouge/demos/epp +4 -0
  15. data/lib/rouge/demos/escape +3 -0
  16. data/lib/rouge/demos/gdscript +18 -0
  17. data/lib/rouge/demos/hocon +8 -0
  18. data/lib/rouge/demos/magik +6 -0
  19. data/lib/rouge/demos/mason +22 -0
  20. data/lib/rouge/demos/msgtrans +4 -0
  21. data/lib/rouge/demos/openedge +4 -0
  22. data/lib/rouge/demos/opentype_feature_file +6 -0
  23. data/lib/rouge/demos/plist +1 -132
  24. data/lib/rouge/demos/powershell +12 -48
  25. data/lib/rouge/demos/reasonml +12 -0
  26. data/lib/rouge/demos/sas +13 -0
  27. data/lib/rouge/demos/supercollider +11 -0
  28. data/lib/rouge/demos/xojo +14 -0
  29. data/lib/rouge/demos/xpath +2 -0
  30. data/lib/rouge/demos/xquery +22 -0
  31. data/lib/rouge/formatter.rb +37 -1
  32. data/lib/rouge/formatters/html.rb +20 -2
  33. data/lib/rouge/formatters/html_line_table.rb +53 -0
  34. data/lib/rouge/formatters/html_linewise.rb +6 -11
  35. data/lib/rouge/formatters/html_table.rb +20 -31
  36. data/lib/rouge/formatters/terminal256.rb +1 -0
  37. data/lib/rouge/formatters/tex.rb +92 -0
  38. data/lib/rouge/guessers/disambiguation.rb +25 -0
  39. data/lib/rouge/guessers/glob_mapping.rb +1 -1
  40. data/lib/rouge/guessers/modeline.rb +1 -1
  41. data/lib/rouge/guessers/source.rb +1 -1
  42. data/lib/rouge/lexer.rb +64 -14
  43. data/lib/rouge/lexers/abap.rb +11 -11
  44. data/lib/rouge/lexers/actionscript.rb +34 -34
  45. data/lib/rouge/lexers/ada.rb +162 -0
  46. data/lib/rouge/lexers/apache.rb +8 -8
  47. data/lib/rouge/lexers/apple_script.rb +15 -14
  48. data/lib/rouge/lexers/armasm.rb +145 -0
  49. data/lib/rouge/lexers/awk.rb +25 -25
  50. data/lib/rouge/lexers/batchfile.rb +164 -0
  51. data/lib/rouge/lexers/bbcbasic.rb +112 -0
  52. data/lib/rouge/lexers/biml.rb +4 -4
  53. data/lib/rouge/lexers/bpf.rb +104 -0
  54. data/lib/rouge/lexers/brainfuck.rb +53 -0
  55. data/lib/rouge/lexers/bsl.rb +12 -12
  56. data/lib/rouge/lexers/c.rb +34 -57
  57. data/lib/rouge/lexers/ceylon.rb +6 -34
  58. data/lib/rouge/lexers/cfscript.rb +26 -26
  59. data/lib/rouge/lexers/clojure.rb +14 -14
  60. data/lib/rouge/lexers/cmake.rb +14 -14
  61. data/lib/rouge/lexers/cmhg.rb +34 -0
  62. data/lib/rouge/lexers/coffeescript.rb +43 -35
  63. data/lib/rouge/lexers/common_lisp.rb +37 -37
  64. data/lib/rouge/lexers/conf.rb +6 -6
  65. data/lib/rouge/lexers/console.rb +3 -3
  66. data/lib/rouge/lexers/coq.rb +18 -18
  67. data/lib/rouge/lexers/cpp.rb +12 -9
  68. data/lib/rouge/lexers/crystal.rb +70 -70
  69. data/lib/rouge/lexers/csharp.rb +28 -29
  70. data/lib/rouge/lexers/css.rb +23 -23
  71. data/lib/rouge/lexers/cuda.rb +35 -0
  72. data/lib/rouge/lexers/cython.rb +151 -0
  73. data/lib/rouge/lexers/d.rb +59 -59
  74. data/lib/rouge/lexers/dart.rb +33 -33
  75. data/lib/rouge/lexers/diff.rb +8 -4
  76. data/lib/rouge/lexers/digdag.rb +1 -1
  77. data/lib/rouge/lexers/docker.rb +11 -11
  78. data/lib/rouge/lexers/dot.rb +16 -16
  79. data/lib/rouge/lexers/eiffel.rb +20 -20
  80. data/lib/rouge/lexers/elixir.rb +34 -30
  81. data/lib/rouge/lexers/elm.rb +29 -29
  82. data/lib/rouge/lexers/epp.rb +51 -0
  83. data/lib/rouge/lexers/erb.rb +4 -4
  84. data/lib/rouge/lexers/escape.rb +58 -0
  85. data/lib/rouge/lexers/factor.rb +40 -40
  86. data/lib/rouge/lexers/fortran.rb +32 -32
  87. data/lib/rouge/lexers/fsharp.rb +30 -30
  88. data/lib/rouge/lexers/gdscript.rb +171 -0
  89. data/lib/rouge/lexers/gherkin.rb +16 -14
  90. data/lib/rouge/lexers/glsl.rb +1 -5
  91. data/lib/rouge/lexers/go.rb +2 -2
  92. data/lib/rouge/lexers/graphql.rb +77 -60
  93. data/lib/rouge/lexers/groovy.rb +23 -25
  94. data/lib/rouge/lexers/hack.rb +1 -1
  95. data/lib/rouge/lexers/haml.rb +25 -29
  96. data/lib/rouge/lexers/handlebars.rb +31 -20
  97. data/lib/rouge/lexers/haskell.rb +66 -65
  98. data/lib/rouge/lexers/hcl.rb +25 -25
  99. data/lib/rouge/lexers/hocon.rb +86 -0
  100. data/lib/rouge/lexers/html.rb +32 -31
  101. data/lib/rouge/lexers/http.rb +4 -4
  102. data/lib/rouge/lexers/hylang.rb +14 -14
  103. data/lib/rouge/lexers/idlang.rb +32 -32
  104. data/lib/rouge/lexers/igorpro.rb +31 -31
  105. data/lib/rouge/lexers/ini.rb +12 -12
  106. data/lib/rouge/lexers/io.rb +7 -7
  107. data/lib/rouge/lexers/irb.rb +5 -5
  108. data/lib/rouge/lexers/java.rb +28 -24
  109. data/lib/rouge/lexers/javascript.rb +57 -61
  110. data/lib/rouge/lexers/jinja.rb +34 -20
  111. data/lib/rouge/lexers/json.rb +50 -11
  112. data/lib/rouge/lexers/json_doc.rb +2 -2
  113. data/lib/rouge/lexers/jsonnet.rb +18 -18
  114. data/lib/rouge/lexers/jsp.rb +30 -30
  115. data/lib/rouge/lexers/jsx.rb +16 -16
  116. data/lib/rouge/lexers/julia.rb +181 -58
  117. data/lib/rouge/lexers/kotlin.rb +14 -7
  118. data/lib/rouge/lexers/lasso.rb +50 -50
  119. data/lib/rouge/lexers/liquid.rb +76 -53
  120. data/lib/rouge/lexers/literate_coffeescript.rb +2 -2
  121. data/lib/rouge/lexers/literate_haskell.rb +5 -5
  122. data/lib/rouge/lexers/llvm.rb +23 -16
  123. data/lib/rouge/lexers/lua.rb +3 -3
  124. data/lib/rouge/lexers/m68k.rb +18 -19
  125. data/lib/rouge/lexers/magik.rb +127 -0
  126. data/lib/rouge/lexers/make.rb +56 -34
  127. data/lib/rouge/lexers/markdown.rb +55 -38
  128. data/lib/rouge/lexers/mason.rb +115 -0
  129. data/lib/rouge/lexers/mathematica.rb +11 -11
  130. data/lib/rouge/lexers/matlab.rb +23 -16
  131. data/lib/rouge/lexers/moonscript.rb +3 -3
  132. data/lib/rouge/lexers/mosel.rb +63 -63
  133. data/lib/rouge/lexers/msgtrans.rb +26 -0
  134. data/lib/rouge/lexers/mxml.rb +18 -18
  135. data/lib/rouge/lexers/nasm.rb +24 -25
  136. data/lib/rouge/lexers/nginx.rb +14 -14
  137. data/lib/rouge/lexers/nim.rb +3 -2
  138. data/lib/rouge/lexers/nix.rb +43 -43
  139. data/lib/rouge/lexers/objective_c.rb +43 -48
  140. data/lib/rouge/lexers/ocaml.rb +28 -64
  141. data/lib/rouge/lexers/ocaml/common.rb +53 -0
  142. data/lib/rouge/lexers/openedge.rb +429 -0
  143. data/lib/rouge/lexers/opentype_feature_file.rb +113 -0
  144. data/lib/rouge/lexers/pascal.rb +4 -4
  145. data/lib/rouge/lexers/perl.rb +98 -68
  146. data/lib/rouge/lexers/php.rb +66 -44
  147. data/lib/rouge/lexers/php/builtins.rb +181 -174
  148. data/lib/rouge/lexers/plain_text.rb +1 -1
  149. data/lib/rouge/lexers/plist.rb +14 -14
  150. data/lib/rouge/lexers/pony.rb +19 -19
  151. data/lib/rouge/lexers/powershell.rb +184 -638
  152. data/lib/rouge/lexers/praat.rb +75 -75
  153. data/lib/rouge/lexers/prolog.rb +26 -20
  154. data/lib/rouge/lexers/prometheus.rb +30 -30
  155. data/lib/rouge/lexers/properties.rb +12 -12
  156. data/lib/rouge/lexers/protobuf.rb +22 -22
  157. data/lib/rouge/lexers/puppet.rb +32 -32
  158. data/lib/rouge/lexers/python.rb +52 -52
  159. data/lib/rouge/lexers/q.rb +12 -12
  160. data/lib/rouge/lexers/qml.rb +12 -12
  161. data/lib/rouge/lexers/r.rb +12 -13
  162. data/lib/rouge/lexers/racket.rb +22 -22
  163. data/lib/rouge/lexers/reasonml.rb +65 -0
  164. data/lib/rouge/lexers/ruby.rb +72 -70
  165. data/lib/rouge/lexers/rust.rb +38 -35
  166. data/lib/rouge/lexers/sas.rb +563 -0
  167. data/lib/rouge/lexers/sass.rb +8 -8
  168. data/lib/rouge/lexers/sass/common.rb +40 -40
  169. data/lib/rouge/lexers/scala.rb +63 -37
  170. data/lib/rouge/lexers/scheme.rb +18 -18
  171. data/lib/rouge/lexers/scss.rb +3 -3
  172. data/lib/rouge/lexers/sed.rb +30 -30
  173. data/lib/rouge/lexers/shell.rb +62 -53
  174. data/lib/rouge/lexers/sieve.rb +8 -8
  175. data/lib/rouge/lexers/slim.rb +26 -26
  176. data/lib/rouge/lexers/smalltalk.rb +33 -33
  177. data/lib/rouge/lexers/smarty.rb +19 -19
  178. data/lib/rouge/lexers/sml.rb +67 -67
  179. data/lib/rouge/lexers/sqf.rb +1 -1
  180. data/lib/rouge/lexers/sql.rb +21 -21
  181. data/lib/rouge/lexers/supercollider.rb +116 -0
  182. data/lib/rouge/lexers/swift.rb +46 -43
  183. data/lib/rouge/lexers/tap.rb +20 -20
  184. data/lib/rouge/lexers/tcl.rb +27 -27
  185. data/lib/rouge/lexers/terraform.rb +13 -13
  186. data/lib/rouge/lexers/tex.rb +19 -19
  187. data/lib/rouge/lexers/toml.rb +19 -19
  188. data/lib/rouge/lexers/tulip.rb +36 -36
  189. data/lib/rouge/lexers/turtle.rb +35 -38
  190. data/lib/rouge/lexers/vala.rb +18 -18
  191. data/lib/rouge/lexers/vb.rb +27 -27
  192. data/lib/rouge/lexers/verilog.rb +25 -27
  193. data/lib/rouge/lexers/vhdl.rb +11 -11
  194. data/lib/rouge/lexers/viml.rb +14 -14
  195. data/lib/rouge/lexers/vue.rb +9 -9
  196. data/lib/rouge/lexers/wollok.rb +26 -26
  197. data/lib/rouge/lexers/xml.rb +17 -21
  198. data/lib/rouge/lexers/xojo.rb +61 -0
  199. data/lib/rouge/lexers/xpath.rb +332 -0
  200. data/lib/rouge/lexers/xquery.rb +145 -0
  201. data/lib/rouge/lexers/yaml.rb +63 -61
  202. data/lib/rouge/plugins/redcarpet.rb +1 -1
  203. data/lib/rouge/regex_lexer.rb +26 -25
  204. data/lib/rouge/tex_theme_renderer.rb +132 -0
  205. data/lib/rouge/theme.rb +4 -0
  206. data/lib/rouge/themes/bw.rb +41 -0
  207. data/lib/rouge/themes/magritte.rb +78 -0
  208. data/lib/rouge/themes/monokai_sublime.rb +2 -1
  209. data/lib/rouge/themes/pastie.rb +1 -1
  210. data/lib/rouge/themes/thankful_eyes.rb +1 -1
  211. data/lib/rouge/themes/tulip.rb +1 -1
  212. data/lib/rouge/token.rb +30 -22
  213. data/lib/rouge/util.rb +2 -2
  214. data/lib/rouge/version.rb +1 -1
  215. data/rouge.gemspec +4 -3
  216. metadata +61 -6
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Formatters
6
+ class HTMLLineTable < Formatter
7
+ tag 'html_line_table'
8
+
9
+ # @param [Rouge::Formatters::Formatter] formatter An instance of a
10
+ # `Rouge::Formatters::HTML` or `Rouge::Formatters::HTMLInline`
11
+ # @param [Hash] opts options for HTMLLineTable instance.
12
+ # @option opts [Integer] :start_line line number to start from. Defaults to `1`.
13
+ # @option opts [String] :table_class Class name for the table.
14
+ # Defaults to `"rouge-line-table"`.
15
+ # @option opts [String] :line_id a `sprintf` template for generating an `id`
16
+ # attribute for each table row corresponding to current line number.
17
+ # Defaults to `"line-%i"`.
18
+ # @option opts [String] :line_class Class name for each table row.
19
+ # Defaults to `"lineno"`.
20
+ # @option opts [String] :gutter_class Class name for rendered line-number cell.
21
+ # Defaults to `"rouge-gutter"`.
22
+ # @option opts [String] :code_class Class name for rendered code cell.
23
+ # Defaults to `"rouge-code"`.
24
+ def initialize(formatter, opts={})
25
+ @formatter = formatter
26
+ @start_line = opts.fetch :start_line, 1
27
+ @table_class = opts.fetch :table_class, 'rouge-line-table'
28
+ @gutter_class = opts.fetch :gutter_class, 'rouge-gutter'
29
+ @code_class = opts.fetch :code_class, 'rouge-code'
30
+ @line_class = opts.fetch :line_class, 'lineno'
31
+ @line_id = opts.fetch :line_id, 'line-%i'
32
+ end
33
+
34
+ def stream(tokens, &b)
35
+ lineno = @start_line - 1
36
+ buffer = [%(<table class="#@table_class"><tbody>)]
37
+ token_lines(tokens) do |line_tokens|
38
+ lineno += 1
39
+ buffer << %(<tr id="#{sprintf @line_id, lineno}" class="#@line_class">)
40
+ buffer << %(<td class="#@gutter_class gl" )
41
+ buffer << %(style="-moz-user-select: none;-ms-user-select: none;)
42
+ buffer << %(-webkit-user-select: none;user-select: none;">)
43
+ buffer << %(<pre>#{lineno}</pre></td>)
44
+ buffer << %(<td class="#@code_class"><pre>)
45
+ @formatter.stream(line_tokens) { |formatted| buffer << formatted }
46
+ buffer << "\n</pre></td></tr>"
47
+ end
48
+ buffer << %(</tbody></table>)
49
+ yield buffer.join
50
+ end
51
+ end
52
+ end
53
+ end
@@ -6,23 +6,18 @@ module Rouge
6
6
  class HTMLLinewise < Formatter
7
7
  def initialize(formatter, opts={})
8
8
  @formatter = formatter
9
+ @tag_name = opts.fetch(:tag_name, 'div')
9
10
  @class_format = opts.fetch(:class, 'line-%i')
10
11
  end
11
12
 
12
13
  def stream(tokens, &b)
13
- token_lines(tokens) do |line|
14
- yield "<div class=#{next_line_class}>"
15
- line.each do |tok, val|
16
- yield @formatter.span(tok, val)
17
- end
18
- yield '</div>'
14
+ lineno = 0
15
+ token_lines(tokens) do |line_tokens|
16
+ yield %(<#{@tag_name} class="#{sprintf @class_format, lineno += 1}">)
17
+ @formatter.stream(line_tokens) {|formatted| yield formatted }
18
+ yield %(\n</#{@tag_name}>)
19
19
  end
20
20
  end
21
-
22
- def next_line_class
23
- @lineno ||= 0
24
- sprintf(@class_format, @lineno += 1).inspect
25
- end
26
21
  end
27
22
  end
28
23
  end
@@ -16,46 +16,35 @@ module Rouge
16
16
  end
17
17
 
18
18
  def style(scope)
19
- yield "#{scope} .rouge-table { border-spacing: 0 }"
20
- yield "#{scope} .rouge-gutter { text-align: right }"
19
+ yield %(#{scope} .rouge-table { border-spacing: 0 })
20
+ yield %(#{scope} .rouge-gutter { text-align: right })
21
21
  end
22
22
 
23
23
  def stream(tokens, &b)
24
- num_lines = 0
25
- last_val = ''
26
- formatted = String.new('')
27
-
28
- tokens.each do |tok, val|
29
- last_val = val
30
- num_lines += val.scan(/\n/).size
31
- formatted << @inner.span(tok, val)
32
- end
33
-
34
- # add an extra line for non-newline-terminated strings
35
- if last_val[-1] != "\n"
24
+ last_val = nil
25
+ num_lines = tokens.reduce(0) {|count, (_, val)| count + (last_val = val).count(?\n) }
26
+ formatted = @inner.format(tokens)
27
+ unless last_val && last_val.end_with?(?\n)
36
28
  num_lines += 1
37
- @inner.span(Token::Tokens::Text::Whitespace, "\n") { |str| formatted << str }
29
+ formatted << ?\n
38
30
  end
39
31
 
40
32
  # generate a string of newline-separated line numbers for the gutter>
41
- formatted_line_numbers = (@start_line..num_lines+@start_line-1).map do |i|
42
- sprintf("#{@line_format}", i) << "\n"
43
- end.join('')
44
-
45
- numbers = %(<pre class="lineno">#{formatted_line_numbers}</pre>)
46
-
47
- yield %(<table class="#@table_class"><tbody><tr>)
33
+ formatted_line_numbers = (@start_line..(@start_line + num_lines - 1)).map do |i|
34
+ sprintf(@line_format, i)
35
+ end.join(?\n) << ?\n
48
36
 
37
+ buffer = [%(<table class="#@table_class"><tbody><tr>)]
49
38
  # the "gl" class applies the style for Generic.Lineno
50
- yield %(<td class="#@gutter_class gl">)
51
- yield numbers
52
- yield '</td>'
53
-
54
- yield %(<td class="#@code_class"><pre>)
55
- yield formatted
56
- yield '</pre></td>'
57
-
58
- yield "</tr></tbody></table>"
39
+ buffer << %(<td class="#@gutter_class gl">)
40
+ buffer << %(<pre class="lineno">#{formatted_line_numbers}</pre>)
41
+ buffer << '</td>'
42
+ buffer << %(<td class="#@code_class"><pre>)
43
+ buffer << formatted
44
+ buffer << '</pre></td>'
45
+ buffer << '</tr></tbody></table>'
46
+
47
+ yield buffer.join
59
48
  end
60
49
  end
61
50
  end
@@ -159,6 +159,7 @@ module Rouge
159
159
 
160
160
  # private
161
161
  def escape_sequence(token)
162
+ return '' if escape?(token)
162
163
  @escape_sequences ||= {}
163
164
  @escape_sequences[token.qualname] ||=
164
165
  EscapeSequence.new(get_style(token))
@@ -0,0 +1,92 @@
1
+ # -*- coding: utf-8 -*- #
2
+ # frozen_string_literal: true
3
+
4
+ module Rouge
5
+ module Formatters
6
+ class Tex < Formatter
7
+ tag 'tex'
8
+
9
+ # A map of TeX escape characters.
10
+ # Newlines are handled specially by using #token_lines
11
+ # spaces are preserved as long as they aren't at the beginning
12
+ # of a line. see #tag_first for our initial-space strategy
13
+ ESCAPE = {
14
+ '&' => '\&',
15
+ '%' => '\%',
16
+ '$' => '\$',
17
+ '#' => '\#',
18
+ '_' => '\_',
19
+ '{' => '\{',
20
+ '}' => '\}',
21
+ '~' => '{\textasciitilde}',
22
+ '^' => '{\textasciicircum}',
23
+ '|' => '{\textbar}',
24
+ '\\' => '{\textbackslash}',
25
+ '`' => '{\textasciigrave}',
26
+ "'" => "'{}",
27
+ '"' => '"{}',
28
+ "\t" => '{\tab}',
29
+ }
30
+
31
+ ESCAPE_REGEX = /[#{ESCAPE.keys.map(&Regexp.method(:escape)).join}]/om
32
+
33
+ def initialize(opts={})
34
+ @prefix = opts.fetch(:prefix) { 'RG' }
35
+ end
36
+
37
+ def escape_tex(str)
38
+ str.gsub(ESCAPE_REGEX, ESCAPE)
39
+ end
40
+
41
+ def stream(tokens, &b)
42
+ # surround the output with \begin{RG*}...\end{RG*}
43
+ yield "\\begin{#{@prefix}*}%\n"
44
+
45
+ # we strip the newline off the last line to avoid
46
+ # an extra line being rendered. we do this by yielding
47
+ # the \newline tag *before* every line group except
48
+ # the first.
49
+ first = true
50
+
51
+ token_lines tokens do |line|
52
+ if first
53
+ first = false
54
+ else
55
+ yield "\\newline%\n"
56
+ end
57
+
58
+ render_line(line, &b)
59
+ end
60
+
61
+ yield "%\n\\end{#{@prefix}*}%\n"
62
+ end
63
+
64
+ def render_line(line, &b)
65
+ line.each do |(tok, val)|
66
+ hphantom_tag(tok, val, &b)
67
+ end
68
+ end
69
+
70
+ # Special handling for leading spaces, since they may be gobbled
71
+ # by a previous command. We replace all initial spaces with
72
+ # \hphantom{xxxx}, which renders an empty space equal to the size
73
+ # of the x's.
74
+ def hphantom_tag(tok, val)
75
+ leading = nil
76
+ val.sub!(/^[ ]+/) { leading = $&.size; '' }
77
+ yield "\\hphantom{#{'x' * leading}}" if leading
78
+ yield tag(tok, val) unless val.empty?
79
+ end
80
+
81
+ def tag(tok, val)
82
+ if escape?(tok)
83
+ val
84
+ elsif tok == Token::Tokens::Text
85
+ escape_tex(val)
86
+ else
87
+ "\\#@prefix{#{tok.shortname}}{#{escape_tex(val)}}"
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -75,6 +75,8 @@ module Rouge
75
75
  disambiguate '*.h' do
76
76
  next ObjectiveC if matches?(/@(end|implementation|protocol|property)\b/)
77
77
  next ObjectiveC if contains?('@"')
78
+ next Cpp if matches?(/^\s*(?:catch|class|constexpr|namespace|private|
79
+ protected|public|template|throw|try|using)\b/x)
78
80
 
79
81
  C
80
82
  end
@@ -86,7 +88,11 @@ module Rouge
86
88
  next Mathematica if contains?('(*')
87
89
  next Mathematica if contains?(':=')
88
90
 
91
+ next Mason if matches?(/<%(def|method|text|doc|args|flags|attr|init|once|shared|perl|cleanup|filter)([^>]*)(>)/)
92
+
89
93
  next Matlab if matches?(/^\s*?%/)
94
+
95
+ next Mason if matches? %r!(</?%|<&)!
90
96
  end
91
97
 
92
98
  disambiguate '*.php' do
@@ -101,6 +107,25 @@ module Rouge
101
107
 
102
108
  Cpp
103
109
  end
110
+
111
+ disambiguate '*.plist' do
112
+ next XML if matches?(/\A<\?xml\b/)
113
+
114
+ Plist
115
+ end
116
+
117
+ disambiguate '*.sc' do
118
+ next Python if matches?(/^#/)
119
+ next SuperCollider if matches?(/(?:^~|;$)/)
120
+
121
+ next Python
122
+ end
123
+
124
+ disambiguate 'Messages' do
125
+ next MsgTrans if matches?(/^[^\s:]+:[^\s:]+/)
126
+
127
+ next PlainText
128
+ end
104
129
  end
105
130
  end
106
131
  end
@@ -32,7 +32,7 @@ module Rouge
32
32
  basename = File.basename(filename)
33
33
 
34
34
  collect_best(lexers) do |lexer|
35
- score = (@glob_map[lexer.name] || []).map do |pattern|
35
+ (@glob_map[lexer.name] || []).map do |pattern|
36
36
  if test_glob(pattern, basename)
37
37
  # specificity is better the fewer wildcards there are
38
38
  -pattern.scan(/[*?\[]/).size
@@ -37,7 +37,7 @@ module Rouge
37
37
 
38
38
  matches = MODELINES.map { |re| re.match(search_space) }.compact
39
39
  return lexers unless matches.any?
40
-
40
+
41
41
  match_set = Set.new(matches.map { |m| m[1] })
42
42
  lexers.select { |l| match_set.include?(l.tag) || l.aliases.any? { |a| match_set.include?(a) } }
43
43
  end
@@ -22,7 +22,7 @@ module Rouge
22
22
  source_text = TextAnalyzer.new(source_text)
23
23
 
24
24
  collect_best(lexers) do |lexer|
25
- next unless lexer.methods(false).include? :detect?
25
+ next unless lexer.detectable?
26
26
  lexer.detect?(source_text) ? 1 : nil
27
27
  end
28
28
  end
@@ -23,6 +23,14 @@ module Rouge
23
23
  new(opts).lex(stream, &b)
24
24
  end
25
25
 
26
+ # In case #continue_lex is called statically, we simply
27
+ # begin a new lex from the beginning, since there is no state.
28
+ #
29
+ # @see #continue_lex
30
+ def continue_lex(*a, &b)
31
+ lex(*a, &b)
32
+ end
33
+
26
34
  # Given a name in string, return the correct lexer class.
27
35
  # @param [String] name
28
36
  # @return [Class<Rouge::Lexer>,nil]
@@ -106,7 +114,7 @@ module Rouge
106
114
  def demo_file(arg=:absent)
107
115
  return @demo_file = Pathname.new(arg) unless arg == :absent
108
116
 
109
- @demo_file = Pathname.new(__FILE__).dirname.join('demos', tag)
117
+ @demo_file = Pathname.new(File.join(__dir__, 'demos', tag))
110
118
  end
111
119
 
112
120
  # Specify or get a small demo string for this lexer
@@ -118,7 +126,7 @@ module Rouge
118
126
 
119
127
  # @return a list of all lexers.
120
128
  def all
121
- registry.values.uniq
129
+ @all ||= registry.values.uniq
122
130
  end
123
131
 
124
132
  # Guess which lexer to use based on a hash of info.
@@ -188,16 +196,24 @@ module Rouge
188
196
  end
189
197
 
190
198
  def disable_debug!
191
- @debug_enabled = false
199
+ remove_instance_variable :@debug_enabled if defined? @debug_enabled
192
200
  end
193
201
 
194
202
  def debug_enabled?
195
- !!@debug_enabled
203
+ (defined? @debug_enabled) ? true : false
204
+ end
205
+
206
+ # Determine if a lexer has a method named +:detect?+ defined in its
207
+ # singleton class.
208
+ def detectable?
209
+ @detectable ||= methods(false).include?(:detect?)
196
210
  end
197
211
 
198
212
  protected
199
213
  # @private
200
214
  def register(name, lexer)
215
+ # reset an existing list of lexers
216
+ @all = nil if defined?(@all)
201
217
  registry[name.to_s] = lexer
202
218
  end
203
219
 
@@ -236,6 +252,13 @@ module Rouge
236
252
 
237
253
  # Specify a list of filename globs associated with this lexer.
238
254
  #
255
+ # If a filename glob is associated with more than one lexer, this can
256
+ # cause a Guesser::Ambiguous error to be raised in various guessing
257
+ # methods. These errors can be avoided by disambiguation. Filename globs
258
+ # are disambiguated in one of two ways. Either the lexer will define a
259
+ # `self.detect?` method (intended for use with shebangs and doctypes) or a
260
+ # manual rule will be specified in Guessers::Disambiguation.
261
+ #
239
262
  # @example
240
263
  # class Ruby < Lexer
241
264
  # filenames '*.rb', '*.ruby', 'Gemfile', 'Rakefile'
@@ -256,7 +279,9 @@ module Rouge
256
279
 
257
280
  # @private
258
281
  def assert_utf8!(str)
259
- return if %w(US-ASCII UTF-8 ASCII-8BIT).include? str.encoding.name
282
+ encoding = str.encoding.name
283
+ return if encoding == 'US-ASCII' || encoding == 'UTF-8' || encoding == 'ASCII-8BIT'
284
+
260
285
  raise EncodingError.new(
261
286
  "Bad encoding: #{str.encoding.names.join(',')}. " +
262
287
  "Please convert your string to UTF-8."
@@ -285,7 +310,7 @@ module Rouge
285
310
  @options = {}
286
311
  opts.each { |k, v| @options[k.to_s] = v }
287
312
 
288
- @debug = Lexer.debug_enabled? && bool_option(:debug)
313
+ @debug = Lexer.debug_enabled? && bool_option('debug')
289
314
  end
290
315
 
291
316
  def as_bool(val)
@@ -340,8 +365,10 @@ module Rouge
340
365
  end
341
366
 
342
367
  def bool_option(name, &default)
343
- if @options.key?(name.to_s)
344
- as_bool(@options[name.to_s])
368
+ name_str = name.to_s
369
+
370
+ if @options.key?(name_str)
371
+ as_bool(@options[name_str])
345
372
  else
346
373
  default ? default.call : false
347
374
  end
@@ -393,12 +420,37 @@ module Rouge
393
420
  #
394
421
  # @option opts :continue
395
422
  # Continue the lex from the previous state (i.e. don't call #reset!)
396
- def lex(string, opts={}, &b)
397
- return enum_for(:lex, string, opts) unless block_given?
423
+ #
424
+ # @note The use of :continue => true has been deprecated. A warning is
425
+ # issued if run with `$VERBOSE` set to true.
426
+ #
427
+ # @note The use of arbitrary `opts` has never been supported, but we
428
+ # previously ignored them with no error. We now warn unconditionally.
429
+ def lex(string, opts=nil, &b)
430
+ if opts
431
+ if (opts.keys - [:continue]).size > 0
432
+ # improper use of options hash
433
+ warn('Improper use of Lexer#lex - this method does not receive options.' +
434
+ ' This will become an error in a future version.')
435
+ end
436
+
437
+ if opts[:continue]
438
+ warn '`lex :continue => true` is deprecated, please use #continue_lex instead'
439
+ return continue_lex(string, &b)
440
+ end
441
+ end
442
+
443
+ return enum_for(:lex, string) unless block_given?
398
444
 
399
445
  Lexer.assert_utf8!(string)
446
+ reset!
447
+
448
+ continue_lex(string, &b)
449
+ end
400
450
 
401
- reset! unless opts[:continue]
451
+ # Continue the lex from the the current state without resetting
452
+ def continue_lex(string, &b)
453
+ return enum_for(:continue_lex, string, &b) unless block_given?
402
454
 
403
455
  # consolidate consecutive tokens of the same type
404
456
  last_token = nil
@@ -454,9 +506,7 @@ module Rouge
454
506
  def self.load_lexer(relpath)
455
507
  return if @_loaded_lexers.key?(relpath)
456
508
  @_loaded_lexers[relpath] = true
457
-
458
- root = Pathname.new(__FILE__).dirname.join('lexers')
459
- load root.join(relpath)
509
+ load File.join(__dir__, 'lexers', relpath)
460
510
  end
461
511
  end
462
512
  end