ver 2009.11.29 → 2009.12.14

Sign up to get free protection for your applications and to get access to all the features.
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