ver 2010.02 → 2010.08

Sign up to get free protection for your applications and to get access to all the features.
Files changed (651) hide show
  1. data/.gitignore +1 -0
  2. data/.yardopts +1 -1
  3. data/AUTHORS +2 -2
  4. data/CHANGELOG +1160 -0
  5. data/MANIFEST +212 -62
  6. data/README.textile +68 -9
  7. data/Rakefile +2 -2
  8. data/bin/ver +33 -8
  9. data/config/commands/ANTLR.rb +11 -0
  10. data/config/commands/ActionScript.rb +102 -0
  11. data/config/commands/Active4D.rb +30 -0
  12. data/config/commands/Ada.rb +11 -0
  13. data/config/commands/Ant.rb +90 -0
  14. data/config/commands/Apache.rb +98 -0
  15. data/config/commands/AppleScript.rb +169 -0
  16. data/config/commands/Blogging.rb +72 -0
  17. data/config/commands/Bulletin Board.rb +10 -0
  18. data/config/commands/Bundle Development.rb +83 -0
  19. data/config/commands/C++ Qt.rb +158 -0
  20. data/config/commands/C.rb +82 -0
  21. data/config/commands/CMake.rb +32 -0
  22. data/config/commands/CSS.rb +76 -0
  23. data/config/commands/CTags.rb +29 -0
  24. data/config/commands/CVS.rb +114 -0
  25. data/config/commands/CoffeeScript.rb +58 -0
  26. data/config/commands/Context Free.rb +20 -0
  27. data/config/commands/Cucumber.rb +94 -0
  28. data/config/commands/D.rb +47 -0
  29. data/config/commands/Darcs.rb +72 -0
  30. data/config/commands/Diff.rb +76 -0
  31. data/config/commands/Doxygen.rb +9 -0
  32. data/config/commands/Experimental Wiki.rb +9 -0
  33. data/config/commands/Experimental.rb +172 -0
  34. data/config/commands/F-Script.rb +13 -0
  35. data/config/commands/FXScript.rb +11 -0
  36. data/config/commands/FileMerge.rb +42 -0
  37. data/config/commands/Fortran.rb +58 -0
  38. data/config/commands/GTD2.rb +134 -0
  39. data/config/commands/GTDAlt.rb +225 -0
  40. data/config/commands/GetBundle.rb +41 -0
  41. data/config/commands/Go.rb +29 -0
  42. data/config/commands/Graphviz.rb +11 -0
  43. data/config/commands/Greasemonkey.rb +158 -0
  44. data/config/commands/Gri.rb +11 -0
  45. data/config/commands/Groovy Grails.rb +174 -0
  46. data/config/commands/Groovy.rb +66 -0
  47. data/config/commands/HTML.rb +206 -0
  48. data/config/commands/Haskell.rb +48 -0
  49. data/config/commands/Hotkey.rb +50 -0
  50. data/config/commands/Hyperlink Helper.rb +81 -0
  51. data/config/commands/ImageBrowser.rb +10 -0
  52. data/config/commands/Io.rb +11 -0
  53. data/config/commands/JSFL.rb +29 -0
  54. data/config/commands/JSON.rb +11 -0
  55. data/config/commands/Java.rb +45 -0
  56. data/config/commands/JavaDoc.rb +12 -0
  57. data/config/commands/JavaScript Prototype & Script.aculo.us.rb +51 -0
  58. data/config/commands/JavaScript YUI.rb +12 -0
  59. data/config/commands/JavaScript jQuery.rb +12 -0
  60. data/config/commands/JavaScript.rb +50 -0
  61. data/config/commands/LaTeX.rb +423 -0
  62. data/config/commands/Lisp.rb +20 -0
  63. data/config/commands/Logo.rb +10 -0
  64. data/config/commands/Logtalk.rb +34 -0
  65. data/config/commands/Lua.rb +29 -0
  66. data/config/commands/MEL.rb +20 -0
  67. data/config/commands/Mail.rb +73 -0
  68. data/config/commands/Make.rb +20 -0
  69. data/config/commands/Man Pages.rb +20 -0
  70. data/config/commands/Markdown.rb +194 -0
  71. data/config/commands/Math.rb +79 -0
  72. data/config/commands/Matlab.rb +188 -0
  73. data/config/commands/Maven.rb +162 -0
  74. data/config/commands/Mediawiki.rb +12 -0
  75. data/config/commands/Mercurial.rb +185 -0
  76. data/config/commands/MoinMoin.rb +74 -0
  77. data/config/commands/Movable Type.rb +68 -0
  78. data/config/commands/Nemerle.rb +29 -0
  79. data/config/commands/OCaml Experimental Completions.rb +22 -0
  80. data/config/commands/OCaml.rb +99 -0
  81. data/config/commands/Objective-C.rb +181 -0
  82. data/config/commands/Outlines.rb +54 -0
  83. data/config/commands/PHP Smarty.rb +10 -0
  84. data/config/commands/Pascal.rb +11 -0
  85. data/config/commands/Perforce.rb +102 -0
  86. data/config/commands/Perl.rb +78 -0
  87. data/config/commands/Processing.rb +11 -0
  88. data/config/commands/Prolog.rb +11 -0
  89. data/config/commands/Property List.rb +38 -0
  90. data/config/commands/Python Django.rb +11 -0
  91. data/config/commands/Python.rb +131 -0
  92. data/config/commands/R Console (R.app).rb +80 -0
  93. data/config/commands/R Console (Rdaemon).rb +414 -0
  94. data/config/commands/R.rb +337 -0
  95. data/config/commands/Ragel.rb +10 -0
  96. data/config/commands/Regular Expressions.rb +18 -0
  97. data/config/commands/Remind.rb +44 -0
  98. data/config/commands/Ruby RSpec.rb +40 -0
  99. data/config/commands/Ruby on Rails.rb +331 -0
  100. data/config/commands/Ruby.rb +220 -0
  101. data/config/commands/S5 Slide Show.rb +37 -0
  102. data/config/commands/SCons.rb +24 -0
  103. data/config/commands/SQL.rb +60 -0
  104. data/config/commands/SVK.rb +83 -0
  105. data/config/commands/SWeave.rb +63 -0
  106. data/config/commands/Scheme.rb +30 -0
  107. data/config/commands/Scilab.rb +28 -0
  108. data/config/commands/Setext.rb +20 -0
  109. data/config/commands/Shell Script.rb +59 -0
  110. data/config/commands/Slate.rb +9 -0
  111. data/config/commands/Source.rb +84 -0
  112. data/config/commands/Standard ML.rb +38 -0
  113. data/config/commands/Subversion.rb +181 -0
  114. data/config/commands/TODO.rb +32 -0
  115. data/config/commands/Tcl.rb +21 -0
  116. data/config/commands/TerminalMate.rb +30 -0
  117. data/config/commands/Text.rb +137 -0
  118. data/config/commands/TextMate.rb +100 -0
  119. data/config/commands/Textile.rb +58 -0
  120. data/config/commands/Thrift.rb +20 -0
  121. data/config/commands/Transmit.rb +34 -0
  122. data/config/commands/Txt2tags.rb +213 -0
  123. data/config/commands/Vectorscript.rb +19 -0
  124. data/config/commands/Widget Creator.rb +23 -0
  125. data/config/commands/XML.rb +29 -0
  126. data/config/commands/Xcode.rb +106 -0
  127. data/config/commands/YAML.rb +39 -0
  128. data/config/commands/YARD.rb +12 -0
  129. data/config/commands/iTerm.rb +26 -0
  130. data/config/commands/reStructuredText.rb +126 -0
  131. data/config/detect.rb +13 -1
  132. data/config/keymap/diakonos.rb +113 -115
  133. data/config/keymap/emacs.rb +6 -2
  134. data/config/keymap/nano.rb +104 -112
  135. data/config/keymap/vim.rb +329 -258
  136. data/config/plugin/autosave.rb +3 -6
  137. data/config/plugin/git.rb +18 -12
  138. data/config/plugin/soma.rb +1 -1
  139. data/config/preferences/Apache.rb +17 -17
  140. data/config/preferences/AppleScript.rb +5 -5
  141. data/config/preferences/Bundle Development.rb +10 -10
  142. data/config/preferences/C.rb +38 -30
  143. data/config/preferences/CoffeeScript.rb +28 -0
  144. data/config/preferences/ColdFusion.rb +6 -6
  145. data/config/preferences/Cucumber.rb +40 -0
  146. data/config/preferences/Diff.rb +4 -4
  147. data/config/preferences/Eiffel.rb +6 -6
  148. data/config/preferences/Erlang.rb +16 -16
  149. data/config/preferences/F-Script.rb +12 -12
  150. data/config/preferences/FXScript.rb +5 -5
  151. data/config/preferences/Fortran.rb +17 -17
  152. data/config/preferences/Go.rb +23 -0
  153. data/config/preferences/Groovy.rb +29 -0
  154. data/config/preferences/HTML.rb +44 -44
  155. data/config/preferences/Haskell.rb +14 -14
  156. data/config/preferences/Io.rb +11 -11
  157. data/config/preferences/Java.rb +8 -8
  158. data/config/preferences/LaTeX.rb +24 -24
  159. data/config/preferences/Logo.rb +6 -6
  160. data/config/preferences/Logtalk.rb +5 -5
  161. data/config/preferences/Markdown.rb +43 -0
  162. data/config/preferences/Maven.rb +42 -42
  163. data/config/preferences/Mediawiki.rb +8 -8
  164. data/config/preferences/Movable Type.rb +14 -14
  165. data/config/preferences/OCaml.rb +15 -15
  166. data/config/preferences/Objective-C.rb +5 -5
  167. data/config/preferences/PHP.rb +2564 -0
  168. data/config/preferences/Property List.rb +8 -8
  169. data/config/preferences/R.rb +5 -5
  170. data/config/preferences/Ruby.rb +24 -24
  171. data/config/preferences/Source.rb +13 -13
  172. data/config/preferences/Standard ML.rb +9 -9
  173. data/config/preferences/Tcl.rb +5 -5
  174. data/config/preferences/Text.rb +14 -14
  175. data/config/preferences/TextMate.rb +5 -5
  176. data/config/preferences/Textile.rb +8 -8
  177. data/config/preferences/YARD.rb +9 -0
  178. data/config/preferences/iTerm.rb +9 -9
  179. data/config/rc.rb +5 -2
  180. data/config/snippets/ASP vb.NET.rb +203 -54
  181. data/config/snippets/ASP.rb +51 -36
  182. data/config/snippets/ActionScript.rb +332 -205
  183. data/config/snippets/Active4D.rb +325 -256
  184. data/config/snippets/Ada.rb +106 -60
  185. data/config/snippets/Ant.rb +7 -5
  186. data/config/snippets/Apache.rb +24 -20
  187. data/config/snippets/AppleScript.rb +213 -82
  188. data/config/snippets/Blogging.rb +41 -18
  189. data/config/snippets/Bulletin Board.rb +56 -21
  190. data/config/snippets/Bundle Development.rb +108 -63
  191. data/config/snippets/C++ Qt.rb +72 -57
  192. data/config/snippets/C.rb +128 -100
  193. data/config/snippets/CMake.rb +42 -32
  194. data/config/snippets/CSS.rb +515 -115
  195. data/config/snippets/CoffeeScript.rb +85 -0
  196. data/config/snippets/ColdFusion.rb +2228 -1547
  197. data/config/snippets/Context Free.rb +35 -28
  198. data/config/snippets/Cucumber.rb +55 -0
  199. data/config/snippets/D.rb +164 -111
  200. data/config/snippets/DokuWiki.rb +103 -54
  201. data/config/snippets/Doxygen.rb +87 -40
  202. data/config/snippets/Eiffel.rb +121 -18
  203. data/config/snippets/Erlang.rb +109 -68
  204. data/config/snippets/F-Script.rb +30 -24
  205. data/config/snippets/FXScript.rb +364 -210
  206. data/config/snippets/Fortran.rb +462 -280
  207. data/config/snippets/GTDAlt.rb +10 -4
  208. data/config/snippets/Gettext.rb +10 -8
  209. data/config/snippets/Go.rb +52 -0
  210. data/config/snippets/Greasemonkey.rb +52 -42
  211. data/config/snippets/Gri.rb +12 -10
  212. data/config/snippets/Groovy Grails.rb +313 -0
  213. data/config/snippets/Groovy.rb +685 -0
  214. data/config/snippets/HTML.rb +325 -126
  215. data/config/snippets/Haskell.rb +32 -24
  216. data/config/snippets/Io.rb +53 -42
  217. data/config/snippets/Java.rb +204 -92
  218. data/config/snippets/JavaDoc.rb +105 -56
  219. data/config/snippets/JavaScript MooTools.rb +208 -13
  220. data/config/snippets/JavaScript Objective-J.rb +18 -15
  221. data/config/snippets/JavaScript Prototype & Script.aculo.us.rb +362 -107
  222. data/config/snippets/JavaScript YUI.rb +1245 -186
  223. data/config/snippets/JavaScript jQuery.rb +693 -375
  224. data/config/snippets/JavaScript.rb +71 -53
  225. data/config/snippets/LaTeX.rb +188 -0
  226. data/config/snippets/Lisp.rb +59 -40
  227. data/config/snippets/Logo.rb +12 -6
  228. data/config/snippets/Logtalk.rb +131 -60
  229. data/config/snippets/Lua.rb +43 -33
  230. data/config/snippets/MIPS Assembler.rb +7 -5
  231. data/config/snippets/Mail.rb +10 -1
  232. data/config/snippets/Markdown.rb +7 -0
  233. data/config/snippets/Matlab.rb +232 -178
  234. data/config/snippets/Maven.rb +6 -5
  235. data/config/snippets/Mediawiki.rb +43 -12
  236. data/config/snippets/MoinMoin.rb +50 -10
  237. data/config/snippets/Movable Type.rb +368 -53
  238. data/config/snippets/Nemerle.rb +127 -79
  239. data/config/snippets/OCaml Code Completion Misc.rb +1716 -72
  240. data/config/snippets/OCaml Code Completion Unix.rb +2128 -203
  241. data/config/snippets/OCaml.rb +107 -73
  242. data/config/snippets/ODCompletion.rb +169 -118
  243. data/config/snippets/Objective-C.rb +281 -193
  244. data/config/snippets/PHP Smarty.rb +149 -79
  245. data/config/snippets/PHP.rb +186 -0
  246. data/config/snippets/Pascal.rb +47 -33
  247. data/config/snippets/Perl HTML-Template.rb +33 -0
  248. data/config/snippets/Perl Mason.rb +50 -30
  249. data/config/snippets/Perl Template Toolkit.rb +25 -20
  250. data/config/snippets/Perl.rb +91 -72
  251. data/config/snippets/Processing.rb +55 -33
  252. data/config/snippets/Propel.rb +36 -30
  253. data/config/snippets/Property List.rb +57 -24
  254. data/config/snippets/Python Django Templates.rb +381 -95
  255. data/config/snippets/Python Django.rb +159 -132
  256. data/config/snippets/Python.rb +88 -0
  257. data/config/snippets/R Console (Rdaemon).rb +11 -9
  258. data/config/snippets/R.rb +96 -77
  259. data/config/snippets/Remind.rb +18 -15
  260. data/config/snippets/Ruby RSpec.rb +343 -238
  261. data/config/snippets/Ruby on Rails.rb +1116 -765
  262. data/config/snippets/Ruby.rb +770 -545
  263. data/config/snippets/S5 Slide Show.rb +32 -24
  264. data/config/snippets/SSH Config.rb +21 -17
  265. data/config/snippets/SWIG.rb +30 -18
  266. data/config/snippets/Scilab.rb +98 -79
  267. data/config/snippets/Setext.rb +10 -8
  268. data/config/snippets/Shell Script.rb +52 -42
  269. data/config/snippets/Slate.rb +62 -48
  270. data/config/snippets/Source.rb +24 -1
  271. data/config/snippets/Standard ML.rb +37 -27
  272. data/config/snippets/Tcl.rb +32 -26
  273. data/config/snippets/Text.rb +28 -15
  274. data/config/snippets/Textile.rb +130 -45
  275. data/config/snippets/Thrift.rb +22 -18
  276. data/config/snippets/Twiki.rb +158 -105
  277. data/config/snippets/Txt2tags.rb +166 -79
  278. data/config/snippets/Vectorscript.rb +47 -38
  279. data/config/snippets/Widget Creator.rb +5 -5
  280. data/config/snippets/XML.rb +30 -18
  281. data/config/snippets/YAML.rb +5 -4
  282. data/config/snippets/YARD.rb +93 -0
  283. data/config/snippets/reStructuredText.rb +25 -20
  284. data/config/syntax/ANTLR.rb +17 -15
  285. data/config/syntax/ASP vb.NET.rb +27 -24
  286. data/config/syntax/ASP.rb +21 -19
  287. data/config/syntax/ActionScript.rb +16 -16
  288. data/config/syntax/Active4D Config.rb +5 -5
  289. data/config/syntax/Active4D Library.rb +2 -2
  290. data/config/syntax/Active4D.rb +32 -30
  291. data/config/syntax/Ada.rb +13 -10
  292. data/config/syntax/Ant.rb +9 -7
  293. data/config/syntax/Apache.rb +22 -18
  294. data/config/syntax/AppleScript.rb +486 -192
  295. data/config/syntax/AsciiDoc.rb +21 -0
  296. data/config/syntax/BibTeX.rb +7 -7
  297. data/config/syntax/Blog - HTML.rb +7 -7
  298. data/config/syntax/Blog - Markdown.rb +6 -6
  299. data/config/syntax/Blog - Text.rb +2 -2
  300. data/config/syntax/Blog - Textile.rb +2 -2
  301. data/config/syntax/Bulletin Board.rb +33 -32
  302. data/config/syntax/C++ Qt.rb +7 -6
  303. data/config/syntax/C++.rb +31 -28
  304. data/config/syntax/C.rb +55 -51
  305. data/config/syntax/CMake Listfile.rb +12 -11
  306. data/config/syntax/CSS.rb +24 -23
  307. data/config/syntax/CSV.rb +3 -3
  308. data/config/syntax/CoffeeScript.rb +161 -0
  309. data/config/syntax/ColdFusion.rb +8 -8
  310. data/config/syntax/Context Free.rb +18 -16
  311. data/config/syntax/Cucumber Steps.rb +108 -0
  312. data/config/syntax/D.rb +70 -69
  313. data/config/syntax/Diff.rb +13 -10
  314. data/config/syntax/DokuWiki.rb +22 -18
  315. data/config/syntax/Doxygen.rb +1 -1
  316. data/config/syntax/Dylan.rb +8 -8
  317. data/config/syntax/Eiffel.rb +12 -12
  318. data/config/syntax/Erlang.rb +96 -89
  319. data/config/syntax/F-Script.rb +11 -9
  320. data/config/syntax/FXScript.rb +16 -14
  321. data/config/syntax/Fortran - Modern.rb +25 -24
  322. data/config/syntax/Fortran - Punchcard.rb +43 -40
  323. data/config/syntax/GTD.rb +1 -1
  324. data/config/syntax/GTDalt.rb +14 -11
  325. data/config/syntax/Gettext.rb +10 -9
  326. data/config/syntax/Gherkin.rb +65 -0
  327. data/config/syntax/Go.rb +256 -0
  328. data/config/syntax/Grails Server Page.rb +108 -0
  329. data/config/syntax/Graphviz (DOT).rb +6 -6
  330. data/config/syntax/Greasemonkey.rb +3 -3
  331. data/config/syntax/Gri.rb +12 -12
  332. data/config/syntax/Groovy.rb +502 -0
  333. data/config/syntax/HTML (ASP).rb +3 -3
  334. data/config/syntax/HTML (ASP.net).rb +31 -31
  335. data/config/syntax/HTML (Active4D).rb +19 -19
  336. data/config/syntax/HTML (Django).rb +6 -6
  337. data/config/syntax/HTML (Erlang).rb +4 -4
  338. data/config/syntax/HTML (Mason).rb +13 -13
  339. data/config/syntax/HTML (Rails).rb +5 -5
  340. data/config/syntax/HTML (Tcl).rb +3 -3
  341. data/config/syntax/HTML (Template Toolkit).rb +9 -9
  342. data/config/syntax/HTML.rb +27 -27
  343. data/config/syntax/Haskell.rb +31 -28
  344. data/config/syntax/Inform.rb +5 -5
  345. data/config/syntax/Ini.rb +4 -4
  346. data/config/syntax/Installer Distribution Script.rb +19 -18
  347. data/config/syntax/Io.rb +17 -15
  348. data/config/syntax/JSFL.rb +7 -6
  349. data/config/syntax/Java Properties.rb +3 -3
  350. data/config/syntax/Java Server Page (JSP).rb +5 -4
  351. data/config/syntax/Java.rb +40 -33
  352. data/config/syntax/JavaDoc.rb +24 -22
  353. data/config/syntax/JavaScript (Rails).rb +1 -1
  354. data/config/syntax/JavaScript.rb +41 -34
  355. data/config/syntax/Javascript YUI.rb +109 -101
  356. data/config/syntax/LaTeX Beamer.rb +3 -3
  357. data/config/syntax/LaTeX Log.rb +3 -3
  358. data/config/syntax/LaTeX Memoir.rb +7 -5
  359. data/config/syntax/LaTeX Rdaemon.rb +1 -1
  360. data/config/syntax/LaTeX.rb +52 -47
  361. data/config/syntax/Language Grammar.rb +58 -55
  362. data/config/syntax/Lex-Flex.rb +13 -13
  363. data/config/syntax/Lighttpd.rb +7 -7
  364. data/config/syntax/Lisp.rb +6 -5
  365. data/config/syntax/Literate Haskell.rb +2 -2
  366. data/config/syntax/Logo.rb +4 -4
  367. data/config/syntax/Logtalk.rb +64 -49
  368. data/config/syntax/Lua.rb +12 -12
  369. data/config/syntax/MATLAB.rb +71 -70
  370. data/config/syntax/MEL.rb +16 -15
  371. data/config/syntax/MIPS Assembler.rb +11 -11
  372. data/config/syntax/MacPorts Portfile.rb +16 -15
  373. data/config/syntax/Mail.rb +5 -4
  374. data/config/syntax/Makefile.rb +3 -3
  375. data/config/syntax/Man.rb +2 -2
  376. data/config/syntax/Markdown.rb +440 -0
  377. data/config/syntax/Maven POM.rb +17 -16
  378. data/config/syntax/Mediawiki.rb +46 -46
  379. data/config/syntax/Modula-3.rb +7 -6
  380. data/config/syntax/MoinMoin.rb +16 -16
  381. data/config/syntax/MooTools.rb +75 -65
  382. data/config/syntax/Movable Type (MT only).rb +18 -18
  383. data/config/syntax/Movable Type.rb +20 -20
  384. data/config/syntax/MultiMarkdown.rb +35 -0
  385. data/config/syntax/Nemerle.rb +12 -12
  386. data/config/syntax/OCaml.rb +79 -71
  387. data/config/syntax/OCamllex.rb +14 -14
  388. data/config/syntax/OCamlyacc.rb +14 -12
  389. data/config/syntax/Objective-C++.rb +2 -2
  390. data/config/syntax/Objective-C.rb +76 -70
  391. data/config/syntax/Objective-J.rb +30 -29
  392. data/config/syntax/Octave.rb +27 -27
  393. data/config/syntax/OpenGL.rb +4 -4
  394. data/config/syntax/PHP.rb +1154 -0
  395. data/config/syntax/Pascal.rb +8 -8
  396. data/config/syntax/Perl HTML-Template.rb +5 -5
  397. data/config/syntax/Perl.rb +80 -76
  398. data/config/syntax/Plain Text.rb +5 -5
  399. data/config/syntax/Postscript.rb +6 -6
  400. data/config/syntax/Processing.rb +20 -20
  401. data/config/syntax/Prolog.rb +2 -2
  402. data/config/syntax/Property List.rb +50 -47
  403. data/config/syntax/Prototype & Script.aculo.us (JavaScript) Bracketed.rb +15 -13
  404. data/config/syntax/Prototype & Script.aculo.us (JavaScript).rb +9 -8
  405. data/config/syntax/Python Django.rb +6 -6
  406. data/config/syntax/Python.rb +94 -87
  407. data/config/syntax/Quake Style .cfg.rb +4 -4
  408. data/config/syntax/R Console (Rdaemon) Plain.rb +2 -2
  409. data/config/syntax/R Console (Rdaemon).rb +2 -2
  410. data/config/syntax/R.rb +21 -20
  411. data/config/syntax/RSpec.rb +15 -15
  412. data/config/syntax/Ragel.rb +14 -13
  413. data/config/syntax/Rd (R Documentation).rb +4 -4
  414. data/config/syntax/Regular Expressions (Oniguruma).rb +11 -10
  415. data/config/syntax/Regular Expressions (Python).rb +9 -9
  416. data/config/syntax/Release Notes.rb +7 -6
  417. data/config/syntax/Remind.rb +19 -17
  418. data/config/syntax/Rez.rb +10 -9
  419. data/config/syntax/Ruby Haml.rb +11 -11
  420. data/config/syntax/Ruby on Rails.rb +26 -24
  421. data/config/syntax/Ruby.rb +73 -71
  422. data/config/syntax/S5 Slide Show.rb +9 -9
  423. data/config/syntax/SQL.rb +29 -27
  424. data/config/syntax/SSH Config.rb +4 -4
  425. data/config/syntax/SWIG.rb +12 -11
  426. data/config/syntax/SWeave.rb +8 -7
  427. data/config/syntax/Scheme.rb +56 -54
  428. data/config/syntax/Scilab.rb +7 -6
  429. data/config/syntax/Setext.rb +14 -13
  430. data/config/syntax/Shell Script (Bash).rb +42 -42
  431. data/config/syntax/Slate.rb +24 -19
  432. data/config/syntax/Smarty.rb +11 -10
  433. data/config/syntax/Standard ML - CM.rb +2 -2
  434. data/config/syntax/Standard ML.rb +26 -23
  435. data/config/syntax/Strings File.rb +6 -6
  436. data/config/syntax/TSV.rb +2 -2
  437. data/config/syntax/Tcl.rb +10 -9
  438. data/config/syntax/TeX Math.rb +7 -6
  439. data/config/syntax/TeX.rb +7 -7
  440. data/config/syntax/Textile.rb +33 -27
  441. data/config/syntax/Thrift.rb +37 -29
  442. data/config/syntax/Twiki.rb +19 -18
  443. data/config/syntax/Txt2tags.rb +26 -23
  444. data/config/syntax/Vectorscript.rb +9 -7
  445. data/config/syntax/XML strict.rb +6 -4
  446. data/config/syntax/XML.rb +55 -30
  447. data/config/syntax/XSL.rb +5 -5
  448. data/config/syntax/YAML.rb +14 -12
  449. data/config/syntax/camlp4.rb +5 -5
  450. data/config/syntax/iCalendar.rb +3 -3
  451. data/config/syntax/jQuery (JavaScript).rb +9 -9
  452. data/config/syntax/mod_perl.rb +6 -6
  453. data/config/syntax/qmake Project file.rb +16 -15
  454. data/config/syntax/reStructuredText.rb +23 -21
  455. data/config/syntax/svn-commit.tmp.rb +5 -5
  456. data/lib/ver.rb +169 -85
  457. data/lib/ver/action.rb +39 -30
  458. data/lib/ver/buffer.rb +962 -144
  459. data/lib/ver/buffer/frame.rb +23 -0
  460. data/lib/ver/buffer/invalid_trailing_whitespace.rb +17 -0
  461. data/lib/ver/buffer/markup_underline_link.rb +30 -0
  462. data/lib/ver/buffer/matching_brace.rb +22 -0
  463. data/lib/ver/buffer/term.rb +1 -1
  464. data/lib/ver/clipboard.rb +107 -0
  465. data/lib/ver/digraphs.rb +1373 -0
  466. data/lib/ver/entry.rb +54 -43
  467. data/lib/ver/event.rb +335 -0
  468. data/lib/ver/exception_view.rb +3 -1
  469. data/lib/ver/executor.rb +7 -7
  470. data/lib/ver/executor/buffer.rb +4 -4
  471. data/lib/ver/executor/encoding.rb +19 -0
  472. data/lib/ver/executor/entry.rb +9 -9
  473. data/lib/ver/executor/fuzzy_file_finder.rb +1 -1
  474. data/lib/ver/executor/label.rb +2 -0
  475. data/lib/ver/executor/method.rb +2 -3
  476. data/lib/ver/help/describe_key.rb +44 -44
  477. data/lib/ver/hover_completion.rb +11 -6
  478. data/lib/ver/keymap.rb +68 -39
  479. data/lib/ver/layout/paned.rb +56 -44
  480. data/lib/ver/layout/toplevel.rb +68 -0
  481. data/lib/ver/layout/vim.rb +919 -0
  482. data/lib/ver/major_mode.rb +49 -49
  483. data/lib/ver/methods.rb +22 -25
  484. data/lib/ver/methods/basic.rb +49 -20
  485. data/lib/ver/methods/bookmark.rb +33 -33
  486. data/lib/ver/methods/clipboard.rb +186 -49
  487. data/lib/ver/methods/completion.rb +5 -5
  488. data/lib/ver/methods/control.rb +47 -66
  489. data/lib/ver/methods/delete.rb +5 -122
  490. data/lib/ver/methods/help.rb +2 -2
  491. data/lib/ver/methods/insert.rb +101 -29
  492. data/lib/ver/methods/layout.rb +62 -64
  493. data/lib/ver/methods/macro.rb +45 -0
  494. data/lib/ver/methods/move.rb +63 -349
  495. data/lib/ver/methods/nano.rb +99 -71
  496. data/lib/ver/methods/open.rb +8 -7
  497. data/lib/ver/methods/preview.rb +34 -14
  498. data/lib/ver/methods/save.rb +194 -163
  499. data/lib/ver/methods/search.rb +169 -81
  500. data/lib/ver/methods/search_and_replace.rb +62 -49
  501. data/lib/ver/methods/selection.rb +26 -54
  502. data/lib/ver/methods/snippet.rb +79 -54
  503. data/lib/ver/methods/undo.rb +12 -16
  504. data/lib/ver/minibuffer.rb +283 -134
  505. data/lib/ver/minor_mode.rb +36 -47
  506. data/lib/ver/mode_resolving.rb +71 -0
  507. data/lib/ver/platform.rb +41 -0
  508. data/lib/ver/plist.rb +16 -4
  509. data/lib/ver/register.rb +86 -0
  510. data/lib/ver/status.rb +44 -6
  511. data/lib/ver/status/battery.rb +1 -1
  512. data/lib/ver/status/buffer_position.rb +2 -2
  513. data/lib/ver/status/diakonos_position.rb +3 -3
  514. data/lib/ver/status/encoding.rb +1 -1
  515. data/lib/ver/status/filename.rb +1 -1
  516. data/lib/ver/status/label.rb +20 -20
  517. data/lib/ver/status/mode.rb +1 -1
  518. data/lib/ver/status/nano_help.rb +3 -14
  519. data/lib/ver/status/nano_position.rb +6 -6
  520. data/lib/ver/status/percent.rb +2 -2
  521. data/lib/ver/status/position.rb +2 -2
  522. data/lib/ver/status/short_filename.rb +1 -1
  523. data/lib/ver/status/syntax.rb +1 -1
  524. data/lib/ver/struct.rb +28 -0
  525. data/lib/ver/syntax/processor.rb +2 -1
  526. data/lib/ver/text.rb +48 -520
  527. data/lib/ver/text/end.rb +14 -0
  528. data/lib/ver/text/index.rb +16 -101
  529. data/lib/ver/text/insert.rb +138 -0
  530. data/lib/ver/text/mark.rb +559 -0
  531. data/lib/ver/text/position.rb +240 -0
  532. data/lib/ver/text/range.rb +74 -0
  533. data/lib/ver/text/selection.rb +402 -0
  534. data/lib/ver/text/selection/block.rb +69 -0
  535. data/lib/ver/text/selection/char.rb +93 -0
  536. data/lib/ver/text/selection/line.rb +64 -0
  537. data/lib/ver/text/tag.rb +322 -0
  538. data/lib/ver/undo.rb +109 -34
  539. data/lib/ver/vendor/eval_completer.rb +184 -0
  540. data/lib/ver/vendor/json_store.rb +23 -0
  541. data/lib/ver/vendor/open3.rb +729 -0
  542. data/lib/ver/vendor/pathname.rb +73 -0
  543. data/lib/ver/vendor/textpow.rb +1 -1
  544. data/lib/ver/version.rb +1 -1
  545. data/lib/ver/widget_event.rb +9 -5
  546. data/lib/ver/widget_major_mode.rb +69 -23
  547. data/spec/helper.rb +124 -8
  548. data/spec/ver/action.rb +160 -46
  549. data/spec/ver/buffer.rb +23 -0
  550. data/spec/ver/clipboard.rb +92 -0
  551. data/spec/ver/keymap.rb +63 -61
  552. data/spec/ver/keymap/diakonos.rb +88 -0
  553. data/spec/ver/keymap/emacs.rb +65 -0
  554. data/spec/ver/keymap/general.rb +98 -0
  555. data/spec/ver/keymap/nano.rb +84 -0
  556. data/spec/ver/keymap/vim.rb +205 -0
  557. data/spec/ver/keymap/vim/changing_text.rb +489 -0
  558. data/spec/ver/keymap/vim/complex_changes.rb +53 -0
  559. data/spec/ver/keymap/vim/copying_and_moving_text.rb +258 -0
  560. data/spec/ver/keymap/vim/deleting_text.rb +188 -0
  561. data/spec/ver/keymap/vim/digraphs.rb +52 -0
  562. data/spec/ver/keymap/vim/external_commands.rb +21 -0
  563. data/spec/ver/keymap/vim/inserting_mode_keys.rb +115 -0
  564. data/spec/ver/keymap/vim/inserting_mode_special.rb +168 -0
  565. data/spec/ver/keymap/vim/inserting_text.rb +108 -0
  566. data/spec/ver/keymap/vim/left_right_motion.rb +120 -0
  567. data/spec/ver/keymap/vim/mark_motion.rb +73 -0
  568. data/spec/ver/keymap/vim/repeating_commands.rb +64 -0
  569. data/spec/ver/keymap/vim/text_object_motion.rb +137 -0
  570. data/spec/ver/keymap/vim/text_objects.rb +101 -0
  571. data/spec/ver/keymap/vim/undo_redo.rb +21 -0
  572. data/spec/ver/keymap/vim/up_down_motion.rb +94 -0
  573. data/spec/ver/keymap/vim/various_motion.rb +33 -0
  574. data/spec/ver/keysyms.rb +13 -0
  575. data/spec/ver/major_mode.rb +37 -37
  576. data/spec/ver/minor_mode.rb +21 -20
  577. data/spec/ver/plugin/smart_autoindent.rb +2 -2
  578. data/spec/ver/text/index.rb +122 -0
  579. data/spec/ver/text/insert.rb +299 -0
  580. data/spec/ver/text/mark.rb +94 -0
  581. data/spec/ver/text/range.rb +71 -0
  582. data/spec/ver/text/selection.rb +315 -0
  583. data/spec/ver/text/tag.rb +93 -0
  584. data/spec/ver/undo.rb +133 -0
  585. data/spec/ver/undo/record_sanitize.rb +85 -0
  586. data/spec/ver/vendor/eval_completer.rb +91 -0
  587. data/spec/ver/widget_major_mode.rb +4 -3
  588. data/ver.gemspec +8 -8
  589. metadata +234 -72
  590. data/.todo +0 -102
  591. data/ROADMAP.textile +0 -187
  592. data/config/snippets/ANTLR.rb +0 -3
  593. data/config/snippets/Bison.rb +0 -3
  594. data/config/snippets/CTags.rb +0 -3
  595. data/config/snippets/CVS.rb +0 -3
  596. data/config/snippets/Darcs.rb +0 -3
  597. data/config/snippets/Diff.rb +0 -3
  598. data/config/snippets/Dylan.rb +0 -3
  599. data/config/snippets/Experimental Wiki.rb +0 -3
  600. data/config/snippets/Experimental.rb +0 -3
  601. data/config/snippets/FileMerge.rb +0 -3
  602. data/config/snippets/GTD2.rb +0 -3
  603. data/config/snippets/GetBundle.rb +0 -3
  604. data/config/snippets/Graphviz.rb +0 -3
  605. data/config/snippets/Hotkey.rb +0 -3
  606. data/config/snippets/Hyperlink Helper.rb +0 -3
  607. data/config/snippets/ImageBrowser.rb +0 -3
  608. data/config/snippets/Inform.rb +0 -3
  609. data/config/snippets/Ini.rb +0 -3
  610. data/config/snippets/Installer.rb +0 -3
  611. data/config/snippets/JSFL.rb +0 -3
  612. data/config/snippets/JSON.rb +0 -3
  613. data/config/snippets/Lex-Flex.rb +0 -3
  614. data/config/snippets/Lighttpd.rb +0 -3
  615. data/config/snippets/MEL.rb +0 -3
  616. data/config/snippets/MacPorts.rb +0 -3
  617. data/config/snippets/Make.rb +0 -3
  618. data/config/snippets/Man Pages.rb +0 -3
  619. data/config/snippets/Math.rb +0 -3
  620. data/config/snippets/Mercurial.rb +0 -3
  621. data/config/snippets/Modula.rb +0 -3
  622. data/config/snippets/Navigation.rb +0 -3
  623. data/config/snippets/OCaml Experimental Completions.rb +0 -3
  624. data/config/snippets/OpenGL.rb +0 -3
  625. data/config/snippets/Outlines.rb +0 -3
  626. data/config/snippets/Perforce.rb +0 -3
  627. data/config/snippets/Perl HTML::Template.rb +0 -27
  628. data/config/snippets/Postscript.rb +0 -3
  629. data/config/snippets/Prolog.rb +0 -3
  630. data/config/snippets/Quake.rb +0 -3
  631. data/config/snippets/R Console (R.app).rb +0 -3
  632. data/config/snippets/Ragel.rb +0 -3
  633. data/config/snippets/Regular Expressions.rb +0 -3
  634. data/config/snippets/Rez.rb +0 -3
  635. data/config/snippets/Ruby Haml.rb +0 -3
  636. data/config/snippets/SCons.rb +0 -3
  637. data/config/snippets/SQL.rb +0 -3
  638. data/config/snippets/SVK.rb +0 -3
  639. data/config/snippets/SWeave.rb +0 -3
  640. data/config/snippets/Scheme.rb +0 -3
  641. data/config/snippets/Subversion.rb +0 -3
  642. data/config/snippets/TODO.rb +0 -3
  643. data/config/snippets/Tabular.rb +0 -3
  644. data/config/snippets/TerminalMate.rb +0 -3
  645. data/config/snippets/TextMate.rb +0 -3
  646. data/config/snippets/Transmit.rb +0 -3
  647. data/config/snippets/Xcode.rb +0 -3
  648. data/config/snippets/iCalendar.rb +0 -3
  649. data/config/snippets/iTerm.rb +0 -3
  650. data/lib/ver/keysyms.rb +0 -104
  651. data/spec/ver/methods/move.rb +0 -150
@@ -24,7 +24,12 @@ module VER
24
24
  # together.
25
25
  # It would also be handy if these operations could be identified
26
26
  # automagically (like multiple operations within one record block).
27
- class Tree < Struct.new(:widget, :applied, :pending)
27
+ class Tree < Struct.new(:widget, :applied, :pending, :stack, :recording)
28
+ def initialize(widget)
29
+ self.widget = widget
30
+ self.stack = []
31
+ end
32
+
28
33
  def record_multi
29
34
  AutoSeparator.new self do |auto_separator|
30
35
  yield auto_separator
@@ -34,17 +39,27 @@ module VER
34
39
  end
35
40
 
36
41
  def record
37
- current = Record.new(widget, applied)
42
+ if recording
43
+ stack << Proc.new
44
+ else
45
+ self.recording = true
46
+ current = Record.new(self, widget, applied)
38
47
 
39
- yield current
48
+ yield current
40
49
 
41
- applied.next = current if applied = self.applied
50
+ applied.next = current if applied = self.applied
42
51
 
43
- self.applied = current
44
- self.applied = current
45
- self.pending = nil
52
+ self.applied = current
53
+ self.applied = current
54
+ self.pending = nil
46
55
 
47
- compact!
56
+ compact!
57
+ self.recording = false
58
+
59
+ if pending = stack.shift
60
+ record(&pending)
61
+ end
62
+ end
48
63
  end
49
64
 
50
65
  # Undo last applied change so it becomes the next pending change.
@@ -142,11 +157,11 @@ module VER
142
157
  #
143
158
  # The applied property indicates whether or not this change has been applied
144
159
  # already.
145
- class Record < Struct.new(:widget, :parent, :ctime, :childs, :applied,
146
- :undo_info, :redo_info, :separator)
160
+ class Record < Struct.new(:tree, :widget, :parent, :ctime, :childs,
161
+ :applied, :undo_info, :redo_info, :separator)
147
162
 
148
- def initialize(widget, parent = nil)
149
- self.widget, self.parent = widget, parent
163
+ def initialize(tree, widget, parent = nil)
164
+ self.tree, self.widget, self.parent = tree, widget, parent
150
165
  self.ctime = Time.now
151
166
  self.childs = []
152
167
  self.applied = false
@@ -157,38 +172,50 @@ module VER
157
172
  pos = index(pos)
158
173
 
159
174
  widget.execute_only(:insert, pos, string, tag)
160
- widget.touch!(pos.linestart, (pos + string.size).lineend)
175
+ widget.touch!(pos, "#{pos} + #{string.size} chars")
161
176
 
162
177
  self.redo_info = [:insert, pos, string, tag]
163
- self.undo_info = [pos, pos + string.size, '']
178
+ self.undo_info = [pos, index("#{pos} + #{string.size} chars"), '']
164
179
  self.applied = true
165
180
  pos
166
181
  end
167
182
 
168
- def replace(from, to, string)
183
+ def replace(from, to, string, tag = Tk::None)
169
184
  from, to = indices(from, to)
170
185
 
171
186
  data = widget.get(from, to)
172
- widget.execute_only(:replace, from, to, string)
173
- widget.touch!(from.linestart, to.lineend)
187
+ widget.execute_only(:replace, from, to, string, tag)
188
+ widget.touch!(from, to)
174
189
 
175
- self.redo_info = [:replace, from, to, string]
176
- self.undo_info = [from, from + string.size, data]
190
+ self.redo_info = [:replace, from, to, string, tag]
191
+ self.undo_info = [from, index("#{from} + #{string.size} chars"), data]
177
192
  self.applied = true
178
193
  from
179
194
  end
180
195
 
181
- def delete(from, to)
182
- from, to = indices(from, to)
183
-
184
- data = widget.get(from, to)
185
- widget.execute_only(:delete, from, to)
186
- widget.touch!(from.linestart, to.lineend)
187
-
188
- self.redo_info = [:delete, from, to]
189
- self.undo_info = [from, from, data]
190
- self.applied = true
191
- from
196
+ def delete(*indices)
197
+ case indices.size
198
+ when 0
199
+ return
200
+ when 1 # pad to two
201
+ index = index(*indices)
202
+ delete(index, index + '1 chars')
203
+ when 2
204
+ first, last = indices(*indices)
205
+
206
+ data = widget.get(first, last)
207
+ widget.execute_only(:delete, first, last)
208
+ widget.touch!(first, last)
209
+
210
+ self.redo_info = [:delete, first, last]
211
+ self.undo_info = [first, first, data]
212
+ self.applied = true
213
+ first
214
+ else # sanitize and chunk into deletes
215
+ sanitize(*indices).map{|first, last|
216
+ tree.record{|rec| rec.delete(first, last) }
217
+ }.last
218
+ end
192
219
  end
193
220
 
194
221
  def undo
@@ -196,7 +223,7 @@ module VER
196
223
 
197
224
  from, to, string = undo_info
198
225
  widget.execute_only(:replace, from, to, string)
199
- widget.touch!(from.linestart, to.lineend)
226
+ widget.touch!(from, to)
200
227
  widget.mark_set(:insert, from)
201
228
 
202
229
  self.applied = false
@@ -228,7 +255,7 @@ module VER
228
255
 
229
256
  # the records have to be consecutive so they can still be applied by a
230
257
  # single undo/redo
231
- consecutive = (predo_pos + predo_string.size) == sredo_pos
258
+ consecutive = index("#{predo_pos} + #{predo_string.size} chars") == sredo_pos
232
259
  return parent.compact! unless consecutive
233
260
 
234
261
  redo_string = "#{predo_string}#{sredo_string}"
@@ -288,9 +315,9 @@ module VER
288
315
  end
289
316
 
290
317
  def indices(*given_indices)
291
- given_indices.map do |index|
318
+ given_indices.map{|index|
292
319
  index.respond_to?(:to_index) ? index.to_index : widget.index(index)
293
- end
320
+ }.sort
294
321
  end
295
322
 
296
323
  def index(given_index)
@@ -301,6 +328,54 @@ module VER
301
328
  end
302
329
  end
303
330
 
331
+ # Multi-index pair case requires that we prevalidate the indices and sort
332
+ # from last to first so that deletes occur in the exact (unshifted) text.
333
+ # It also needs to handle partial and fully overlapping ranges. We have to
334
+ # do this with multiple passes.
335
+ def sanitize(*indices)
336
+ raise ArgumentError if indices.size % 2 != 0
337
+
338
+ # first we get the real indices
339
+ indices = indices.map{|index| widget.index(index) }
340
+
341
+ # pair them, to make later code easier.
342
+ indices = indices.each_slice(2).to_a
343
+
344
+ # then we sort the indices in increasing order
345
+ indices = indices.sort
346
+
347
+ # Now we eliminate ranges where end is before start.
348
+ indices = indices.select{|st, en| st <= en }
349
+
350
+ # And finally we merge ranges where the end is after the start of a
351
+ # following range.
352
+ final = []
353
+
354
+ while rang = indices.shift
355
+ if prev = final.last
356
+ prev_start, prev_end = prev.at(0), prev.at(1)
357
+ rang_start, rang_end = rang.at(0), rang.at(1)
358
+ else
359
+ final << rang
360
+ next
361
+ end
362
+
363
+ if prev_start == rang_start
364
+ # starts are overlapping, use longer end
365
+ prev[1] = [prev_end, rang_end].max
366
+ elsif prev_end >= rang_start
367
+ # prev end is overlapping rang start, use longer end
368
+ prev[1] = [prev_end, rang_end].max
369
+ elsif prev_end >= rang_end
370
+ # prev end is overlapping rang end, skip
371
+ else
372
+ final << rang
373
+ end
374
+ end
375
+
376
+ final.reverse
377
+ end
378
+
304
379
  def inspect
305
380
  "#<Undo::Record sep=%p undo=%p redo=%p>" % [separator, undo_info, redo_info]
306
381
  end
@@ -0,0 +1,184 @@
1
+ module VER
2
+ # Completion based on some code of IRB::InputCompleter
3
+ #
4
+ # Copyright by Keiju ISHITSUKA <keiju@ishitsuka.com>
5
+ # and Michael Fellinger <m.fellinger@gmail.com>
6
+ # From Original Idea of shugo@ruby-lang.org
7
+ module EvalCompleter
8
+ ReservedWords = %w[
9
+ BEGIN END alias and begin break case class def defined do else elsif end
10
+ ensure false for if in module next nil not or redo rescue retry return self
11
+ super then true undef unless until when while yield
12
+ ]
13
+
14
+ Operators = %w[
15
+ % & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~
16
+ ]
17
+
18
+ WordBreak = /[\t\n"'`><=;|&{(]/
19
+
20
+ module_function
21
+
22
+ def complete(input, bind = TOPLEVEL_BINDING)
23
+ case input
24
+ when /^(\/[^\/]*\/)\.([^.]*)$/
25
+ complete_regexp_method($1, Regexp.quote($2))
26
+ when /^([^\]]*\])\.([^.]*)$/
27
+ complete_array_method($1, Regexp.quote($2))
28
+ when /^([^\}]*\})\.([^.]*)$/
29
+ complete_proc_or_hash_method($1, Regexp.quote($2))
30
+ when /^(:[^:.]*)$/
31
+ complete_symbol(Regexp.quote($1))
32
+ when /^::([A-Z][^:\.\(]*)$/
33
+ complete_absolute_constant_or_class_method(Regexp.quote($1))
34
+ when /^(((::)?[A-Z][^:.\(]*)+)::?([^:.]*)$/
35
+ complete_constant_or_class_method(bind, $1, Regexp.quote($4))
36
+ when /^(:[^:.]+)\.([^.]*)$/
37
+ complete_symbol_method($1, Regexp.quote($2))
38
+ when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
39
+ complete_numeric_method(bind, $1, Regexp.quote($5))
40
+ when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
41
+ complete_numeric_hex_method(bind, $1, Regexp.quote($2))
42
+ when /^(\$[^.]*)$/
43
+ complete_global_variable(Regexp.new(Regexp.quote($1)))
44
+ when /^((\.?[^.]+)+)\.([^.]*)$/
45
+ complete_variable(bind, $1, Regexp.quote($3))
46
+ when /^\.([^.]*)$/
47
+ complete_unknown(Regexp.quote($1))
48
+ else
49
+ complete_else(bind, Regexp.quote(input))
50
+ end
51
+ end
52
+
53
+ def complete_regexp_method(receiver, message)
54
+ candidates = Regexp.instance_methods
55
+ select_message(receiver, message, candidates)
56
+ end
57
+
58
+ def complete_array_method(receiver, message)
59
+ candidates = Array.instance_methods
60
+ select_message(receiver, message, candidates)
61
+ end
62
+
63
+ def complete_proc_or_hash_method(receiver, message)
64
+ candidates = Proc.instance_methods
65
+ candidates |= Hash.instance_methods
66
+ select_message(receiver, message, candidates)
67
+ end
68
+
69
+ def complete_symbol(sym)
70
+ candidates = Symbol.all_symbols.map(&:inspect)
71
+ candidates.grep(/^#{sym}/)
72
+ end
73
+
74
+ def complete_absolute_constant_or_class_method(receiver)
75
+ candidates = Object.constants
76
+ candidates.grep(/^#{receiver}/).map{|name| "::#{name}" }
77
+ end
78
+
79
+ def complete_constant_or_class_method(bind, receiver, message)
80
+ begin
81
+ candidates = eval("#{receiver}.constants", bind)
82
+ candidates |= eval("#{receiver}.methods", bind)
83
+ rescue Exception
84
+ candidates = [*candidates]
85
+ end
86
+
87
+ candidates.grep(/^#{message}/).map{|name| "#{receiver}::#{name}" }
88
+ end
89
+
90
+ def complete_symbol_method(receiver, message)
91
+ candidates = Symbol.instance_methods
92
+ select_message(receiver, message, candidates)
93
+ end
94
+
95
+ def complete_numeric_method(bind, receiver, message)
96
+ begin
97
+ candidates = eval(receiver, bind).methods
98
+ rescue Exception
99
+ candidates = []
100
+ end
101
+
102
+ select_message(receiver, message, candidates)
103
+ end
104
+
105
+ # Numeric(0xFFFF)
106
+ def complete_numeric_hex_method(bind, receiver, message)
107
+ begin
108
+ candidates = eval(receiver, bind).methods
109
+ rescue Exception
110
+ candidates = []
111
+ end
112
+
113
+ select_message(receiver, message, candidates)
114
+ end
115
+
116
+ def complete_global_variable(regmessage)
117
+ global_variables.grep(regmessage).map(&:to_s)
118
+ end
119
+
120
+ def complete_variable(bind, receiver, message)
121
+ gv = eval("global_variables", bind).map(&:to_s)
122
+ lv = eval("local_variables", bind).map(&:to_s)
123
+ cv = eval("self.class.constants", bind).map(&:to_s)
124
+
125
+ if (gv | lv | cv).include?(receiver)
126
+ # foo.func and foo is local var.
127
+ candidates = eval("#{receiver}.methods", bind)
128
+ elsif /^[A-Z]/ =~ receiver and /\./ !~ receiver
129
+ # Foo::Bar.func
130
+ begin
131
+ candidates = eval("#{receiver}.methods", bind)
132
+ rescue Exception
133
+ candidates = []
134
+ end
135
+ else
136
+ # func1.func2
137
+ candidates = []
138
+
139
+ ObjectSpace.each_object(Module) do |mod|
140
+ begin
141
+ name = mod.name
142
+ rescue Exception
143
+ name = ""
144
+ end
145
+
146
+ next if name != "IRB::Context" && /^(IRB|SLex|RubyLex|RubyToken)/ =~ name
147
+ candidates.concat mod.instance_methods(false)
148
+ end
149
+
150
+ candidates.sort!
151
+ candidates.uniq!
152
+ end
153
+
154
+ select_message(receiver, message, candidates)
155
+ end
156
+
157
+ # unknown(maybe String)
158
+ def complete_unknown(message)
159
+ receiver = ""
160
+
161
+ candidates = String.instance_methods(true)
162
+ select_message(receiver, message, candidates)
163
+ end
164
+
165
+ def complete_else(bind, receiver)
166
+ code = "methods | private_methods | local_variables | self.class.constants"
167
+ candidates = eval(code, bind)
168
+
169
+ (candidates|ReservedWords).grep(/^#{receiver}/).map(&:to_s)
170
+ end
171
+
172
+ def select_message(receiver, message, candidates)
173
+ candidates.grep(/^#{message}/).map{|entity|
174
+ case entity
175
+ when /^[a-zA-Z_]/
176
+ "#{receiver}.#{entity}"
177
+ when /^[0-9]/
178
+ when *Operators
179
+ # "#{receiver} #{entity}"
180
+ end
181
+ }.compact
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,23 @@
1
+ require 'json'
2
+ require 'pstore'
3
+
4
+ class JSON::Store < PStore
5
+ def dump(table)
6
+ JSON.pretty_unparse(@table)
7
+ end
8
+
9
+ def load(content)
10
+ JSON.load(content)
11
+ end
12
+
13
+ EMPTY_MARSHAL_DATA = {}.to_json
14
+ EMPTY_MARSHAL_CHECKSUM = Digest::MD5.digest(EMPTY_MARSHAL_DATA)
15
+
16
+ def empty_marshal_data
17
+ EMPTY_MARSHAL_DATA
18
+ end
19
+
20
+ def empty_marshal_checksum
21
+ EMPTY_MARSHAL_CHECKSUM
22
+ end
23
+ end
@@ -0,0 +1,729 @@
1
+ #
2
+ # = open3.rb: Popen, but with stderr, too
3
+ #
4
+ # Author:: Yukihiro Matsumoto
5
+ # Documentation:: Konrad Meyer
6
+ #
7
+ # Open3 gives you access to stdin, stdout, and stderr when running other
8
+ # programs.
9
+ #
10
+
11
+ #
12
+ # Open3 grants you access to stdin, stdout, stderr and a thread to wait the
13
+ # child process when running another program.
14
+ # You can specify various attributes, redirections, current directory, etc., of
15
+ # the program as Process.spawn.
16
+ #
17
+ # - Open3.popen3 : pipes for stdin, stdout, stderr
18
+ # - Open3.popen2 : pipes for stdin, stdout
19
+ # - Open3.popen2e : pipes for stdin, merged stdout and stderr
20
+ # - Open3.capture3 : give a string for stdin. get strings for stdout, stderr
21
+ # - Open3.capture2 : give a string for stdin. get a string for stdout
22
+ # - Open3.capture2e : give a string for stdin. get a string for merged stdout and stderr
23
+ # - Open3.pipeline_rw : pipes for first stdin and last stdout of a pipeline
24
+ # - Open3.pipeline_r : pipe for last stdout of a pipeline
25
+ # - Open3.pipeline_w : pipe for first stdin of a pipeline
26
+ # - Open3.pipeline_start : a pipeline
27
+ # - Open3.pipeline : run a pipline and wait
28
+ #
29
+
30
+ module Open3
31
+
32
+ # Open stdin, stdout, and stderr streams and start external executable.
33
+ # In addition, a thread for waiting the started process is noticed.
34
+ # The thread has a pid method and thread variable :pid which is the pid of
35
+ # the started process.
36
+ #
37
+ # Block form:
38
+ #
39
+ # Open3.popen3([env,] cmd... [, opts]) {|stdin, stdout, stderr, wait_thr|
40
+ # pid = wait_thr.pid # pid of the started process.
41
+ # ...
42
+ # exit_status = wait_thr.value # Process::Status object returned.
43
+ # }
44
+ #
45
+ # Non-block form:
46
+ #
47
+ # stdin, stdout, stderr, wait_thr = Open3.popen3([env,] cmd... [, opts])
48
+ # pid = wait_thr[:pid] # pid of the started process.
49
+ # ...
50
+ # stdin.close # stdin, stdout and stderr should be closed explicitly in this form.
51
+ # stdout.close
52
+ # stderr.close
53
+ # exit_status = wait_thr.value # Process::Status object returned.
54
+ #
55
+ # The parameters +cmd...+ is passed to Process.spawn.
56
+ # So a commandline string and list of argument strings can be accepted as follows.
57
+ #
58
+ # Open3.popen3("echo a") {|i, o, e, t| ... }
59
+ # Open3.popen3("echo", "a") {|i, o, e, t| ... }
60
+ # Open3.popen3(["echo", "argv0"], "a") {|i, o, e, t| ... }
61
+ #
62
+ # If the last parameter, opts, is a Hash, it is recognized as an option for Process.spawn.
63
+ #
64
+ # Open3.popen3("pwd", :chdir=>"/") {|i,o,e,t|
65
+ # p o.read.chomp #=> "/"
66
+ # }
67
+ #
68
+ # wait_thr.value waits the termination of the process.
69
+ # The block form also waits the process when it returns.
70
+ #
71
+ # Closing stdin, stdout and stderr does not wait the process.
72
+ #
73
+ def popen3(*cmd, &block)
74
+ if Hash === cmd.last
75
+ opts = cmd.pop.dup
76
+ else
77
+ opts = {}
78
+ end
79
+
80
+ in_r, in_w = IO.pipe
81
+ opts[:in] = in_r
82
+ in_w.sync = true
83
+
84
+ out_r, out_w = IO.pipe
85
+ opts[:out] = out_w
86
+
87
+ err_r, err_w = IO.pipe
88
+ opts[:err] = err_w
89
+
90
+ popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block)
91
+ end
92
+ module_function :popen3
93
+
94
+ # Open3.popen2 is similer to Open3.popen3 except it doesn't make a pipe for
95
+ # the standard error stream.
96
+ #
97
+ # Block form:
98
+ #
99
+ # Open3.popen2([env,] cmd... [, opts]) {|stdin, stdout, wait_thr|
100
+ # pid = wait_thr.pid # pid of the started process.
101
+ # ...
102
+ # exit_status = wait_thr.value # Process::Status object returned.
103
+ # }
104
+ #
105
+ # Non-block form:
106
+ #
107
+ # stdin, stdout, wait_thr = Open3.popen2([env,] cmd... [, opts])
108
+ # ...
109
+ # stdin.close # stdin and stdout should be closed explicitly in this form.
110
+ # stdout.close
111
+ #
112
+ # See Process.spawn for the optional hash arguments _env_ and _opts_.
113
+ #
114
+ # Example:
115
+ #
116
+ # Open3.popen2("wc -c") {|i,o,t|
117
+ # i.print "answer to life the universe and everything"
118
+ # i.close
119
+ # p o.gets #=> "42\n"
120
+ # }
121
+ #
122
+ # Open3.popen2("bc -q") {|i,o,t|
123
+ # i.puts "obase=13"
124
+ # i.puts "6 * 9"
125
+ # p o.gets #=> "42\n"
126
+ # }
127
+ #
128
+ # Open3.popen2("dc") {|i,o,t|
129
+ # i.print "42P"
130
+ # i.close
131
+ # p o.read #=> "*"
132
+ # }
133
+ #
134
+ def popen2(*cmd, &block)
135
+ if Hash === cmd.last
136
+ opts = cmd.pop.dup
137
+ else
138
+ opts = {}
139
+ end
140
+
141
+ in_r, in_w = IO.pipe
142
+ opts[:in] = in_r
143
+ in_w.sync = true
144
+
145
+ out_r, out_w = IO.pipe
146
+ opts[:out] = out_w
147
+
148
+ popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
149
+ end
150
+ module_function :popen2
151
+
152
+ # Open3.popen2e is similer to Open3.popen3 except it merges
153
+ # the standard output stream and the standard error stream.
154
+ #
155
+ # Block form:
156
+ #
157
+ # Open3.popen2e([env,] cmd... [, opts]) {|stdin, stdout_and_stderr, wait_thr|
158
+ # pid = wait_thr.pid # pid of the started process.
159
+ # ...
160
+ # exit_status = wait_thr.value # Process::Status object returned.
161
+ # }
162
+ #
163
+ # Non-block form:
164
+ #
165
+ # stdin, stdout_and_stderr, wait_thr = Open3.popen2e([env,] cmd... [, opts])
166
+ # ...
167
+ # stdin.close # stdin and stdout_and_stderr should be closed explicitly in this form.
168
+ # stdout_and_stderr.close
169
+ #
170
+ # See Process.spawn for the optional hash arguments _env_ and _opts_.
171
+ #
172
+ # Example:
173
+ # # check gcc warnings
174
+ # source = "foo.c"
175
+ # Open3.popen2e("gcc", "-Wall", source) {|i,oe,t|
176
+ # oe.each {|line|
177
+ # if /warning/ =~ line
178
+ # ...
179
+ # end
180
+ # }
181
+ # }
182
+ #
183
+ def popen2e(*cmd, &block)
184
+ if Hash === cmd.last
185
+ opts = cmd.pop.dup
186
+ else
187
+ opts = {}
188
+ end
189
+
190
+ in_r, in_w = IO.pipe
191
+ opts[:in] = in_r
192
+ in_w.sync = true
193
+
194
+ out_r, out_w = IO.pipe
195
+ opts[[:out, :err]] = out_w
196
+
197
+ popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
198
+ end
199
+ module_function :popen2e
200
+
201
+ def popen_run(cmd, opts, child_io, parent_io) # :nodoc:
202
+ pid = spawn(*cmd, opts)
203
+ wait_thr = Process.detach(pid)
204
+ child_io.each {|io| io.close }
205
+ result = [*parent_io, wait_thr]
206
+ if defined? yield
207
+ begin
208
+ return yield(*result)
209
+ ensure
210
+ parent_io.each{|io| io.close unless io.closed?}
211
+ wait_thr.join
212
+ end
213
+ end
214
+ result
215
+ end
216
+ module_function :popen_run
217
+ class << self
218
+ private :popen_run
219
+ end
220
+
221
+ # Open3.capture3 captures the standard output and the standard error of a command.
222
+ #
223
+ # stdout_str, stderr_str, status = Open3.capture3([env,] cmd... [, opts])
224
+ #
225
+ # The arguments env, cmd and opts are passed to Open3.popen3 except
226
+ # opts[:stdin_data] and opts[:stdin_data]. See Process.spawn.
227
+ #
228
+ # If opts[:stdin_data] is specified, it is sent to the command's standard input.
229
+ #
230
+ # If opts[:binmode] is true, internal pipes are set to binary mode.
231
+ #
232
+ # Example:
233
+ #
234
+ # # dot is a command of graphviz.
235
+ # graph = <<'End'
236
+ # digraph g {
237
+ # a -> b
238
+ # }
239
+ # End
240
+ # layouted_graph, dot_log = Open3.capture3("dot -v", :stdin_data=>graph)
241
+ #
242
+ # o, e, s = Open3.capture3("echo a; sort >&2", :stdin_data=>"foo\nbar\nbaz\n")
243
+ # p o #=> "a\n"
244
+ # p e #=> "bar\nbaz\nfoo\n"
245
+ # p s #=> #<Process::Status: pid 32682 exit 0>
246
+ #
247
+ # # generate a thumnail image using the convert command of ImageMagick.
248
+ # # However, if the image stored really in a file,
249
+ # # system("convert", "-thumbnail", "80", "png:#{filename}", "png:-") is better
250
+ # # because memory consumption.
251
+ # # But if the image is stored in a DB or generated by gnuplot Open3.capture2 example,
252
+ # # Open3.capture3 is considerable.
253
+ # #
254
+ # image = File.read("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true)
255
+ # thumnail, err, s = Open3.capture3("convert -thumbnail 80 png:- png:-", :stdin_data=>image, :binmode=>true)
256
+ # if s.success?
257
+ # STDOUT.binmode; print thumnail
258
+ # end
259
+ #
260
+ def capture3(*cmd, &block)
261
+ if Hash === cmd.last
262
+ opts = cmd.pop.dup
263
+ else
264
+ opts = {}
265
+ end
266
+
267
+ stdin_data = opts.delete(:stdin_data) || ''
268
+ binmode = opts.delete(:binmode)
269
+
270
+ popen3(*cmd, opts) {|i, o, e, t|
271
+ if binmode
272
+ i.binmode
273
+ o.binmode
274
+ e.binmode
275
+ end
276
+ out_reader = Thread.new { o.read }
277
+ err_reader = Thread.new { e.read }
278
+ i.write stdin_data
279
+ i.close
280
+ [out_reader.value, err_reader.value, t.value]
281
+ }
282
+ end
283
+ module_function :capture3
284
+
285
+ # Open3.capture2 captures the standard output of a command.
286
+ #
287
+ # stdout_str, status = Open3.capture2([env,] cmd... [, opts])
288
+ #
289
+ # The arguments env, cmd and opts are passed to Open3.popen3 except
290
+ # opts[:stdin_data] and opts[:stdin_data]. See Process.spawn.
291
+ #
292
+ # If opts[:stdin_data] is specified, it is sent to the command's standard input.
293
+ #
294
+ # If opts[:binmode] is true, internal pipes are set to binary mode.
295
+ #
296
+ # Example:
297
+ #
298
+ # # factor is a command for integer factorization.
299
+ # o, s = Open3.capture2("factor", :stdin_data=>"42")
300
+ # p o #=> "42: 2 3 7\n"
301
+ #
302
+ # # generate x**2 graph in png using gnuplot.
303
+ # gnuplot_commands = <<"End"
304
+ # set terminal png
305
+ # plot x**2, "-" with lines
306
+ # 1 14
307
+ # 2 1
308
+ # 3 8
309
+ # 4 5
310
+ # e
311
+ # End
312
+ # image, s = Open3.capture2("gnuplot", :stdin_data=>gnuplot_commands, :binmode=>true)
313
+ #
314
+ def capture2(*cmd, &block)
315
+ if Hash === cmd.last
316
+ opts = cmd.pop.dup
317
+ else
318
+ opts = {}
319
+ end
320
+
321
+ stdin_data = opts.delete(:stdin_data) || ''
322
+ binmode = opts.delete(:binmode)
323
+
324
+ popen2(*cmd, opts) {|i, o, t|
325
+ if binmode
326
+ i.binmode
327
+ o.binmode
328
+ end
329
+ out_reader = Thread.new { o.read }
330
+ i.write stdin_data
331
+ i.close
332
+ [out_reader.value, t.value]
333
+ }
334
+ end
335
+ module_function :capture2
336
+
337
+ # Open3.capture2e captures the standard output and the standard error of a command.
338
+ #
339
+ # stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts])
340
+ #
341
+ # The arguments env, cmd and opts are passed to Open3.popen3 except
342
+ # opts[:stdin_data] and opts[:stdin_data]. See Process.spawn.
343
+ #
344
+ # If opts[:stdin_data] is specified, it is sent to the command's standard input.
345
+ #
346
+ # If opts[:binmode] is true, internal pipes are set to binary mode.
347
+ #
348
+ # Example:
349
+ #
350
+ # # capture make log
351
+ # make_log, s = Open3.capture2e("make")
352
+ #
353
+ def capture2e(*cmd, &block)
354
+ if Hash === cmd.last
355
+ opts = cmd.pop.dup
356
+ else
357
+ opts = {}
358
+ end
359
+
360
+ stdin_data = opts.delete(:stdin_data) || ''
361
+ binmode = opts.delete(:binmode)
362
+
363
+ popen2e(*cmd, opts) {|i, oe, t|
364
+ if binmode
365
+ i.binmode
366
+ oe.binmode
367
+ end
368
+ outerr_reader = Thread.new { oe.read }
369
+ i.write stdin_data
370
+ i.close
371
+ [outerr_reader.value, t.value]
372
+ }
373
+ end
374
+ module_function :capture2e
375
+
376
+ # Open3.pipeline_rw starts a list of commands as a pipeline with pipes
377
+ # which connects stdin of the first command and stdout of the last command.
378
+ #
379
+ # Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads|
380
+ # ...
381
+ # }
382
+ #
383
+ # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts])
384
+ # ...
385
+ # first_stdin.close
386
+ # last_stdout.close
387
+ #
388
+ # Each cmd is a string or an array.
389
+ # If it is an array, the elements are passed to Process.spawn.
390
+ #
391
+ # cmd:
392
+ # commandline command line string which is passed to a shell
393
+ # [env, commandline, opts] command line string which is passed to a shell
394
+ # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
395
+ # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
396
+ #
397
+ # Note that env and opts are optional, as Process.spawn.
398
+ #
399
+ # The option to pass Process.spawn is constructed by merging
400
+ # +opts+, the last hash element of the array and
401
+ # specification for the pipe between each commands.
402
+ #
403
+ # Example:
404
+ #
405
+ # Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i,o,ts|
406
+ # i.puts "All persons more than a mile high to leave the court."
407
+ # i.close
408
+ # p o.gets #=> "42\n"
409
+ # }
410
+ #
411
+ # Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs|
412
+ # stdin.puts "foo"
413
+ # stdin.puts "bar"
414
+ # stdin.puts "baz"
415
+ # stdin.close # send EOF to sort.
416
+ # p stdout.read #=> " 1\tbar\n 2\tbaz\n 3\tfoo\n"
417
+ # }
418
+ def pipeline_rw(*cmds, &block)
419
+ if Hash === cmds.last
420
+ opts = cmds.pop.dup
421
+ else
422
+ opts = {}
423
+ end
424
+
425
+ in_r, in_w = IO.pipe
426
+ opts[:in] = in_r
427
+ in_w.sync = true
428
+
429
+ out_r, out_w = IO.pipe
430
+ opts[:out] = out_w
431
+
432
+ pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block)
433
+ end
434
+ module_function :pipeline_rw
435
+
436
+ # Open3.pipeline_r starts a list of commands as a pipeline with a pipe
437
+ # which connects stdout of the last command.
438
+ #
439
+ # Open3.pipeline_r(cmd1, cmd2, ... [, opts]) {|last_stdout, wait_threads|
440
+ # ...
441
+ # }
442
+ #
443
+ # last_stdout, wait_threads = Open3.pipeline_r(cmd1, cmd2, ... [, opts])
444
+ # ...
445
+ # last_stdout.close
446
+ #
447
+ # Each cmd is a string or an array.
448
+ # If it is an array, the elements are passed to Process.spawn.
449
+ #
450
+ # cmd:
451
+ # commandline command line string which is passed to a shell
452
+ # [env, commandline, opts] command line string which is passed to a shell
453
+ # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
454
+ # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
455
+ #
456
+ # Note that env and opts are optional, as Process.spawn.
457
+ #
458
+ # Example:
459
+ #
460
+ # Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz",
461
+ # [{"LANG"=>"C"}, "grep", "GET /favicon.ico"],
462
+ # "logresolve") {|r, ts|
463
+ # r.each_line {|line|
464
+ # ...
465
+ # }
466
+ # }
467
+ #
468
+ # Open3.pipeline_r("yes", "head -10") {|r, ts|
469
+ # p r.read #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"
470
+ # p ts[0].value #=> #<Process::Status: pid 24910 SIGPIPE (signal 13)>
471
+ # p ts[1].value #=> #<Process::Status: pid 24913 exit 0>
472
+ # }
473
+ #
474
+ def pipeline_r(*cmds, &block)
475
+ if Hash === cmds.last
476
+ opts = cmds.pop.dup
477
+ else
478
+ opts = {}
479
+ end
480
+
481
+ out_r, out_w = IO.pipe
482
+ opts[:out] = out_w
483
+
484
+ pipeline_run(cmds, opts, [out_w], [out_r], &block)
485
+ end
486
+ module_function :pipeline_r
487
+
488
+ # Open3.pipeline_w starts a list of commands as a pipeline with a pipe
489
+ # which connects stdin of the first command.
490
+ #
491
+ # Open3.pipeline_w(cmd1, cmd2, ... [, opts]) {|first_stdin, wait_threads|
492
+ # ...
493
+ # }
494
+ #
495
+ # first_stdin, wait_threads = Open3.pipeline_w(cmd1, cmd2, ... [, opts])
496
+ # ...
497
+ # first_stdin.close
498
+ #
499
+ # Each cmd is a string or an array.
500
+ # If it is an array, the elements are passed to Process.spawn.
501
+ #
502
+ # cmd:
503
+ # commandline command line string which is passed to a shell
504
+ # [env, commandline, opts] command line string which is passed to a shell
505
+ # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
506
+ # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
507
+ #
508
+ # Note that env and opts are optional, as Process.spawn.
509
+ #
510
+ # Example:
511
+ #
512
+ # Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|w, ts|
513
+ # w.puts "hello"
514
+ # }
515
+ #
516
+ def pipeline_w(*cmds, &block)
517
+ if Hash === cmds.last
518
+ opts = cmds.pop.dup
519
+ else
520
+ opts = {}
521
+ end
522
+
523
+ in_r, in_w = IO.pipe
524
+ opts[:in] = in_r
525
+ in_w.sync = true
526
+
527
+ pipeline_run(cmds, opts, [in_r], [in_w], &block)
528
+ end
529
+ module_function :pipeline_w
530
+
531
+ # Open3.pipeline_start starts a list of commands as a pipeline.
532
+ # No pipe made for stdin of the first command and
533
+ # stdout of the last command.
534
+ #
535
+ # Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads|
536
+ # ...
537
+ # }
538
+ #
539
+ # wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts])
540
+ # ...
541
+ #
542
+ # Each cmd is a string or an array.
543
+ # If it is an array, the elements are passed to Process.spawn.
544
+ #
545
+ # cmd:
546
+ # commandline command line string which is passed to a shell
547
+ # [env, commandline, opts] command line string which is passed to a shell
548
+ # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
549
+ # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
550
+ #
551
+ # Note that env and opts are optional, as Process.spawn.
552
+ #
553
+ # Example:
554
+ #
555
+ # # run xeyes in 10 seconds.
556
+ # Open3.pipeline_start("xeyes") {|ts|
557
+ # sleep 10
558
+ # t = ts[0]
559
+ # Process.kill("TERM", t.pid)
560
+ # p t.value #=> #<Process::Status: pid 911 SIGTERM (signal 15)>
561
+ # }
562
+ #
563
+ # # convert pdf to ps and send it to a printer.
564
+ # # collect error message of pdftops and lpr.
565
+ # pdf_file = "paper.pdf"
566
+ # printer = "printer-name"
567
+ # err_r, err_w = IO.pipe
568
+ # Open3.pipeline_start(["pdftops", pdf_file, "-"],
569
+ # ["lpr", "-P#{printer}"],
570
+ # :err=>err_w) {|ts|
571
+ # err_w.close
572
+ # p err_r.read # error messages of pdftops and lpr.
573
+ # }
574
+ #
575
+ def pipeline_start(*cmds, &block)
576
+ if Hash === cmds.last
577
+ opts = cmds.pop.dup
578
+ else
579
+ opts = {}
580
+ end
581
+
582
+ if block
583
+ pipeline_run(cmds, opts, [], [], &block)
584
+ else
585
+ ts, = pipeline_run(cmds, opts, [], [])
586
+ ts
587
+ end
588
+ end
589
+ module_function :pipeline_start
590
+
591
+ # Open3.pipeline starts a list of commands as a pipeline.
592
+ # It waits the finish of the commands.
593
+ # No pipe made for stdin of the first command and
594
+ # stdout of the last command.
595
+ #
596
+ # status_list = Open3.pipeline(cmd1, cmd2, ... [, opts])
597
+ #
598
+ # Each cmd is a string or an array.
599
+ # If it is an array, the elements are passed to Process.spawn.
600
+ #
601
+ # cmd:
602
+ # commandline command line string which is passed to a shell
603
+ # [env, commandline, opts] command line string which is passed to a shell
604
+ # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell)
605
+ # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell)
606
+ #
607
+ # Note that env and opts are optional, as Process.spawn.
608
+ #
609
+ # Example:
610
+ #
611
+ # fname = "/usr/share/man/man1/ruby.1.gz"
612
+ # p Open3.pipeline(["zcat", fname], "nroff -man", "less")
613
+ # #=> [#<Process::Status: pid 11817 exit 0>,
614
+ # # #<Process::Status: pid 11820 exit 0>,
615
+ # # #<Process::Status: pid 11828 exit 0>]
616
+ #
617
+ # fname = "/usr/share/man/man1/ls.1.gz"
618
+ # Open3.pipeline(["zcat", fname], "nroff -man", "colcrt")
619
+ #
620
+ # # convert PDF to PS and send to a printer by lpr
621
+ # pdf_file = "paper.pdf"
622
+ # printer = "printer-name"
623
+ # Open3.pipeline(["pdftops", pdf_file, "-"],
624
+ # ["lpr", "-P#{printer}"])
625
+ #
626
+ # # count lines
627
+ # Open3.pipeline("sort", "uniq -c", :in=>"names.txt", :out=>"count")
628
+ #
629
+ # # cyclic pipeline
630
+ # r,w = IO.pipe
631
+ # w.print "ibase=14\n10\n"
632
+ # Open3.pipeline("bc", "tee /dev/tty", :in=>r, :out=>w)
633
+ # #=> 14
634
+ # # 18
635
+ # # 22
636
+ # # 30
637
+ # # 42
638
+ # # 58
639
+ # # 78
640
+ # # 106
641
+ # # 202
642
+ #
643
+ def pipeline(*cmds)
644
+ if Hash === cmds.last
645
+ opts = cmds.pop.dup
646
+ else
647
+ opts = {}
648
+ end
649
+
650
+ pipeline_run(cmds, opts, [], []) {|ts|
651
+ ts.map {|t| t.value }
652
+ }
653
+ end
654
+ module_function :pipeline
655
+
656
+ def pipeline_run(cmds, pipeline_opts, child_io, parent_io, &block) # :nodoc:
657
+ if cmds.empty?
658
+ raise ArgumentError, "no commands"
659
+ end
660
+
661
+ opts_base = pipeline_opts.dup
662
+ opts_base.delete :in
663
+ opts_base.delete :out
664
+
665
+ wait_thrs = []
666
+ r = nil
667
+ cmds.each_with_index {|cmd, i|
668
+ cmd_opts = opts_base.dup
669
+ if String === cmd
670
+ cmd = [cmd]
671
+ else
672
+ cmd_opts.update cmd.pop if Hash === cmd.last
673
+ end
674
+ if i == 0
675
+ if !cmd_opts.include?(:in)
676
+ if pipeline_opts.include?(:in)
677
+ cmd_opts[:in] = pipeline_opts[:in]
678
+ end
679
+ end
680
+ else
681
+ cmd_opts[:in] = r
682
+ end
683
+ if i != cmds.length - 1
684
+ r2, w2 = IO.pipe
685
+ cmd_opts[:out] = w2
686
+ else
687
+ if !cmd_opts.include?(:out)
688
+ if pipeline_opts.include?(:out)
689
+ cmd_opts[:out] = pipeline_opts[:out]
690
+ end
691
+ end
692
+ end
693
+ pid = spawn(*cmd, cmd_opts)
694
+ wait_thrs << Process.detach(pid)
695
+ r.close if r
696
+ w2.close if w2
697
+ r = r2
698
+ }
699
+ result = parent_io + [wait_thrs]
700
+ child_io.each {|io| io.close }
701
+ if defined? yield
702
+ begin
703
+ return yield(*result)
704
+ ensure
705
+ parent_io.each{|io| io.close unless io.closed?}
706
+ wait_thrs.each {|t| t.join }
707
+ end
708
+ end
709
+ result
710
+ end
711
+ module_function :pipeline_run
712
+ class << self
713
+ private :pipeline_run
714
+ end
715
+
716
+ end
717
+
718
+ if $0 == __FILE__
719
+ a = Open3.popen3("nroff -man")
720
+ Thread.start do
721
+ while line = gets
722
+ a[0].print line
723
+ end
724
+ a[0].close
725
+ end
726
+ while line = a[1].gets
727
+ print ":", line
728
+ end
729
+ end