ver 2009.11.29 → 2009.12.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. data/AUTHORS +6 -0
  2. data/CHANGELOG +353 -1
  3. data/LICENSE +18 -0
  4. data/MANIFEST +11 -1
  5. data/Rakefile +2 -1
  6. data/bin/ver +3 -12
  7. data/config/detect.rb +1 -1
  8. data/config/keymap/diakonos.rb +181 -0
  9. data/config/keymap/emacs.rb +24 -24
  10. data/config/keymap/vim.rb +162 -127
  11. data/config/rc.rb +29 -14
  12. data/config/syntax/Nemerle.json +3 -3
  13. data/lib/ver.rb +88 -134
  14. data/lib/ver/entry.rb +5 -0
  15. data/lib/ver/exception_view.rb +97 -0
  16. data/lib/ver/hover_completion.rb +14 -7
  17. data/lib/ver/keymap.rb +30 -1
  18. data/lib/ver/layout.rb +20 -14
  19. data/lib/ver/methods.rb +6 -15
  20. data/lib/ver/methods/bookmark.rb +189 -0
  21. data/lib/ver/methods/completion.rb +2 -2
  22. data/lib/ver/methods/control.rb +109 -26
  23. data/lib/ver/methods/ctags.rb +28 -4
  24. data/lib/ver/methods/delete.rb +85 -4
  25. data/lib/ver/methods/insert.rb +73 -52
  26. data/lib/ver/methods/move.rb +122 -35
  27. data/lib/ver/methods/open.rb +4 -43
  28. data/lib/ver/methods/search.rb +46 -17
  29. data/lib/ver/methods/select.rb +121 -24
  30. data/lib/ver/methods/undo.rb +23 -0
  31. data/lib/ver/methods/views.rb +5 -0
  32. data/lib/ver/mode.rb +18 -17
  33. data/lib/ver/status.rb +2 -2
  34. data/lib/ver/status/context.rb +166 -0
  35. data/lib/ver/text.rb +43 -81
  36. data/lib/ver/text/index.rb +24 -7
  37. data/lib/ver/undo.rb +289 -0
  38. data/lib/ver/vendor/sized_array.rb +70 -0
  39. data/lib/ver/vendor/textpow.rb +6 -1
  40. data/lib/ver/version.rb +3 -0
  41. data/lib/ver/view.rb +11 -8
  42. data/lib/ver/view/list/grep.rb +15 -4
  43. data/lib/ver/view/term.rb +9 -3
  44. data/spec/helper.rb +94 -0
  45. data/ver.gemspec +9 -6
  46. metadata +25 -5
  47. data/spec/keymap.rb +0 -224
@@ -1,10 +1,28 @@
1
1
  VER.options.dsl do
2
- o "Default Font for all widgets",
3
- :font, "TkFixedFont 10"
2
+ o "Use automatic indentation",
3
+ :autoindent, true
4
+
5
+ o "Sequence to comment a line, may change through file type preferences",
6
+ :comment_line, '#'
7
+
8
+ o "Start and end sequence to comment a region, may change through file type preferences",
9
+ :comment_region, ['=begin', '=end']
4
10
 
5
11
  o "Internal:External encoding",
6
12
  :encoding, "UTF-8:UTF-8"
7
13
 
14
+ o "Expand all tabs into spaces",
15
+ :expandtab, true
16
+
17
+ o "In case of a total failure, this key binding should bail you out",
18
+ :emergency_exit, "<Control-q>"
19
+
20
+ o "Default Font for all widgets",
21
+ :font, "TkFixedFont 10"
22
+
23
+ o "Fork off on startup to avoid dying with the terminal",
24
+ :fork, true
25
+
8
26
  o "Tk Tile Theme",
9
27
  :tk_theme, 'clam'
10
28
 
@@ -14,12 +32,6 @@ VER.options.dsl do
14
32
  o "Keymap used",
15
33
  :keymap, 'vim'
16
34
 
17
- o "Expand all tabs into spaces",
18
- :expandtab, true
19
-
20
- o "Use automatic indentation",
21
- :autoindent, true
22
-
23
35
  o "Number of spaces used in autoindent",
24
36
  :shiftwidth, 2
25
37
 
@@ -29,11 +41,14 @@ VER.options.dsl do
29
41
  o "Number of characters after which wrap commands will wrap",
30
42
  :textwidth, 80
31
43
 
32
- o "In case of a total failure, this key binding should bail you out",
33
- :emergency_exit, "<Control-q>"
44
+ o "Minimum size of search term to start incremental highlighting",
45
+ :search_incremental_min, 1
34
46
 
35
- o "Fork off on startup to avoid dying with the terminal",
36
- :fork, true
47
+ o "Show vertical scrollbar",
48
+ :vertical_scrollbar, false
49
+
50
+ o "Show horizontal scrollbar",
51
+ :horizontal_scrollbar, false
37
52
 
38
53
  o "Milliseconds that the cursor is visible when blinking",
39
54
  :insertontime, 500
@@ -41,8 +56,8 @@ VER.options.dsl do
41
56
  o "Milliseconds that the cursor is invisible when blinking",
42
57
  :insertofftime, 0
43
58
 
44
- o "Width of one tab in pixel",
45
- :tabs, 10
59
+ o "Format for Statusline",
60
+ :statusline, '%r\t%4l,%c %P\t[%m%_s%_e]'
46
61
 
47
62
  o "Default filetype if no matching syntax can be found",
48
63
  :filetype, "Plain Text"
@@ -2,8 +2,8 @@
2
2
  "fileTypes": [
3
3
  "n"
4
4
  ],
5
- "foldingStartMarker": "(\\{|(|<\\[)",
6
- "foldingStopMarker": "(\\}|)|]>)",
5
+ "foldingStartMarker": "(\\{|\\(|<\\[)",
6
+ "foldingStopMarker": "(\\}|\\)|\\]>)",
7
7
  "keyEquivalent": "^~N",
8
8
  "name": "Nemerle",
9
9
  "patterns": [
@@ -125,4 +125,4 @@
125
125
  ],
126
126
  "scopeName": "source.nemerle",
127
127
  "uuid": "F563968D-4CB3-11DB-9F95-00112474B8F0"
128
- }
128
+ }
data/lib/ver.rb CHANGED
@@ -1,5 +1,5 @@
1
- # Well begun is half done.
2
- # -- Aristotle
1
+ # Man must shape his tools lest they shape him.
2
+ # -- Arthur R. Miller
3
3
 
4
4
  # lazy stdlib
5
5
  autoload :Benchmark, 'benchmark'
@@ -14,6 +14,9 @@ require 'json'
14
14
  # require 'pp'
15
15
  require 'securerandom'
16
16
  require 'set'
17
+ require 'pathname'
18
+
19
+ autoload :SizedArray, 'ver/vendor/sized_array'
17
20
 
18
21
  module VER
19
22
  autoload :Entry, 'ver/entry'
@@ -31,62 +34,35 @@ module VER
31
34
  autoload :Levenshtein, 'ver/vendor/levenshtein'
32
35
  autoload :Theme, 'ver/theme'
33
36
  autoload :View, 'ver/view'
37
+ autoload :ExceptionView, 'ver/exception_view'
38
+ autoload :Bookmarks, 'ver/methods/bookmark'
39
+ autoload :Bookmark, 'ver/methods/bookmark'
40
+ autoload :Undo, 'ver/undo'
34
41
 
35
42
  require 'ver/options'
36
43
  @options = Options.new(:ver)
37
44
 
38
45
  class << self
39
- attr_reader :root, :layout, :status, :paths, :options
46
+ attr_reader(:root, :layout, :status, :paths, :options, :bookmarks,
47
+ :ctag_stack)
40
48
  end
41
49
 
50
+ # the rest of the options are in config/rc.rb
42
51
  options.dsl do
43
- o "Default Font for all widgets",
44
- :font, "TkFixedFont 10"
52
+ o "Fork off on startup to avoid dying with the terminal",
53
+ :fork, true
45
54
 
46
55
  o "Internal:External encoding",
47
56
  :encoding, "UTF-8:UTF-8"
48
57
 
49
- o "Tk Tile Theme",
50
- :tk_theme, 'clam'
51
-
52
- o "Syntax highlighting theme",
53
- :theme, "Blackboard"
54
-
55
58
  o "Keymap used",
56
59
  :keymap, 'vim'
57
60
 
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
61
  o "Width of one tab in pixel",
86
62
  :tabs, 10
87
63
 
88
- o "Default filetype if no matching syntax can be found",
89
- :filetype, "Plain Text"
64
+ o "Minimum size of search term to start incremental highlighting",
65
+ :search_incremental_min, 1
90
66
 
91
67
  o "Location of personal configuration",
92
68
  :home_conf_dir, Pathname('~/.config/ver').expand_path
@@ -104,39 +80,56 @@ module VER
104
80
  options.loadpath
105
81
  end
106
82
 
107
- def run(given_options = {})
108
- @options.merge!(given_options)
109
-
83
+ def run(given_options = {}, &block)
110
84
  setup_tk
85
+ run_startup(given_options)
111
86
 
112
- if Tk::RUN_EVENTLOOP_ON_MAIN_THREAD
113
- run_aqua
114
- else
115
- run_x11
87
+ forking do
88
+ if Tk::RUN_EVENTLOOP_ON_MAIN_THREAD
89
+ run_aqua(&block)
90
+ else
91
+ run_x11(&block)
92
+ end
116
93
  end
117
94
  rescue => exception
118
95
  VER.error(exception)
119
96
  exit
120
97
  end
121
98
 
122
- def run_aqua
99
+ def run_aqua(&block)
123
100
  run_core
124
- EM.run{ Tk.mainloop }
101
+ EM.defer(&block) if block
102
+ Tk.mainloop
103
+ end
104
+
105
+ def run_x11(&block)
106
+ EM.defer do
107
+ run_core
108
+ EM.defer(&block) if block
109
+ Tk.mainloop
110
+ end
125
111
  end
126
112
 
127
- def run_x11
128
- EM.run do
129
- EM.defer do
130
- run_core
131
- Tk.mainloop
113
+ def forking
114
+ if options.fork
115
+ fork do
116
+ trap(:HUP){ 'terminal disconnected' }
117
+ EM.run{ yield }
132
118
  end
119
+ else
120
+ EM.run{ yield }
133
121
  end
134
122
  end
135
123
 
136
- def run_core
124
+ def run_startup(given_options)
137
125
  first_startup unless options.home_conf_dir.directory?
138
126
  load 'rc'
127
+ @options.merge!(given_options)
128
+ end
129
+
130
+ def run_core
139
131
  sanitize_options
132
+ # dump_options
140
133
  setup_widgets
141
134
  open_argv || open_welcome
142
135
  emergency_bindings
@@ -151,13 +144,20 @@ module VER
151
144
  Tk::Tile.set_theme options.tk_theme
152
145
 
153
146
  @paths = Set.new
147
+
154
148
  @root = Tk.root
155
149
  @root.wm_geometry = '160x80'
150
+
156
151
  @layout = Layout.new(@root)
157
152
  @layout.strategy = Layout::VerticalTiling
153
+
158
154
  @status = Entry.new(@root, font: options.font)
159
155
  @status.insert :end, 'For information about VER, type F1'
160
156
  @status.pack(fill: :x)
157
+
158
+ @exception_view = nil
159
+ @bookmarks = Bookmarks.new
160
+ @ctag_stack = []
161
161
  end
162
162
 
163
163
  def sanitize_options
@@ -268,9 +268,30 @@ module VER
268
268
  @paths << text.filename
269
269
  end
270
270
 
271
+ def dump_options
272
+ out = []
273
+
274
+ options.each_pair do |key, value|
275
+ out << [key,
276
+ case value
277
+ when Tk::Font
278
+ "VER::Font[%p]" % [value.actual_hash]
279
+ when Pathname
280
+ value.to_s
281
+ else
282
+ value
283
+ end
284
+ ]
285
+ end
286
+
287
+ out.each do |pair|
288
+ puts("VER.options.%s = %p" % pair)
289
+ end
290
+ end
291
+
271
292
  def error(exception)
272
293
  @status.value = exception.message if @status
273
- error_tree(exception) if @root
294
+ exception_view(exception) if @root
274
295
  $stderr.puts("#{exception.class}: #{exception}", *exception.backtrace)
275
296
  rescue Errno::EIO
276
297
  # The original terminal has disappeared, the $stderr pipe was closed on the
@@ -281,87 +302,20 @@ module VER
281
302
  # in a nicer way, maybe let it bubble up to Tk handling.
282
303
  end
283
304
 
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)
305
+ def exception_view(exception)
306
+ unless @exception_view
307
+ @exception_view ||= ExceptionView.new(@root)
310
308
 
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
309
+ @exception_view.bind '<<TreeviewOpen>>' do
310
+ @exception_view.on_treeview_open
329
311
  end
330
- end
331
-
332
- @tree.focus
333
- @tree.pack expand: true, fill: :both
334
312
 
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
313
+ @exception_view.bind '<Escape>' do
314
+ @exception_view.pack_forget
315
+ @layout.views.first.focus
360
316
  end
361
- }
362
- @tree.bind('<Escape>'){
363
- @tree.pack_forget
364
- @layout.views.first.focus
365
- }
317
+ end
318
+
319
+ @exception_view.show(exception)
366
320
  end
367
321
  end
@@ -53,6 +53,7 @@ module VER
53
53
  Tk::Event.generate(self, '<<Deleted>>')
54
54
  Tk::Event.generate(self, '<<Modified>>')
55
55
  end
56
+ alias kill delete # nobody wants to copy that way, right? ;)
56
57
 
57
58
  def insert(*args)
58
59
  super
@@ -198,6 +199,10 @@ module VER
198
199
  delete(*virtual_movement(motion, count))
199
200
  end
200
201
 
202
+ def kill_motion(motion, count = 1)
203
+ kill(*virtual_movement(motion, count))
204
+ end
205
+
201
206
  private
202
207
 
203
208
  def virtual_movement(name, count = 1)
@@ -0,0 +1,97 @@
1
+ module VER
2
+ class ExceptionView < Tk::Tile::Treeview
3
+ OPTIONS = {
4
+ context: 7,
5
+ }
6
+
7
+ attr_reader :tree, :frames, :context_size, :error_tags, :backtrace_tags
8
+
9
+ def initialize(parent, options = {})
10
+ super
11
+
12
+ @frames = {}
13
+ @context_size = OPTIONS[:context]
14
+ @error_tags = ['error']
15
+ @backtrace_tags = ['backtrace']
16
+
17
+ setup_config
18
+ end
19
+
20
+ def setup_config
21
+ configure(
22
+ columns: %w[line method],
23
+ displaycolumns: %w[line method]
24
+ )
25
+
26
+ heading('#0', text: 'File')
27
+ heading('line', text: 'Line')
28
+ heading('method', text: 'Method')
29
+
30
+ tag_configure('error', background: '#f88')
31
+ tag_configure('backtrace', background: '#8f8')
32
+ end
33
+
34
+ def on_treeview_open
35
+ item = focus_item
36
+ frame = frames[item.id]
37
+
38
+ case frame
39
+ when Hash
40
+ filename, lineno, first_lineno, context =
41
+ frame.values_at(:filename, :lineno, :first_lineno, :context)
42
+
43
+ context.each_with_index{|line, idx|
44
+ line_lineno = first_lineno + idx + 1
45
+ tags = line_lineno == lineno ? error_tags : backtrace_tags
46
+ line_item = item.insert(:end,
47
+ text: line, values: [line_lineno], tags: tags)
48
+ frames[line_item.id] = [filename, lineno]
49
+ }
50
+ when Array
51
+ filename, lineno = frame
52
+ VER.layout.views.first.find_or_create(filename, lineno){|view|
53
+ pack_forget
54
+ }
55
+ end
56
+ rescue => ex # careful here, don't want infinite loop
57
+ puts ex, ex.backtrace
58
+ end
59
+
60
+ def show(exception)
61
+ clear
62
+
63
+ # from Rack::ShowExceptions
64
+ exception.backtrace.each do |line|
65
+ next unless line =~ /(.*?):(\d+)(:in `(.*)')?/
66
+ show_line($1, $2.to_i, $4)
67
+ end
68
+
69
+ focus
70
+ pack expand: true, fill: :both
71
+ end
72
+
73
+ def show_line(filename, lineno, function)
74
+ item = insert(nil, :end,
75
+ text: filename, values: [lineno, function], tags: error_tags)
76
+
77
+ # may fail from here on without issues.
78
+ lines = ::File.readlines(filename)
79
+ _lineno = lineno - 1
80
+
81
+ first_lineno = [_lineno - context_size, 0].max
82
+ last_lineno = [_lineno + context_size, lines.size].min
83
+ context = lines[first_lineno..last_lineno]
84
+
85
+ frames[item.id] = {
86
+ filename: filename,
87
+ lineno: lineno,
88
+ function: function,
89
+ first_lineno: first_lineno,
90
+ last_lineno: last_lineno,
91
+ context: context,
92
+ }
93
+ rescue => ex
94
+ puts ex, ex.backtrace
95
+ end
96
+ end
97
+ end