ver 2009.10.14 → 2009.11.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (318) hide show
  1. data/CHANGELOG +1094 -0
  2. data/MANIFEST +227 -25
  3. data/README.textile +185 -0
  4. data/bin/ver +96 -12
  5. data/config/detect.rb +73 -21
  6. data/config/keymap/emacs.rb +66 -0
  7. data/config/keymap/vim.rb +250 -140
  8. data/config/preferences/ANTLR.json +10 -0
  9. data/config/preferences/ASP vb.NET.json +3 -0
  10. data/config/preferences/ASP.json +15 -0
  11. data/config/preferences/ActionScript.json +755 -0
  12. data/config/preferences/Active4D.json +89 -0
  13. data/config/preferences/Ada.json +23 -0
  14. data/config/preferences/Ant.json +356 -0
  15. data/config/preferences/Apache.json +644 -0
  16. data/config/preferences/AppleScript.json +92 -0
  17. data/config/preferences/Bison.json +3 -0
  18. data/config/preferences/Blogging.json +3 -0
  19. data/config/preferences/C.json +127 -0
  20. data/config/preferences/CMake.json +41 -0
  21. data/config/preferences/CSS.json +461 -0
  22. data/config/preferences/CTags.json +3 -0
  23. data/config/preferences/CVS.json +3 -0
  24. data/config/preferences/ColdFusion.json +32 -0
  25. data/config/preferences/D.json +58 -0
  26. data/config/preferences/Darcs.json +3 -0
  27. data/config/preferences/Diff.json +67 -0
  28. data/config/preferences/DokuWiki.json +19 -0
  29. data/config/preferences/Doxygen.json +3 -0
  30. data/config/preferences/Dylan.json +3 -0
  31. data/config/preferences/Eiffel.json +59 -0
  32. data/config/preferences/Erlang.json +72 -0
  33. data/config/preferences/Experimental.json +1356 -0
  34. data/config/preferences/F-Script.json +87 -0
  35. data/config/preferences/FXScript.json +78 -0
  36. data/config/preferences/FileMerge.json +3 -0
  37. data/config/preferences/Fortran.json +158 -0
  38. data/config/preferences/GTD2.json +11 -0
  39. data/config/preferences/GTDAlt.json +20 -0
  40. data/config/preferences/GetBundle.json +3 -0
  41. data/config/preferences/Gettext.json +24 -0
  42. data/config/preferences/Graphviz.json +42 -0
  43. data/config/preferences/Greasemonkey.json +3 -0
  44. data/config/preferences/Gri.json +34 -0
  45. data/config/preferences/HTML.json +492 -0
  46. data/config/preferences/Haskell.json +72 -0
  47. data/config/preferences/Hotkey.json +3 -0
  48. data/config/preferences/ImageBrowser.json +3 -0
  49. data/config/preferences/Inform.json +3 -0
  50. data/config/preferences/Ini.json +60 -0
  51. data/config/preferences/Installer.json +3 -0
  52. data/config/preferences/Io.json +64 -0
  53. data/config/preferences/JSON.json +3 -0
  54. data/config/preferences/Java.json +86 -0
  55. data/config/preferences/JavaDoc.json +3 -0
  56. data/config/preferences/JavaScript.json +76 -0
  57. data/config/preferences/LaTeX.json +267 -0
  58. data/config/preferences/Lex/Flex.json +3 -0
  59. data/config/preferences/Lighttpd.json +3 -0
  60. data/config/preferences/LilyPond.json +77 -0
  61. data/config/preferences/Lisp.json +63 -0
  62. data/config/preferences/Logo.json +58 -0
  63. data/config/preferences/Logtalk.json +236 -0
  64. data/config/preferences/Lua.json +24 -0
  65. data/config/preferences/MEL.json +19 -0
  66. data/config/preferences/MIPS Assembler.json +26 -0
  67. data/config/preferences/MacPorts.json +3 -0
  68. data/config/preferences/Mail.json +3 -0
  69. data/config/preferences/Make.json +16 -0
  70. data/config/preferences/Markdown.json +102 -0
  71. data/config/preferences/Math.json +3 -0
  72. data/config/preferences/Matlab.json +128 -0
  73. data/config/preferences/Maven.json +308 -0
  74. data/config/preferences/Mediawiki.json +73 -0
  75. data/config/preferences/Mercurial.json +3 -0
  76. data/config/preferences/Modula.json +37 -0
  77. data/config/preferences/MoinMoin.json +52 -0
  78. data/config/preferences/Navigation.json +3 -0
  79. data/config/preferences/Nemerle.json +3 -0
  80. data/config/preferences/OCaml Code Completion.json +3 -0
  81. data/config/preferences/OCaml.json +163 -0
  82. data/config/preferences/ODCompletion.json +3 -0
  83. data/config/preferences/Objective-C.json +84 -0
  84. data/config/preferences/OpenGL.json +3331 -0
  85. data/config/preferences/Outlines.json +3 -0
  86. data/config/preferences/Pascal.json +60 -0
  87. data/config/preferences/Perforce.json +3 -0
  88. data/config/preferences/Perl.json +15 -0
  89. data/config/preferences/PmWiki.json +27 -0
  90. data/config/preferences/Postscript.json +15 -0
  91. data/config/preferences/Processing.json +32 -0
  92. data/config/preferences/Prolog.json +3 -0
  93. data/config/preferences/Propel.json +3 -0
  94. data/config/preferences/Python.json +38 -0
  95. data/config/preferences/Quake.json +15 -0
  96. data/config/preferences/R.json +33 -0
  97. data/config/preferences/Ragel.json +15 -0
  98. data/config/preferences/Regular Expressions.json +3 -0
  99. data/config/preferences/Remind.json +15 -0
  100. data/config/preferences/Rez.json +46 -0
  101. data/config/preferences/Ruby.json +98 -0
  102. data/config/preferences/S5 Slide Show.json +20 -0
  103. data/config/preferences/SCons.json +3 -0
  104. data/config/preferences/SQL.json +32 -0
  105. data/config/preferences/SSH Config.json +15 -0
  106. data/config/preferences/SVK.json +3 -0
  107. data/config/preferences/SWIG.json +3 -0
  108. data/config/preferences/SWeave.json +32 -0
  109. data/config/preferences/Scheme.json +35 -0
  110. data/config/preferences/Scilab.json +15 -0
  111. data/config/preferences/Setext.json +3 -0
  112. data/config/preferences/Shell Script.json +25 -0
  113. data/config/preferences/Slate.json +113 -0
  114. data/config/preferences/Source.json +132 -0
  115. data/config/preferences/Subversion.json +10 -0
  116. data/config/preferences/TODO.json +3 -0
  117. data/config/preferences/Tabular.json +3 -0
  118. data/config/preferences/Tcl.json +82 -0
  119. data/config/preferences/TerminalMate.json +112 -0
  120. data/config/preferences/Text.json +89 -0
  121. data/config/preferences/TextMate.json +38 -0
  122. data/config/preferences/Textile.json +76 -0
  123. data/config/preferences/Thrift.json +56 -0
  124. data/config/preferences/Transmit.json +3 -0
  125. data/config/preferences/Twiki.json +51 -0
  126. data/config/preferences/Txt2tags.json +81 -0
  127. data/config/preferences/Vectorscript.json +1280 -0
  128. data/config/preferences/XML.json +60 -0
  129. data/config/preferences/Xcode.json +3 -0
  130. data/config/preferences/YAML.json +24 -0
  131. data/config/preferences/iCalendar.json +10 -0
  132. data/config/preferences/iTerm.json +36 -0
  133. data/config/preferences/reStructuredText.json +48 -0
  134. data/config/rc.rb +49 -0
  135. data/config/syntax/ANTLR.json +5 -5
  136. data/config/syntax/{ASP VB.net.json → ASP vb.NET.json } +3 -3
  137. data/config/syntax/ASP.json +1 -1
  138. data/config/syntax/ActionScript.json +6 -6
  139. data/config/syntax/Active4D Config.json +86 -0
  140. data/config/syntax/Active4D Library.json +20 -0
  141. data/config/syntax/Active4D.json +418 -0
  142. data/config/syntax/Ada.json +3 -3
  143. data/config/syntax/Ant.json +196 -0
  144. data/config/syntax/Apache.json +7 -7
  145. data/config/syntax/AppleScript.json +3 -3
  146. data/config/syntax/{Bibtex.json → BibTeX.json} +1 -1
  147. data/config/syntax/Bison.json +59 -0
  148. data/config/syntax/{Blog (HTML).json → Blog - HTML.json } +2 -2
  149. data/config/syntax/{Blog (Markdown).json → Blog - Markdown.json } +2 -2
  150. data/config/syntax/Blog (Text).json b/data/config/syntax/Blog - → Text.json +0 -0
  151. data/config/syntax/Blog (Textile).json b/data/config/syntax/Blog - → Textile.json +0 -0
  152. data/config/syntax/C++.json +3 -3
  153. data/config/syntax/C.json +13 -13
  154. data/config/syntax/CMake Listfile.json +171 -0
  155. data/config/syntax/CSS.json +6 -6
  156. data/config/syntax/CSV.json +108 -0
  157. data/config/syntax/ColdFusion.json +204 -0
  158. data/config/syntax/D.json +560 -0
  159. data/config/syntax/Diff.json +1 -1
  160. data/config/syntax/DokuWiki.json +412 -0
  161. data/config/syntax/Doxygen.json +80 -0
  162. data/config/syntax/Dylan.json +4 -4
  163. data/config/syntax/Erlang.json +5 -5
  164. data/config/syntax/F-Script.json +1 -1
  165. data/config/syntax/FXScript.json +5 -5
  166. data/config/syntax/Fortran - Modern.json +221 -0
  167. data/config/syntax/Fortran - Punchcard.json +468 -0
  168. data/config/syntax/GTD.json +39 -0
  169. data/config/syntax/GTDalt.json +233 -0
  170. data/config/syntax/Gettext.json +118 -0
  171. data/config/syntax/Go.json +555 -0
  172. data/config/syntax/{DOT.json → Graphviz (DOT).json } +3 -3
  173. data/config/syntax/Greasemonkey.json +56 -0
  174. data/config/syntax/Gri.json +4 -4
  175. data/config/syntax/{HTML-ASP.json → HTML (ASP).json } +1 -1
  176. data/config/syntax/{HTML for ASP.net.json → HTML (ASP.net).json } +19 -19
  177. data/config/syntax/HTML (Active4D).json +540 -0
  178. data/config/syntax/HTML (Erlang).json +31 -0
  179. data/config/syntax/HTML (Tcl).json +1 -1
  180. data/config/syntax/HTML.json +20 -20
  181. data/config/syntax/Haskell.json +3 -3
  182. data/config/syntax/Installer Distribution Script.json +135 -0
  183. data/config/syntax/Io.json +6 -6
  184. data/config/syntax/JSON.json +151 -0
  185. data/config/syntax/{JavaProperties.json → Java Properties.json } +2 -2
  186. data/config/syntax/Java Server Page (JSP).json +163 -0
  187. data/config/syntax/Java.json +7 -7
  188. data/config/syntax/JavaDoc.json +435 -0
  189. data/config/syntax/JavaScript.json +8 -8
  190. data/config/syntax/LaTeX Log.json +3 -3
  191. data/config/syntax/LaTeX Memoir.json +101 -0
  192. data/config/syntax/LaTeX.json +2 -2
  193. data/config/syntax/Lex-Flex.json +396 -0
  194. data/config/syntax/LilyPond.json +608 -0
  195. data/config/syntax/Logo.json +48 -0
  196. data/config/syntax/Logtalk.json +6 -6
  197. data/config/syntax/Lua.json +1 -1
  198. data/config/syntax/{M.json → MATLAB.json} +3 -3
  199. data/config/syntax/MEL.json +7 -7
  200. data/config/syntax/MIPS.json b/data/config/syntax/MIPS → Assembler.json +0 -0
  201. data/config/syntax/MacPorts Portfile.json +298 -0
  202. data/config/syntax/Mail.json +1 -1
  203. data/config/syntax/Markdown.json +6 -6
  204. data/config/syntax/Maven POM.json +774 -0
  205. data/config/syntax/Mediawiki.json +736 -0
  206. data/config/syntax/MoinMoin.json +335 -0
  207. data/config/syntax/MultiMarkdown.json +41 -0
  208. data/config/syntax/Nemerle.json +128 -0
  209. data/config/syntax/OCaml.json +4 -4
  210. data/config/syntax/OCamllex.json +307 -0
  211. data/config/syntax/OCamlyacc.json +346 -0
  212. data/config/syntax/Objective-C++.json +2 -2
  213. data/config/syntax/Objective-C.json +979 -0
  214. data/config/syntax/Octave.json +417 -0
  215. data/config/syntax/PHP.json +32 -32
  216. data/config/syntax/Pascal.json +1 -1
  217. data/config/syntax/Perl.json +8 -8
  218. data/config/syntax/{Plain text.json → Plain Text.json } +1 -1
  219. data/config/syntax/PmWiki.json +241 -0
  220. data/config/syntax/Postscript.json +206 -0
  221. data/config/syntax/Processing.json +8 -8
  222. data/config/syntax/Prolog.json +70 -0
  223. data/config/syntax/Python.json +1934 -0
  224. data/config/syntax/{Quake3 Config.json → Quake Style .cfg.json } +1 -1
  225. data/config/syntax/R.json +2 -2
  226. data/config/syntax/Ragel.json +362 -0
  227. data/config/syntax/Rd (R Documentation).json +119 -0
  228. data/config/syntax/Regular Expressions (Oniguruma).json +186 -0
  229. data/config/syntax/Regular Expressions (Python).json +188 -0
  230. data/config/syntax/Release Notes.json +78 -0
  231. data/config/syntax/Remind.json +461 -0
  232. data/config/syntax/Rez.json +5 -5
  233. data/config/syntax/Ruby Sass.json +497 -0
  234. data/config/syntax/Ruby.json +13 -13
  235. data/config/syntax/S5 Slide Show.json +85 -0
  236. data/config/syntax/SQL.json +11 -11
  237. data/config/syntax/SSH Config.json +55 -0
  238. data/config/syntax/SWIG.json +2 -2
  239. data/config/syntax/SWeave.json +139 -0
  240. data/config/syntax/Scheme.json +8 -8
  241. data/config/syntax/Scilab.json +69 -0
  242. data/config/syntax/Setext.json +247 -0
  243. data/config/syntax/{Shell-Unix-Generic.json → Shell Script (Bash).json } +4 -4
  244. data/config/syntax/Slate.json +5 -5
  245. data/config/syntax/Strings File.json +53 -0
  246. data/config/syntax/TSV.json +83 -0
  247. data/config/syntax/Tcl.json +1 -1
  248. data/config/syntax/TeX Math.json +2 -2
  249. data/config/syntax/TeX.json +2 -2
  250. data/config/syntax/Textile.json +9 -9
  251. data/config/syntax/Thrift.json +641 -0
  252. data/config/syntax/Twiki.json +1 -1
  253. data/config/syntax/Txt2tags.json +154 -0
  254. data/config/syntax/XML strict.json +4 -4
  255. data/config/syntax/XML.json +6 -6
  256. data/config/syntax/XSL.json +2 -2
  257. data/config/syntax/camlp4.json +63 -0
  258. data/config/syntax/mod_perl.json +72 -0
  259. data/config/syntax/reStructuredText.json +1 -1
  260. data/config/syntax/{Subversion commit message.json → svn-commit.tmp.json} +0 -0
  261. data/config/tutorial +23 -19
  262. data/config/welcome +3 -3
  263. data/lib/ver.rb +273 -62
  264. data/lib/ver/entry.rb +142 -26
  265. data/lib/ver/font.rb +51 -0
  266. data/lib/ver/help.rb +16 -0
  267. data/lib/ver/help/describe_key.rb +82 -0
  268. data/lib/ver/help/help_for_help.rb +39 -0
  269. data/lib/ver/hover_completion.rb +129 -0
  270. data/lib/ver/keymap.rb +95 -24
  271. data/lib/ver/layout.rb +107 -43
  272. data/lib/ver/methods.rb +24 -8
  273. data/lib/ver/methods/clipboard.rb +91 -0
  274. data/lib/ver/methods/completion.rb +146 -71
  275. data/lib/ver/methods/control.rb +203 -222
  276. data/lib/ver/methods/ctags.rb +55 -0
  277. data/lib/ver/methods/delete.rb +30 -0
  278. data/lib/ver/methods/help.rb +7 -0
  279. data/lib/ver/methods/insert.rb +233 -1
  280. data/lib/ver/methods/move.rb +181 -32
  281. data/lib/ver/methods/open.rb +208 -0
  282. data/lib/ver/methods/preview.rb +14 -0
  283. data/lib/ver/methods/save.rb +111 -0
  284. data/lib/ver/methods/search.rb +57 -7
  285. data/lib/ver/methods/select.rb +97 -17
  286. data/lib/ver/methods/shortcuts.rb +21 -0
  287. data/lib/ver/methods/views.rb +56 -1
  288. data/lib/ver/mode.rb +60 -14
  289. data/lib/ver/status.rb +97 -19
  290. data/lib/ver/syntax.rb +14 -6
  291. data/lib/ver/syntax/detector.rb +16 -5
  292. data/lib/ver/syntax/processor.rb +9 -3
  293. data/lib/ver/text.rb +258 -199
  294. data/lib/ver/text/index.rb +103 -0
  295. data/lib/ver/theme.rb +27 -16
  296. data/lib/ver/tooltip.rb +59 -0
  297. data/lib/ver/vendor/binary_search.rb +61 -0
  298. data/lib/ver/vendor/levenshtein.rb +57 -0
  299. data/lib/ver/{textpow.rb → vendor/textpow.rb} +31 -29
  300. data/lib/ver/view.rb +65 -41
  301. data/lib/ver/view/console.rb +171 -0
  302. data/lib/ver/view/entry.rb +9 -5
  303. data/lib/ver/view/list.rb +44 -29
  304. data/lib/ver/view/list/ex.rb +71 -0
  305. data/lib/ver/view/list/grep.rb +42 -0
  306. data/lib/ver/view/list/methods.rb +159 -0
  307. data/lib/ver/view/term.rb +249 -0
  308. data/tasks/syntax_list.rake +3 -2
  309. data/ver.gemspec +4 -4
  310. metadata +230 -28
  311. data/config/syntax/Bulletin Board.json +0 -428
  312. data/config/syntax/HTML (Mason).json +0 -207
  313. data/config/syntax/HTML (Rails).json +0 -52
  314. data/config/syntax/Movable Type.json +0 -348
  315. data/config/syntax/Ruby on Rails.json +0 -170
  316. data/config/syntax/SQL (Rails).json +0 -31
  317. data/config/syntax/Smarty.json +0 -110
  318. data/config/syntax/Standard ML.json +0 -322
@@ -110,6 +110,6 @@ Todo:
110
110
 
111
111
  - [M-s] : Save file under different name
112
112
  - [M-x] : Live ruby console (figure out some nice way)
113
- - FFI bindings for X11 so we can communicate with it and have a proper clipboard (xclip is weak)
114
- - Proper handling of [esc], halfdelay works if it's called later, but makes other control characters send signals.
115
- - Handling tabs
113
+ - Better configuration for tabs.
114
+ - Easy runtime configuration
115
+ - Replace that stops after receiving a single char
data/lib/ver.rb CHANGED
@@ -1,107 +1,202 @@
1
1
  # Well begun is half done.
2
2
  # -- Aristotle
3
3
 
4
- # TODO: remove before release
5
- $LOAD_PATH.unshift File.expand_path('../', __FILE__)
4
+ # lazy stdlib
5
+ autoload :Benchmark, 'benchmark'
6
+ autoload :FileUtils, 'fileutils'
6
7
 
7
- # stdlib
8
- require 'tk'
9
- require 'benchmark'
8
+ # 3rd party
9
+ require 'eventmachine'
10
+
11
+ # eager stdlib
10
12
  require 'digest/sha1'
11
- require 'fileutils'
12
13
  require 'json'
13
- require 'pathname'
14
- require 'pp'
14
+ # require 'pp'
15
15
  require 'securerandom'
16
16
  require 'set'
17
- require 'tmpdir'
18
-
19
- class Pathname
20
- alias / join
21
-
22
- def cp(dest)
23
- FileUtils.copy_file(expand_path.to_s, dest.to_s, preserve = true)
24
- end
25
-
26
- def =~(regexp)
27
- to_s =~ regexp
28
- end
29
- end
30
17
 
31
18
  module VER
32
- autoload :BufferListView, 'ver/view/buffer_list_view'
33
19
  autoload :Entry, 'ver/entry'
34
- autoload :FuzzyFileFinderView, 'ver/view/fuzzy_file_finder_view'
20
+ autoload :Help, 'ver/help'
21
+ autoload :Font, 'ver/font'
22
+ autoload :HoverCompletion, 'ver/hover_completion'
35
23
  autoload :Keymap, 'ver/keymap'
36
24
  autoload :Layout, 'ver/layout'
37
- autoload :ListView, 'ver/view/list_view'
38
25
  autoload :Methods, 'ver/methods'
39
26
  autoload :Mode, 'ver/mode'
40
27
  autoload :Status, 'ver/status'
41
- autoload :SyntaxListView, 'ver/view/syntax_list_view'
42
28
  autoload :Syntax, 'ver/syntax'
43
29
  autoload :Text, 'ver/text'
44
- autoload :Textpow, 'ver/textpow'
30
+ autoload :Textpow, 'ver/vendor/textpow'
31
+ autoload :Levenshtein, 'ver/vendor/levenshtein'
45
32
  autoload :Theme, 'ver/theme'
46
- autoload :ThemeListView, 'ver/view/theme_list_view'
47
33
  autoload :View, 'ver/view'
48
34
 
49
- home_conf_dir = Pathname('~/.config/ver').expand_path
50
- core_conf_dir = Pathname(File.expand_path('../../config/', __FILE__))
51
-
52
- # poor man's option system
53
- # p Tk::Tile.themes # a list of available themes
54
- # Linux themes: "classic", "default", "clam", "alt"
55
- OPTIONS = {
56
- font: TkFont.new(family: 'Terminus', size: 9),
57
- tk_theme: 'clam',
58
- theme: 'Blackboard',
59
- keymap: 'vim',
60
- global_quit: 'Control-q',
61
- home_conf_dir: home_conf_dir,
62
- core_conf_dir: core_conf_dir,
63
- loadpath: [home_conf_dir, core_conf_dir],
64
- }
35
+ require 'ver/options'
36
+ @options = Options.new(:ver)
65
37
 
66
38
  class << self
67
39
  attr_reader :root, :layout, :status, :paths, :options
68
40
  end
69
41
 
42
+ options.dsl do
43
+ o "Default Font for all widgets",
44
+ :font, "TkFixedFont 10"
45
+
46
+ o "Internal:External encoding",
47
+ :encoding, "UTF-8:UTF-8"
48
+
49
+ o "Tk Tile Theme",
50
+ :tk_theme, 'clam'
51
+
52
+ o "Syntax highlighting theme",
53
+ :theme, "Blackboard"
54
+
55
+ o "Keymap used",
56
+ :keymap, 'vim'
57
+
58
+ o "Expand all tabs into spaces",
59
+ :expandtab, true
60
+
61
+ o "Use automatic indentation",
62
+ :autoindent, true
63
+
64
+ o "Number of spaces used in autoindent",
65
+ :shiftwidth, 2
66
+
67
+ o "Number of spaces a tab stands for",
68
+ :tabstop, 8
69
+
70
+ o "Number of characters after which wrap commands will wrap",
71
+ :textwidth, 80
72
+
73
+ o "In case of a total failure, this key binding should bail you out",
74
+ :emergency_exit, "<Control-q>"
75
+
76
+ o "Fork off on startup to avoid dying with the terminal",
77
+ :fork, true
78
+
79
+ o "Milliseconds that the cursor is visible when blinking",
80
+ :insertontime, 500
81
+
82
+ o "Milliseconds that the cursor is invisible when blinking",
83
+ :insertofftime, 0
84
+
85
+ o "Width of one tab in pixel",
86
+ :tabs, 10
87
+
88
+ o "Default filetype if no matching syntax can be found",
89
+ :filetype, "Plain Text"
90
+
91
+ o "Location of personal configuration",
92
+ :home_conf_dir, Pathname('~/.config/ver').expand_path
93
+
94
+ o "Location of system-wide configuration",
95
+ :core_conf_dir, Pathname(File.expand_path('../../config/', __FILE__))
96
+
97
+ o "Locations where we look for configuration",
98
+ :loadpath, [home_conf_dir, core_conf_dir]
99
+ end
100
+
70
101
  module_function
71
102
 
72
103
  def loadpath
73
- options[:loadpath]
104
+ options.loadpath
74
105
  end
75
106
 
76
107
  def run(given_options = {})
77
- @options = OPTIONS.merge(given_options)
108
+ @options.merge!(given_options)
109
+
110
+ setup_tk
111
+
112
+ if Tk::RUN_EVENTLOOP_ON_MAIN_THREAD
113
+ run_aqua
114
+ else
115
+ run_x11
116
+ end
117
+ rescue => exception
118
+ VER.error(exception)
119
+ exit
120
+ end
121
+
122
+ def run_aqua
123
+ run_core
124
+ EM.run{ Tk.mainloop }
125
+ end
126
+
127
+ def run_x11
128
+ EM.run do
129
+ EM.defer do
130
+ run_core
131
+ Tk.mainloop
132
+ end
133
+ end
134
+ end
78
135
 
79
- setup
80
- first_startup unless options[:home_conf_dir].directory?
136
+ def run_core
137
+ first_startup unless options.home_conf_dir.directory?
81
138
  load 'rc'
139
+ sanitize_options
140
+ setup_widgets
82
141
  open_argv || open_welcome
83
142
  emergency_bindings
84
-
85
- rescue => exception
86
- puts "#{exception.class}: #{exception}", *exception.backtrace
87
- Tk.exit
88
- else
89
- Tk.mainloop
90
143
  end
91
144
 
92
- def setup
145
+ def setup_tk
146
+ require 'ffi-tk'
93
147
  Thread.abort_on_exception = true
148
+ end
94
149
 
95
- Tk::Tile.set_theme options[:tk_theme]
150
+ def setup_widgets
151
+ Tk::Tile.set_theme options.tk_theme
96
152
 
97
153
  @paths = Set.new
98
- @root = TkRoot.new
154
+ @root = Tk.root
155
+ @root.wm_geometry = '160x80'
99
156
  @layout = Layout.new(@root)
100
157
  @layout.strategy = Layout::VerticalTiling
158
+ @status = Entry.new(@root, font: options.font)
159
+ @status.insert :end, 'For information about VER, type F1'
160
+ @status.pack(fill: :x)
161
+ end
162
+
163
+ def sanitize_options
164
+ font = options.font
165
+
166
+ unless font.respond_to?(:measure)
167
+ font = Tk::Font.new(font)
168
+ actual_hash = font.actual_hash
169
+ options.font = Font.cache[actual_hash] = font
170
+ end
171
+
172
+ tabs = font.measure('0') * options.tabstop
173
+ options.tabs = tabs
174
+
175
+ encoding = options[:encoding]
176
+ unless encoding.is_a?(Encoding)
177
+ external, internal = encoding.to_s.split(':', 2)
178
+
179
+ Encoding.default_external = Encoding.find(external) if external
180
+ Encoding.default_internal = Encoding.find(internal) if internal
181
+ end
182
+
183
+ # We supply a reasonable default in case the platform doesn't have the theme
184
+ # wished for.
185
+ unless Tk::Tile::Style.theme_names.include?(options.tk_theme)
186
+ options.tk_theme = 'default'
187
+ end
188
+
189
+ letter = /[\w\n.-]/
190
+ space = /[^\w.-]/
191
+
192
+ # make sure Tcl already has the vars set
193
+ Tk.interp.eval('catch {tcl_endOfWord}')
194
+ Tk.execute('set', 'tcl_wordchars', letter)
195
+ Tk.execute('set', 'tcl_nonwordchars', space)
101
196
  end
102
197
 
103
198
  def first_startup
104
- home, core = options.values_at(:home_conf_dir, :core_conf_dir)
199
+ home, core = options.home_conf_dir, options.core_conf_dir
105
200
  home.mkpath
106
201
 
107
202
  (core/'rc.rb').cp(home/'rc.rb')
@@ -110,6 +205,12 @@ module VER
110
205
  (core/'welcome').cp(home/'welcome')
111
206
  end
112
207
 
208
+ def exit
209
+ Tk.exit rescue nil
210
+ EM.stop rescue nil
211
+ Kernel.exit
212
+ end
213
+
113
214
  def load(name)
114
215
  loadpath.each do |path|
115
216
  file = File.join(path, name)
@@ -117,7 +218,8 @@ module VER
117
218
  begin
118
219
  require(file)
119
220
  return
120
- rescue LoadError
221
+ rescue LoadError, TypeError => ex
222
+ # TypeError happens on JRuby sometimes...
121
223
  end
122
224
  end
123
225
  end
@@ -132,11 +234,23 @@ module VER
132
234
  end
133
235
 
134
236
  def open_argv
135
- ARGV.each{|arg|
237
+ argv = ARGV.dup
238
+ any = false
239
+
240
+ while arg = argv.shift
136
241
  layout.create_view do |view|
137
- view.open_path(arg)
242
+ if argv.first =~ /\+\d+/
243
+ line = argv.shift.to_i
244
+ view.open_path(arg, line)
245
+ else
246
+ view.open_path(arg)
247
+ end
248
+
249
+ any = true
138
250
  end
139
- }.any?
251
+ end
252
+
253
+ any
140
254
  end
141
255
 
142
256
  def open_welcome
@@ -147,10 +261,107 @@ module VER
147
261
  end
148
262
 
149
263
  def emergency_bindings
150
- Tk.bind :all, options[:global_quit], proc{ exit }
264
+ Tk::Bind.bind(:all, options.emergency_exit){ exit }
151
265
  end
152
266
 
153
267
  def opened_file(text)
154
268
  @paths << text.filename
155
269
  end
270
+
271
+ def error(exception)
272
+ @status.value = exception.message if @status
273
+ error_tree(exception) if @root
274
+ $stderr.puts("#{exception.class}: #{exception}", *exception.backtrace)
275
+ rescue Errno::EIO
276
+ # The original terminal has disappeared, the $stderr pipe was closed on the
277
+ # other side.
278
+ [$stderr, $stdout, $stdin].each(&:close)
279
+ rescue IOError
280
+ # Our pipes are closed, maybe put some output to a file logger here, or display
281
+ # in a nicer way, maybe let it bubble up to Tk handling.
282
+ end
283
+
284
+ def error_tree(exception)
285
+ @tree ||= Tk::Tile::Treeview.new(@root)
286
+ @tree.clear
287
+
288
+ @tree.configure(
289
+ columns: %w[line method],
290
+ displaycolumns: %w[line method]
291
+ )
292
+ @tree.heading('#0', text: 'File')
293
+ @tree.heading('line', text: 'Line')
294
+ @tree.heading('method', text: 'Method')
295
+ @tree.tag_configure('error', background: '#f88')
296
+ @tree.tag_configure('backtrace', background: '#8f8')
297
+
298
+ context_size = 7
299
+ frames = {}
300
+ error_tags = ['error']
301
+ backtrace_tags = ['backtrace']
302
+
303
+ # from Rack::ShowExceptions
304
+ exception.backtrace.each do |line|
305
+ next unless line =~ /(.*?):(\d+)(:in `(.*)')?/
306
+ filename, lineno, function = $1, $2.to_i, $4
307
+
308
+ item = @tree.insert(nil, :end,
309
+ text: filename, values: [lineno, function], tags: error_tags)
310
+
311
+ begin
312
+ lines = ::File.readlines(filename)
313
+ _lineno = lineno - 1
314
+
315
+ first_lineno = [_lineno - context_size, 0].max
316
+ last_lineno = [_lineno + context_size, lines.size].min
317
+ context = lines[first_lineno..last_lineno]
318
+
319
+ frames[item.id] = {
320
+ filename: filename,
321
+ lineno: lineno,
322
+ function: function,
323
+ first_lineno: first_lineno,
324
+ last_lineno: last_lineno,
325
+ context: context,
326
+ }
327
+ rescue => ex
328
+ puts ex, ex.backtrace
329
+ end
330
+ end
331
+
332
+ @tree.focus
333
+ @tree.pack expand: true, fill: :both
334
+
335
+ @tree.bind('<<TreeviewOpen>>'){|event|
336
+ begin
337
+ item = @tree.focus_item
338
+ frame = frames[item.id]
339
+
340
+ case frame
341
+ when Hash
342
+ filename, lineno, first_lineno, context =
343
+ frame.values_at(:filename, :lineno, :first_lineno, :context)
344
+
345
+ context.each_with_index{|line, idx|
346
+ line_lineno = first_lineno + idx + 1
347
+ tags = line_lineno == lineno ? error_tags : backtrace_tags
348
+ line_item = item.insert(:end,
349
+ text: line, values: [line_lineno], tags: tags)
350
+ frames[line_item.id] = [filename, lineno]
351
+ }
352
+ when Array
353
+ filename, lineno = frame
354
+ @layout.views.first.find_or_create(filename, lineno){|view|
355
+ @tree.pack_forget
356
+ }
357
+ end
358
+ rescue => ex
359
+ puts ex, ex.backtrace
360
+ end
361
+ }
362
+ @tree.bind('<Escape>'){
363
+ @tree.pack_forget
364
+ @layout.views.first.focus
365
+ }
366
+ end
156
367
  end
@@ -1,14 +1,21 @@
1
1
  module VER
2
2
  # A custom widget for easier integration
3
3
  #
4
- # The style related things are needed for Tk versions around 8.5.7, which is what everybody is using currently.
5
- # It doesn't GC styles of widgets that are no longer used, so if we simply keep using new style names, we would eventually run out of memory.
4
+ # The style related things are needed for Tk versions around 8.5.7, which is
5
+ # what everybody is using currently.
6
+ # It doesn't GC styles of widgets that are no longer used, so if we simply keep
7
+ # using new style names, we would eventually run out of memory.
6
8
  # A small leak, but better we cover this now than tracking it down later.
7
- # Tk should get some user states, called like 'user1', 'user2', 'user3', that would allow some flexibility, but still won't be able to represent every mode.
9
+ # Tk should get some user states, called like 'user1', 'user2', 'user3', that
10
+ # would allow some flexibility, but still won't be able to represent every mode.
8
11
  class Entry < Tk::Tile::Entry
9
12
  STYLE_NAME_REGISTER = []
10
13
  STYLE_NAME_POOL = []
11
14
 
15
+ space, word = /[^[:alnum:]]+/, /[[:alnum:]]/
16
+ FORWARD_WORD = /#{space}+#{word}|#{word}+#{space}+#{word}/
17
+ BACKWARD_WORD = /#{word}+/
18
+
12
19
  def self.obtain_style_name
13
20
  unless style_name = STYLE_NAME_POOL.shift
14
21
  begin
@@ -31,22 +38,26 @@ module VER
31
38
  end
32
39
 
33
40
  def quit
34
- Tk.exit
41
+ VER.exit
35
42
  end
36
43
 
37
44
  def value=(string)
38
- super
39
- Tk.event_generate(self, '<Modified>')
45
+ execute_only(:delete, 0, :end)
46
+ execute_only(:insert, 0, string)
47
+ Tk::Event.generate(self, '<<Replaced>>')
48
+ Tk::Event.generate(self, '<<Modified>>')
40
49
  end
41
50
 
42
51
  def delete(*args)
43
52
  super
44
- Tk.event_generate(self, '<Modified>')
53
+ Tk::Event.generate(self, '<<Deleted>>')
54
+ Tk::Event.generate(self, '<<Modified>>')
45
55
  end
46
56
 
47
57
  def insert(*args)
48
58
  super
49
- Tk.event_generate(self, '<Modified>')
59
+ Tk::Event.generate(self, '<<Inserted>>')
60
+ Tk::Event.generate(self, '<<Modified>>')
50
61
  end
51
62
 
52
63
  def message(string)
@@ -61,37 +72,142 @@ module VER
61
72
  insert cursor, string
62
73
  end
63
74
 
64
- def delete_char_left
65
- delete(cursor - 1)
75
+ def noop(*args)
66
76
  end
67
77
 
68
- def delete_char_right
69
- delete(cursor)
78
+ # Move to the start of the current line.
79
+ def beginning_of_line
80
+ self.cursor = 0
81
+ end
82
+
83
+ # Move to the end of the line.
84
+ def end_of_line
85
+ self.cursor = :end
86
+ end
87
+
88
+ # Move forward a character.
89
+ def forward_char(count = 1)
90
+ self.cursor += count
91
+ end
92
+
93
+ # Move back a character.
94
+ def backward_char(count = 1)
95
+ self.cursor -= count
96
+ end
97
+
98
+ # Move forward to the end of the next word.
99
+ # Words are composed of alphanumeric characters (letters and digits).
100
+ def forward_word(count = 1)
101
+ count.times do
102
+ return unless md = get.match(FORWARD_WORD, cursor)
103
+ self.cursor = md.offset(0).last
104
+ end
70
105
  end
71
106
 
72
- def go_char_left
73
- self.cursor = cursor - 1
107
+ # Move back to the start of the current or previous word.
108
+ # Words are composed of alphanumeric characters (letters and digits).
109
+ def backward_word(count = 1)
110
+ line = get.reverse
111
+ count.times do
112
+ pos = get.size - cursor
113
+
114
+ return unless md = line.match(BACKWARD_WORD, pos)
115
+ self.cursor = (line.size - md.offset(0).last)
116
+ end
74
117
  end
75
118
 
76
- def go_char_right
77
- self.cursor = cursor + 1
119
+ # Accept the line regardless of where the cursor is.
120
+ # If this line is non-empty, it will be added to the history list.
121
+ # If the line is a modified history line, the history line is restored to
122
+ # its original state.
123
+ def accept_line
124
+ line = get
125
+ @history.unshift(line) unless line.empty?
126
+ @history_index = nil
127
+ Event.generate(self, '<<AcceptLine>>')
128
+ delete 0, :end
78
129
  end
79
130
 
80
- def go_word_left
81
- if index = value.rindex(/.\b\s/, cursor - 1)
82
- self.cursor = index
131
+ # Fetch the previous command from the history list, moving back in the list.
132
+ def previous_history
133
+ history_size = @history.size
134
+
135
+ if @history_index && @history_index < history_size
136
+ @history_index = [@history_index + 1, history_size - 1].min
83
137
  else
84
- self.cursor = 0
138
+ @history_index = 0
139
+ end
140
+
141
+ self.value = @history[@history_index]
142
+ end
143
+
144
+ # Fetch the next command from the history list, moving forward in the list.
145
+ def next_history
146
+ if @history_index && @history_index > 0
147
+ @history_index -= 1
148
+ else
149
+ @history_index = @history.size - 1
150
+ end
151
+
152
+ self.value = @history[@history_index]
153
+ end
154
+
155
+ def beginning_of_history
156
+ @history_index = @history.size - 1
157
+ self.value = @history[@history_index]
158
+ end
159
+
160
+ def end_of_history
161
+ @history_index = 0
162
+ self.value = @history[@history_index]
163
+ end
164
+
165
+ def delete_char
166
+ delete(cursor)
167
+ end
168
+
169
+ def backward_delete_char(yank = nil)
170
+ return if cursor == 0
171
+
172
+ if yank
173
+ @killring.unshift get[cursor - 2]
85
174
  end
175
+
176
+ delete(cursor - 1)
86
177
  end
87
178
 
88
- def go_word_right
89
- if match = value.match(/\s\b/, cursor)
90
- offset_from, offset_to = match.offset(0)
91
- self.cursor = offset_to
179
+ # Delete the character under the cursor, unless the cursor is at the end of
180
+ # the line, in which case the character behind the cursor is deleted.
181
+ def forward_backward_delete_char
182
+ pos = cursor
183
+
184
+ if index(:end) == pos
185
+ delete(cursor - 1)
92
186
  else
93
- self.cursor = :end
187
+ delete(cursor)
94
188
  end
95
189
  end
190
+
191
+ def transpose_chars
192
+ char = get[cursor]
193
+ delete(cursor)
194
+ insert(cursor - 1, char)
195
+ end
196
+
197
+ def delete_motion(motion, count = 1)
198
+ delete(*virtual_movement(motion, count))
199
+ end
200
+
201
+ private
202
+
203
+ def virtual_movement(name, count = 1)
204
+ pos = cursor
205
+ __send__(name, count)
206
+ mark = cursor
207
+ self.cursor = pos
208
+ return [pos, mark].sort
209
+ rescue => ex
210
+ VER.error(ex)
211
+ end
96
212
  end
97
- end
213
+ end