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.
- data/AUTHORS +6 -0
- data/CHANGELOG +353 -1
- data/LICENSE +18 -0
- data/MANIFEST +11 -1
- data/Rakefile +2 -1
- data/bin/ver +3 -12
- data/config/detect.rb +1 -1
- data/config/keymap/diakonos.rb +181 -0
- data/config/keymap/emacs.rb +24 -24
- data/config/keymap/vim.rb +162 -127
- data/config/rc.rb +29 -14
- data/config/syntax/Nemerle.json +3 -3
- data/lib/ver.rb +88 -134
- data/lib/ver/entry.rb +5 -0
- data/lib/ver/exception_view.rb +97 -0
- data/lib/ver/hover_completion.rb +14 -7
- data/lib/ver/keymap.rb +30 -1
- data/lib/ver/layout.rb +20 -14
- data/lib/ver/methods.rb +6 -15
- data/lib/ver/methods/bookmark.rb +189 -0
- data/lib/ver/methods/completion.rb +2 -2
- data/lib/ver/methods/control.rb +109 -26
- data/lib/ver/methods/ctags.rb +28 -4
- data/lib/ver/methods/delete.rb +85 -4
- data/lib/ver/methods/insert.rb +73 -52
- data/lib/ver/methods/move.rb +122 -35
- data/lib/ver/methods/open.rb +4 -43
- data/lib/ver/methods/search.rb +46 -17
- data/lib/ver/methods/select.rb +121 -24
- data/lib/ver/methods/undo.rb +23 -0
- data/lib/ver/methods/views.rb +5 -0
- data/lib/ver/mode.rb +18 -17
- data/lib/ver/status.rb +2 -2
- data/lib/ver/status/context.rb +166 -0
- data/lib/ver/text.rb +43 -81
- data/lib/ver/text/index.rb +24 -7
- data/lib/ver/undo.rb +289 -0
- data/lib/ver/vendor/sized_array.rb +70 -0
- data/lib/ver/vendor/textpow.rb +6 -1
- data/lib/ver/version.rb +3 -0
- data/lib/ver/view.rb +11 -8
- data/lib/ver/view/list/grep.rb +15 -4
- data/lib/ver/view/term.rb +9 -3
- data/spec/helper.rb +94 -0
- data/ver.gemspec +9 -6
- metadata +25 -5
- data/spec/keymap.rb +0 -224
data/lib/ver/status.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module VER
|
2
2
|
# The status bar
|
3
3
|
class Status < VER::Entry
|
4
|
+
autoload :Context, 'ver/status/context'
|
5
|
+
|
4
6
|
attr_accessor :keymap, :view
|
5
7
|
attr_reader :mode
|
6
8
|
|
@@ -112,7 +114,6 @@ module VER
|
|
112
114
|
@history_idx = history.size - 1
|
113
115
|
end
|
114
116
|
|
115
|
-
p prev: [history, @history_idx]
|
116
117
|
answer = history[@history_idx]
|
117
118
|
return unless answer
|
118
119
|
self.value = answer
|
@@ -126,7 +127,6 @@ module VER
|
|
126
127
|
@history_idx = 0
|
127
128
|
end
|
128
129
|
|
129
|
-
p next: [history, @history_idx]
|
130
130
|
answer = history[@history_idx]
|
131
131
|
return unless answer
|
132
132
|
self.value = answer
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module VER
|
2
|
+
class Status
|
3
|
+
class Context < Struct.new(:text)
|
4
|
+
def filename(width = 0)
|
5
|
+
"%#{width}s" % text.filename
|
6
|
+
end
|
7
|
+
alias F filename
|
8
|
+
|
9
|
+
def basename(width = 0)
|
10
|
+
"%#{width}s" % text.filename.basename
|
11
|
+
end
|
12
|
+
alias f basename
|
13
|
+
|
14
|
+
def relative(width = 0)
|
15
|
+
"%#{width}s" % text.short_filename
|
16
|
+
end
|
17
|
+
alias r relative
|
18
|
+
|
19
|
+
def dir(width = 0)
|
20
|
+
"%#{width}s" % text.filename.directory
|
21
|
+
end
|
22
|
+
alias d dir
|
23
|
+
|
24
|
+
def line(width = 0)
|
25
|
+
"%#{width}s" % (text.count(1.0, :insert, :lines) + 1)
|
26
|
+
end
|
27
|
+
alias l line
|
28
|
+
|
29
|
+
def lines(width = 0)
|
30
|
+
"%#{width}s" % text.count(1.0, :end, :lines)
|
31
|
+
end
|
32
|
+
alias L lines
|
33
|
+
|
34
|
+
def column(width = 0)
|
35
|
+
"%#{width}s" % text.count('insert linestart', :insert, :displaychars)
|
36
|
+
end
|
37
|
+
alias c column
|
38
|
+
|
39
|
+
def percent
|
40
|
+
here = text.count(1.0, :insert, :lines)
|
41
|
+
total = text.count(1.0, :end, :lines)
|
42
|
+
percent = ((100.0 / total) * here).round
|
43
|
+
|
44
|
+
case percent
|
45
|
+
when 100; 'Bot'
|
46
|
+
when 0 ; 'Top'
|
47
|
+
else ; '%2d%%' % percent
|
48
|
+
end
|
49
|
+
end
|
50
|
+
alias P percent
|
51
|
+
|
52
|
+
def buffer(width = 0)
|
53
|
+
"%#{width}s" % text.layout.views.index(text.view)
|
54
|
+
end
|
55
|
+
alias b buffer
|
56
|
+
|
57
|
+
def buffers(width = 0)
|
58
|
+
"%#{width}s" % text.layout.views.size
|
59
|
+
end
|
60
|
+
alias B buffers
|
61
|
+
|
62
|
+
def encoding(width = 0)
|
63
|
+
"%#{width}s" % text.encoding
|
64
|
+
end
|
65
|
+
alias e encoding
|
66
|
+
|
67
|
+
def syntax(width = 0)
|
68
|
+
"%#{width}s" % text.syntax.name if text.syntax
|
69
|
+
end
|
70
|
+
alias s syntax
|
71
|
+
|
72
|
+
def mode(width = 0)
|
73
|
+
"%#{width}s" % text.keymap.mode
|
74
|
+
end
|
75
|
+
alias m mode
|
76
|
+
|
77
|
+
# format sequences:
|
78
|
+
#
|
79
|
+
# %c Current capacity (mAh)
|
80
|
+
# %r Current rate
|
81
|
+
# %b short battery status, '+', '-', '!'
|
82
|
+
# %p battery load percentage
|
83
|
+
# %m remaining time in minutes
|
84
|
+
# %h remaining time in hours
|
85
|
+
# %t remaining time in as 'H:M'
|
86
|
+
def battery(format = '[%b] %p% %t')
|
87
|
+
now = Time.now
|
88
|
+
|
89
|
+
if @battery_last
|
90
|
+
if @battery_last < (now - 60)
|
91
|
+
@battery_last = now
|
92
|
+
@battery_value = battery_build(format)
|
93
|
+
else
|
94
|
+
@battery_value
|
95
|
+
end
|
96
|
+
else
|
97
|
+
@battery_last = now
|
98
|
+
@battery_value = battery_build(format)
|
99
|
+
end
|
100
|
+
rescue => ex
|
101
|
+
puts ex, *ex.backtrace
|
102
|
+
ex.message
|
103
|
+
end
|
104
|
+
|
105
|
+
def battery_build(format)
|
106
|
+
total = {}
|
107
|
+
|
108
|
+
Dir.glob('/proc/acpi/battery/*/{state,info}') do |file|
|
109
|
+
parsed = battery_parse(file)
|
110
|
+
next unless parsed[:present] == 'yes'
|
111
|
+
# FIXME: doesn't take care of multiple batteries
|
112
|
+
total.merge!(parsed)
|
113
|
+
end
|
114
|
+
|
115
|
+
# rate might be 0
|
116
|
+
rate = total[:present_rate].to_i
|
117
|
+
capacity = total[:remaining_capacity].to_i
|
118
|
+
|
119
|
+
if rate == 0
|
120
|
+
hours, percent = 2, 100
|
121
|
+
time = hours_left = minutes_left = 'N/A'
|
122
|
+
else
|
123
|
+
hours, minutes = ((capacity * 60.0) / rate).divmod(60)
|
124
|
+
minutes = minutes.round
|
125
|
+
percent = ((100 / total[:last_full_capacity].to_f) * capacity).round
|
126
|
+
hours_left = (hours + (minutes / 60.0)).round
|
127
|
+
minutes_left = (hours / 60.0) + minutes
|
128
|
+
time = "#{hours}:#{minutes}"
|
129
|
+
end
|
130
|
+
|
131
|
+
case total[:charging_state]
|
132
|
+
when 'discharging'
|
133
|
+
b = hours < 1 ? '!' : '-'
|
134
|
+
when 'charging'
|
135
|
+
b = '+'
|
136
|
+
end
|
137
|
+
|
138
|
+
final = {
|
139
|
+
'%c' => capacity,
|
140
|
+
'%r' => rate,
|
141
|
+
'%b' => b,
|
142
|
+
'%p' => percent,
|
143
|
+
'%m' => minutes_left,
|
144
|
+
'%h' => hours_left,
|
145
|
+
'%t' => time,
|
146
|
+
}
|
147
|
+
|
148
|
+
@last = Time.now
|
149
|
+
format.gsub(/%\w/, final)
|
150
|
+
end
|
151
|
+
|
152
|
+
def battery_parse(file)
|
153
|
+
data = {}
|
154
|
+
|
155
|
+
File.open(file) do |io|
|
156
|
+
io.each_line do |line|
|
157
|
+
next unless line =~ /^([^:]+):\s*(.+)$/
|
158
|
+
data[$1.downcase.tr(' ', '_').to_sym] = $2
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
data
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/lib/ver/text.rb
CHANGED
@@ -42,7 +42,7 @@ module VER
|
|
42
42
|
MATCH_WORD_LEFT = /(^|\b)\S+(\b|$)/
|
43
43
|
|
44
44
|
attr_accessor :keymap, :view, :status
|
45
|
-
attr_reader :filename, :encoding, :pristine, :syntax
|
45
|
+
attr_reader :filename, :encoding, :pristine, :syntax, :undoer
|
46
46
|
|
47
47
|
# attributes for diverse functionality
|
48
48
|
attr_accessor :selection_mode, :selection_start
|
@@ -50,17 +50,19 @@ module VER
|
|
50
50
|
def initialize(view, options = {})
|
51
51
|
super
|
52
52
|
self.view = view
|
53
|
+
@options = Options.new(:text, VER.options)
|
53
54
|
|
54
|
-
keymap_name =
|
55
|
+
keymap_name = @options.keymap
|
55
56
|
self.keymap = Keymap.get(name: keymap_name, receiver: self)
|
56
57
|
|
57
58
|
apply_mode_style(keymap.mode) # for startup
|
58
59
|
setup_tags
|
59
60
|
|
61
|
+
@undoer = VER::Undo::Tree.new(self)
|
62
|
+
|
60
63
|
self.selection_start = nil
|
61
64
|
@pristine = true
|
62
65
|
@syntax = nil
|
63
|
-
@options = Options.new(:text, VER.options)
|
64
66
|
@encoding = Encoding.default_internal
|
65
67
|
@dirty_indices = []
|
66
68
|
|
@@ -91,34 +93,20 @@ module VER
|
|
91
93
|
view.layout
|
92
94
|
end
|
93
95
|
|
94
|
-
# lines start from 1
|
95
|
-
# end is maximum lines + 1
|
96
96
|
def status_projection(into)
|
97
|
-
format =
|
98
|
-
|
99
|
-
top, bot = yview
|
100
|
-
|
101
|
-
if top < 0.5
|
102
|
-
percent = '[top]'
|
103
|
-
elsif bot > 99.5
|
104
|
-
percent = '[bot]'
|
105
|
-
else
|
106
|
-
percent = "#{bot.to_i}%"
|
107
|
-
end
|
97
|
+
format = options.statusline.dup
|
108
98
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
99
|
+
format.gsub!(/%([[:alpha:]]+)/, '#{\1()}')
|
100
|
+
format.gsub!(/%_([[:alpha:]]+)/, '#{(_ = \1()) ? " #{_}" : ""}')
|
101
|
+
format.gsub!(/%([+-]?\d+)([[:alpha:]]+)/, '#{\2(\1)}')
|
102
|
+
format = "%{#{format}}"
|
113
103
|
|
114
|
-
|
115
|
-
|
116
|
-
index(:insert).idx,
|
117
|
-
percent,
|
118
|
-
additional.join(' | '),
|
119
|
-
]
|
104
|
+
context = Status::Context.new(self)
|
105
|
+
line = context.instance_eval(format)
|
120
106
|
|
121
|
-
into.value =
|
107
|
+
into.value = line
|
108
|
+
rescue => ex
|
109
|
+
puts ex, ex.backtrace
|
122
110
|
end
|
123
111
|
|
124
112
|
TAG_ALL_MATCHING_OPTIONS = { from: '1.0', to: 'end - 1 chars' }
|
@@ -183,49 +171,12 @@ module VER
|
|
183
171
|
Tk::Event.generate(self, '<<Movement>>')
|
184
172
|
end
|
185
173
|
|
186
|
-
def
|
187
|
-
|
188
|
-
|
189
|
-
now = index(:insert)
|
190
|
-
left, right = [start, now].sort
|
191
|
-
tag_remove :sel, '1.0', 'end'
|
192
|
-
|
193
|
-
case selection_mode
|
194
|
-
when :select_char
|
195
|
-
tag_add :sel, left, "#{right} + 1 chars"
|
196
|
-
when :select_line
|
197
|
-
tag_add :sel, "#{left} linestart", "#{right} lineend"
|
198
|
-
when :select_block
|
199
|
-
ly, lx = left.split
|
200
|
-
ry, rx = right.split
|
201
|
-
|
202
|
-
from_y, to_y = [ly, ry].sort
|
203
|
-
from_x, to_x = [lx, rx].sort
|
174
|
+
def insert(index, string)
|
175
|
+
index = index(index) unless index.respond_to?(:to_index)
|
204
176
|
|
205
|
-
|
206
|
-
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
# fix the ruby definition of delete, Tk allows more than 2 indices
|
212
|
-
def delete(*args)
|
213
|
-
if args.size > 2
|
214
|
-
deleted = args.each_slice(2).map{|left, right| get(left, right) }
|
215
|
-
else
|
216
|
-
deleted = get(*args)
|
177
|
+
undo_record do |record|
|
178
|
+
record.insert(index, string)
|
217
179
|
end
|
218
|
-
|
219
|
-
copy(deleted)
|
220
|
-
|
221
|
-
execute('delete', *args)
|
222
|
-
|
223
|
-
touch!(*args)
|
224
|
-
end
|
225
|
-
|
226
|
-
def insert(*args)
|
227
|
-
super
|
228
|
-
touch!(args.first)
|
229
180
|
end
|
230
181
|
|
231
182
|
# Replaces the range of characters between index1 and index2 with the given
|
@@ -241,9 +192,14 @@ module VER
|
|
241
192
|
# are active in the text widget.
|
242
193
|
#
|
243
194
|
# replace index1 index2 chars ?tagList chars tagList ...?
|
244
|
-
def replace(index1, index2,
|
245
|
-
|
246
|
-
|
195
|
+
def replace(index1, index2, string)
|
196
|
+
index1 = index(index1) unless index1.respond_to?(:to_index)
|
197
|
+
index2 = index(index2) unless index2.respond_to?(:to_index)
|
198
|
+
return if index1 == index2
|
199
|
+
|
200
|
+
undo_record do |record|
|
201
|
+
record.replace(index1, index2, string)
|
202
|
+
end
|
247
203
|
end
|
248
204
|
|
249
205
|
def focus
|
@@ -282,6 +238,7 @@ module VER
|
|
282
238
|
|
283
239
|
if @syntax = Syntax.from_filename(filename)
|
284
240
|
defer{ syntax.highlight(self, value) }
|
241
|
+
status_projection(status) if status
|
285
242
|
end
|
286
243
|
end
|
287
244
|
|
@@ -296,6 +253,13 @@ module VER
|
|
296
253
|
schedule_highlight!
|
297
254
|
end
|
298
255
|
|
256
|
+
# TODO: maybe we can make this one faster when many lines are going to be
|
257
|
+
# highlighted at once by bundling them.
|
258
|
+
def touch!(*args)
|
259
|
+
args.each{|arg| schedule_line_highlight(arg) } if @syntax
|
260
|
+
Tk::Event.generate(self, '<<Modified>>')
|
261
|
+
end
|
262
|
+
|
299
263
|
private
|
300
264
|
|
301
265
|
def schedule_highlight!(*args)
|
@@ -315,22 +279,16 @@ module VER
|
|
315
279
|
end
|
316
280
|
end
|
317
281
|
|
318
|
-
# TODO: maybe we can make this one faster when many lines are going to be
|
319
|
-
# highlighted at once by bundling them.
|
320
|
-
def touch!(*args)
|
321
|
-
args.each{|arg| schedule_line_highlight(arg) } if @syntax
|
322
|
-
Tk::Event.generate(self, '<<Modified>>')
|
323
|
-
end
|
324
|
-
|
325
282
|
def mode=(name)
|
326
283
|
keymap.mode = mode = name.to_sym
|
327
|
-
|
284
|
+
undo_separator
|
328
285
|
apply_mode_style(mode)
|
329
286
|
status_projection(status) if status
|
330
287
|
end
|
331
288
|
|
332
289
|
def apply_mode_style(mode)
|
333
290
|
cursor = MODE_CURSOR[mode]
|
291
|
+
return unless cursor
|
334
292
|
configure cursor
|
335
293
|
|
336
294
|
return unless status && color = cursor[:insertbackground]
|
@@ -426,8 +384,12 @@ module VER
|
|
426
384
|
end
|
427
385
|
end
|
428
386
|
|
429
|
-
def font(
|
430
|
-
|
387
|
+
def font(given_options = nil)
|
388
|
+
if given_options
|
389
|
+
options.font.configure(given_options)
|
390
|
+
else
|
391
|
+
options.font
|
392
|
+
end
|
431
393
|
end
|
432
394
|
end
|
433
395
|
end
|
data/lib/ver/text/index.rb
CHANGED
@@ -19,6 +19,11 @@ module VER
|
|
19
19
|
return 0 if widget.compare(self_idx, '==', other_idx)
|
20
20
|
end
|
21
21
|
|
22
|
+
def ==(other)
|
23
|
+
self_idx, other_idx = idx, other.to_index.idx
|
24
|
+
widget.compare(self_idx, '==', other_idx)
|
25
|
+
end
|
26
|
+
|
22
27
|
def delta(other)
|
23
28
|
y_diff = other.y - y
|
24
29
|
|
@@ -38,27 +43,39 @@ module VER
|
|
38
43
|
end
|
39
44
|
|
40
45
|
def linestart
|
41
|
-
"#{idx} linestart"
|
46
|
+
widget.index "#{idx} linestart"
|
42
47
|
end
|
43
48
|
|
44
49
|
def lineend
|
45
|
-
"#{idx} lineend"
|
50
|
+
widget.index "#{idx} lineend"
|
46
51
|
end
|
47
52
|
|
48
53
|
def wordstart
|
49
|
-
"#{idx} wordstart"
|
54
|
+
widget.index "#{idx} wordstart"
|
50
55
|
end
|
51
56
|
|
52
57
|
def wordend
|
53
|
-
"#{idx} wordend"
|
58
|
+
widget.index "#{idx} wordend"
|
54
59
|
end
|
55
60
|
|
56
61
|
def next
|
57
|
-
|
62
|
+
widget.index "#{y + 1}.#{x}"
|
58
63
|
end
|
59
64
|
|
60
65
|
def prev
|
61
|
-
|
66
|
+
widget.index "#{y - 1}.#{x}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def +(chars)
|
70
|
+
widget.index "#{idx} + #{chars} chars"
|
71
|
+
end
|
72
|
+
|
73
|
+
def -(other)
|
74
|
+
if other.is_a?(self.class)
|
75
|
+
widget.count(other, self, :displaychars)
|
76
|
+
else
|
77
|
+
widget.index "#{idx} - #{other.to_int} chars"
|
78
|
+
end
|
62
79
|
end
|
63
80
|
|
64
81
|
def split
|
@@ -66,7 +83,7 @@ module VER
|
|
66
83
|
end
|
67
84
|
|
68
85
|
def inspect
|
69
|
-
"#<Text::Index #{self}>"
|
86
|
+
to_s # "#<Text::Index #{self}>"
|
70
87
|
end
|
71
88
|
|
72
89
|
def to_str
|