pygments.rb 1.1.2 → 2.0.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 (383) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +13 -0
  3. data/.github/workflows/ci.yml +28 -0
  4. data/.github/workflows/release.yml +24 -0
  5. data/.gitignore +5 -5
  6. data/CHANGELOG.adoc +128 -0
  7. data/Gemfile +3 -1
  8. data/LICENSE +1 -1
  9. data/README.adoc +160 -0
  10. data/Rakefile +13 -19
  11. data/bench.rb +8 -7
  12. data/cache-lexers.rb +3 -2
  13. data/lexers +0 -0
  14. data/lib/pygments.rb +10 -11
  15. data/lib/pygments/lexer.rb +5 -5
  16. data/lib/pygments/mentos.py +23 -110
  17. data/lib/pygments/popen.rb +148 -229
  18. data/lib/pygments/version.rb +2 -2
  19. data/pygments.rb.gemspec +12 -11
  20. data/test/test_pygments.rb +46 -104
  21. data/vendor/pygments-main/{AUTHORS → Pygments-2.7.3.dist-info/AUTHORS} +23 -3
  22. data/vendor/pygments-main/Pygments-2.7.3.dist-info/INSTALLER +1 -0
  23. data/vendor/pygments-main/{LICENSE → Pygments-2.7.3.dist-info/LICENSE} +1 -1
  24. data/vendor/pygments-main/Pygments-2.7.3.dist-info/METADATA +49 -0
  25. data/vendor/pygments-main/Pygments-2.7.3.dist-info/RECORD +482 -0
  26. data/vendor/pygments-main/Pygments-2.7.3.dist-info/REQUESTED +0 -0
  27. data/vendor/pygments-main/Pygments-2.7.3.dist-info/WHEEL +5 -0
  28. data/vendor/pygments-main/Pygments-2.7.3.dist-info/entry_points.txt +3 -0
  29. data/vendor/pygments-main/Pygments-2.7.3.dist-info/top_level.txt +1 -0
  30. data/vendor/pygments-main/bin/pygmentize +8 -0
  31. data/vendor/pygments-main/pygments/__init__.py +6 -11
  32. data/vendor/pygments-main/pygments/__main__.py +18 -0
  33. data/vendor/pygments-main/pygments/cmdline.py +94 -41
  34. data/vendor/pygments-main/pygments/console.py +6 -9
  35. data/vendor/pygments-main/pygments/filter.py +4 -6
  36. data/vendor/pygments-main/pygments/filters/__init__.py +609 -21
  37. data/vendor/pygments-main/pygments/formatter.py +4 -4
  38. data/vendor/pygments-main/pygments/formatters/__init__.py +42 -6
  39. data/vendor/pygments-main/pygments/formatters/_mapping.py +1 -3
  40. data/vendor/pygments-main/pygments/formatters/bbcode.py +1 -1
  41. data/vendor/pygments-main/pygments/formatters/html.py +223 -135
  42. data/vendor/pygments-main/pygments/formatters/img.py +102 -38
  43. data/vendor/pygments-main/pygments/formatters/irc.py +39 -39
  44. data/vendor/pygments-main/pygments/formatters/latex.py +56 -26
  45. data/vendor/pygments-main/pygments/formatters/other.py +12 -8
  46. data/vendor/pygments-main/pygments/formatters/rtf.py +29 -29
  47. data/vendor/pygments-main/pygments/formatters/svg.py +38 -4
  48. data/vendor/pygments-main/pygments/formatters/terminal.py +25 -31
  49. data/vendor/pygments-main/pygments/formatters/terminal256.py +22 -12
  50. data/vendor/pygments-main/pygments/lexer.py +41 -39
  51. data/vendor/pygments-main/pygments/lexers/__init__.py +62 -15
  52. data/vendor/pygments-main/pygments/lexers/_asy_builtins.py +5 -5
  53. data/vendor/pygments-main/pygments/lexers/_cl_builtins.py +15 -15
  54. data/vendor/pygments-main/pygments/lexers/_cocoa_builtins.py +11 -12
  55. data/vendor/pygments-main/pygments/lexers/_csound_builtins.py +1717 -1338
  56. data/vendor/pygments-main/pygments/lexers/_lasso_builtins.py +8 -1
  57. data/vendor/pygments-main/pygments/lexers/_lua_builtins.py +2 -4
  58. data/vendor/pygments-main/pygments/lexers/_mapping.py +79 -33
  59. data/vendor/pygments-main/pygments/lexers/_mql_builtins.py +2 -2
  60. data/vendor/pygments-main/pygments/lexers/_mysql_builtins.py +1282 -0
  61. data/vendor/pygments-main/pygments/lexers/_openedge_builtins.py +1 -1
  62. data/vendor/pygments-main/pygments/lexers/_php_builtins.py +17 -20
  63. data/vendor/pygments-main/pygments/lexers/_postgres_builtins.py +73 -16
  64. data/vendor/pygments-main/pygments/lexers/_scilab_builtins.py +2 -2
  65. data/vendor/pygments-main/pygments/lexers/_sourcemod_builtins.py +1 -3
  66. data/vendor/pygments-main/pygments/lexers/_stan_builtins.py +151 -125
  67. data/vendor/pygments-main/pygments/lexers/_stata_builtins.py +6 -4
  68. data/vendor/pygments-main/pygments/lexers/_tsql_builtins.py +1 -1
  69. data/vendor/pygments-main/pygments/lexers/_usd_builtins.py +113 -0
  70. data/vendor/pygments-main/pygments/lexers/_vbscript_builtins.py +280 -0
  71. data/vendor/pygments-main/pygments/lexers/_vim_builtins.py +1 -1
  72. data/vendor/pygments-main/pygments/lexers/actionscript.py +8 -3
  73. data/vendor/pygments-main/pygments/lexers/agile.py +1 -1
  74. data/vendor/pygments-main/pygments/lexers/algebra.py +20 -1
  75. data/vendor/pygments-main/pygments/lexers/ambient.py +1 -1
  76. data/vendor/pygments-main/pygments/lexers/ampl.py +3 -3
  77. data/vendor/pygments-main/pygments/lexers/apl.py +15 -15
  78. data/vendor/pygments-main/pygments/lexers/archetype.py +3 -3
  79. data/vendor/pygments-main/pygments/lexers/arrow.py +117 -0
  80. data/vendor/pygments-main/pygments/lexers/asm.py +445 -70
  81. data/vendor/pygments-main/pygments/lexers/automation.py +3 -3
  82. data/vendor/pygments-main/pygments/lexers/bare.py +104 -0
  83. data/vendor/pygments-main/pygments/lexers/basic.py +166 -4
  84. data/vendor/pygments-main/pygments/lexers/bibtex.py +13 -9
  85. data/vendor/pygments-main/pygments/lexers/boa.py +102 -0
  86. data/vendor/pygments-main/pygments/lexers/business.py +69 -36
  87. data/vendor/pygments-main/pygments/lexers/c_cpp.py +137 -45
  88. data/vendor/pygments-main/pygments/lexers/c_like.py +68 -43
  89. data/vendor/pygments-main/pygments/lexers/capnproto.py +20 -21
  90. data/vendor/pygments-main/pygments/lexers/chapel.py +25 -14
  91. data/vendor/pygments-main/pygments/lexers/clean.py +135 -244
  92. data/vendor/pygments-main/pygments/lexers/compiled.py +1 -1
  93. data/vendor/pygments-main/pygments/lexers/configs.py +188 -37
  94. data/vendor/pygments-main/pygments/lexers/console.py +1 -1
  95. data/vendor/pygments-main/pygments/lexers/crystal.py +31 -23
  96. data/vendor/pygments-main/pygments/lexers/csound.py +288 -187
  97. data/vendor/pygments-main/pygments/lexers/css.py +18 -16
  98. data/vendor/pygments-main/pygments/lexers/d.py +10 -5
  99. data/vendor/pygments-main/pygments/lexers/dalvik.py +1 -1
  100. data/vendor/pygments-main/pygments/lexers/data.py +240 -97
  101. data/vendor/pygments-main/pygments/lexers/devicetree.py +109 -0
  102. data/vendor/pygments-main/pygments/lexers/diff.py +4 -4
  103. data/vendor/pygments-main/pygments/lexers/dotnet.py +40 -24
  104. data/vendor/pygments-main/pygments/lexers/dsls.py +147 -65
  105. data/vendor/pygments-main/pygments/lexers/dylan.py +16 -18
  106. data/vendor/pygments-main/pygments/lexers/ecl.py +16 -2
  107. data/vendor/pygments-main/pygments/lexers/eiffel.py +1 -1
  108. data/vendor/pygments-main/pygments/lexers/elm.py +5 -5
  109. data/vendor/pygments-main/pygments/lexers/email.py +151 -0
  110. data/vendor/pygments-main/pygments/lexers/erlang.py +29 -32
  111. data/vendor/pygments-main/pygments/lexers/esoteric.py +54 -25
  112. data/vendor/pygments-main/pygments/lexers/ezhil.py +24 -15
  113. data/vendor/pygments-main/pygments/lexers/factor.py +1 -1
  114. data/vendor/pygments-main/pygments/lexers/fantom.py +1 -1
  115. data/vendor/pygments-main/pygments/lexers/felix.py +1 -1
  116. data/vendor/pygments-main/pygments/lexers/floscript.py +83 -0
  117. data/vendor/pygments-main/pygments/lexers/forth.py +41 -40
  118. data/vendor/pygments-main/pygments/lexers/fortran.py +5 -4
  119. data/vendor/pygments-main/pygments/lexers/foxpro.py +2 -2
  120. data/vendor/pygments-main/pygments/lexers/freefem.py +898 -0
  121. data/vendor/pygments-main/pygments/lexers/functional.py +1 -1
  122. data/vendor/pygments-main/pygments/lexers/gdscript.py +346 -0
  123. data/vendor/pygments-main/pygments/lexers/go.py +1 -1
  124. data/vendor/pygments-main/pygments/lexers/grammar_notation.py +63 -6
  125. data/vendor/pygments-main/pygments/lexers/graph.py +14 -9
  126. data/vendor/pygments-main/pygments/lexers/graphics.py +272 -25
  127. data/vendor/pygments-main/pygments/lexers/haskell.py +52 -22
  128. data/vendor/pygments-main/pygments/lexers/haxe.py +6 -6
  129. data/vendor/pygments-main/pygments/lexers/hdl.py +176 -86
  130. data/vendor/pygments-main/pygments/lexers/hexdump.py +18 -12
  131. data/vendor/pygments-main/pygments/lexers/html.py +31 -19
  132. data/vendor/pygments-main/pygments/lexers/idl.py +20 -9
  133. data/vendor/pygments-main/pygments/lexers/igor.py +244 -112
  134. data/vendor/pygments-main/pygments/lexers/inferno.py +2 -2
  135. data/vendor/pygments-main/pygments/lexers/installers.py +1 -1
  136. data/vendor/pygments-main/pygments/lexers/int_fiction.py +40 -15
  137. data/vendor/pygments-main/pygments/lexers/iolang.py +2 -2
  138. data/vendor/pygments-main/pygments/lexers/j.py +3 -3
  139. data/vendor/pygments-main/pygments/lexers/javascript.py +100 -66
  140. data/vendor/pygments-main/pygments/lexers/julia.py +46 -48
  141. data/vendor/pygments-main/pygments/lexers/jvm.py +265 -165
  142. data/vendor/pygments-main/pygments/lexers/lisp.py +882 -804
  143. data/vendor/pygments-main/pygments/lexers/make.py +10 -6
  144. data/vendor/pygments-main/pygments/lexers/markup.py +213 -43
  145. data/vendor/pygments-main/pygments/lexers/math.py +1 -1
  146. data/vendor/pygments-main/pygments/lexers/matlab.py +98 -41
  147. data/vendor/pygments-main/pygments/lexers/mime.py +226 -0
  148. data/vendor/pygments-main/pygments/lexers/ml.py +198 -9
  149. data/vendor/pygments-main/pygments/lexers/modeling.py +26 -18
  150. data/vendor/pygments-main/pygments/lexers/modula2.py +25 -6
  151. data/vendor/pygments-main/pygments/lexers/monte.py +4 -3
  152. data/vendor/pygments-main/pygments/lexers/mosel.py +448 -0
  153. data/vendor/pygments-main/pygments/lexers/ncl.py +85 -244
  154. data/vendor/pygments-main/pygments/lexers/nimrod.py +4 -4
  155. data/vendor/pygments-main/pygments/lexers/nit.py +1 -1
  156. data/vendor/pygments-main/pygments/lexers/nix.py +1 -1
  157. data/vendor/pygments-main/pygments/lexers/oberon.py +17 -1
  158. data/vendor/pygments-main/pygments/lexers/objective.py +16 -16
  159. data/vendor/pygments-main/pygments/lexers/ooc.py +1 -1
  160. data/vendor/pygments-main/pygments/lexers/other.py +1 -1
  161. data/vendor/pygments-main/pygments/lexers/parasail.py +1 -1
  162. data/vendor/pygments-main/pygments/lexers/parsers.py +23 -58
  163. data/vendor/pygments-main/pygments/lexers/pascal.py +23 -23
  164. data/vendor/pygments-main/pygments/lexers/pawn.py +30 -24
  165. data/vendor/pygments-main/pygments/lexers/perl.py +276 -160
  166. data/vendor/pygments-main/pygments/lexers/php.py +64 -10
  167. data/vendor/pygments-main/pygments/lexers/pointless.py +71 -0
  168. data/vendor/pygments-main/pygments/lexers/pony.py +94 -0
  169. data/vendor/pygments-main/pygments/lexers/praat.py +38 -30
  170. data/vendor/pygments-main/pygments/lexers/prolog.py +36 -36
  171. data/vendor/pygments-main/pygments/lexers/promql.py +183 -0
  172. data/vendor/pygments-main/pygments/lexers/python.py +439 -226
  173. data/vendor/pygments-main/pygments/lexers/qvt.py +6 -6
  174. data/vendor/pygments-main/pygments/lexers/r.py +13 -275
  175. data/vendor/pygments-main/pygments/lexers/rdf.py +232 -39
  176. data/vendor/pygments-main/pygments/lexers/rebol.py +8 -8
  177. data/vendor/pygments-main/pygments/lexers/resource.py +2 -2
  178. data/vendor/pygments-main/pygments/lexers/ride.py +139 -0
  179. data/vendor/pygments-main/pygments/lexers/rnc.py +1 -1
  180. data/vendor/pygments-main/pygments/lexers/roboconf.py +1 -1
  181. data/vendor/pygments-main/pygments/lexers/robotframework.py +23 -31
  182. data/vendor/pygments-main/pygments/lexers/ruby.py +22 -24
  183. data/vendor/pygments-main/pygments/lexers/rust.py +86 -71
  184. data/vendor/pygments-main/pygments/lexers/sas.py +7 -7
  185. data/vendor/pygments-main/pygments/lexers/scdoc.py +83 -0
  186. data/vendor/pygments-main/pygments/lexers/scripting.py +75 -13
  187. data/vendor/pygments-main/pygments/lexers/sgf.py +61 -0
  188. data/vendor/pygments-main/pygments/lexers/shell.py +175 -51
  189. data/vendor/pygments-main/pygments/lexers/sieve.py +69 -0
  190. data/vendor/pygments-main/pygments/lexers/slash.py +185 -0
  191. data/vendor/pygments-main/pygments/lexers/smalltalk.py +2 -2
  192. data/vendor/pygments-main/pygments/lexers/smv.py +30 -26
  193. data/vendor/pygments-main/pygments/lexers/snobol.py +1 -1
  194. data/vendor/pygments-main/pygments/lexers/solidity.py +92 -0
  195. data/vendor/pygments-main/pygments/lexers/special.py +5 -3
  196. data/vendor/pygments-main/pygments/lexers/sql.py +333 -177
  197. data/vendor/pygments-main/pygments/lexers/stata.py +107 -42
  198. data/vendor/pygments-main/pygments/lexers/supercollider.py +6 -1
  199. data/vendor/pygments-main/pygments/lexers/tcl.py +1 -1
  200. data/vendor/pygments-main/pygments/lexers/templates.py +144 -132
  201. data/vendor/pygments-main/pygments/lexers/teraterm.py +335 -0
  202. data/vendor/pygments-main/pygments/lexers/testing.py +6 -6
  203. data/vendor/pygments-main/pygments/lexers/text.py +2 -1
  204. data/vendor/pygments-main/pygments/lexers/textedit.py +4 -4
  205. data/vendor/pygments-main/pygments/lexers/textfmts.py +146 -13
  206. data/vendor/pygments-main/pygments/lexers/theorem.py +69 -53
  207. data/vendor/pygments-main/pygments/lexers/tnt.py +263 -0
  208. data/vendor/pygments-main/pygments/lexers/trafficscript.py +1 -1
  209. data/vendor/pygments-main/pygments/lexers/typoscript.py +8 -14
  210. data/vendor/pygments-main/pygments/lexers/unicon.py +412 -0
  211. data/vendor/pygments-main/pygments/lexers/urbi.py +14 -1
  212. data/vendor/pygments-main/pygments/lexers/usd.py +90 -0
  213. data/vendor/pygments-main/pygments/lexers/varnish.py +5 -5
  214. data/vendor/pygments-main/pygments/lexers/verification.py +15 -12
  215. data/vendor/pygments-main/pygments/lexers/web.py +1 -1
  216. data/vendor/pygments-main/pygments/lexers/webidl.py +299 -0
  217. data/vendor/pygments-main/pygments/lexers/webmisc.py +50 -38
  218. data/vendor/pygments-main/pygments/lexers/whiley.py +11 -12
  219. data/vendor/pygments-main/pygments/lexers/x10.py +1 -1
  220. data/vendor/pygments-main/pygments/lexers/xorg.py +37 -0
  221. data/vendor/pygments-main/pygments/lexers/yang.py +104 -0
  222. data/vendor/pygments-main/pygments/lexers/zig.py +124 -0
  223. data/vendor/pygments-main/pygments/modeline.py +6 -5
  224. data/vendor/pygments-main/pygments/plugin.py +14 -18
  225. data/vendor/pygments-main/pygments/regexopt.py +1 -1
  226. data/vendor/pygments-main/pygments/scanner.py +2 -2
  227. data/vendor/pygments-main/pygments/sphinxext.py +2 -4
  228. data/vendor/pygments-main/pygments/style.py +61 -24
  229. data/vendor/pygments-main/pygments/styles/__init__.py +13 -5
  230. data/vendor/pygments-main/pygments/styles/abap.py +29 -0
  231. data/vendor/pygments-main/pygments/styles/algol.py +1 -1
  232. data/vendor/pygments-main/pygments/styles/algol_nu.py +1 -1
  233. data/vendor/pygments-main/pygments/styles/arduino.py +2 -2
  234. data/vendor/pygments-main/pygments/styles/autumn.py +1 -1
  235. data/vendor/pygments-main/pygments/styles/borland.py +1 -1
  236. data/vendor/pygments-main/pygments/styles/bw.py +1 -1
  237. data/vendor/pygments-main/pygments/styles/colorful.py +1 -1
  238. data/vendor/pygments-main/pygments/styles/default.py +1 -1
  239. data/vendor/pygments-main/pygments/styles/emacs.py +1 -1
  240. data/vendor/pygments-main/pygments/styles/friendly.py +1 -1
  241. data/vendor/pygments-main/pygments/styles/fruity.py +1 -1
  242. data/vendor/pygments-main/pygments/styles/igor.py +1 -1
  243. data/vendor/pygments-main/pygments/styles/inkpot.py +67 -0
  244. data/vendor/pygments-main/pygments/styles/lovelace.py +1 -1
  245. data/vendor/pygments-main/pygments/styles/manni.py +1 -1
  246. data/vendor/pygments-main/pygments/styles/monokai.py +4 -3
  247. data/vendor/pygments-main/pygments/styles/murphy.py +1 -1
  248. data/vendor/pygments-main/pygments/styles/native.py +1 -1
  249. data/vendor/pygments-main/pygments/styles/paraiso_dark.py +1 -1
  250. data/vendor/pygments-main/pygments/styles/paraiso_light.py +1 -1
  251. data/vendor/pygments-main/pygments/styles/pastie.py +1 -1
  252. data/vendor/pygments-main/pygments/styles/perldoc.py +1 -1
  253. data/vendor/pygments-main/pygments/styles/rainbow_dash.py +89 -0
  254. data/vendor/pygments-main/pygments/styles/rrt.py +1 -1
  255. data/vendor/pygments-main/pygments/styles/sas.py +3 -0
  256. data/vendor/pygments-main/pygments/styles/solarized.py +134 -0
  257. data/vendor/pygments-main/pygments/styles/stata_dark.py +41 -0
  258. data/vendor/pygments-main/pygments/styles/stata_light.py +39 -0
  259. data/vendor/pygments-main/pygments/styles/tango.py +1 -1
  260. data/vendor/pygments-main/pygments/styles/trac.py +1 -1
  261. data/vendor/pygments-main/pygments/styles/vim.py +1 -1
  262. data/vendor/pygments-main/pygments/styles/vs.py +1 -1
  263. data/vendor/pygments-main/pygments/styles/xcode.py +1 -1
  264. data/vendor/pygments-main/pygments/token.py +1 -1
  265. data/vendor/pygments-main/pygments/unistring.py +47 -108
  266. data/vendor/pygments-main/pygments/util.py +19 -95
  267. metadata +71 -137
  268. data/CHANGELOG.md +0 -98
  269. data/README.md +0 -121
  270. data/circle.yml +0 -20
  271. data/test/test_data.c +0 -2581
  272. data/test/test_data.py +0 -514
  273. data/test/test_data_generated +0 -2582
  274. data/vendor/custom_lexers/github.py +0 -565
  275. data/vendor/pygments-main/CHANGES +0 -1163
  276. data/vendor/pygments-main/MANIFEST.in +0 -6
  277. data/vendor/pygments-main/Makefile +0 -65
  278. data/vendor/pygments-main/README.rst +0 -39
  279. data/vendor/pygments-main/REVISION +0 -1
  280. data/vendor/pygments-main/TODO +0 -12
  281. data/vendor/pygments-main/doc/Makefile +0 -153
  282. data/vendor/pygments-main/doc/_static/favicon.ico +0 -0
  283. data/vendor/pygments-main/doc/_static/logo_new.png +0 -0
  284. data/vendor/pygments-main/doc/_static/logo_only.png +0 -0
  285. data/vendor/pygments-main/doc/_templates/docssidebar.html +0 -3
  286. data/vendor/pygments-main/doc/_templates/indexsidebar.html +0 -25
  287. data/vendor/pygments-main/doc/_themes/pygments14/layout.html +0 -98
  288. data/vendor/pygments-main/doc/_themes/pygments14/static/bodybg.png +0 -0
  289. data/vendor/pygments-main/doc/_themes/pygments14/static/docbg.png +0 -0
  290. data/vendor/pygments-main/doc/_themes/pygments14/static/listitem.png +0 -0
  291. data/vendor/pygments-main/doc/_themes/pygments14/static/logo.png +0 -0
  292. data/vendor/pygments-main/doc/_themes/pygments14/static/pocoo.png +0 -0
  293. data/vendor/pygments-main/doc/_themes/pygments14/static/pygments14.css_t +0 -401
  294. data/vendor/pygments-main/doc/_themes/pygments14/theme.conf +0 -15
  295. data/vendor/pygments-main/doc/conf.py +0 -241
  296. data/vendor/pygments-main/doc/docs/api.rst +0 -331
  297. data/vendor/pygments-main/doc/docs/authors.rst +0 -4
  298. data/vendor/pygments-main/doc/docs/changelog.rst +0 -1
  299. data/vendor/pygments-main/doc/docs/cmdline.rst +0 -149
  300. data/vendor/pygments-main/doc/docs/filterdevelopment.rst +0 -71
  301. data/vendor/pygments-main/doc/docs/filters.rst +0 -41
  302. data/vendor/pygments-main/doc/docs/formatterdevelopment.rst +0 -169
  303. data/vendor/pygments-main/doc/docs/formatters.rst +0 -48
  304. data/vendor/pygments-main/doc/docs/index.rst +0 -66
  305. data/vendor/pygments-main/doc/docs/integrate.rst +0 -40
  306. data/vendor/pygments-main/doc/docs/java.rst +0 -70
  307. data/vendor/pygments-main/doc/docs/lexerdevelopment.rst +0 -689
  308. data/vendor/pygments-main/doc/docs/lexers.rst +0 -69
  309. data/vendor/pygments-main/doc/docs/moinmoin.rst +0 -39
  310. data/vendor/pygments-main/doc/docs/plugins.rst +0 -93
  311. data/vendor/pygments-main/doc/docs/quickstart.rst +0 -205
  312. data/vendor/pygments-main/doc/docs/rstdirective.rst +0 -22
  313. data/vendor/pygments-main/doc/docs/styles.rst +0 -201
  314. data/vendor/pygments-main/doc/docs/tokens.rst +0 -372
  315. data/vendor/pygments-main/doc/docs/unicode.rst +0 -58
  316. data/vendor/pygments-main/doc/download.rst +0 -41
  317. data/vendor/pygments-main/doc/faq.rst +0 -139
  318. data/vendor/pygments-main/doc/index.rst +0 -54
  319. data/vendor/pygments-main/doc/languages.rst +0 -154
  320. data/vendor/pygments-main/doc/make.bat +0 -190
  321. data/vendor/pygments-main/doc/pygmentize.1 +0 -94
  322. data/vendor/pygments-main/external/autopygmentize +0 -84
  323. data/vendor/pygments-main/external/lasso-builtins-generator-9.lasso +0 -162
  324. data/vendor/pygments-main/external/markdown-processor.py +0 -67
  325. data/vendor/pygments-main/external/moin-parser.py +0 -112
  326. data/vendor/pygments-main/external/pygments.bashcomp +0 -38
  327. data/vendor/pygments-main/external/rst-directive.py +0 -82
  328. data/vendor/pygments-main/pygmentize +0 -8
  329. data/vendor/pygments-main/pygments/lexers/github.py +0 -565
  330. data/vendor/pygments-main/pygments/styles/stata.py +0 -37
  331. data/vendor/pygments-main/requirements.txt +0 -5
  332. data/vendor/pygments-main/scripts/check_sources.py +0 -211
  333. data/vendor/pygments-main/scripts/debug_lexer.py +0 -246
  334. data/vendor/pygments-main/scripts/detect_missing_analyse_text.py +0 -33
  335. data/vendor/pygments-main/scripts/epydoc.css +0 -280
  336. data/vendor/pygments-main/scripts/find_error.py +0 -1
  337. data/vendor/pygments-main/scripts/get_vimkw.py +0 -74
  338. data/vendor/pygments-main/scripts/pylintrc +0 -301
  339. data/vendor/pygments-main/scripts/vim2pygments.py +0 -935
  340. data/vendor/pygments-main/setup.cfg +0 -10
  341. data/vendor/pygments-main/setup.py +0 -77
  342. data/vendor/pygments-main/tox.ini +0 -7
  343. data/vendor/simplejson/.gitignore +0 -10
  344. data/vendor/simplejson/.travis.yml +0 -5
  345. data/vendor/simplejson/CHANGES.txt +0 -291
  346. data/vendor/simplejson/LICENSE.txt +0 -19
  347. data/vendor/simplejson/MANIFEST.in +0 -5
  348. data/vendor/simplejson/README.rst +0 -19
  349. data/vendor/simplejson/conf.py +0 -179
  350. data/vendor/simplejson/index.rst +0 -628
  351. data/vendor/simplejson/scripts/make_docs.py +0 -18
  352. data/vendor/simplejson/setup.py +0 -104
  353. data/vendor/simplejson/simplejson/__init__.py +0 -510
  354. data/vendor/simplejson/simplejson/_speedups.c +0 -2745
  355. data/vendor/simplejson/simplejson/decoder.py +0 -425
  356. data/vendor/simplejson/simplejson/encoder.py +0 -567
  357. data/vendor/simplejson/simplejson/ordered_dict.py +0 -119
  358. data/vendor/simplejson/simplejson/scanner.py +0 -77
  359. data/vendor/simplejson/simplejson/tests/__init__.py +0 -67
  360. data/vendor/simplejson/simplejson/tests/test_bigint_as_string.py +0 -55
  361. data/vendor/simplejson/simplejson/tests/test_check_circular.py +0 -30
  362. data/vendor/simplejson/simplejson/tests/test_decimal.py +0 -66
  363. data/vendor/simplejson/simplejson/tests/test_decode.py +0 -83
  364. data/vendor/simplejson/simplejson/tests/test_default.py +0 -9
  365. data/vendor/simplejson/simplejson/tests/test_dump.py +0 -67
  366. data/vendor/simplejson/simplejson/tests/test_encode_basestring_ascii.py +0 -46
  367. data/vendor/simplejson/simplejson/tests/test_encode_for_html.py +0 -32
  368. data/vendor/simplejson/simplejson/tests/test_errors.py +0 -34
  369. data/vendor/simplejson/simplejson/tests/test_fail.py +0 -91
  370. data/vendor/simplejson/simplejson/tests/test_float.py +0 -19
  371. data/vendor/simplejson/simplejson/tests/test_indent.py +0 -86
  372. data/vendor/simplejson/simplejson/tests/test_item_sort_key.py +0 -20
  373. data/vendor/simplejson/simplejson/tests/test_namedtuple.py +0 -121
  374. data/vendor/simplejson/simplejson/tests/test_pass1.py +0 -76
  375. data/vendor/simplejson/simplejson/tests/test_pass2.py +0 -14
  376. data/vendor/simplejson/simplejson/tests/test_pass3.py +0 -20
  377. data/vendor/simplejson/simplejson/tests/test_recursion.py +0 -67
  378. data/vendor/simplejson/simplejson/tests/test_scanstring.py +0 -117
  379. data/vendor/simplejson/simplejson/tests/test_separators.py +0 -42
  380. data/vendor/simplejson/simplejson/tests/test_speedups.py +0 -20
  381. data/vendor/simplejson/simplejson/tests/test_tuple.py +0 -49
  382. data/vendor/simplejson/simplejson/tests/test_unicode.py +0 -109
  383. data/vendor/simplejson/simplejson/tool.py +0 -39
data/bench.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.join(File.dirname(__FILE__), '/lib/pygments.rb')
2
4
  require 'benchmark'
3
5
 
@@ -8,15 +10,14 @@ num = ARGV[0] ? ARGV[0].to_i : 10
8
10
  # we can also repeat the code itself
9
11
  repeats = ARGV[1] ? ARGV[1].to_i : 1
10
12
 
11
- code = File.open('test/test_data.py').read.to_s * repeats
13
+ code = File.open('test/test_pygments.rb').read.to_s * repeats
12
14
 
13
15
  puts "Benchmarking....\n"
14
- puts "Size: " + code.bytesize.to_s + " bytes\n"
15
- puts "Iterations: " + num.to_s + "\n"
16
+ puts 'Size: ' + code.bytesize.to_s + " bytes\n"
17
+ puts 'Iterations: ' + num.to_s + "\n"
16
18
 
17
19
  Benchmark.bm(40) do |x|
18
- x.report("pygments popen ") { for i in 1..num; Pygments.highlight(code, :lexer => 'python'); end }
19
- x.report("pygments popen (process already started) ") { for i in 1..num; Pygments.highlight(code, :lexer => 'python'); end }
20
- x.report("pygments popen (process already started 2) ") { for i in 1..num; Pygments.highlight(code, :lexer => 'python'); end }
20
+ x.report('pygments popen ') { (1..num).each { |_i|; Pygments.highlight(code, lexer: 'python'); } }
21
+ x.report('pygments popen (process already started) ') { (1..num).each { |_i|; Pygments.highlight(code, lexer: 'python'); } }
22
+ x.report('pygments popen (process already started 2) ') { (1..num).each { |_i|; Pygments.highlight(code, lexer: 'python'); } }
21
23
  end
22
-
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.join(File.dirname(__FILE__), '/lib/pygments.rb')
2
4
 
3
5
  # Simple marshalling
4
6
  serialized_lexers = Marshal.dump(Pygments.lexers!)
5
7
 
6
8
  # Write to a file
7
- File.open("lexers", 'wb') { |file| file.write(serialized_lexers) }
8
-
9
+ File.open('lexers', 'wb') { |file| file.write(serialized_lexers) }
data/lexers CHANGED
Binary file
@@ -1,10 +1,9 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
2
+
3
3
  require File.join(File.dirname(__FILE__), 'pygments/popen')
4
4
  require 'forwardable'
5
5
 
6
6
  module Pygments
7
-
8
7
  autoload :Lexer, 'pygments/lexer'
9
8
 
10
9
  class << self
@@ -16,14 +15,14 @@ module Pygments
16
15
  end
17
16
 
18
17
  def_delegators :engine,
19
- :formatters,
20
- :lexers,
21
- :lexers!,
22
- :filters,
23
- :styles,
24
- :css,
25
- :lexer_name_for,
26
- :highlight,
27
- :start
18
+ :formatters,
19
+ :lexers,
20
+ :lexers!,
21
+ :filters,
22
+ :styles,
23
+ :css,
24
+ :lexer_name_for,
25
+ :highlight,
26
+ :start
28
27
  end
29
28
  end
@@ -1,5 +1,5 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
2
+
3
3
  module Pygments
4
4
  class Lexer < Struct.new(:name, :aliases, :filenames, :mimetypes)
5
5
  @lexers = []
@@ -34,13 +34,13 @@ module Pygments
34
34
  m[1].scan(/./).each do |s|
35
35
  extnames << extname.sub(m[0], s)
36
36
  end
37
- elsif extname != ""
37
+ elsif extname != ''
38
38
  extnames << extname
39
39
  end
40
40
 
41
41
  extnames.each do |the_extname|
42
42
  @extname_index[the_extname] = lexer
43
- @index[the_extname.downcase.sub(/^\./, "")] ||= lexer
43
+ @index[the_extname.downcase.sub(/^\./, '')] ||= lexer
44
44
  end
45
45
  end
46
46
 
@@ -142,8 +142,8 @@ module Pygments
142
142
  Pygments.highlight(text, options)
143
143
  end
144
144
 
145
- alias_method :==, :equal?
146
- alias_method :eql?, :equal?
145
+ alias == equal?
146
+ alias eql? equal?
147
147
  end
148
148
 
149
149
  lexers.values.each { |h| Lexer.create(h) }
@@ -1,6 +1,7 @@
1
- #!/usr/bin/env python
1
+ #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
+ import struct
4
5
  import sys, re, os, signal
5
6
  import traceback
6
7
  if 'PYGMENTS_PATH' in os.environ:
@@ -9,15 +10,11 @@ if 'PYGMENTS_PATH' in os.environ:
9
10
  dirname = os.path.dirname
10
11
 
11
12
  base_dir = dirname(dirname(dirname(os.path.abspath(__file__))))
12
- sys.path.append(base_dir + "/vendor")
13
13
  sys.path.append(base_dir + "/vendor/pygments-main")
14
- sys.path.append(base_dir + "/vendor/simplejson")
15
14
 
16
15
  import pygments
17
16
  from pygments import lexers, formatters, styles, filters
18
17
 
19
- from threading import Lock
20
-
21
18
  try:
22
19
  import json
23
20
  except ImportError:
@@ -27,22 +24,16 @@ def _convert_keys(dictionary):
27
24
  if not isinstance(dictionary, dict):
28
25
  return dictionary
29
26
  return dict((str(k), _convert_keys(v))
30
- for k, v in dictionary.items())
27
+ for k, v in list(dictionary.items()))
31
28
 
32
29
  def _write_error(error):
33
30
  res = {"error": error}
34
- out_header = json.dumps(res).encode('utf-8')
35
- bits = _get_fixed_bits_from_header(out_header)
36
- sys.stdout.write(bits + "\n")
37
- sys.stdout.flush()
38
- sys.stdout.write(out_header + "\n")
31
+ out_header_bytes = json.dumps(res).encode('utf-8')
32
+ sys.stdout.buffer.write(struct.pack('!i', len(out_header_bytes)))
33
+ sys.stdout.buffer.write(out_header_bytes)
39
34
  sys.stdout.flush()
40
35
  return
41
36
 
42
- def _get_fixed_bits_from_header(out_header):
43
- size = len(out_header)
44
- return "".join(map(lambda y:str((size>>y)&1), range(32-1, -1, -1)))
45
-
46
37
  def _signal_handler(signal, frame):
47
38
  """
48
39
  Handle the signal given in the first argument, exiting gracefully
@@ -163,12 +154,9 @@ class Mentos(object):
163
154
  res = json.dumps(res)
164
155
 
165
156
  elif method == 'highlight':
166
- try:
167
- text = text.decode('utf-8')
168
- except UnicodeDecodeError:
169
- # The text may already be encoded
170
- text = text
171
157
  res = self.highlight_text(text, lexer, formatter_name, args, _convert_keys(opts))
158
+ if type(res) is bytes:
159
+ res = res.decode('utf-8')
172
160
 
173
161
  elif method == 'css':
174
162
  kwargs = _convert_keys(kwargs)
@@ -193,52 +181,21 @@ class Mentos(object):
193
181
 
194
182
 
195
183
  def _send_data(self, res, method):
196
-
197
184
  # Base header. We'll build on this, adding keys as necessary.
198
185
  base_header = {"method": method}
199
186
 
200
- res_bytes = len(res) + 1
201
- base_header["bytes"] = res_bytes
187
+ res_bytes = res.encode("utf-8")
188
+ bytes = len(res_bytes)
189
+ base_header["bytes"] = bytes
202
190
 
203
- out_header = json.dumps(base_header).encode('utf-8')
204
-
205
- # Following the protocol, send over a fixed size represenation of the
206
- # size of the JSON header
207
- bits = _get_fixed_bits_from_header(out_header)
191
+ out_header_bytes = json.dumps(base_header).encode('utf-8')
208
192
 
209
193
  # Send it to Rubyland
210
- sys.stdout.write(bits + "\n")
211
- sys.stdout.flush()
212
-
213
- # Send the header.
214
- sys.stdout.write(out_header + "\n")
194
+ sys.stdout.buffer.write(struct.pack('!i', len(out_header_bytes)))
195
+ sys.stdout.buffer.write(out_header_bytes)
196
+ sys.stdout.buffer.write(res_bytes)
215
197
  sys.stdout.flush()
216
198
 
217
- # Finally, send the result
218
- sys.stdout.write(res + "\n")
219
- sys.stdout.flush()
220
-
221
-
222
- def _get_ids(self, text):
223
- start_id = text[:8]
224
- end_id = text[-8:]
225
- return start_id, end_id
226
-
227
- def _check_and_return_text(self, text, start_id, end_id):
228
-
229
- # Sanity check.
230
- id_regex = re.compile('[A-Z]{8}')
231
-
232
- if not id_regex.match(start_id) and not id_regex.match(end_id):
233
- _write_error("ID check failed. Not an ID.")
234
-
235
- if not start_id == end_id:
236
- _write_error("ID check failed. ID's did not match.")
237
-
238
- # Passed the sanity check. Remove the id's and return
239
- text = text[10:-10]
240
- return text
241
-
242
199
  def _parse_header(self, header):
243
200
  method = header["method"]
244
201
  args = header.get("args", [])
@@ -256,29 +213,18 @@ class Mentos(object):
256
213
  pygmentized, this header will be followed by the text to be pygmentized.
257
214
 
258
215
  The header is of form:
259
- { "method": "highlight", "args": [], "kwargs": {"arg1": "v"}, "bytes": 128, "fd": "8"}
216
+ { "method": "highlight", "args": [], "kwargs": {"arg1": "v"}, "bytes": 128}
260
217
  """
261
- lock = Lock()
262
218
 
263
219
  while True:
264
- # The loop begins by reading off a simple 32-arity string
265
- # representing an integer of 32 bits. This is the length of
266
- # our JSON header.
267
- size = sys.stdin.read(32)
220
+ header_size_bytes = sys.stdin.buffer.read(4)
221
+ if not header_size_bytes:
222
+ break
268
223
 
269
- lock.acquire()
224
+ header_size = struct.unpack('!i', header_size_bytes)[0]
270
225
 
271
226
  try:
272
- # Read from stdin the amount of bytes we were told to expect.
273
- header_bytes = int(size, 2)
274
-
275
- # Sanity check the size
276
- size_regex = re.compile('[0-1]{32}')
277
- if not size_regex.match(size):
278
- _write_error("Size received is not valid.")
279
-
280
- line = sys.stdin.read(header_bytes)
281
-
227
+ line = sys.stdin.buffer.read(header_size).decode('utf-8')
282
228
  header = json.loads(line)
283
229
 
284
230
  method, args, kwargs, lexer = self._parse_header(header)
@@ -291,30 +237,18 @@ class Mentos(object):
291
237
  if kwargs:
292
238
  _bytes = kwargs.get("bytes", 0)
293
239
 
294
- # Read up to the given number bytes (possibly 0)
295
- text = sys.stdin.read(_bytes)
296
-
297
- # Sanity check the return.
298
- if _bytes:
299
- start_id, end_id = self._get_ids(text)
300
- text = self._check_and_return_text(text, start_id, end_id)
240
+ # Read up to the given number of *bytes* (not chars) (possibly 0)
241
+ text = sys.stdin.buffer.read(_bytes).decode('utf-8')
301
242
 
302
243
  # Get the actual data from pygments.
303
244
  res = self.get_data(method, lexer, args, kwargs, text)
304
245
 
305
- # Put back the sanity check values.
306
- if method == "highlight":
307
- res = start_id + " " + res + " " + end_id
308
-
309
246
  self._send_data(res, method)
310
247
 
311
248
  except:
312
249
  tb = traceback.format_exc()
313
250
  _write_error(tb)
314
251
 
315
- finally:
316
- lock.release()
317
-
318
252
  def main():
319
253
 
320
254
  # Signal handlers to trap signals.
@@ -324,28 +258,7 @@ def main():
324
258
  signal.signal(signal.SIGHUP, _signal_handler)
325
259
 
326
260
  mentos = Mentos()
327
-
328
- if sys.platform == "win32":
329
- # disable CRLF
330
- import msvcrt
331
- msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
332
- else:
333
- # close fd's inherited from the ruby parent
334
- import resource
335
- maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
336
- if maxfd == resource.RLIM_INFINITY:
337
- maxfd = 65536
338
-
339
- for fd in range(3, maxfd):
340
- try:
341
- os.close(fd)
342
- except:
343
- pass
344
-
345
261
  mentos.start()
346
262
 
347
263
  if __name__ == "__main__":
348
264
  main()
349
-
350
-
351
-
@@ -1,9 +1,7 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
3
+ require 'json'
4
4
  require 'open3'
5
- require 'multi_json'
6
- require 'timeout'
7
5
  require 'logger'
8
6
  require 'time'
9
7
 
@@ -15,38 +13,36 @@ end
15
13
  # Python process.
16
14
  module Pygments
17
15
  class Popen
18
-
19
- def popen4(cmd)
20
- stdin, stdout, stderr, wait_thr = Open3.popen3(cmd)
21
- [wait_thr[:pid], stdin, stdout, stderr]
16
+ def popen4(argv)
17
+ stdin, stdout, stderr, wait_thr = Open3.popen3(*argv, { close_others: true })
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
22
  end
23
23
 
24
24
  # Get things started by opening a pipe to mentos (the freshmaker), a
25
25
  # Python process that talks to the Pygments library. We'll talk back and
26
26
  # forth across this pipe.
27
- def start(pygments_path = File.expand_path('../../../vendor/pygments-main/', __FILE__))
27
+ def start(pygments_path = File.expand_path('../../vendor/pygments-main', __dir__))
28
28
  begin
29
- @log = Logger.new(ENV['MENTOS_LOG'] ||= File::NULL)
29
+ @log = Logger.new(ENV['MENTOS_LOG'] || File::NULL)
30
30
  @log.level = Logger::INFO
31
- @log.datetime_format = "%Y-%m-%d %H:%M "
32
- rescue
33
- @log = Logger.new(File::NULL)
31
+ @log.datetime_format = '%Y-%m-%d %H:%M '
34
32
  end
35
33
 
36
34
  ENV['PYGMENTS_PATH'] = pygments_path
37
35
 
38
36
  # Make sure we kill off the child when we're done
39
- at_exit { stop "Exiting" }
37
+ at_exit { stop 'Exiting' }
40
38
 
41
39
  # A pipe to the mentos python process. #popen4 gives us
42
40
  # the pid and three IO objects to write and read.
43
- script = "#{python_binary} #{File.expand_path('../mentos.py', __FILE__)}"
44
- @pid, @in, @out, @err = popen4(script)
45
- @log.info "Starting pid #{@pid} with fd #{@out.to_i} and python #{python_binary}."
46
- end
47
-
48
- def windows?
49
- RUBY_PLATFORM =~ /mswin|mingw/
41
+ argv = [*python_binary, File.expand_path('mentos.py', __dir__)]
42
+ @pid, @in, @out, @err = popen4(argv)
43
+ @in.binmode
44
+ @out.binmode
45
+ @log.info "Starting pid #{@pid} with python #{python_binary}."
50
46
  end
51
47
 
52
48
  def python_binary
@@ -58,14 +54,13 @@ module Pygments
58
54
  end
59
55
 
60
56
  # Detect a suitable Python binary to use.
61
- # Or return $PYGMENTS_RB_PYTHON if it's exists.
62
57
  def find_python_binary
63
- if ENV['PYGMENTS_RB_PYTHON']
64
- return which(ENV['PYGMENTS_RB_PYTHON'])
65
- elsif windows? && which('py')
66
- return 'py -2'
58
+ if Gem.win_platform?
59
+ return %w[py python3 python].first { |py| !which(py).nil? }
67
60
  end
68
- return which('python2') || which('python')
61
+
62
+ # On non-Windows platforms, we simply rely on shebang
63
+ []
69
64
  end
70
65
 
71
66
  # Cross platform which command
@@ -73,12 +68,12 @@ module Pygments
73
68
  def which(command)
74
69
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
75
70
  ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
76
- exts.each { |ext|
71
+ exts.each do |ext|
77
72
  path = File.join(dir, "#{command}#{ext}")
78
73
  return path if File.executable?(path) && !File.directory?(path)
79
- }
74
+ end
80
75
  end
81
- return nil
76
+ nil
82
77
  end
83
78
 
84
79
  # Stop the child process by issuing a kill -9.
@@ -94,14 +89,14 @@ module Pygments
94
89
  # the signal isn't sent); but we have permissions, and
95
90
  # we're not doing anything invalid here.
96
91
  def stop(reason)
97
- if @pid
92
+ unless @pid.nil?
93
+ @log.info "Killing pid: #{@pid}. Reason: #{reason}"
98
94
  begin
99
95
  Process.kill('KILL', @pid)
100
96
  Process.waitpid(@pid)
101
97
  rescue Errno::ESRCH, Errno::ECHILD
102
98
  end
103
99
  end
104
- @log.info "Killing pid: #{@pid.to_s}. Reason: #{reason}"
105
100
  @pid = nil
106
101
  end
107
102
 
@@ -116,30 +111,29 @@ module Pygments
116
111
  # Returns true if the child is alive.
117
112
  def alive?
118
113
  return true if defined?(@pid) && @pid && Process.kill(0, @pid)
114
+
119
115
  false
120
116
  rescue Errno::ENOENT, Errno::ESRCH
121
117
  false
122
118
  rescue Errno::EPERM
123
- raise MentosError, "EPERM checking if child process is alive."
119
+ raise MentosError, 'EPERM checking if child process is alive.'
124
120
  end
125
121
 
126
122
  # Public: Get an array of available Pygments formatters
127
123
  #
128
124
  # Returns an array of formatters.
129
125
  def formatters
130
- mentos(:get_all_formatters).inject(Hash.new) do | hash, (name, desc, aliases) |
126
+ mentos(:get_all_formatters).each_with_object({}) do |(name, desc, aliases), hash|
131
127
  # Remove the long-winded and repetitive 'Formatter' suffix
132
128
  name.sub!(/Formatter$/, '')
133
129
  hash[name] = {
134
- :name => name,
135
- :description => desc,
136
- :aliases => aliases
130
+ name: name,
131
+ description: desc,
132
+ aliases: aliases
137
133
  }
138
- hash
139
134
  end
140
135
  end
141
136
 
142
-
143
137
  # Public: Get all lexers from a serialized array. This avoids needing to spawn
144
138
  # mentos when it's not really needed (e.g., one-off jobs, loading the Rails env, etc).
145
139
  #
@@ -147,33 +141,25 @@ module Pygments
147
141
  #
148
142
  # Returns an array of lexers.
149
143
  def lexers
150
- begin
151
- lexer_file = File.expand_path('../../../lexers', __FILE__)
152
- raw = File.open(lexer_file, "rb").read
153
- Marshal.load(raw)
154
- rescue Errno::ENOENT
155
- raise MentosError, "Error loading lexer file. Was it created and vendored?"
156
- end
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?'
157
149
  end
158
150
 
159
151
  # Public: Get back all available lexers from mentos itself
160
152
  #
161
153
  # Returns an array of lexers.
162
154
  def lexers!
163
- mentos(:get_all_lexers).inject(Hash.new) do |hash, lxr|
155
+ mentos(:get_all_lexers).each_with_object({}) do |lxr, hash|
164
156
  name = lxr[0]
165
157
  hash[name] = {
166
- :name => name,
167
- :aliases => lxr[1],
168
- :filenames => lxr[2],
169
- :mimetypes => lxr[3]
158
+ name: name,
159
+ aliases: lxr[1],
160
+ filenames: lxr[2],
161
+ mimetypes: lxr[3]
170
162
  }
171
- hash["dasm16"] = {:name=>"dasm16", :aliases=>["DASM16"], :filenames=>["*.dasm16", "*.dasm"], :mimetypes=>['text/x-dasm16']}
172
- hash["Puppet"] = {:name=>"Puppet", :aliases=>["puppet"], :filenames=>["*.pp"], :mimetypes=>[]}
173
- hash["Augeas"] = {:name=>"Augeas", :aliases=>["augeas"], :filenames=>["*.aug"], :mimetypes=>[]}
174
- hash["TOML"] = {:name=>"TOML", :aliases=>["toml"], :filenames=>["*.toml"], :mimetypes=>[]}
175
- hash["Slash"] = {:name=>"Slash", :aliases=>["slash"], :filenames=>["*.sl"], :mimetypes=>[]}
176
- hash
177
163
  end
178
164
  end
179
165
 
@@ -188,7 +174,7 @@ module Pygments
188
174
  end
189
175
 
190
176
  # Public: Return css for highlighted code
191
- def css(klass='', opts={})
177
+ def css(klass = '', opts = {})
192
178
  if klass.is_a?(Hash)
193
179
  opts = klass
194
180
  klass = ''
@@ -199,17 +185,13 @@ module Pygments
199
185
  # Public: Return the name of a lexer.
200
186
  def lexer_name_for(*args)
201
187
  # Pop off the last arg if it's a hash, which becomes our opts
202
- if args.last.is_a?(Hash)
203
- opts = args.pop
204
- else
205
- opts = {}
206
- end
188
+ opts = if args.last.is_a?(Hash)
189
+ args.pop
190
+ else
191
+ {}
192
+ end
207
193
 
208
- if args.last.is_a?(String)
209
- code = args.pop
210
- else
211
- code = nil
212
- end
194
+ code = (args.pop if args.last.is_a?(String))
213
195
 
214
196
  mentos(:lexer_name_for, args, opts, code)
215
197
  end
@@ -221,7 +203,7 @@ module Pygments
221
203
  #
222
204
  # Returns the highlighted string
223
205
  # or nil when the request to the Python process timed out.
224
- def highlight(code, opts={})
206
+ def highlight(code, opts = {})
225
207
  # If the caller didn't give us any code, we have nothing to do,
226
208
  # so return right away.
227
209
  return code if code.nil? || code.empty?
@@ -234,191 +216,142 @@ module Pygments
234
216
 
235
217
  # Get back the string from mentos and force encoding if we can
236
218
  str = mentos(:highlight, nil, opts, code)
237
- str.force_encoding(opts[:options][:outencoding]) if str.respond_to?(:force_encoding)
219
+ if str.respond_to?(:force_encoding)
220
+ str.force_encoding(opts[:options][:outencoding])
221
+ end
238
222
  str
239
223
  end
240
224
 
241
225
  private
242
226
 
227
+ def with_watchdog(timeout_time, error_message)
228
+ state_mutex = Mutex.new
229
+ state = :alive
230
+ wd_cleanup = ConditionVariable.new
231
+
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
240
+ end
241
+ end : nil
242
+ begin
243
+ yield
244
+ ensure
245
+ if watchdog
246
+ state_mutex.synchronize do
247
+ state = :finished if state == :alive
248
+ # wake up watchdog thread
249
+ wd_cleanup.signal
250
+ end
251
+ watchdog.join
252
+ end
253
+
254
+ raise MentosError, error_message if state == :timeout
255
+ end
256
+ end
257
+
243
258
  # Our 'rpc'-ish request to mentos. Requires a method name, and then optional
244
259
  # args, kwargs, code.
245
- def mentos(method, args=[], kwargs={}, original_code=nil)
260
+ def mentos(method, args = [], kwargs = {}, code = nil)
246
261
  # Open the pipe if necessary
247
262
  start unless alive?
248
263
 
249
- begin
250
- # Timeout requests that take too long.
251
- # Invalid MENTOS_TIMEOUT results in just using default.
252
- timeout_time = Integer(ENV["MENTOS_TIMEOUT"]) rescue 8
253
-
254
- Timeout::timeout(timeout_time) do
255
- # For sanity checking on both sides of the pipe when highlighting, we prepend and
256
- # append an id. mentos checks that these are 8 character ids and that they match.
257
- # It then returns the id's back to Rubyland.
258
- id = (0...8).map{65.+(rand(25)).chr}.join
259
- code = add_ids(original_code, id) if original_code
260
-
261
- # Add metadata to the header and generate it.
262
- if code
263
- bytesize = code.bytesize
264
- else
265
- bytesize = 0
266
- end
264
+ # Timeout requests that take too long.
265
+ # Invalid MENTOS_TIMEOUT results in just using default.
266
+ timeout_time = kwargs.delete(:timeout)
267
+ if timeout_time.nil?
268
+ timeout_time = begin
269
+ Integer(ENV['MENTOS_TIMEOUT'])
270
+ rescue TypeError
271
+ 0
272
+ end
273
+ end
267
274
 
268
- kwargs.freeze
269
- kwargs = kwargs.merge("fd" => @out.to_i, "id" => id, "bytes" => bytesize)
270
- out_header = MultiJson.dump(:method => method, :args => args, :kwargs => kwargs)
275
+ # Add metadata to the header and generate it.
276
+ bytesize = if code
277
+ code.bytesize
278
+ else
279
+ 0
280
+ end
271
281
 
282
+ kwargs.freeze
283
+ kwargs = kwargs.merge('bytes' => bytesize)
284
+ out_header = JSON.generate(method: method, args: args, kwargs: kwargs)
285
+
286
+ begin
287
+ res = with_watchdog(timeout_time, "Timeout on a mentos #{method} call") do
272
288
  # Get the size of the header itself and write that.
273
- bits = get_fixed_bits_from_header(out_header)
274
- @in.write(bits)
289
+ @in.write([out_header.bytesize].pack('N'))
290
+ @log.info "Size out: #{out_header.bytesize}"
275
291
 
276
292
  # mentos is now waiting for the header, and, potentially, code.
277
- write_data(out_header, code)
293
+ @in.write(out_header)
294
+ @log.info "Out header: #{out_header}"
295
+ @in.write(code) unless code.nil?
278
296
 
279
- check_for_error
297
+ @in.flush
280
298
 
281
299
  # mentos will now return data to us. First it sends the header.
282
- header = get_header
283
300
 
284
- # Now handle the header, any read any more data required.
285
- res = handle_header_and_return(header, id)
286
-
287
- # Finally, return what we got.
288
- return_result(res, method)
289
- end
290
- rescue Timeout::Error
291
- # If we timeout, we need to clear out the pipe and start over.
292
- @log.error "Timeout on a mentos #{method} call"
293
- stop "Timeout on mentos #{method} call."
294
- end
295
-
296
- rescue Errno::EPIPE, EOFError
297
- stop "EPIPE"
298
- raise MentosError, "EPIPE"
299
- end
300
-
301
- def check_for_error
302
- return if @err.closed?
301
+ header_len_bytes = @out.read(4)
302
+ if header_len_bytes.nil?
303
+ raise Errno::EPIPE, %(Failed to read response from Python process on a mentos #{method} call)
304
+ end
303
305
 
304
- timeout_time = 0.25 # set a very little timeout so that we do not hang the parser
306
+ header_len = header_len_bytes.unpack('N')[0]
307
+ @log.info "Size in: #{header_len}"
308
+ header = @out.read(header_len)
305
309
 
306
- Timeout::timeout(timeout_time) do
307
- error_msg = @err.read
310
+ # Now handle the header, any read any more data required.
311
+ handle_header_and_return(header)
312
+ end
308
313
 
309
- unless error_msg.empty?
310
- @log.error "Error running python script: #{error_msg}"
311
- stop "Error running python script: #{error_msg}"
312
- raise MentosError, error_msg
314
+ # Finally, return what we got.
315
+ return_result(res, method)
316
+ rescue Errno::EPIPE => e
317
+ begin
318
+ error_msg = @err.read
319
+ @log.error "Error running Python script: #{error_msg}"
320
+ stop "Error running Python script: #{error_msg}"
321
+ raise MentosError, %(#{e}: #{error_msg})
322
+ rescue Errno::EPIPE
323
+ @log.error e.to_s
324
+ stop e.to_s
325
+ raise e
313
326
  end
327
+ rescue StandardError => e
328
+ @log.error e.to_s
329
+ stop e.to_s
330
+ raise e
314
331
  end
315
- rescue Timeout::Error
316
- # during the specified time no error were found
317
- @err.close
318
332
  end
319
333
 
320
-
321
334
  # Based on the header we receive, determine if we need
322
335
  # to read more bytes, and read those bytes if necessary.
323
336
  #
324
- # Then, do a sanity check with the ids.
325
- #
326
- # Returns a result — either highlighted text or metadata.
327
- def handle_header_and_return(header, id)
337
+ # Returns a result - either highlighted text or metadata.
338
+ def handle_header_and_return(header)
328
339
  if header
340
+ @log.info "In header: #{header}"
329
341
  header = header_to_json(header)
330
342
  bytes = header[:bytes]
331
343
 
332
344
  # Read more bytes (the actual response body)
333
345
  res = @out.read(bytes.to_i)
334
346
 
335
- if header[:method] == "highlight"
347
+ if header[:method] == 'highlight'
336
348
  # Make sure we have a result back; else consider this an error.
337
- if res.nil?
338
- @log.warn "No highlight result back from mentos."
339
- stop "No highlight result back from mentos."
340
- raise MentosError, "No highlight result back from mentos."
341
- end
342
-
343
- # Remove the newline from Python
344
- res = res[0..-2]
345
- @log.info "Highlight in process."
346
-
347
- # Get the id's
348
- start_id = res[0..7]
349
- end_id = res[-8..-1]
350
-
351
- # Sanity check.
352
- if not (start_id == id and end_id == id)
353
- @log.error "ID's did not match. Aborting."
354
- stop "ID's did not match. Aborting."
355
- raise MentosError, "ID's did not match. Aborting."
356
- else
357
- # We're good. Remove the padding
358
- res = res[10..-11]
359
- @log.info "Highlighting complete."
360
- res
361
- end
349
+ raise MentosError, 'No highlight result back from mentos.' if res.nil?
362
350
  end
363
- res
364
- else
365
- @log.error "No header data back."
366
- stop "No header data back."
367
- raise MentosError, "No header received back."
368
- end
369
- end
370
351
 
371
- # With the code, prepend the id (with two spaces to avoid escaping weirdness if
372
- # the following text starts with a slash (like terminal code), and append the
373
- # id, with two padding also. This means we are sending over the 8 characters +
374
- # code + 8 characters.
375
- def add_ids(code, id)
376
- (id + " #{code} #{id}").freeze
377
- end
378
-
379
- # Write data to mentos, the Python process.
380
- #
381
- # Returns nothing.
382
- def write_data(out_header, code=nil)
383
- @in.write(out_header)
384
- @log.info "Out header: #{out_header}"
385
- @in.write(code) if code
386
- end
387
-
388
- # Sanity check for size (32-arity of 0's and 1's)
389
- def size_check(size)
390
- size_regex = /[0-1]{32}/
391
- if size_regex.match(size)
392
- true
352
+ res
393
353
  else
394
- false
395
- end
396
- end
397
-
398
- # Read the header via the pipe.
399
- #
400
- # Returns a header.
401
- def get_header
402
- begin
403
- size = @out.read(33)
404
- size = size[0..-2]
405
-
406
- # Sanity check the size
407
- if not size_check(size)
408
- @log.error "Size returned from mentos.py invalid."
409
- stop "Size returned from mentos.py invalid."
410
- raise MentosError, "Size returned from mentos.py invalid."
411
- end
412
-
413
- # Read the amount of bytes we should be expecting. We first
414
- # convert the string of bits into an integer.
415
- header_bytes = size.to_s.to_i(2) + 1
416
- @log.info "Size in: #{size.to_s} (#{header_bytes.to_s})"
417
- @out.read(header_bytes)
418
- rescue
419
- @log.error "Failed to get header."
420
- stop "Failed to get header."
421
- raise MentosError, "Failed to get header."
354
+ raise MentosError, 'No header received back.'
422
355
  end
423
356
  end
424
357
 
@@ -426,7 +359,7 @@ module Pygments
426
359
  # want them, text otherwise.
427
360
  def return_result(res, method)
428
361
  unless method == :lexer_name_for || method == :highlight || method == :css
429
- res = MultiJson.load(res, :symbolize_keys => true)
362
+ res = JSON.parse(res, symbolize_names: true)
430
363
  end
431
364
  res = res.rstrip if res.class == String
432
365
  res
@@ -434,27 +367,13 @@ module Pygments
434
367
 
435
368
  # Convert a text header into JSON for easy access.
436
369
  def header_to_json(header)
437
- @log.info "[In header: #{header} "
438
- header = MultiJson.load(header, :symbolize_keys => true)
370
+ header = JSON.parse(header, symbolize_names: true)
439
371
 
440
372
  if header[:error]
441
- # Raise this as a Ruby exception of the MentosError class.
442
- # Stop so we don't leave the pipe in an inconsistent state.
443
- @log.error "Failed to convert header to JSON."
444
- stop header[:error]
445
373
  raise MentosError, header[:error]
446
374
  else
447
375
  header
448
376
  end
449
377
  end
450
-
451
- def get_fixed_bits_from_header(out_header)
452
- size = out_header.bytesize
453
-
454
- # Fixed 32 bits to represent the int. We return a string
455
- # representation: e.g, "00000000000000000000000000011110"
456
- Array.new(32) { |i| size[i] }.reverse!.join
457
- end
458
378
  end
459
379
  end
460
-