pygments.rb 1.2.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (388) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +13 -0
  3. data/.github/workflows/ci.yml +40 -0
  4. data/.github/workflows/release.yml +24 -0
  5. data/.gitignore +5 -5
  6. data/.rubocop.yml +18 -0
  7. data/CHANGELOG.adoc +132 -0
  8. data/Gemfile +3 -1
  9. data/LICENSE +1 -1
  10. data/README.adoc +160 -0
  11. data/Rakefile +12 -21
  12. data/bench.rb +14 -8
  13. data/{cache-lexers.rb → cache_lexers.rb} +3 -2
  14. data/lexers +0 -0
  15. data/lib/pygments.rb +10 -11
  16. data/lib/pygments/lexer.rb +6 -6
  17. data/lib/pygments/mentos.py +23 -110
  18. data/lib/pygments/popen.rb +196 -275
  19. data/lib/pygments/version.rb +2 -2
  20. data/pygments.rb.gemspec +12 -10
  21. data/test/test_pygments.rb +50 -110
  22. data/vendor/pygments-main/{AUTHORS → Pygments-2.8.0.dist-info/AUTHORS} +26 -3
  23. data/vendor/pygments-main/Pygments-2.8.0.dist-info/INSTALLER +1 -0
  24. data/vendor/pygments-main/{LICENSE → Pygments-2.8.0.dist-info/LICENSE} +1 -1
  25. data/vendor/pygments-main/Pygments-2.8.0.dist-info/METADATA +48 -0
  26. data/vendor/pygments-main/Pygments-2.8.0.dist-info/RECORD +494 -0
  27. data/vendor/pygments-main/Pygments-2.8.0.dist-info/REQUESTED +0 -0
  28. data/vendor/pygments-main/Pygments-2.8.0.dist-info/WHEEL +5 -0
  29. data/vendor/pygments-main/Pygments-2.8.0.dist-info/entry_points.txt +3 -0
  30. data/vendor/pygments-main/Pygments-2.8.0.dist-info/top_level.txt +1 -0
  31. data/vendor/pygments-main/bin/pygmentize +8 -0
  32. data/vendor/pygments-main/pygments/__init__.py +6 -12
  33. data/vendor/pygments-main/pygments/__main__.py +17 -0
  34. data/vendor/pygments-main/pygments/cmdline.py +213 -184
  35. data/vendor/pygments-main/pygments/console.py +6 -10
  36. data/vendor/pygments-main/pygments/filter.py +4 -7
  37. data/vendor/pygments-main/pygments/filters/__init__.py +609 -22
  38. data/vendor/pygments-main/pygments/formatter.py +4 -5
  39. data/vendor/pygments-main/pygments/formatters/__init__.py +10 -10
  40. data/vendor/pygments-main/pygments/formatters/_mapping.py +1 -4
  41. data/vendor/pygments-main/pygments/formatters/bbcode.py +1 -2
  42. data/vendor/pygments-main/pygments/formatters/html.py +242 -139
  43. data/vendor/pygments-main/pygments/formatters/img.py +91 -50
  44. data/vendor/pygments-main/pygments/formatters/irc.py +39 -40
  45. data/vendor/pygments-main/pygments/formatters/latex.py +62 -33
  46. data/vendor/pygments-main/pygments/formatters/other.py +18 -17
  47. data/vendor/pygments-main/pygments/formatters/rtf.py +29 -30
  48. data/vendor/pygments-main/pygments/formatters/svg.py +40 -5
  49. data/vendor/pygments-main/pygments/formatters/terminal.py +25 -32
  50. data/vendor/pygments-main/pygments/formatters/terminal256.py +45 -14
  51. data/vendor/pygments-main/pygments/lexer.py +47 -44
  52. data/vendor/pygments-main/pygments/lexers/__init__.py +29 -17
  53. data/vendor/pygments-main/pygments/lexers/_asy_builtins.py +5 -6
  54. data/vendor/pygments-main/pygments/lexers/_cl_builtins.py +15 -16
  55. data/vendor/pygments-main/pygments/lexers/_cocoa_builtins.py +21 -18
  56. data/vendor/pygments-main/pygments/lexers/_csound_builtins.py +1717 -1339
  57. data/vendor/pygments-main/pygments/lexers/_lasso_builtins.py +1 -2
  58. data/vendor/pygments-main/pygments/lexers/_lua_builtins.py +2 -5
  59. data/vendor/pygments-main/pygments/lexers/_mapping.py +79 -31
  60. data/vendor/pygments-main/pygments/lexers/_mql_builtins.py +2 -3
  61. data/vendor/pygments-main/pygments/lexers/_mysql_builtins.py +1281 -0
  62. data/vendor/pygments-main/pygments/lexers/_openedge_builtins.py +439 -386
  63. data/vendor/pygments-main/pygments/lexers/_php_builtins.py +17 -21
  64. data/vendor/pygments-main/pygments/lexers/_postgres_builtins.py +73 -17
  65. data/vendor/pygments-main/pygments/lexers/_scilab_builtins.py +2 -3
  66. data/vendor/pygments-main/pygments/lexers/_sourcemod_builtins.py +1 -4
  67. data/vendor/pygments-main/pygments/lexers/_stan_builtins.py +151 -126
  68. data/vendor/pygments-main/pygments/lexers/_stata_builtins.py +96 -58
  69. data/vendor/pygments-main/pygments/lexers/_tsql_builtins.py +1 -2
  70. data/vendor/pygments-main/pygments/lexers/_usd_builtins.py +112 -0
  71. data/vendor/pygments-main/pygments/lexers/_vbscript_builtins.py +279 -0
  72. data/vendor/pygments-main/pygments/lexers/_vim_builtins.py +1 -2
  73. data/vendor/pygments-main/pygments/lexers/actionscript.py +14 -10
  74. data/vendor/pygments-main/pygments/lexers/agile.py +1 -2
  75. data/vendor/pygments-main/pygments/lexers/algebra.py +20 -2
  76. data/vendor/pygments-main/pygments/lexers/ambient.py +2 -3
  77. data/vendor/pygments-main/pygments/lexers/amdgpu.py +48 -0
  78. data/vendor/pygments-main/pygments/lexers/ampl.py +3 -4
  79. data/vendor/pygments-main/pygments/lexers/apl.py +15 -16
  80. data/vendor/pygments-main/pygments/lexers/archetype.py +4 -5
  81. data/vendor/pygments-main/pygments/lexers/arrow.py +116 -0
  82. data/vendor/pygments-main/pygments/lexers/asm.py +440 -77
  83. data/vendor/pygments-main/pygments/lexers/automation.py +7 -2
  84. data/vendor/pygments-main/pygments/lexers/bare.py +103 -0
  85. data/vendor/pygments-main/pygments/lexers/basic.py +168 -7
  86. data/vendor/pygments-main/pygments/lexers/bibtex.py +5 -6
  87. data/vendor/pygments-main/pygments/lexers/boa.py +101 -0
  88. data/vendor/pygments-main/pygments/lexers/business.py +19 -5
  89. data/vendor/pygments-main/pygments/lexers/c_cpp.py +138 -48
  90. data/vendor/pygments-main/pygments/lexers/c_like.py +67 -43
  91. data/vendor/pygments-main/pygments/lexers/capnproto.py +7 -8
  92. data/vendor/pygments-main/pygments/lexers/cddl.py +190 -0
  93. data/vendor/pygments-main/pygments/lexers/chapel.py +25 -16
  94. data/vendor/pygments-main/pygments/lexers/clean.py +135 -245
  95. data/vendor/pygments-main/pygments/lexers/compiled.py +1 -2
  96. data/vendor/pygments-main/pygments/lexers/configs.py +190 -38
  97. data/vendor/pygments-main/pygments/lexers/console.py +1 -2
  98. data/vendor/pygments-main/pygments/lexers/crystal.py +54 -81
  99. data/vendor/pygments-main/pygments/lexers/csound.py +288 -188
  100. data/vendor/pygments-main/pygments/lexers/css.py +28 -23
  101. data/vendor/pygments-main/pygments/lexers/d.py +12 -8
  102. data/vendor/pygments-main/pygments/lexers/dalvik.py +1 -2
  103. data/vendor/pygments-main/pygments/lexers/data.py +240 -98
  104. data/vendor/pygments-main/pygments/lexers/devicetree.py +108 -0
  105. data/vendor/pygments-main/pygments/lexers/diff.py +4 -5
  106. data/vendor/pygments-main/pygments/lexers/dotnet.py +46 -31
  107. data/vendor/pygments-main/pygments/lexers/dsls.py +146 -65
  108. data/vendor/pygments-main/pygments/lexers/dylan.py +16 -19
  109. data/vendor/pygments-main/pygments/lexers/ecl.py +17 -5
  110. data/vendor/pygments-main/pygments/lexers/eiffel.py +2 -3
  111. data/vendor/pygments-main/pygments/lexers/elm.py +5 -6
  112. data/vendor/pygments-main/pygments/lexers/email.py +150 -0
  113. data/vendor/pygments-main/pygments/lexers/erlang.py +29 -33
  114. data/vendor/pygments-main/pygments/lexers/esoteric.py +46 -20
  115. data/vendor/pygments-main/pygments/lexers/ezhil.py +21 -14
  116. data/vendor/pygments-main/pygments/lexers/factor.py +3 -4
  117. data/vendor/pygments-main/pygments/lexers/fantom.py +1 -2
  118. data/vendor/pygments-main/pygments/lexers/felix.py +1 -2
  119. data/vendor/pygments-main/pygments/lexers/floscript.py +82 -0
  120. data/vendor/pygments-main/pygments/lexers/forth.py +41 -41
  121. data/vendor/pygments-main/pygments/lexers/fortran.py +13 -10
  122. data/vendor/pygments-main/pygments/lexers/foxpro.py +2 -3
  123. data/vendor/pygments-main/pygments/lexers/freefem.py +897 -0
  124. data/vendor/pygments-main/pygments/lexers/functional.py +1 -2
  125. data/vendor/pygments-main/pygments/lexers/futhark.py +110 -0
  126. data/vendor/pygments-main/pygments/lexers/gdscript.py +345 -0
  127. data/vendor/pygments-main/pygments/lexers/go.py +2 -3
  128. data/vendor/pygments-main/pygments/lexers/grammar_notation.py +62 -6
  129. data/vendor/pygments-main/pygments/lexers/graph.py +14 -10
  130. data/vendor/pygments-main/pygments/lexers/graphics.py +274 -28
  131. data/vendor/pygments-main/pygments/lexers/graphviz.py +57 -0
  132. data/vendor/pygments-main/pygments/lexers/haskell.py +48 -22
  133. data/vendor/pygments-main/pygments/lexers/haxe.py +8 -9
  134. data/vendor/pygments-main/pygments/lexers/hdl.py +176 -90
  135. data/vendor/pygments-main/pygments/lexers/hexdump.py +1 -2
  136. data/vendor/pygments-main/pygments/lexers/html.py +37 -26
  137. data/vendor/pygments-main/pygments/lexers/idl.py +19 -9
  138. data/vendor/pygments-main/pygments/lexers/igor.py +244 -113
  139. data/vendor/pygments-main/pygments/lexers/inferno.py +2 -3
  140. data/vendor/pygments-main/pygments/lexers/installers.py +1 -2
  141. data/vendor/pygments-main/pygments/lexers/int_fiction.py +40 -16
  142. data/vendor/pygments-main/pygments/lexers/iolang.py +3 -4
  143. data/vendor/pygments-main/pygments/lexers/j.py +4 -5
  144. data/vendor/pygments-main/pygments/lexers/javascript.py +115 -104
  145. data/vendor/pygments-main/pygments/lexers/julia.py +44 -47
  146. data/vendor/pygments-main/pygments/lexers/jvm.py +368 -202
  147. data/vendor/pygments-main/pygments/lexers/lisp.py +887 -810
  148. data/vendor/pygments-main/pygments/lexers/make.py +12 -9
  149. data/vendor/pygments-main/pygments/lexers/markup.py +212 -45
  150. data/vendor/pygments-main/pygments/lexers/math.py +1 -2
  151. data/vendor/pygments-main/pygments/lexers/matlab.py +2705 -88
  152. data/vendor/pygments-main/pygments/lexers/mime.py +225 -0
  153. data/vendor/pygments-main/pygments/lexers/ml.py +203 -15
  154. data/vendor/pygments-main/pygments/lexers/modeling.py +26 -19
  155. data/vendor/pygments-main/pygments/lexers/modula2.py +27 -9
  156. data/vendor/pygments-main/pygments/lexers/monte.py +1 -2
  157. data/vendor/pygments-main/pygments/lexers/mosel.py +447 -0
  158. data/vendor/pygments-main/pygments/lexers/ncl.py +1 -2
  159. data/vendor/pygments-main/pygments/lexers/nimrod.py +4 -5
  160. data/vendor/pygments-main/pygments/lexers/nit.py +1 -2
  161. data/vendor/pygments-main/pygments/lexers/nix.py +1 -2
  162. data/vendor/pygments-main/pygments/lexers/oberon.py +17 -2
  163. data/vendor/pygments-main/pygments/lexers/objective.py +18 -19
  164. data/vendor/pygments-main/pygments/lexers/ooc.py +1 -2
  165. data/vendor/pygments-main/pygments/lexers/other.py +1 -2
  166. data/vendor/pygments-main/pygments/lexers/parasail.py +1 -2
  167. data/vendor/pygments-main/pygments/lexers/parsers.py +47 -83
  168. data/vendor/pygments-main/pygments/lexers/pascal.py +22 -23
  169. data/vendor/pygments-main/pygments/lexers/pawn.py +31 -28
  170. data/vendor/pygments-main/pygments/lexers/perl.py +260 -149
  171. data/vendor/pygments-main/pygments/lexers/php.py +66 -13
  172. data/vendor/pygments-main/pygments/lexers/pointless.py +70 -0
  173. data/vendor/pygments-main/pygments/lexers/pony.py +93 -0
  174. data/vendor/pygments-main/pygments/lexers/praat.py +38 -31
  175. data/vendor/pygments-main/pygments/lexers/prolog.py +38 -39
  176. data/vendor/pygments-main/pygments/lexers/promql.py +182 -0
  177. data/vendor/pygments-main/pygments/lexers/python.py +450 -231
  178. data/vendor/pygments-main/pygments/lexers/qvt.py +6 -7
  179. data/vendor/pygments-main/pygments/lexers/r.py +13 -276
  180. data/vendor/pygments-main/pygments/lexers/rdf.py +232 -40
  181. data/vendor/pygments-main/pygments/lexers/rebol.py +8 -9
  182. data/vendor/pygments-main/pygments/lexers/resource.py +2 -3
  183. data/vendor/pygments-main/pygments/lexers/ride.py +138 -0
  184. data/vendor/pygments-main/pygments/lexers/rnc.py +1 -2
  185. data/vendor/pygments-main/pygments/lexers/roboconf.py +1 -2
  186. data/vendor/pygments-main/pygments/lexers/robotframework.py +23 -32
  187. data/vendor/pygments-main/pygments/lexers/ruby.py +50 -46
  188. data/vendor/pygments-main/pygments/lexers/rust.py +76 -73
  189. data/vendor/pygments-main/pygments/lexers/sas.py +1 -2
  190. data/vendor/pygments-main/pygments/lexers/scdoc.py +82 -0
  191. data/vendor/pygments-main/pygments/lexers/scripting.py +79 -18
  192. data/vendor/pygments-main/pygments/lexers/sgf.py +60 -0
  193. data/vendor/pygments-main/pygments/lexers/shell.py +164 -49
  194. data/vendor/pygments-main/pygments/lexers/sieve.py +68 -0
  195. data/vendor/pygments-main/pygments/lexers/slash.py +184 -0
  196. data/vendor/pygments-main/pygments/lexers/smalltalk.py +2 -3
  197. data/vendor/pygments-main/pygments/lexers/smv.py +3 -4
  198. data/vendor/pygments-main/pygments/lexers/snobol.py +1 -2
  199. data/vendor/pygments-main/pygments/lexers/solidity.py +91 -0
  200. data/vendor/pygments-main/pygments/lexers/special.py +31 -28
  201. data/vendor/pygments-main/pygments/lexers/sql.py +330 -179
  202. data/vendor/pygments-main/pygments/lexers/stata.py +107 -45
  203. data/vendor/pygments-main/pygments/lexers/supercollider.py +8 -4
  204. data/vendor/pygments-main/pygments/lexers/tcl.py +1 -2
  205. data/vendor/pygments-main/pygments/lexers/templates.py +116 -136
  206. data/vendor/pygments-main/pygments/lexers/teraterm.py +334 -0
  207. data/vendor/pygments-main/pygments/lexers/testing.py +6 -7
  208. data/vendor/pygments-main/pygments/lexers/text.py +2 -2
  209. data/vendor/pygments-main/pygments/lexers/textedit.py +6 -7
  210. data/vendor/pygments-main/pygments/lexers/textfmts.py +146 -14
  211. data/vendor/pygments-main/pygments/lexers/theorem.py +74 -56
  212. data/vendor/pygments-main/pygments/lexers/tnt.py +262 -0
  213. data/vendor/pygments-main/pygments/lexers/trafficscript.py +1 -2
  214. data/vendor/pygments-main/pygments/lexers/typoscript.py +4 -12
  215. data/vendor/pygments-main/pygments/lexers/unicon.py +411 -0
  216. data/vendor/pygments-main/pygments/lexers/urbi.py +16 -4
  217. data/vendor/pygments-main/pygments/lexers/usd.py +89 -0
  218. data/vendor/pygments-main/pygments/lexers/varnish.py +4 -5
  219. data/vendor/pygments-main/pygments/lexers/verification.py +13 -11
  220. data/vendor/pygments-main/pygments/lexers/web.py +1 -2
  221. data/vendor/pygments-main/pygments/lexers/webidl.py +298 -0
  222. data/vendor/pygments-main/pygments/lexers/webmisc.py +35 -32
  223. data/vendor/pygments-main/pygments/lexers/whiley.py +5 -6
  224. data/vendor/pygments-main/pygments/lexers/x10.py +2 -3
  225. data/vendor/pygments-main/pygments/lexers/xorg.py +5 -5
  226. data/vendor/pygments-main/pygments/lexers/yang.py +103 -0
  227. data/vendor/pygments-main/pygments/lexers/zig.py +123 -0
  228. data/vendor/pygments-main/pygments/modeline.py +1 -2
  229. data/vendor/pygments-main/pygments/plugin.py +4 -3
  230. data/vendor/pygments-main/pygments/regexopt.py +1 -2
  231. data/vendor/pygments-main/pygments/scanner.py +2 -3
  232. data/vendor/pygments-main/pygments/sphinxext.py +2 -5
  233. data/vendor/pygments-main/pygments/style.py +61 -25
  234. data/vendor/pygments-main/pygments/styles/__init__.py +12 -5
  235. data/vendor/pygments-main/pygments/styles/abap.py +1 -2
  236. data/vendor/pygments-main/pygments/styles/algol.py +1 -2
  237. data/vendor/pygments-main/pygments/styles/algol_nu.py +1 -2
  238. data/vendor/pygments-main/pygments/styles/arduino.py +2 -3
  239. data/vendor/pygments-main/pygments/styles/autumn.py +1 -2
  240. data/vendor/pygments-main/pygments/styles/borland.py +1 -2
  241. data/vendor/pygments-main/pygments/styles/bw.py +1 -2
  242. data/vendor/pygments-main/pygments/styles/colorful.py +1 -2
  243. data/vendor/pygments-main/pygments/styles/default.py +1 -2
  244. data/vendor/pygments-main/pygments/styles/emacs.py +1 -2
  245. data/vendor/pygments-main/pygments/styles/friendly.py +1 -2
  246. data/vendor/pygments-main/pygments/styles/fruity.py +1 -2
  247. data/vendor/pygments-main/pygments/styles/igor.py +1 -2
  248. data/vendor/pygments-main/pygments/styles/inkpot.py +66 -0
  249. data/vendor/pygments-main/pygments/styles/lovelace.py +1 -2
  250. data/vendor/pygments-main/pygments/styles/manni.py +1 -2
  251. data/vendor/pygments-main/pygments/styles/material.py +118 -0
  252. data/vendor/pygments-main/pygments/styles/monokai.py +4 -4
  253. data/vendor/pygments-main/pygments/styles/murphy.py +1 -2
  254. data/vendor/pygments-main/pygments/styles/native.py +1 -2
  255. data/vendor/pygments-main/pygments/styles/paraiso_dark.py +1 -2
  256. data/vendor/pygments-main/pygments/styles/paraiso_light.py +1 -2
  257. data/vendor/pygments-main/pygments/styles/pastie.py +1 -2
  258. data/vendor/pygments-main/pygments/styles/perldoc.py +1 -2
  259. data/vendor/pygments-main/pygments/styles/rainbow_dash.py +1 -2
  260. data/vendor/pygments-main/pygments/styles/rrt.py +1 -2
  261. data/vendor/pygments-main/pygments/styles/sas.py +1 -2
  262. data/vendor/pygments-main/pygments/styles/solarized.py +136 -0
  263. data/vendor/pygments-main/pygments/styles/stata_dark.py +40 -0
  264. data/vendor/pygments-main/pygments/styles/{stata.py → stata_light.py} +14 -16
  265. data/vendor/pygments-main/pygments/styles/tango.py +1 -2
  266. data/vendor/pygments-main/pygments/styles/trac.py +1 -2
  267. data/vendor/pygments-main/pygments/styles/vim.py +1 -2
  268. data/vendor/pygments-main/pygments/styles/vs.py +1 -2
  269. data/vendor/pygments-main/pygments/styles/xcode.py +1 -2
  270. data/vendor/pygments-main/pygments/styles/zenburn.py +80 -0
  271. data/vendor/pygments-main/pygments/token.py +1 -2
  272. data/vendor/pygments-main/pygments/unistring.py +47 -109
  273. data/vendor/pygments-main/pygments/util.py +16 -96
  274. metadata +76 -137
  275. data/CHANGELOG.md +0 -105
  276. data/README.md +0 -121
  277. data/circle.yml +0 -20
  278. data/test/test_data.c +0 -2581
  279. data/test/test_data.py +0 -514
  280. data/test/test_data_generated +0 -2582
  281. data/vendor/custom_lexers/github.py +0 -565
  282. data/vendor/pygments-main/CHANGES +0 -1186
  283. data/vendor/pygments-main/MANIFEST.in +0 -6
  284. data/vendor/pygments-main/Makefile +0 -65
  285. data/vendor/pygments-main/README.rst +0 -39
  286. data/vendor/pygments-main/REVISION +0 -1
  287. data/vendor/pygments-main/TODO +0 -12
  288. data/vendor/pygments-main/doc/Makefile +0 -153
  289. data/vendor/pygments-main/doc/_static/favicon.ico +0 -0
  290. data/vendor/pygments-main/doc/_static/logo_new.png +0 -0
  291. data/vendor/pygments-main/doc/_static/logo_only.png +0 -0
  292. data/vendor/pygments-main/doc/_templates/docssidebar.html +0 -3
  293. data/vendor/pygments-main/doc/_templates/indexsidebar.html +0 -25
  294. data/vendor/pygments-main/doc/_themes/pygments14/layout.html +0 -98
  295. data/vendor/pygments-main/doc/_themes/pygments14/static/bodybg.png +0 -0
  296. data/vendor/pygments-main/doc/_themes/pygments14/static/docbg.png +0 -0
  297. data/vendor/pygments-main/doc/_themes/pygments14/static/listitem.png +0 -0
  298. data/vendor/pygments-main/doc/_themes/pygments14/static/logo.png +0 -0
  299. data/vendor/pygments-main/doc/_themes/pygments14/static/pocoo.png +0 -0
  300. data/vendor/pygments-main/doc/_themes/pygments14/static/pygments14.css_t +0 -401
  301. data/vendor/pygments-main/doc/_themes/pygments14/theme.conf +0 -15
  302. data/vendor/pygments-main/doc/conf.py +0 -241
  303. data/vendor/pygments-main/doc/docs/api.rst +0 -354
  304. data/vendor/pygments-main/doc/docs/authors.rst +0 -4
  305. data/vendor/pygments-main/doc/docs/changelog.rst +0 -1
  306. data/vendor/pygments-main/doc/docs/cmdline.rst +0 -166
  307. data/vendor/pygments-main/doc/docs/filterdevelopment.rst +0 -71
  308. data/vendor/pygments-main/doc/docs/filters.rst +0 -41
  309. data/vendor/pygments-main/doc/docs/formatterdevelopment.rst +0 -169
  310. data/vendor/pygments-main/doc/docs/formatters.rst +0 -48
  311. data/vendor/pygments-main/doc/docs/index.rst +0 -66
  312. data/vendor/pygments-main/doc/docs/integrate.rst +0 -40
  313. data/vendor/pygments-main/doc/docs/java.rst +0 -70
  314. data/vendor/pygments-main/doc/docs/lexerdevelopment.rst +0 -728
  315. data/vendor/pygments-main/doc/docs/lexers.rst +0 -69
  316. data/vendor/pygments-main/doc/docs/moinmoin.rst +0 -39
  317. data/vendor/pygments-main/doc/docs/plugins.rst +0 -93
  318. data/vendor/pygments-main/doc/docs/quickstart.rst +0 -205
  319. data/vendor/pygments-main/doc/docs/rstdirective.rst +0 -22
  320. data/vendor/pygments-main/doc/docs/styles.rst +0 -201
  321. data/vendor/pygments-main/doc/docs/tokens.rst +0 -372
  322. data/vendor/pygments-main/doc/docs/unicode.rst +0 -58
  323. data/vendor/pygments-main/doc/download.rst +0 -41
  324. data/vendor/pygments-main/doc/faq.rst +0 -139
  325. data/vendor/pygments-main/doc/index.rst +0 -54
  326. data/vendor/pygments-main/doc/languages.rst +0 -154
  327. data/vendor/pygments-main/doc/make.bat +0 -190
  328. data/vendor/pygments-main/doc/pygmentize.1 +0 -94
  329. data/vendor/pygments-main/external/autopygmentize +0 -101
  330. data/vendor/pygments-main/external/lasso-builtins-generator-9.lasso +0 -162
  331. data/vendor/pygments-main/external/markdown-processor.py +0 -67
  332. data/vendor/pygments-main/external/moin-parser.py +0 -112
  333. data/vendor/pygments-main/external/pygments.bashcomp +0 -38
  334. data/vendor/pygments-main/external/rst-directive.py +0 -82
  335. data/vendor/pygments-main/pygmentize +0 -8
  336. data/vendor/pygments-main/pygments/lexers/github.py +0 -565
  337. data/vendor/pygments-main/requirements.txt +0 -5
  338. data/vendor/pygments-main/scripts/check_sources.py +0 -211
  339. data/vendor/pygments-main/scripts/debug_lexer.py +0 -246
  340. data/vendor/pygments-main/scripts/detect_missing_analyse_text.py +0 -33
  341. data/vendor/pygments-main/scripts/epydoc.css +0 -280
  342. data/vendor/pygments-main/scripts/get_vimkw.py +0 -74
  343. data/vendor/pygments-main/scripts/pylintrc +0 -301
  344. data/vendor/pygments-main/scripts/vim2pygments.py +0 -935
  345. data/vendor/pygments-main/setup.cfg +0 -10
  346. data/vendor/pygments-main/setup.py +0 -77
  347. data/vendor/pygments-main/tox.ini +0 -7
  348. data/vendor/simplejson/.gitignore +0 -10
  349. data/vendor/simplejson/.travis.yml +0 -5
  350. data/vendor/simplejson/CHANGES.txt +0 -291
  351. data/vendor/simplejson/LICENSE.txt +0 -19
  352. data/vendor/simplejson/MANIFEST.in +0 -5
  353. data/vendor/simplejson/README.rst +0 -19
  354. data/vendor/simplejson/conf.py +0 -179
  355. data/vendor/simplejson/index.rst +0 -628
  356. data/vendor/simplejson/scripts/make_docs.py +0 -18
  357. data/vendor/simplejson/setup.py +0 -104
  358. data/vendor/simplejson/simplejson/__init__.py +0 -510
  359. data/vendor/simplejson/simplejson/_speedups.c +0 -2745
  360. data/vendor/simplejson/simplejson/decoder.py +0 -425
  361. data/vendor/simplejson/simplejson/encoder.py +0 -567
  362. data/vendor/simplejson/simplejson/ordered_dict.py +0 -119
  363. data/vendor/simplejson/simplejson/scanner.py +0 -77
  364. data/vendor/simplejson/simplejson/tests/__init__.py +0 -67
  365. data/vendor/simplejson/simplejson/tests/test_bigint_as_string.py +0 -55
  366. data/vendor/simplejson/simplejson/tests/test_check_circular.py +0 -30
  367. data/vendor/simplejson/simplejson/tests/test_decimal.py +0 -66
  368. data/vendor/simplejson/simplejson/tests/test_decode.py +0 -83
  369. data/vendor/simplejson/simplejson/tests/test_default.py +0 -9
  370. data/vendor/simplejson/simplejson/tests/test_dump.py +0 -67
  371. data/vendor/simplejson/simplejson/tests/test_encode_basestring_ascii.py +0 -46
  372. data/vendor/simplejson/simplejson/tests/test_encode_for_html.py +0 -32
  373. data/vendor/simplejson/simplejson/tests/test_errors.py +0 -34
  374. data/vendor/simplejson/simplejson/tests/test_fail.py +0 -91
  375. data/vendor/simplejson/simplejson/tests/test_float.py +0 -19
  376. data/vendor/simplejson/simplejson/tests/test_indent.py +0 -86
  377. data/vendor/simplejson/simplejson/tests/test_item_sort_key.py +0 -20
  378. data/vendor/simplejson/simplejson/tests/test_namedtuple.py +0 -121
  379. data/vendor/simplejson/simplejson/tests/test_pass1.py +0 -76
  380. data/vendor/simplejson/simplejson/tests/test_pass2.py +0 -14
  381. data/vendor/simplejson/simplejson/tests/test_pass3.py +0 -20
  382. data/vendor/simplejson/simplejson/tests/test_recursion.py +0 -67
  383. data/vendor/simplejson/simplejson/tests/test_scanstring.py +0 -117
  384. data/vendor/simplejson/simplejson/tests/test_separators.py +0 -42
  385. data/vendor/simplejson/simplejson/tests/test_speedups.py +0 -20
  386. data/vendor/simplejson/simplejson/tests/test_tuple.py +0 -49
  387. data/vendor/simplejson/simplejson/tests/test_unicode.py +0 -109
  388. data/vendor/simplejson/simplejson/tool.py +0 -39
data/bench.rb CHANGED
@@ -1,22 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.join(File.dirname(__FILE__), '/lib/pygments.rb')
2
4
  require 'benchmark'
3
5
 
4
- include Benchmark
5
6
  # number of iterations
6
7
  num = ARGV[0] ? ARGV[0].to_i : 10
7
8
 
8
9
  # we can also repeat the code itself
9
10
  repeats = ARGV[1] ? ARGV[1].to_i : 1
10
11
 
11
- code = File.open('test/test_data.py').read.to_s * repeats
12
+ code = File.open('test/test_pygments.rb').read.to_s * repeats
12
13
 
13
14
  puts "Benchmarking....\n"
14
- puts "Size: " + code.bytesize.to_s + " bytes\n"
15
- puts "Iterations: " + num.to_s + "\n"
15
+ puts 'Size: ' + code.bytesize.to_s + " bytes\n"
16
+ puts 'Iterations: ' + num.to_s + "\n"
16
17
 
17
18
  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 }
19
+ x.report('pygments popen ') do
20
+ (1..num).each { |_i|; Pygments.highlight(code, lexer: 'python'); }
21
+ end
22
+ x.report('pygments popen (process already started) ') do
23
+ (1..num).each { |_i|; Pygments.highlight(code, lexer: 'python'); }
24
+ end
25
+ x.report('pygments popen (process already started 2) ') do
26
+ (1..num).each { |_i|; Pygments.highlight(code, lexer: 'python'); }
27
+ end
21
28
  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
data/lib/pygments.rb CHANGED
@@ -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 = []
@@ -30,17 +30,17 @@ module Pygments
30
30
  extnames = []
31
31
 
32
32
  extname = File.extname(filename)
33
- if m = extname.match(/\[(.+)\]/)
33
+ if (m = extname.match(/\[(.+)\]/))
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,26 @@ 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]
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/', __FILE__))
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
- rescue
33
- @log = Logger.new(File::NULL)
34
- 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 '
35
23
 
36
24
  ENV['PYGMENTS_PATH'] = pygments_path
37
25
 
38
26
  # Make sure we kill off the child when we're done
39
- at_exit { stop "Exiting" }
27
+ at_exit { stop 'Exiting' }
40
28
 
41
29
  # A pipe to the mentos python process. #popen4 gives us
42
30
  # 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/
31
+ argv = [*python_binary, File.join(__dir__, 'mentos.py')]
32
+ @pid, @in, @out, @err = popen4(argv)
33
+ @in.binmode
34
+ @out.binmode
35
+ @log.info "Starting pid #{@pid} with python #{python_binary}."
50
36
  end
51
37
 
52
38
  def python_binary
@@ -57,30 +43,6 @@ module Pygments
57
43
  @python_bin = python_bin
58
44
  end
59
45
 
60
- # Detect a suitable Python binary to use.
61
- # Or return $PYGMENTS_RB_PYTHON if it's exists.
62
- 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'
67
- end
68
- return which('python2') || which('python')
69
- end
70
-
71
- # Cross platform which command
72
- # from http://stackoverflow.com/a/5471032/284795
73
- def which(command)
74
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
75
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
76
- exts.each { |ext|
77
- path = File.join(dir, "#{command}#{ext}")
78
- return path if File.executable?(path) && !File.directory?(path)
79
- }
80
- end
81
- return nil
82
- end
83
-
84
46
  # Stop the child process by issuing a kill -9.
85
47
  #
86
48
  # We then call waitpid() with the pid, which waits for that particular
@@ -93,15 +55,17 @@ module Pygments
93
55
  # Technically, kill() can also fail with EPERM or EINVAL (wherein
94
56
  # the signal isn't sent); but we have permissions, and
95
57
  # we're not doing anything invalid here.
58
+ # @param reason [String]
96
59
  def stop(reason)
97
- if @pid
60
+ unless @pid.nil?
61
+ @log.info "Killing pid: #{@pid}. Reason: #{reason}"
98
62
  begin
99
63
  Process.kill('KILL', @pid)
100
64
  Process.waitpid(@pid)
101
- rescue Errno::ESRCH, Errno::ECHILD
65
+ rescue Errno::ESRCH, Errno::ECHILD => e
66
+ @log.warn(e)
102
67
  end
103
68
  end
104
- @log.info "Killing pid: #{@pid.to_s}. Reason: #{reason}"
105
69
  @pid = nil
106
70
  end
107
71
 
@@ -113,82 +77,77 @@ module Pygments
113
77
  # process and the pid has already been re-used) we'll want to raise
114
78
  # that as a more informative Mentos exception.
115
79
  #
116
- # Returns true if the child is alive.
80
+ # @return [Boolean] true if the child is alive.
117
81
  def alive?
118
82
  return true if defined?(@pid) && @pid && Process.kill(0, @pid)
83
+
119
84
  false
120
85
  rescue Errno::ENOENT, Errno::ESRCH
121
86
  false
122
87
  rescue Errno::EPERM
123
- raise MentosError, "EPERM checking if child process is alive."
88
+ raise MentosError, 'EPERM checking if child process is alive.'
124
89
  end
125
90
 
126
91
  # Public: Get an array of available Pygments formatters
127
92
  #
128
- # Returns an array of formatters.
93
+ # @return [Array<String>] an array of formatters
129
94
  def formatters
130
- mentos(:get_all_formatters).inject(Hash.new) do | hash, (name, desc, aliases) |
95
+ mentos(:get_all_formatters).each_with_object({}) do |(name, desc, aliases), hash|
131
96
  # Remove the long-winded and repetitive 'Formatter' suffix
132
97
  name.sub!(/Formatter$/, '')
133
98
  hash[name] = {
134
- :name => name,
135
- :description => desc,
136
- :aliases => aliases
99
+ name: name,
100
+ description: desc,
101
+ aliases: aliases
137
102
  }
138
- hash
139
103
  end
140
104
  end
141
105
 
142
-
143
- # Public: Get all lexers from a serialized array. This avoids needing to spawn
144
- # mentos when it's not really needed (e.g., one-off jobs, loading the Rails env, etc).
106
+ # Get all lexers from a serialized array.
107
+ # This avoids needing to spawn mentos when it's not really needed
108
+ # (e.g., one-off jobs, loading the Rails env, etc).
145
109
  #
146
110
  # Should be preferred to #lexers!
147
111
  #
148
- # Returns an array of lexers.
112
+ # @return [Array<String>] an array of lexers
149
113
  def lexers
114
+ lexer_file = File.join(__dir__, '..', '..', 'lexers')
150
115
  begin
151
- lexer_file = File.expand_path('../../../lexers', __FILE__)
152
- raw = File.open(lexer_file, "rb").read
153
- Marshal.load(raw)
116
+ File.open(lexer_file, 'rb') do |f|
117
+ Marshal.load(f)
118
+ end
154
119
  rescue Errno::ENOENT
155
- raise MentosError, "Error loading lexer file. Was it created and vendored?"
120
+ raise MentosError, %(Error loading #{lexer_file}. Was it created and vendored?)
156
121
  end
157
122
  end
158
123
 
159
- # Public: Get back all available lexers from mentos itself
124
+ # Get back all available lexers from mentos itself
160
125
  #
161
- # Returns an array of lexers.
126
+ # @return [Array<String>] an array of lexers
162
127
  def lexers!
163
- mentos(:get_all_lexers).inject(Hash.new) do |hash, lxr|
128
+ mentos(:get_all_lexers).each_with_object({}) do |lxr, hash|
164
129
  name = lxr[0]
165
130
  hash[name] = {
166
- :name => name,
167
- :aliases => lxr[1],
168
- :filenames => lxr[2],
169
- :mimetypes => lxr[3]
131
+ name: name,
132
+ aliases: lxr[1],
133
+ filenames: lxr[2],
134
+ mimetypes: lxr[3]
170
135
  }
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
136
  end
178
137
  end
179
138
 
180
- # Public: Return an array of all available filters
139
+ # @return [Array<String>] an array of all available filters
181
140
  def filters
182
141
  mentos(:get_all_filters)
183
142
  end
184
143
 
185
- # Public: Return an array of all available styles
144
+ # @return [Array<String>] an array of all available styles
186
145
  def styles
187
146
  mentos(:get_all_styles)
188
147
  end
189
148
 
190
- # Public: Return css for highlighted code
191
- def css(klass='', opts={})
149
+ # @return [String] css for highlighted code
150
+ def css(klass = '', opts = {})
192
151
  if klass.is_a?(Hash)
193
152
  opts = klass
194
153
  klass = ''
@@ -196,32 +155,29 @@ module Pygments
196
155
  mentos(:css, ['html', klass], opts)
197
156
  end
198
157
 
199
- # Public: Return the name of a lexer.
158
+ # @return [String, nil] the name of a lexer.
200
159
  def lexer_name_for(*args)
201
160
  # 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
161
+ opts = if args.last.is_a?(Hash)
162
+ args.pop
163
+ else
164
+ {}
165
+ end
207
166
 
208
- if args.last.is_a?(String)
209
- code = args.pop
210
- else
211
- code = nil
212
- end
167
+ code = (args.pop if args.last.is_a?(String))
213
168
 
214
169
  mentos(:lexer_name_for, args, opts, code)
215
170
  end
216
171
 
217
172
  # Public: Highlight code.
218
173
  #
219
- # Takes a first-position argument of the code to be highlighted, and a
220
- # second-position hash of various arguments specifying highlighting properties.
174
+ # Takes a first-position argument of the code to be highlighted,
175
+ # and a second-position hash of various arguments specifying
176
+ # highlighting properties.
221
177
  #
222
178
  # Returns the highlighted string
223
179
  # or nil when the request to the Python process timed out.
224
- def highlight(code, opts={})
180
+ def highlight(code, opts = {})
225
181
  # If the caller didn't give us any code, we have nothing to do,
226
182
  # so return right away.
227
183
  return code if code.nil? || code.empty?
@@ -240,221 +196,186 @@ module Pygments
240
196
 
241
197
  private
242
198
 
243
- # Our 'rpc'-ish request to mentos. Requires a method name, and then optional
244
- # args, kwargs, code.
245
- def mentos(method, args=[], kwargs={}, original_code=nil)
246
- # Open the pipe if necessary
247
- start unless alive?
199
+ # @param argv [Array<String>]
200
+ def popen4(argv)
201
+ stdin, stdout, stderr, wait_thr = Open3.popen3(*argv, { close_others: true })
202
+ while (pid = wait_thr.pid).nil? && wait_thr.alive?
203
+ # wait_thr.pid is not immediately available on JRuby. Why???
204
+ end
205
+ [pid, stdin, stdout, stderr]
206
+ end
207
+
208
+ # Detect a suitable Python binary to use.
209
+ def find_python_binary
210
+ return %w[py python3 python].first { |py| !which(py).nil? } if Gem.win_platform?
211
+
212
+ # On non-Windows platforms, we simply rely on shebang
213
+ []
214
+ end
215
+
216
+ # Cross platform which command
217
+ # from http://stackoverflow.com/a/5471032/284795
218
+ def which(command)
219
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
220
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
221
+ exts.each do |ext|
222
+ path = File.join(dir, "#{command}#{ext}")
223
+ return path if File.executable?(path) && !File.directory?(path)
224
+ end
225
+ end
226
+ nil
227
+ end
228
+
229
+ # @param timeout [Integer]
230
+ # @param error_message [String]
231
+ # @yield
232
+ def with_watchdog(timeout, error_message)
233
+ state_mutex = Mutex.new
234
+ state = :alive
235
+ wd_cleanup = ConditionVariable.new
236
+
237
+ watchdog = if timeout.positive?
238
+ Thread.new do
239
+ state_mutex.synchronize do
240
+ wd_cleanup.wait(state_mutex, timeout) if state != :finished
241
+ if state != :finished
242
+ @log.error error_message
243
+ stop error_message
244
+ state = :timeout
245
+ end
246
+ end
247
+ end
248
+ end
248
249
 
249
250
  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
251
+ yield
252
+ ensure
253
+ if watchdog
254
+ state_mutex.synchronize do
255
+ state = :finished if state == :alive
256
+ # wake up watchdog thread
257
+ wd_cleanup.signal
266
258
  end
259
+ watchdog.join
260
+ end
267
261
 
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)
262
+ raise MentosError, error_message if state == :timeout
263
+ end
264
+ end
271
265
 
272
- # Get the size of the header itself and write that.
273
- bits = get_fixed_bits_from_header(out_header)
274
- @in.write(bits)
266
+ # Our 'rpc'-ish request to mentos. Requires a method name, and then optional
267
+ # args, kwargs, code.
268
+ def mentos(method, args = [], kwargs = {}, code = nil)
269
+ # Open the pipe if necessary
270
+ start unless alive?
275
271
 
276
- # mentos is now waiting for the header, and, potentially, code.
277
- write_data(out_header, code)
272
+ # Add metadata to the header and generate it.
273
+ kwargs = kwargs.merge('bytes' => (code.nil? ? 0 : code.bytesize))
274
+ out_header = JSON.generate(method: method, args: args, kwargs: kwargs)
278
275
 
279
- check_for_error
276
+ begin
277
+ timeout = get_timeout(kwargs.delete(:timeout))
278
+ res = with_watchdog(timeout, "Timeout on a mentos #{method} call") do
279
+ write_header(out_header, code)
280
280
 
281
281
  # mentos will now return data to us. First it sends the header.
282
- header = get_header
282
+ header_len_bytes = @out.read(4)
283
+ if header_len_bytes.nil?
284
+ raise Errno::EPIPE, %(Failed to read response from Python process on a mentos #{method} call)
285
+ end
286
+
287
+ header_len = header_len_bytes.unpack('N')[0]
288
+ @log.info "Size in: #{header_len}"
289
+ header = @out.read(header_len)
283
290
 
284
291
  # Now handle the header, any read any more data required.
285
- res = handle_header_and_return(header, id)
292
+ handle_header_and_return(header)
293
+ end
286
294
 
287
- # Finally, return what we got.
288
- return_result(res, method)
295
+ # Finally, return what we got.
296
+ return_result(res, method)
297
+ rescue Errno::EPIPE => e
298
+ begin
299
+ error_msg = @err.read
300
+ @log.error "Error running Python script: #{error_msg}"
301
+ stop "Error running Python script: #{error_msg}"
302
+ raise MentosError, %(#{e}: #{error_msg})
303
+ rescue Errno::EPIPE
304
+ @log.error e.to_s
305
+ stop e.to_s
306
+ raise e
289
307
  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."
308
+ rescue StandardError => e
309
+ @log.error e.to_s
310
+ stop e.to_s
311
+ raise e
294
312
  end
295
-
296
- rescue Errno::EPIPE, EOFError
297
- stop "EPIPE"
298
- raise MentosError, "EPIPE"
299
313
  end
300
314
 
301
- def check_for_error
302
- return if @err.closed?
303
-
304
- timeout_time = 0.25 # set a very little timeout so that we do not hang the parser
315
+ # @param header [String]
316
+ # @param code [String, nil]
317
+ def write_header(header, code)
318
+ # Get the size of the header itself and write that.
319
+ @in.write([header.bytesize].pack('N'))
320
+ @log.info "Size out: #{header.bytesize}"
321
+
322
+ # mentos is now waiting for the header, and, potentially, code.
323
+ @in.write(header)
324
+ @log.info "Out header: #{header}"
325
+ @in.write(code) unless code.nil?
326
+ @in.flush
327
+ end
305
328
 
306
- Timeout::timeout(timeout_time) do
307
- error_msg = @err.read
329
+ # @param timeout [Integer, nil]
330
+ # @return [Integer]
331
+ def get_timeout(timeout)
332
+ return timeout unless timeout.nil?
308
333
 
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
313
- end
334
+ begin
335
+ Integer(ENV['MENTOS_TIMEOUT'])
336
+ rescue TypeError
337
+ 0
314
338
  end
315
- rescue Timeout::Error
316
- # during the specified time no error were found
317
- @err.close
318
339
  end
319
340
 
320
-
321
341
  # Based on the header we receive, determine if we need
322
342
  # to read more bytes, and read those bytes if necessary.
323
343
  #
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)
328
- if header
329
- header = header_to_json(header)
330
- bytes = header[:bytes]
331
-
332
- # Read more bytes (the actual response body)
333
- res = @out.read(bytes.to_i)
334
-
335
- if header[:method] == "highlight"
336
- # 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
344
+ # @param header [String, nil]
345
+ # @return [String, nil] either highlighted text or metadata.
346
+ def handle_header_and_return(header)
347
+ raise MentosError, 'No header received back.' if header.nil?
342
348
 
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
362
- 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
349
+ @log.info "In header: #{header}"
350
+ header = header_to_json(header)
351
+ bytes = header[:bytes]
370
352
 
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
353
+ # Read more bytes (the actual response body)
354
+ res = @out.read(bytes.to_i)
378
355
 
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
393
- else
394
- false
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?
395
359
  end
396
- end
397
360
 
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."
422
- end
361
+ res
423
362
  end
424
363
 
425
- # Return the final result for the API. Return Ruby objects for the methods that
426
- # want them, text otherwise.
364
+ # @return Ruby objects for the methods that want them, text otherwise.
427
365
  def return_result(res, method)
428
- unless method == :lexer_name_for || method == :highlight || method == :css
429
- res = MultiJson.load(res, :symbolize_keys => true)
430
- end
366
+ res = JSON.parse(res, symbolize_names: true) unless %i[lexer_name_for highlight css].include?(method)
431
367
  res = res.rstrip if res.class == String
432
368
  res
433
369
  end
434
370
 
435
371
  # Convert a text header into JSON for easy access.
372
+ # @param header [String]
373
+ # @return [JSON]
436
374
  def header_to_json(header)
437
- @log.info "[In header: #{header} "
438
- header = MultiJson.load(header, :symbolize_keys => true)
439
-
440
- 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
- raise MentosError, header[:error]
446
- else
447
- header
448
- end
449
- end
375
+ json = JSON.parse(header, symbolize_names: true)
376
+ raise MentosError, json[:error] unless json[:error].nil?
450
377
 
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
378
+ json
457
379
  end
458
380
  end
459
381
  end
460
-