pygments.rb 2.0.0.rc3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +13 -1
  3. data/.gitignore +0 -1
  4. data/.rubocop.yml +16 -0
  5. data/CHANGELOG.adoc +19 -0
  6. data/README.adoc +1 -3
  7. data/Rakefile +0 -14
  8. data/bench.rb +11 -6
  9. data/lib/pygments/lexer.rb +84 -62
  10. data/lib/pygments/mentos.py +7 -49
  11. data/lib/pygments/popen.rb +133 -173
  12. data/lib/pygments/version.rb +1 -1
  13. data/lib/pygments.rb +15 -6
  14. data/pygments.rb.gemspec +16 -11
  15. data/test/test_pygments.rb +19 -40
  16. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/AUTHORS +13 -1
  17. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/INSTALLER +0 -0
  18. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/LICENSE +1 -1
  19. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/METADATA +8 -9
  20. data/vendor/pygments-main/Pygments-2.10.0.dist-info/RECORD +524 -0
  21. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/REQUESTED +0 -0
  22. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/WHEEL +0 -0
  23. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/entry_points.txt +0 -0
  24. data/vendor/pygments-main/{Pygments-2.7.3.dist-info → Pygments-2.10.0.dist-info}/top_level.txt +0 -0
  25. data/vendor/pygments-main/bin/pygmentize +1 -1
  26. data/vendor/pygments-main/pygments/__init__.py +2 -3
  27. data/vendor/pygments-main/pygments/__main__.py +1 -2
  28. data/vendor/pygments-main/pygments/cmdline.py +179 -159
  29. data/vendor/pygments-main/pygments/console.py +1 -2
  30. data/vendor/pygments-main/pygments/filter.py +1 -2
  31. data/vendor/pygments-main/pygments/filters/__init__.py +1 -2
  32. data/vendor/pygments-main/pygments/formatter.py +1 -2
  33. data/vendor/pygments-main/pygments/formatters/__init__.py +2 -3
  34. data/vendor/pygments-main/pygments/formatters/_mapping.py +2 -2
  35. data/vendor/pygments-main/pygments/formatters/bbcode.py +1 -2
  36. data/vendor/pygments-main/pygments/formatters/html.py +53 -25
  37. data/vendor/pygments-main/pygments/formatters/img.py +24 -10
  38. data/vendor/pygments-main/pygments/formatters/irc.py +1 -2
  39. data/vendor/pygments-main/pygments/formatters/latex.py +8 -9
  40. data/vendor/pygments-main/pygments/formatters/other.py +7 -10
  41. data/vendor/pygments-main/pygments/formatters/pangomarkup.py +83 -0
  42. data/vendor/pygments-main/pygments/formatters/rtf.py +1 -2
  43. data/vendor/pygments-main/pygments/formatters/svg.py +5 -4
  44. data/vendor/pygments-main/pygments/formatters/terminal.py +1 -2
  45. data/vendor/pygments-main/pygments/formatters/terminal256.py +24 -3
  46. data/vendor/pygments-main/pygments/lexer.py +7 -6
  47. data/vendor/pygments-main/pygments/lexers/__init__.py +2 -3
  48. data/vendor/pygments-main/pygments/lexers/_asy_builtins.py +1 -2
  49. data/vendor/pygments-main/pygments/lexers/_cl_builtins.py +1 -2
  50. data/vendor/pygments-main/pygments/lexers/_cocoa_builtins.py +16 -12
  51. data/vendor/pygments-main/pygments/lexers/_csound_builtins.py +56 -16
  52. data/vendor/pygments-main/pygments/lexers/_julia_builtins.py +401 -0
  53. data/vendor/pygments-main/pygments/lexers/_lasso_builtins.py +1 -2
  54. data/vendor/pygments-main/pygments/lexers/_lua_builtins.py +1 -2
  55. data/vendor/pygments-main/pygments/lexers/_mapping.py +73 -54
  56. data/vendor/pygments-main/pygments/lexers/_mql_builtins.py +1 -2
  57. data/vendor/pygments-main/pygments/lexers/_mysql_builtins.py +2 -3
  58. data/vendor/pygments-main/pygments/lexers/_openedge_builtins.py +439 -386
  59. data/vendor/pygments-main/pygments/lexers/_php_builtins.py +1 -2
  60. data/vendor/pygments-main/pygments/lexers/_postgres_builtins.py +1 -2
  61. data/vendor/pygments-main/pygments/lexers/_scilab_builtins.py +1 -2
  62. data/vendor/pygments-main/pygments/lexers/_sourcemod_builtins.py +1 -2
  63. data/vendor/pygments-main/pygments/lexers/_stan_builtins.py +1 -2
  64. data/vendor/pygments-main/pygments/lexers/_stata_builtins.py +91 -55
  65. data/vendor/pygments-main/pygments/lexers/_tsql_builtins.py +1 -2
  66. data/vendor/pygments-main/pygments/lexers/_usd_builtins.py +1 -2
  67. data/vendor/pygments-main/pygments/lexers/_vbscript_builtins.py +1 -2
  68. data/vendor/pygments-main/pygments/lexers/_vim_builtins.py +1 -2
  69. data/vendor/pygments-main/pygments/lexers/actionscript.py +9 -10
  70. data/vendor/pygments-main/pygments/lexers/agile.py +1 -2
  71. data/vendor/pygments-main/pygments/lexers/algebra.py +1 -2
  72. data/vendor/pygments-main/pygments/lexers/ambient.py +3 -4
  73. data/vendor/pygments-main/pygments/lexers/amdgpu.py +53 -0
  74. data/vendor/pygments-main/pygments/lexers/ampl.py +1 -2
  75. data/vendor/pygments-main/pygments/lexers/apdlexer.py +448 -0
  76. data/vendor/pygments-main/pygments/lexers/apl.py +7 -5
  77. data/vendor/pygments-main/pygments/lexers/archetype.py +2 -3
  78. data/vendor/pygments-main/pygments/lexers/arrow.py +1 -2
  79. data/vendor/pygments-main/pygments/lexers/asc.py +51 -0
  80. data/vendor/pygments-main/pygments/lexers/asm.py +87 -60
  81. data/vendor/pygments-main/pygments/lexers/automation.py +8 -3
  82. data/vendor/pygments-main/pygments/lexers/bare.py +1 -2
  83. data/vendor/pygments-main/pygments/lexers/basic.py +3 -4
  84. data/vendor/pygments-main/pygments/lexers/bibtex.py +3 -4
  85. data/vendor/pygments-main/pygments/lexers/boa.py +4 -5
  86. data/vendor/pygments-main/pygments/lexers/business.py +3 -4
  87. data/vendor/pygments-main/pygments/lexers/c_cpp.py +61 -36
  88. data/vendor/pygments-main/pygments/lexers/c_like.py +103 -5
  89. data/vendor/pygments-main/pygments/lexers/capnproto.py +1 -2
  90. data/vendor/pygments-main/pygments/lexers/cddl.py +190 -0
  91. data/vendor/pygments-main/pygments/lexers/chapel.py +52 -29
  92. data/vendor/pygments-main/pygments/lexers/clean.py +7 -8
  93. data/vendor/pygments-main/pygments/lexers/compiled.py +1 -2
  94. data/vendor/pygments-main/pygments/lexers/configs.py +139 -48
  95. data/vendor/pygments-main/pygments/lexers/console.py +1 -2
  96. data/vendor/pygments-main/pygments/lexers/crystal.py +53 -79
  97. data/vendor/pygments-main/pygments/lexers/csound.py +3 -4
  98. data/vendor/pygments-main/pygments/lexers/css.py +11 -8
  99. data/vendor/pygments-main/pygments/lexers/d.py +3 -4
  100. data/vendor/pygments-main/pygments/lexers/dalvik.py +1 -2
  101. data/vendor/pygments-main/pygments/lexers/data.py +2 -3
  102. data/vendor/pygments-main/pygments/lexers/devicetree.py +2 -3
  103. data/vendor/pygments-main/pygments/lexers/diff.py +1 -2
  104. data/vendor/pygments-main/pygments/lexers/dotnet.py +7 -8
  105. data/vendor/pygments-main/pygments/lexers/dsls.py +3 -4
  106. data/vendor/pygments-main/pygments/lexers/dylan.py +1 -2
  107. data/vendor/pygments-main/pygments/lexers/ecl.py +4 -6
  108. data/vendor/pygments-main/pygments/lexers/eiffel.py +2 -3
  109. data/vendor/pygments-main/pygments/lexers/elm.py +1 -2
  110. data/vendor/pygments-main/pygments/lexers/email.py +1 -2
  111. data/vendor/pygments-main/pygments/lexers/erlang.py +2 -3
  112. data/vendor/pygments-main/pygments/lexers/esoteric.py +1 -2
  113. data/vendor/pygments-main/pygments/lexers/ezhil.py +1 -2
  114. data/vendor/pygments-main/pygments/lexers/factor.py +3 -4
  115. data/vendor/pygments-main/pygments/lexers/fantom.py +1 -2
  116. data/vendor/pygments-main/pygments/lexers/felix.py +1 -2
  117. data/vendor/pygments-main/pygments/lexers/floscript.py +2 -3
  118. data/vendor/pygments-main/pygments/lexers/forth.py +2 -3
  119. data/vendor/pygments-main/pygments/lexers/fortran.py +9 -7
  120. data/vendor/pygments-main/pygments/lexers/foxpro.py +1 -2
  121. data/vendor/pygments-main/pygments/lexers/freefem.py +1 -2
  122. data/vendor/pygments-main/pygments/lexers/functional.py +1 -2
  123. data/vendor/pygments-main/pygments/lexers/futhark.py +111 -0
  124. data/vendor/pygments-main/pygments/lexers/gcodelexer.py +36 -0
  125. data/vendor/pygments-main/pygments/lexers/gdscript.py +1 -2
  126. data/vendor/pygments-main/pygments/lexers/go.py +3 -4
  127. data/vendor/pygments-main/pygments/lexers/grammar_notation.py +1 -2
  128. data/vendor/pygments-main/pygments/lexers/graph.py +1 -2
  129. data/vendor/pygments-main/pygments/lexers/graphics.py +4 -5
  130. data/vendor/pygments-main/pygments/lexers/graphviz.py +58 -0
  131. data/vendor/pygments-main/pygments/lexers/gsql.py +92 -0
  132. data/vendor/pygments-main/pygments/lexers/haskell.py +5 -6
  133. data/vendor/pygments-main/pygments/lexers/haxe.py +4 -5
  134. data/vendor/pygments-main/pygments/lexers/hdl.py +2 -6
  135. data/vendor/pygments-main/pygments/lexers/hexdump.py +1 -2
  136. data/vendor/pygments-main/pygments/lexers/html.py +7 -8
  137. data/vendor/pygments-main/pygments/lexers/idl.py +1 -2
  138. data/vendor/pygments-main/pygments/lexers/igor.py +1 -2
  139. data/vendor/pygments-main/pygments/lexers/inferno.py +1 -2
  140. data/vendor/pygments-main/pygments/lexers/installers.py +3 -4
  141. data/vendor/pygments-main/pygments/lexers/int_fiction.py +1 -2
  142. data/vendor/pygments-main/pygments/lexers/iolang.py +2 -3
  143. data/vendor/pygments-main/pygments/lexers/j.py +2 -3
  144. data/vendor/pygments-main/pygments/lexers/javascript.py +170 -156
  145. data/vendor/pygments-main/pygments/lexers/jslt.py +94 -0
  146. data/vendor/pygments-main/pygments/lexers/julia.py +136 -185
  147. data/vendor/pygments-main/pygments/lexers/jvm.py +433 -307
  148. data/vendor/pygments-main/pygments/lexers/kuin.py +299 -0
  149. data/vendor/pygments-main/pygments/lexers/lisp.py +25 -23
  150. data/vendor/pygments-main/pygments/lexers/make.py +3 -4
  151. data/vendor/pygments-main/pygments/lexers/markup.py +13 -16
  152. data/vendor/pygments-main/pygments/lexers/math.py +1 -2
  153. data/vendor/pygments-main/pygments/lexers/matlab.py +2666 -93
  154. data/vendor/pygments-main/pygments/lexers/meson.py +155 -0
  155. data/vendor/pygments-main/pygments/lexers/mime.py +7 -23
  156. data/vendor/pygments-main/pygments/lexers/ml.py +8 -9
  157. data/vendor/pygments-main/pygments/lexers/modeling.py +1 -2
  158. data/vendor/pygments-main/pygments/lexers/modula2.py +3 -4
  159. data/vendor/pygments-main/pygments/lexers/monte.py +1 -2
  160. data/vendor/pygments-main/pygments/lexers/mosel.py +1 -2
  161. data/vendor/pygments-main/pygments/lexers/ncl.py +1 -2
  162. data/vendor/pygments-main/pygments/lexers/nimrod.py +2 -3
  163. data/vendor/pygments-main/pygments/lexers/nit.py +1 -2
  164. data/vendor/pygments-main/pygments/lexers/nix.py +1 -2
  165. data/vendor/pygments-main/pygments/lexers/oberon.py +1 -2
  166. data/vendor/pygments-main/pygments/lexers/objective.py +6 -7
  167. data/vendor/pygments-main/pygments/lexers/ooc.py +1 -2
  168. data/vendor/pygments-main/pygments/lexers/other.py +1 -2
  169. data/vendor/pygments-main/pygments/lexers/parasail.py +1 -2
  170. data/vendor/pygments-main/pygments/lexers/parsers.py +26 -27
  171. data/vendor/pygments-main/pygments/lexers/pascal.py +1 -2
  172. data/vendor/pygments-main/pygments/lexers/pawn.py +2 -5
  173. data/vendor/pygments-main/pygments/lexers/perl.py +1 -2
  174. data/vendor/pygments-main/pygments/lexers/php.py +3 -4
  175. data/vendor/pygments-main/pygments/lexers/pointless.py +1 -2
  176. data/vendor/pygments-main/pygments/lexers/pony.py +1 -2
  177. data/vendor/pygments-main/pygments/lexers/praat.py +1 -2
  178. data/vendor/pygments-main/pygments/lexers/procfile.py +43 -0
  179. data/vendor/pygments-main/pygments/lexers/prolog.py +3 -4
  180. data/vendor/pygments-main/pygments/lexers/promql.py +2 -3
  181. data/vendor/pygments-main/pygments/lexers/python.py +38 -17
  182. data/vendor/pygments-main/pygments/lexers/qvt.py +1 -2
  183. data/vendor/pygments-main/pygments/lexers/r.py +1 -2
  184. data/vendor/pygments-main/pygments/lexers/rdf.py +1 -2
  185. data/vendor/pygments-main/pygments/lexers/rebol.py +1 -2
  186. data/vendor/pygments-main/pygments/lexers/resource.py +2 -3
  187. data/vendor/pygments-main/pygments/lexers/ride.py +1 -2
  188. data/vendor/pygments-main/pygments/lexers/rnc.py +2 -3
  189. data/vendor/pygments-main/pygments/lexers/roboconf.py +1 -2
  190. data/vendor/pygments-main/pygments/lexers/robotframework.py +1 -2
  191. data/vendor/pygments-main/pygments/lexers/ruby.py +31 -25
  192. data/vendor/pygments-main/pygments/lexers/rust.py +10 -12
  193. data/vendor/pygments-main/pygments/lexers/sas.py +1 -2
  194. data/vendor/pygments-main/pygments/lexers/scdoc.py +1 -2
  195. data/vendor/pygments-main/pygments/lexers/scripting.py +12 -13
  196. data/vendor/pygments-main/pygments/lexers/sgf.py +1 -2
  197. data/vendor/pygments-main/pygments/lexers/shell.py +15 -17
  198. data/vendor/pygments-main/pygments/lexers/sieve.py +1 -2
  199. data/vendor/pygments-main/pygments/lexers/slash.py +1 -2
  200. data/vendor/pygments-main/pygments/lexers/smalltalk.py +1 -2
  201. data/vendor/pygments-main/pygments/lexers/smithy.py +79 -0
  202. data/vendor/pygments-main/pygments/lexers/smv.py +2 -3
  203. data/vendor/pygments-main/pygments/lexers/snobol.py +1 -2
  204. data/vendor/pygments-main/pygments/lexers/solidity.py +1 -2
  205. data/vendor/pygments-main/pygments/lexers/special.py +44 -30
  206. data/vendor/pygments-main/pygments/lexers/sql.py +8 -13
  207. data/vendor/pygments-main/pygments/lexers/stata.py +1 -2
  208. data/vendor/pygments-main/pygments/lexers/supercollider.py +4 -5
  209. data/vendor/pygments-main/pygments/lexers/tcl.py +4 -5
  210. data/vendor/pygments-main/pygments/lexers/teal.py +88 -0
  211. data/vendor/pygments-main/pygments/lexers/templates.py +34 -35
  212. data/vendor/pygments-main/pygments/lexers/teraterm.py +2 -3
  213. data/vendor/pygments-main/pygments/lexers/testing.py +2 -3
  214. data/vendor/pygments-main/pygments/lexers/text.py +1 -2
  215. data/vendor/pygments-main/pygments/lexers/textedit.py +3 -4
  216. data/vendor/pygments-main/pygments/lexers/textfmts.py +1 -2
  217. data/vendor/pygments-main/pygments/lexers/theorem.py +11 -7
  218. data/vendor/pygments-main/pygments/lexers/thingsdb.py +118 -0
  219. data/vendor/pygments-main/pygments/lexers/tnt.py +26 -17
  220. data/vendor/pygments-main/pygments/lexers/trafficscript.py +2 -3
  221. data/vendor/pygments-main/pygments/lexers/typoscript.py +1 -2
  222. data/vendor/pygments-main/pygments/lexers/unicon.py +1 -2
  223. data/vendor/pygments-main/pygments/lexers/urbi.py +3 -4
  224. data/vendor/pygments-main/pygments/lexers/usd.py +1 -2
  225. data/vendor/pygments-main/pygments/lexers/varnish.py +2 -3
  226. data/vendor/pygments-main/pygments/lexers/verification.py +1 -2
  227. data/vendor/pygments-main/pygments/lexers/web.py +1 -2
  228. data/vendor/pygments-main/pygments/lexers/webassembly.py +120 -0
  229. data/vendor/pygments-main/pygments/lexers/webidl.py +1 -2
  230. data/vendor/pygments-main/pygments/lexers/webmisc.py +5 -5
  231. data/vendor/pygments-main/pygments/lexers/whiley.py +1 -2
  232. data/vendor/pygments-main/pygments/lexers/x10.py +2 -3
  233. data/vendor/pygments-main/pygments/lexers/xorg.py +1 -2
  234. data/vendor/pygments-main/pygments/lexers/yang.py +1 -2
  235. data/vendor/pygments-main/pygments/lexers/zig.py +1 -2
  236. data/vendor/pygments-main/pygments/modeline.py +1 -2
  237. data/vendor/pygments-main/pygments/plugin.py +2 -3
  238. data/vendor/pygments-main/pygments/regexopt.py +2 -3
  239. data/vendor/pygments-main/pygments/scanner.py +1 -2
  240. data/vendor/pygments-main/pygments/sphinxext.py +1 -2
  241. data/vendor/pygments-main/pygments/style.py +4 -5
  242. data/vendor/pygments-main/pygments/styles/__init__.py +5 -2
  243. data/vendor/pygments-main/pygments/styles/abap.py +1 -2
  244. data/vendor/pygments-main/pygments/styles/algol.py +1 -2
  245. data/vendor/pygments-main/pygments/styles/algol_nu.py +1 -2
  246. data/vendor/pygments-main/pygments/styles/arduino.py +1 -2
  247. data/vendor/pygments-main/pygments/styles/autumn.py +1 -2
  248. data/vendor/pygments-main/pygments/styles/borland.py +1 -2
  249. data/vendor/pygments-main/pygments/styles/bw.py +1 -2
  250. data/vendor/pygments-main/pygments/styles/colorful.py +1 -2
  251. data/vendor/pygments-main/pygments/styles/default.py +1 -2
  252. data/vendor/pygments-main/pygments/styles/emacs.py +1 -2
  253. data/vendor/pygments-main/pygments/styles/friendly.py +2 -2
  254. data/vendor/pygments-main/pygments/styles/fruity.py +1 -2
  255. data/vendor/pygments-main/pygments/styles/gruvbox.py +107 -0
  256. data/vendor/pygments-main/pygments/styles/igor.py +1 -2
  257. data/vendor/pygments-main/pygments/styles/inkpot.py +1 -2
  258. data/vendor/pygments-main/pygments/styles/lovelace.py +1 -2
  259. data/vendor/pygments-main/pygments/styles/manni.py +1 -2
  260. data/vendor/pygments-main/pygments/styles/material.py +118 -0
  261. data/vendor/pygments-main/pygments/styles/monokai.py +1 -2
  262. data/vendor/pygments-main/pygments/styles/murphy.py +1 -2
  263. data/vendor/pygments-main/pygments/styles/native.py +2 -2
  264. data/vendor/pygments-main/pygments/styles/paraiso_dark.py +1 -2
  265. data/vendor/pygments-main/pygments/styles/paraiso_light.py +1 -2
  266. data/vendor/pygments-main/pygments/styles/pastie.py +1 -2
  267. data/vendor/pygments-main/pygments/styles/perldoc.py +1 -2
  268. data/vendor/pygments-main/pygments/styles/rainbow_dash.py +1 -2
  269. data/vendor/pygments-main/pygments/styles/rrt.py +1 -2
  270. data/vendor/pygments-main/pygments/styles/sas.py +1 -2
  271. data/vendor/pygments-main/pygments/styles/solarized.py +4 -2
  272. data/vendor/pygments-main/pygments/styles/stata_dark.py +1 -2
  273. data/vendor/pygments-main/pygments/styles/stata_light.py +1 -2
  274. data/vendor/pygments-main/pygments/styles/tango.py +1 -2
  275. data/vendor/pygments-main/pygments/styles/trac.py +1 -2
  276. data/vendor/pygments-main/pygments/styles/vim.py +1 -2
  277. data/vendor/pygments-main/pygments/styles/vs.py +1 -2
  278. data/vendor/pygments-main/pygments/styles/xcode.py +1 -2
  279. data/vendor/pygments-main/pygments/styles/zenburn.py +80 -0
  280. data/vendor/pygments-main/pygments/token.py +1 -2
  281. data/vendor/pygments-main/pygments/unistring.py +1 -2
  282. data/vendor/pygments-main/pygments/util.py +2 -5
  283. metadata +48 -23
  284. data/cache-lexers.rb +0 -9
  285. data/lexers +0 -0
  286. data/vendor/pygments-main/Pygments-2.7.3.dist-info/RECORD +0 -482
@@ -13,23 +13,13 @@ end
13
13
  # Python process.
14
14
  module Pygments
15
15
  class Popen
16
- def popen4(argv)
17
- stdin, stdout, stderr, wait_thr = Open3.popen3(*argv)
18
- while (pid = wait_thr.pid).nil? && wait_thr.alive?
19
- # For unknown reasons, wait_thr.pid is not immediately available on JRuby
20
- end
21
- [pid, stdin, stdout, stderr]
22
- end
23
-
24
16
  # Get things started by opening a pipe to mentos (the freshmaker), a
25
17
  # Python process that talks to the Pygments library. We'll talk back and
26
18
  # forth across this pipe.
27
- def start(pygments_path = File.expand_path('../../vendor/pygments-main', __dir__))
28
- begin
29
- @log = Logger.new(ENV['MENTOS_LOG'] || File::NULL)
30
- @log.level = Logger::INFO
31
- @log.datetime_format = '%Y-%m-%d %H:%M '
32
- end
19
+ def start(pygments_path = File.join(__dir__, '..', '..', 'vendor', 'pygments-main'))
20
+ @log = Logger.new(ENV['MENTOS_LOG'] || File::NULL)
21
+ @log.level = Logger::INFO
22
+ @log.datetime_format = '%Y-%m-%d %H:%M '
33
23
 
34
24
  ENV['PYGMENTS_PATH'] = pygments_path
35
25
 
@@ -38,11 +28,11 @@ module Pygments
38
28
 
39
29
  # A pipe to the mentos python process. #popen4 gives us
40
30
  # the pid and three IO objects to write and read.
41
- argv = [*python_binary, File.expand_path('mentos.py', __dir__)]
31
+ argv = [*python_binary, File.join(__dir__, 'mentos.py')]
42
32
  @pid, @in, @out, @err = popen4(argv)
43
33
  @in.binmode
44
34
  @out.binmode
45
- @log.info "Starting pid #{@pid} with fd #{@out.to_i} and python #{python_binary}."
35
+ @log.info "Starting pid #{@pid} with python #{python_binary}."
46
36
  end
47
37
 
48
38
  def python_binary
@@ -53,29 +43,6 @@ module Pygments
53
43
  @python_bin = python_bin
54
44
  end
55
45
 
56
- # Detect a suitable Python binary to use.
57
- def find_python_binary
58
- if Gem.win_platform?
59
- return %w[py python3 python].first { |py| !which(py).nil? }
60
- end
61
-
62
- # On non-Windows platforms, we simply rely on shebang
63
- []
64
- end
65
-
66
- # Cross platform which command
67
- # from http://stackoverflow.com/a/5471032/284795
68
- def which(command)
69
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
70
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
71
- exts.each do |ext|
72
- path = File.join(dir, "#{command}#{ext}")
73
- return path if File.executable?(path) && !File.directory?(path)
74
- end
75
- end
76
- nil
77
- end
78
-
79
46
  # Stop the child process by issuing a kill -9.
80
47
  #
81
48
  # We then call waitpid() with the pid, which waits for that particular
@@ -88,13 +55,15 @@ module Pygments
88
55
  # Technically, kill() can also fail with EPERM or EINVAL (wherein
89
56
  # the signal isn't sent); but we have permissions, and
90
57
  # we're not doing anything invalid here.
58
+ # @param reason [String]
91
59
  def stop(reason)
92
60
  unless @pid.nil?
93
61
  @log.info "Killing pid: #{@pid}. Reason: #{reason}"
94
62
  begin
95
63
  Process.kill('KILL', @pid)
96
64
  Process.waitpid(@pid)
97
- rescue Errno::ESRCH, Errno::ECHILD
65
+ rescue Errno::ESRCH, Errno::ECHILD => e
66
+ @log.warn(e)
98
67
  end
99
68
  end
100
69
  @pid = nil
@@ -108,7 +77,7 @@ module Pygments
108
77
  # process and the pid has already been re-used) we'll want to raise
109
78
  # that as a more informative Mentos exception.
110
79
  #
111
- # Returns true if the child is alive.
80
+ # @return [Boolean] true if the child is alive.
112
81
  def alive?
113
82
  return true if defined?(@pid) && @pid && Process.kill(0, @pid)
114
83
 
@@ -119,9 +88,16 @@ module Pygments
119
88
  raise MentosError, 'EPERM checking if child process is alive.'
120
89
  end
121
90
 
91
+ # Public: Returns version of underlying Pygments library
92
+ #
93
+ # @return [Integer]
94
+ def pygments_version
95
+ mentos(:version)[0]
96
+ end
97
+
122
98
  # Public: Get an array of available Pygments formatters
123
99
  #
124
- # Returns an array of formatters.
100
+ # @return [Array<String>] an array of formatters
125
101
  def formatters
126
102
  mentos(:get_all_formatters).each_with_object({}) do |(name, desc, aliases), hash|
127
103
  # Remove the long-winded and repetitive 'Formatter' suffix
@@ -134,23 +110,10 @@ module Pygments
134
110
  end
135
111
  end
136
112
 
137
- # Public: Get all lexers from a serialized array. This avoids needing to spawn
138
- # mentos when it's not really needed (e.g., one-off jobs, loading the Rails env, etc).
139
- #
140
- # Should be preferred to #lexers!
141
- #
142
- # Returns an array of lexers.
143
- def lexers
144
- lexer_file = File.expand_path('../../lexers', __dir__)
145
- raw = File.open(lexer_file, 'rb').read
146
- Marshal.load(raw)
147
- rescue Errno::ENOENT
148
- raise MentosError, 'Error loading lexer file. Was it created and vendored?'
149
- end
150
-
151
- # Public: Get back all available lexers from mentos itself
113
+ # Get all available lexers from mentos itself
114
+ # Do not use this method directly, instead use Pygments#lexers
152
115
  #
153
- # Returns an array of lexers.
116
+ # @return [Array<String>] an array of lexers
154
117
  def lexers!
155
118
  mentos(:get_all_lexers).each_with_object({}) do |lxr, hash|
156
119
  name = lxr[0]
@@ -163,17 +126,17 @@ module Pygments
163
126
  end
164
127
  end
165
128
 
166
- # Public: Return an array of all available filters
129
+ # @return [Array<String>] an array of all available filters
167
130
  def filters
168
131
  mentos(:get_all_filters)
169
132
  end
170
133
 
171
- # Public: Return an array of all available styles
134
+ # @return [Array<String>] an array of all available styles
172
135
  def styles
173
136
  mentos(:get_all_styles)
174
137
  end
175
138
 
176
- # Public: Return css for highlighted code
139
+ # @return [String] css for highlighted code
177
140
  def css(klass = '', opts = {})
178
141
  if klass.is_a?(Hash)
179
142
  opts = klass
@@ -182,8 +145,8 @@ module Pygments
182
145
  mentos(:css, ['html', klass], opts)
183
146
  end
184
147
 
185
- # Public: Return the name of a lexer.
186
- def lexer_name_for(*args)
148
+ # @return [[String], nil] aliases of a lexer.
149
+ def lexer_names_for(*args)
187
150
  # Pop off the last arg if it's a hash, which becomes our opts
188
151
  opts = if args.last.is_a?(Hash)
189
152
  args.pop
@@ -193,13 +156,14 @@ module Pygments
193
156
 
194
157
  code = (args.pop if args.last.is_a?(String))
195
158
 
196
- mentos(:lexer_name_for, args, opts, code)
159
+ mentos(:lexer_names_for, args, opts, code)
197
160
  end
198
161
 
199
162
  # Public: Highlight code.
200
163
  #
201
- # Takes a first-position argument of the code to be highlighted, and a
202
- # second-position hash of various arguments specifying highlighting properties.
164
+ # Takes a first-position argument of the code to be highlighted,
165
+ # and a second-position hash of various arguments specifying
166
+ # highlighting properties.
203
167
  #
204
168
  # Returns the highlighted string
205
169
  # or nil when the request to the Python process timed out.
@@ -216,30 +180,63 @@ module Pygments
216
180
 
217
181
  # Get back the string from mentos and force encoding if we can
218
182
  str = mentos(:highlight, nil, opts, code)
219
- if str.respond_to?(:force_encoding)
220
- str.force_encoding(opts[:options][:outencoding])
221
- end
183
+ str.force_encoding(opts[:options][:outencoding]) if str.respond_to?(:force_encoding)
222
184
  str
223
185
  end
224
186
 
225
187
  private
226
188
 
227
- def with_watchdog(timeout_time, error_message)
189
+ # @param argv [Array<String>]
190
+ def popen4(argv)
191
+ stdin, stdout, stderr, wait_thr = Open3.popen3(*argv, { close_others: true })
192
+ while (pid = wait_thr.pid).nil? && wait_thr.alive?
193
+ # wait_thr.pid is not immediately available on JRuby. Why???
194
+ end
195
+ [pid, stdin, stdout, stderr]
196
+ end
197
+
198
+ # Detect a suitable Python binary to use.
199
+ def find_python_binary
200
+ return %w[py python3 python].first { |py| !which(py).nil? } if Gem.win_platform?
201
+
202
+ # On non-Windows platforms, we simply rely on shebang
203
+ []
204
+ end
205
+
206
+ # Cross platform which command
207
+ # from http://stackoverflow.com/a/5471032/284795
208
+ def which(command)
209
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
210
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
211
+ exts.each do |ext|
212
+ path = File.join(dir, "#{command}#{ext}")
213
+ return path if File.executable?(path) && !File.directory?(path)
214
+ end
215
+ end
216
+ nil
217
+ end
218
+
219
+ # @param timeout [Integer]
220
+ # @param error_message [String]
221
+ # @yield
222
+ def with_watchdog(timeout, error_message)
228
223
  state_mutex = Mutex.new
229
224
  state = :alive
230
225
  wd_cleanup = ConditionVariable.new
231
226
 
232
- watchdog = timeout_time > 0 ? Thread.new do
233
- state_mutex.synchronize do
234
- wd_cleanup.wait(state_mutex, timeout_time) if state != :finished
235
- if state != :finished
236
- @log.error error_message
237
- stop error_message
238
- state = :timeout
239
- end
227
+ watchdog = if timeout.positive?
228
+ Thread.new do
229
+ state_mutex.synchronize do
230
+ wd_cleanup.wait(state_mutex, timeout) if state != :finished
231
+ if state != :finished
232
+ @log.error error_message
233
+ stop error_message
234
+ state = :timeout
235
+ end
236
+ end
237
+ end
238
+ end
240
239
 
241
- end
242
- end : nil
243
240
  begin
244
241
  yield
245
242
  ensure
@@ -258,53 +255,20 @@ module Pygments
258
255
 
259
256
  # Our 'rpc'-ish request to mentos. Requires a method name, and then optional
260
257
  # args, kwargs, code.
261
- def mentos(method, args = [], kwargs = {}, original_code = nil)
258
+ def mentos(method, args = [], kwargs = {}, code = nil)
262
259
  # Open the pipe if necessary
263
260
  start unless alive?
264
261
 
265
- # Timeout requests that take too long.
266
- # Invalid MENTOS_TIMEOUT results in just using default.
267
- timeout_time = kwargs.delete(:timeout)
268
- if timeout_time.nil?
269
- timeout_time = begin
270
- Integer(ENV['MENTOS_TIMEOUT'])
271
- rescue TypeError
272
- 0
273
- end
274
- end
275
-
276
- # For sanity checking on both sides of the pipe when highlighting, we prepend and
277
- # append an id. mentos checks that these are 8 character ids and that they match.
278
- # It then returns the id's back to Rubyland.
279
- id = (0...8).map { rand(65..89).chr }.join
280
- code = original_code ? add_ids(original_code, id) : nil
281
-
282
262
  # Add metadata to the header and generate it.
283
- bytesize = if code
284
- code.bytesize
285
- else
286
- 0
287
- end
288
-
289
- kwargs.freeze
290
- kwargs = kwargs.merge('fd' => @out.to_i, 'id' => id, 'bytes' => bytesize)
263
+ kwargs = kwargs.merge('bytes' => (code.nil? ? 0 : code.bytesize))
291
264
  out_header = JSON.generate(method: method, args: args, kwargs: kwargs)
292
265
 
293
266
  begin
294
- res = with_watchdog(timeout_time, "Timeout on a mentos #{method} call") do
295
- # Get the size of the header itself and write that.
296
- @in.write([out_header.bytesize].pack('N'))
297
- @log.info "Size out: #{out_header.bytesize}"
298
-
299
- # mentos is now waiting for the header, and, potentially, code.
300
- @in.write(out_header)
301
- @log.info "Out header: #{out_header}"
302
- @in.write(code) unless code.nil?
303
-
304
- @in.flush
267
+ timeout = get_timeout(kwargs.delete(:timeout))
268
+ res = with_watchdog(timeout, "Timeout on a mentos #{method} call") do
269
+ write_header(out_header, code)
305
270
 
306
271
  # mentos will now return data to us. First it sends the header.
307
-
308
272
  header_len_bytes = @out.read(4)
309
273
  if header_len_bytes.nil?
310
274
  raise Errno::EPIPE, %(Failed to read response from Python process on a mentos #{method} call)
@@ -315,7 +279,7 @@ module Pygments
315
279
  header = @out.read(header_len)
316
280
 
317
281
  # Now handle the header, any read any more data required.
318
- handle_header_and_return(header, id)
282
+ handle_header_and_return(header)
319
283
  end
320
284
 
321
285
  # Finally, return what we got.
@@ -338,74 +302,70 @@ module Pygments
338
302
  end
339
303
  end
340
304
 
305
+ # @param header [String]
306
+ # @param code [String, nil]
307
+ def write_header(header, code)
308
+ # Get the size of the header itself and write that.
309
+ @in.write([header.bytesize].pack('N'))
310
+ @log.info "Size out: #{header.bytesize}"
311
+
312
+ # mentos is now waiting for the header, and, potentially, code.
313
+ @in.write(header)
314
+ @log.info "Out header: #{header}"
315
+ @in.write(code) unless code.nil?
316
+ @in.flush
317
+ end
318
+
319
+ # @param timeout [Integer, nil]
320
+ # @return [Integer]
321
+ def get_timeout(timeout)
322
+ return timeout unless timeout.nil?
323
+
324
+ begin
325
+ Integer(ENV['MENTOS_TIMEOUT'])
326
+ rescue TypeError
327
+ 0
328
+ end
329
+ end
330
+
341
331
  # Based on the header we receive, determine if we need
342
332
  # to read more bytes, and read those bytes if necessary.
343
333
  #
344
- # Then, do a sanity check with the ids.
345
- #
346
- # Returns a result - either highlighted text or metadata.
347
- def handle_header_and_return(header, id)
348
- if header
349
- @log.info "In header: #{header}"
350
- header = header_to_json(header)
351
- bytes = header[:bytes]
352
-
353
- # Read more bytes (the actual response body)
354
- res = @out.read(bytes.to_i)
355
-
356
- if header[:method] == 'highlight'
357
- # Make sure we have a result back; else consider this an error.
358
- raise MentosError, 'No highlight result back from mentos.' if res.nil?
359
-
360
- @log.info 'Highlight in process.'
361
-
362
- # Get the id's
363
- start_id = res[0..7]
364
- end_id = res[-8..-1]
365
-
366
- # Sanity check.
367
- if !((start_id == id) && (end_id == id))
368
- raise MentosError, "ID's did not match. Aborting."
369
- else
370
- # We're good. Remove the padding
371
- res = res[10..-11]
372
- @log.info 'Highlighting complete.'
373
- res
374
- end
375
- end
376
- res
377
- else
378
- raise MentosError, 'No header received back.'
334
+ # @param header [String, nil]
335
+ # @return [String, nil] either highlighted text or metadata.
336
+ def handle_header_and_return(header)
337
+ raise MentosError, 'No header received back.' if header.nil?
338
+
339
+ @log.info "In header: #{header}"
340
+ header = header_to_json(header)
341
+ bytes = header[:bytes]
342
+
343
+ # Read more bytes (the actual response body)
344
+ res = @out.read(bytes.to_i)
345
+
346
+ if header[:method] == 'highlight' && res.nil?
347
+ # Make sure we have a result back; else consider this an error.
348
+ raise MentosError, 'No highlight result back from mentos.'
379
349
  end
380
- end
381
350
 
382
- # With the code, prepend the id (with two spaces to avoid escaping weirdness if
383
- # the following text starts with a slash (like terminal code), and append the
384
- # id, with two padding also. This means we are sending over the 8 characters +
385
- # code + 8 characters.
386
- def add_ids(code, id)
387
- (id + " #{code} #{id}").freeze
351
+ res
388
352
  end
389
353
 
390
- # Return the final result for the API. Return Ruby objects for the methods that
391
- # want them, text otherwise.
354
+ # @return Ruby objects for the methods that want them, text otherwise.
392
355
  def return_result(res, method)
393
- unless method == :lexer_name_for || method == :highlight || method == :css
394
- res = JSON.parse(res, symbolize_names: true)
395
- end
396
- res = res.rstrip if res.class == String
356
+ res = JSON.parse(res, symbolize_names: true) unless %i[highlight css].include?(method)
357
+ res = res.rstrip if res.instance_of?(String)
397
358
  res
398
359
  end
399
360
 
400
361
  # Convert a text header into JSON for easy access.
362
+ # @param header [String]
363
+ # @return [JSON]
401
364
  def header_to_json(header)
402
- header = JSON.parse(header, symbolize_names: true)
365
+ json = JSON.parse(header, symbolize_names: true)
366
+ raise MentosError, json[:error] unless json[:error].nil?
403
367
 
404
- if header[:error]
405
- raise MentosError, header[:error]
406
- else
407
- header
408
- end
368
+ json
409
369
  end
410
370
  end
411
371
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pygments
4
- VERSION = '2.0.0.rc3'
4
+ VERSION = '2.3.0'
5
5
  end
data/lib/pygments.rb CHANGED
@@ -1,28 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require File.join(File.dirname(__FILE__), 'pygments/popen')
4
3
  require 'forwardable'
5
4
 
6
- module Pygments
7
- autoload :Lexer, 'pygments/lexer'
5
+ require_relative 'pygments/lexer'
6
+ require_relative 'pygments/popen'
8
7
 
8
+ module Pygments
9
9
  class << self
10
10
  extend Forwardable
11
11
 
12
+ def lexers
13
+ LexerCache.instance.raw_lexers
14
+ end
15
+
12
16
  def engine
13
17
  Thread.current.thread_variable_get(:pygments_engine) ||
14
18
  Thread.current.thread_variable_set(:pygments_engine, Pygments::Popen.new)
15
19
  end
16
20
 
21
+ def lexer_name_for(*args)
22
+ names = engine.lexer_names_for(*args)
23
+ names&.[](0)
24
+ end
25
+
17
26
  def_delegators :engine,
18
27
  :formatters,
19
- :lexers,
20
28
  :lexers!,
21
29
  :filters,
22
30
  :styles,
23
31
  :css,
24
- :lexer_name_for,
32
+ :lexer_names_for,
25
33
  :highlight,
26
- :start
34
+ :start,
35
+ :pygments_version
27
36
  end
28
37
  end
data/pygments.rb.gemspec CHANGED
@@ -1,27 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require File.expand_path('lib/pygments/version', __dir__)
3
+ require_relative 'lib/pygments/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'pygments.rb'
7
7
  s.version = Pygments::VERSION
8
8
 
9
9
  s.summary = 'pygments wrapper for ruby'
10
- s.description = 'pygments.rb exposes the pygments syntax highlighter to Ruby'
11
-
10
+ s.description = 'pygments.rb is a Ruby wrapper for Pygments syntax highlighter'
11
+ s.license = 'MIT'
12
12
  s.homepage = 'https://github.com/pygments/pygments.rb'
13
- s.required_ruby_version = '>= 2.3.0'
14
13
 
15
14
  s.authors = ['Aman Gupta', 'Ted Nyman', 'Marat Radchenko']
16
15
  s.email = ['marat@slonopotamus.org']
17
- s.license = 'MIT'
18
16
 
19
- s.add_development_dependency 'rake-compiler', '~> 1.1.0'
20
- s.add_development_dependency 'rubocop', '~> 0.81.0'
21
- s.add_development_dependency 'test-unit', '~> 3.3.0'
17
+ s.metadata = {
18
+ 'homepage_uri' => s.homepage,
19
+ 'bug_tracker_uri' => "#{s.homepage}/issues",
20
+ 'changelog_uri' => "#{s.homepage}/blob/master/CHANGELOG.adoc",
21
+ 'documentation_uri' => "https://www.rubydoc.info/gems/#{s.name}",
22
+ 'source_code_uri' => s.homepage
23
+ }
24
+
25
+ s.required_ruby_version = '>= 2.3.0'
22
26
 
23
- # s.extensions = ['ext/extconf.rb']
24
- s.require_paths = ['lib']
27
+ s.add_development_dependency 'rake', '~> 13.0.0'
28
+ s.add_development_dependency 'rubocop', '~> 0.81.0'
29
+ s.add_development_dependency 'test-unit', '~> 3.5.0'
25
30
 
26
- s.files = `git ls-files`.split("\n").reject { |f| File.symlink?(f) } + ['lexers']
31
+ s.files = `git ls-files -z`.split("\0").reject { |f| File.symlink?(f) }
27
32
  end
@@ -10,7 +10,9 @@ PE = Pygments.engine
10
10
  class PygmentsHighlightTest < Test::Unit::TestCase
11
11
  RUBY_CODE = "#!/usr/bin/ruby\nputs 'foo'"
12
12
  RUBY_CODE_TRAILING_NEWLINE = "#!/usr/bin/ruby\nputs 'foo'\n"
13
- TEST_CODE = File.read(File.join(File.dirname(__FILE__), '..', 'lib', 'pygments', 'mentos.py'))
13
+ TEST_CODE = File.read(
14
+ File.join(__dir__, '..', 'lib', 'pygments', 'mentos.py')
15
+ )
14
16
 
15
17
  def test_highlight_defaults_to_html
16
18
  code = P.highlight(RUBY_CODE)
@@ -21,13 +23,9 @@ class PygmentsHighlightTest < Test::Unit::TestCase
21
23
  def test_full_html_highlight
22
24
  code = P.highlight(RUBY_CODE)
23
25
  assert_match '<span class="ch">#!/usr/bin/ruby</span>', code
24
- assert_equal "<div class=\"highlight\"><pre><span></span><span class=\"ch\">#!/usr/bin/ruby</span>\n<span class=\"nb\">puts</span> <span class=\"s1\">&#39;foo&#39;</span>\n</pre></div>", code
25
- end
26
-
27
- def test_full_table_highlight
28
- code = P.highlight(RUBY_CODE, options: { linenos: true })
29
- assert_match '<span class="ch">#!/usr/bin/ruby</span>', code
30
- assert_equal "<table class=\"highlighttable\"><tr><td class=\"linenos\"><div class=\"linenodiv\"><pre>1\n2</pre></div></td><td class=\"code\"><div class=\"highlight\"><pre><span></span><span class=\"ch\">#!/usr/bin/ruby</span>\n<span class=\"nb\">puts</span> <span class=\"s1\">&#39;foo&#39;</span>\n</pre></div>\n</td></tr></table>", code
26
+ assert_equal %(<div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/ruby</span>
27
+ <span class="nb">puts</span> <span class="s1">&#39;foo&#39;</span>
28
+ </pre></div>), code
31
29
  end
32
30
 
33
31
  def test_highlight_works_with_larger_files
@@ -94,12 +92,12 @@ class PygmentsHighlightTest < Test::Unit::TestCase
94
92
  end
95
93
 
96
94
  def test_highlight_works_with_multiple_newlines
97
- code = P.highlight(RUBY_CODE_TRAILING_NEWLINE + "derp\n\n")
95
+ code = P.highlight("#{RUBY_CODE_TRAILING_NEWLINE}derp\n\n")
98
96
  assert_match '<span class="ch">#!/usr/bin/ruby</span>', code
99
97
  end
100
98
 
101
99
  def test_highlight_works_with_trailing_cr
102
- code = P.highlight(RUBY_CODE_TRAILING_NEWLINE + "\r")
100
+ code = P.highlight("#{RUBY_CODE_TRAILING_NEWLINE}\r")
103
101
  assert_match '<span class="ch">#!/usr/bin/ruby</span>', code
104
102
  end
105
103
 
@@ -108,6 +106,12 @@ class PygmentsHighlightTest < Test::Unit::TestCase
108
106
  assert_match '>importr</span>', code
109
107
  end
110
108
 
109
+ def test_version
110
+ version_str = P.pygments_version
111
+ # This will throw "Malformed version number string" ArgumentError if version_str is not a valid version string
112
+ Gem::Version.new(version_str)
113
+ end
114
+
111
115
  def test_highlight_on_multi_threads
112
116
  omit 'We do not actually support multithreading'
113
117
 
@@ -119,56 +123,31 @@ class PygmentsHighlightTest < Test::Unit::TestCase
119
123
  end
120
124
  end
121
125
 
122
- # Philosophically, I'm not the biggest fan of testing private
123
- # methods, but given the relative delicacy of validity checking
124
- # over the pipe I think it's necessary and informative.
125
- class PygmentsValidityTest < Test::Unit::TestCase
126
- def test_add_ids_with_padding
127
- res = PE.send(:add_ids, 'herp derp baz boo foo', 'ABCDEFGH')
128
- assert_equal 'ABCDEFGH herp derp baz boo foo ABCDEFGH', res
129
- end
130
-
131
- def test_add_ids_on_empty_string
132
- res = PE.send(:add_ids, '', 'ABCDEFGH')
133
- assert_equal 'ABCDEFGH ABCDEFGH', res
134
- end
135
-
136
- def test_add_ids_with_unicode_data
137
- res = PE.send(:add_ids, '# ø ø ø', 'ABCDEFGH')
138
- assert_equal 'ABCDEFGH # ø ø ø ABCDEFGH', res
139
- end
140
-
141
- def test_add_ids_with_starting_slashes
142
- res = PE.send(:add_ids, '\\# ø ø ø..//', 'ABCDEFGH')
143
- assert_equal 'ABCDEFGH \\# ø ø ø..// ABCDEFGH', res
144
- end
145
- end
146
-
147
126
  class PygmentsLexerTest < Test::Unit::TestCase
148
127
  RUBY_CODE = "#!/usr/bin/ruby\nputs 'foo'"
149
128
 
150
129
  def test_lexer_by_mimetype
151
- assert_equal 'rb', P.lexer_name_for(mimetype: 'text/x-ruby')
130
+ assert_includes P.lexer_names_for(mimetype: 'text/x-ruby'), 'rb'
152
131
  assert_equal 'json', P.lexer_name_for(mimetype: 'application/json')
153
132
  end
154
133
 
155
134
  def test_lexer_by_filename
156
- assert_equal 'rb', P.lexer_name_for(filename: 'test.rb')
135
+ assert_includes P.lexer_names_for(filename: 'test.rb'), 'rb'
157
136
  assert_equal 'scala', P.lexer_name_for(filename: 'test.scala')
158
137
  end
159
138
 
160
139
  def test_lexer_by_name
161
- assert_equal 'rb', P.lexer_name_for(lexer: 'ruby')
140
+ assert_includes P.lexer_names_for(lexer: 'ruby'), 'rb'
162
141
  assert_equal 'python', P.lexer_name_for(lexer: 'python')
163
142
  assert_equal 'c', P.lexer_name_for(lexer: 'c')
164
143
  end
165
144
 
166
145
  def test_lexer_by_filename_and_content
167
- assert_equal 'rb', P.lexer_name_for(RUBY_CODE, filename: 'test.rb')
146
+ assert_includes P.lexer_names_for(RUBY_CODE, filename: 'test.rb'), 'rb'
168
147
  end
169
148
 
170
149
  def test_lexer_by_content
171
- assert_equal 'rb', P.lexer_name_for(RUBY_CODE)
150
+ assert_includes P.lexer_names_for(RUBY_CODE), 'rb'
172
151
  end
173
152
 
174
153
  def test_lexer_by_nothing