pygments.rb 2.0.0.rc3 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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