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
@@ -0,0 +1,289 @@
1
+ module VER
2
+ module Undo
3
+ # The Tree keeps track of the current Record and creates new records.
4
+ #
5
+ # It maintains a pointer to the widget and the current record in the tree.
6
+ # The current record is the record that was last applied.
7
+ #
8
+ # When a record is undone:
9
+ # If there is a parent, it becomes the new current record.
10
+ # If there is no parent, it stays the current record, only flagged as
11
+ # unapplied.
12
+ # it's parent (if there is one), becomes the new
13
+ # current record.
14
+ #
15
+ # When a record is redone, it's current child (if there is one), becomes the
16
+ # new current record.
17
+ #
18
+ # The Tree doesn't have a maximum depth at the moment, but this will be
19
+ # added, when old records are pruned, only the record at depth+1 that is
20
+ # current stays.
21
+ #
22
+ # Eventually we have to separate records and undo/redo stepping.
23
+ # Some operations involve more than one record, but should be undone/redone
24
+ # together.
25
+ # It would also be handy if these operations could be identified
26
+ # automagically (like multiple operations within one record block).
27
+ class Tree < Struct.new(:widget, :applied, :pending)
28
+ def record_multi
29
+ AutoSeparator.new self do |auto_separator|
30
+ yield auto_separator
31
+ end
32
+
33
+ compact!
34
+ end
35
+
36
+ def record
37
+ current = Record.new(widget, applied)
38
+
39
+ yield current
40
+
41
+ applied.next = current if applied = self.applied
42
+
43
+ self.applied = current
44
+ self.applied = current
45
+ self.pending = nil
46
+ end
47
+
48
+ # Undo last applied change so it becomes the next pending change.
49
+ # Parent of the applied change becomes the next applied change.
50
+ def undo
51
+ while applied = self.applied
52
+ applied.undo
53
+
54
+ self.pending = applied
55
+ self.applied = applied = applied.parent
56
+
57
+ break if applied && applied.separator
58
+ end
59
+ end
60
+
61
+ # Redo pending change so it becomes the new applied change.
62
+ # If the pending change has a next child, it becomes the new pending one.
63
+ def redo
64
+ while pending = self.pending
65
+ pending.redo
66
+
67
+ self.applied = pending
68
+ self.pending = pending.next
69
+
70
+ break if pending && pending.separator
71
+ end
72
+ end
73
+
74
+ # Join previous applied changes that have only one child and that modify
75
+ # data consecutive.
76
+ # This rewrites already applied history only.
77
+ def compact!
78
+ return unless applied
79
+ applied.compact!
80
+ self.pending = applied.next
81
+ end
82
+
83
+ def separate!
84
+ applied.separator = true if applied
85
+ end
86
+ end
87
+
88
+ class AutoSeparator < Struct.new(:tree, :records)
89
+ def initialize(tree)
90
+ self.tree = tree
91
+ self.records = []
92
+
93
+ yield(self) if block_given?
94
+
95
+ records.last.separator = true if records.any?
96
+ end
97
+
98
+ def insert(*args)
99
+ tree.record do |record|
100
+ record.insert(*args)
101
+ records << record
102
+ end
103
+ end
104
+
105
+ def replace(*args)
106
+ tree.record do |record|
107
+ record.replace(*args)
108
+ records << record
109
+ end
110
+ end
111
+
112
+ def delete(*args)
113
+ tree.record do |record|
114
+ record.delete(*args)
115
+ records << record
116
+ end
117
+ end
118
+ end
119
+
120
+ # Every Record is responsible for one change that it can apply or undo.
121
+ # There is only a very limited set of methods for modifications, as some of
122
+ # the destructive String methods in Ruby can have unpredictable results.
123
+ # In order to undo a change, we have to predict what the change will do
124
+ # before it happens to avoid expensive diff algorithms.
125
+ #
126
+ # A Record has one parent and a number of childs.
127
+ # If there are any childs, one of them is called current, and is the child
128
+ # that was last active, this way we can provide an intuitive way of choosing
129
+ # a child record to apply when a user wants to redo an undone change.
130
+ #
131
+ # Record has a direct pointer to the data in the tree, since it has to know
132
+ # about nothing else.
133
+ #
134
+ # Apart from that, Record also knows the time when it was created, this way
135
+ # you can move forward and backward in time.
136
+ #
137
+ # Revisions only keep the data necessary to undo/redo a change, not the whole
138
+ # data that was modified, that way it can keep overall memory-usage to a
139
+ # minimum.
140
+ #
141
+ # The applied property indicates whether or not this change has been applied
142
+ # already.
143
+ class Record < Struct.new(:widget, :parent, :ctime, :childs, :applied,
144
+ :undo_info, :redo_info, :separator)
145
+
146
+ def initialize(widget, parent = nil)
147
+ self.widget, self.parent = widget, parent
148
+ self.ctime = Time.now
149
+ self.childs = []
150
+ self.applied = false
151
+ self.separator = false
152
+ end
153
+
154
+ def insert(pos, string)
155
+ pos = widget.index(pos) unless pos.respond_to?(:to_index)
156
+
157
+ widget.execute_only(:insert, pos, string)
158
+ widget.touch!(pos)
159
+
160
+ self.redo_info = [:insert, pos, string]
161
+ self.undo_info = [pos, pos + string.size, '']
162
+ self.applied = true
163
+ end
164
+
165
+ def replace(from, to, string)
166
+ from = widget.index(from) unless from.respond_to?(:to_index)
167
+ to = widget.index(to) unless to.respond_to?(:to_index)
168
+
169
+ data = widget.get(from, to)
170
+ widget.execute_only(:replace, from, to, string)
171
+ widget.touch!(*from.upto(to))
172
+
173
+ self.redo_info = [:replace, from, to, string]
174
+ self.undo_info = [from, from + string.size, data]
175
+ self.applied = true
176
+ end
177
+
178
+ def delete(from, to)
179
+ from = widget.index(from) unless from.respond_to?(:to_index)
180
+ to = widget.index(to) unless to.respond_to?(:to_index)
181
+
182
+ data = widget.get(from, to)
183
+ widget.execute_only(:delete, from, to)
184
+ widget.touch!(*from.upto(to))
185
+
186
+ self.redo_info = [:delete, from, to]
187
+ self.undo_info = [from, from, data]
188
+ self.applied = true
189
+ end
190
+
191
+ def undo
192
+ return unless undo_info && applied
193
+
194
+ from, to, string = undo_info
195
+ widget.execute_only(:replace, from, to, string)
196
+
197
+ self.applied = false
198
+ end
199
+
200
+ def redo
201
+ return unless redo_info && !applied
202
+ send(*redo_info)
203
+ end
204
+
205
+ def compact!
206
+ return if separator
207
+ return unless parent = self.parent
208
+
209
+ pundo_from, pundo_to, pundo_string = parent.undo_info
210
+ sundo_from, sundo_to, sundo_string = undo_info
211
+
212
+ predo_name, *predo_args = parent.redo_info
213
+ sredo_name, *sredo_args = redo_info
214
+
215
+ # only compact identical methods
216
+ return unless predo_name == sredo_name
217
+
218
+ case predo_name
219
+ when :insert
220
+ predo_pos, predo_string = predo_args
221
+ sredo_pos, sredo_string = sredo_args
222
+
223
+ # the records have to be consecutive so they can still be applied by a
224
+ # single undo/redo
225
+ consecutive = (predo_pos + predo_string.size) == sredo_pos
226
+ return parent.compact! unless consecutive
227
+
228
+ redo_string = "#{predo_string}#{sredo_string}"
229
+ self.redo_info = [:insert, predo_pos, redo_string]
230
+
231
+ undo_string = "#{pundo_string}#{sundo_string}"
232
+ self.undo_info = [pundo_from, sundo_to, undo_string]
233
+ when :replace
234
+ predo_from, predo_to, predo_string = predo_args
235
+ sredo_from, sredo_to, sredo_string = sredo_args
236
+
237
+ # the records have to be consecutive so they can still be applied by a
238
+ # single undo/redo
239
+ consecutive = predo_to == sredo_from
240
+ return parent.compact! unless consecutive
241
+
242
+ redo_string = "#{predo_string}#{sredo_string}"
243
+ self.redo_info = [:replace, predo_from, sredo_to, undo_string]
244
+
245
+ undo_string = "#{pundo_string}#{sundo_string}"
246
+ self.undo_info = [pundo_from, sundo_to, undo_string]
247
+ when :delete
248
+ predo_from, predo_to = predo_args
249
+ sredo_from, sredo_to = sredo_args
250
+
251
+ consecutive = predo_to == sredo_from
252
+ return parent.compact! unless consecutive
253
+
254
+ self.redo_info = [:delete, predo_from, sredo_to]
255
+
256
+ undo_string = "#{sundo_string}#{pundo_string}"
257
+ self.undo_info = [pundo_from, sundo_to, undo_string]
258
+ else
259
+ return
260
+ end
261
+
262
+ # the parent of our parent (grandparent) becomes our parent
263
+ self.parent = grandparent = parent.parent
264
+
265
+ # recurse into a new compact cycle if we have a grandparent
266
+ if grandparent
267
+ grandparent.next = self
268
+ compact!
269
+ end
270
+ end
271
+
272
+ def next=(child)
273
+ childs.unshift(childs.delete(child) || child)
274
+ end
275
+
276
+ def next
277
+ childs.first
278
+ end
279
+
280
+ def applied?
281
+ applied
282
+ end
283
+
284
+ def inspect
285
+ "#<Undo::Record sep=%p undo=%p redo=%p>" % [separator, undo_info, redo_info]
286
+ end
287
+ end
288
+ end
289
+ end
@@ -0,0 +1,70 @@
1
+ # The MIT Licence
2
+ #
3
+ # Copyright (c) 2004-2009 Pistos
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ class SizedArray < Array
24
+ attr_reader :capacity
25
+
26
+ def initialize( capacity = 10, *args )
27
+ @capacity = capacity
28
+ super( *args )
29
+ end
30
+
31
+ def resize
32
+ if size > @capacity
33
+ slice!( (0...-@capacity) )
34
+ end
35
+ end
36
+ private :resize
37
+
38
+ def concat( other_array )
39
+ super( other_array )
40
+ resize
41
+ self
42
+ end
43
+
44
+ def fill( *args )
45
+ retval = super( *args )
46
+ resize
47
+ self
48
+ end
49
+
50
+ def <<( item )
51
+ retval = super( item )
52
+ if size > @capacity
53
+ retval = shift
54
+ end
55
+ retval
56
+ end
57
+
58
+ def push( item )
59
+ self << item
60
+ end
61
+
62
+ def unshift( item )
63
+ retval = super( item )
64
+ if size > @capacity
65
+ retval = pop
66
+ end
67
+ retval
68
+ end
69
+ end
70
+
@@ -352,7 +352,12 @@ module Textpow
352
352
  end
353
353
  end
354
354
 
355
- position = end_pos
355
+ if position >= end_pos
356
+ # raise "Parser didn't move forward on line: %p" % [line]
357
+ return
358
+ else
359
+ position = end_pos
360
+ end
356
361
  end
357
362
  end
358
363
  end
@@ -0,0 +1,3 @@
1
+ module VER
2
+ VERSION = "2009.12.14"
3
+ end
@@ -26,21 +26,25 @@ module VER
26
26
  # | @status |
27
27
  # +-----------+
28
28
  def setup
29
- setup_text
30
- # setup_scrollbars # enable if you really want some.
31
- setup_status
29
+ setup_widgets
32
30
  setup_grid
33
31
  setup_misc
34
32
  setup_events
35
33
  end
36
34
 
35
+ def setup_widgets
36
+ setup_text
37
+ setup_vertical_scrollbar if VER.options.vertical_scrollbar
38
+ setup_horizontal_scrollbar if VER.options.horizontal_scrollbar
39
+ setup_status
40
+ end
41
+
37
42
  def setup_text
38
43
  font, tabstop = VER.options.font, VER.options.tabstop
39
44
  tabs = font.measure('0') * tabstop
40
45
 
41
46
  @text = VER::Text.new(
42
47
  self,
43
- autoseparators: true, # insert separators into the undo flow
44
48
  borderwidth: 0,
45
49
  exportselection: true, # copy into X11 buffer automatically
46
50
  font: font,
@@ -50,17 +54,16 @@ module VER
50
54
  takefocus: true,
51
55
  tabs: tabs,
52
56
  tabstyle: :wordprocessor,
53
- undo: true, # enable undo capabilities
54
57
  wrap: :word
55
58
  )
56
59
  end
57
60
 
58
- def setup_scrollbars
59
- # vertical scrollbar
61
+ def setup_vertical_scrollbar
60
62
  @ybar = Tk::Tile::YScrollbar.new(self)
61
63
  @text.yscrollbar(@ybar)
64
+ end
62
65
 
63
- # horizontal scrollbar
66
+ def setup_horizontal_scrollbar
64
67
  @xbar = Tk::Tile::XScrollbar.new(self)
65
68
  @text.xscrollbar(@xbar)
66
69
  end
@@ -1,5 +1,12 @@
1
1
  module VER
2
2
  class View::List::Grep < View::List
3
+ def initialize(parent, glob = nil, &block)
4
+ super(parent, &block)
5
+
6
+ @glob = nil
7
+ @glob = glob.to_s unless glob.nil?
8
+ end
9
+
3
10
  def update
4
11
  list.clear
5
12
 
@@ -17,11 +24,15 @@ module VER
17
24
  def grep(input)
18
25
  @choices = []
19
26
 
20
- input, query = input.split(/ /, 2)
21
- input, query = nil, input unless query
22
- input ||= '*'
27
+ if @glob
28
+ input, query = @glob, input
29
+ else
30
+ input, query = input.split(/ /, 2)
31
+ input, query = nil, input unless query
32
+ input ||= '*'
23
33
 
24
- return [] if !query || query.size < 3 # protect a little
34
+ return [] if !query || query.size < 3 # protect a little
35
+ end
25
36
 
26
37
  regex = /#{Regexp.escape(query)}/
27
38