diakonos 0.8.8 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +433 -0
- data/LICENCE.md +675 -0
- data/bin/diakonos +6 -0
- data/diakonos-256-colour.conf +220 -0
- data/diakonos.conf +1802 -0
- data/help/about-help.dhf +31 -0
- data/help/clipboard.dhf +45 -0
- data/help/close-file.dhf +6 -0
- data/help/code-block-navigation.dhf +16 -0
- data/help/column-markers.dhf +15 -0
- data/help/config.dhf +69 -0
- data/help/cursor-stack.dhf +19 -0
- data/help/delete.dhf +41 -0
- data/help/extensions.dhf +125 -0
- data/help/file-type.dhf +24 -0
- data/help/key-mapping.dhf +127 -0
- data/help/line-numbers.dhf +22 -0
- data/help/macros.dhf +27 -0
- data/help/new-file.dhf +6 -0
- data/help/open-file.dhf +21 -0
- data/help/quit.dhf +7 -0
- data/help/resizing.dhf +19 -0
- data/help/ruby.dhf +17 -0
- data/help/save-file.dhf +10 -0
- data/help/scripting.dhf +92 -0
- data/help/search.dhf +103 -0
- data/help/shell.dhf +60 -0
- data/help/speed.dhf +23 -0
- data/help/support.dhf +15 -0
- data/help/switch-buffers.dhf +15 -0
- data/help/tabs.dhf +36 -0
- data/help/undo.dhf +9 -0
- data/help/uninstall.dhf +18 -0
- data/help/welcome.dhf +32 -0
- data/help/word-wrap.dhf +17 -0
- data/lib/diakonos/about.rb +69 -0
- data/lib/diakonos/bookmark.rb +46 -0
- data/lib/diakonos/buffer/bookmarking.rb +47 -0
- data/lib/diakonos/buffer/cursor.rb +335 -0
- data/lib/diakonos/buffer/delete.rb +170 -0
- data/lib/diakonos/buffer/display.rb +356 -0
- data/lib/diakonos/buffer/file.rb +157 -0
- data/lib/diakonos/buffer/indentation.rb +175 -0
- data/lib/diakonos/buffer/searching.rb +552 -0
- data/lib/diakonos/buffer/selection.rb +360 -0
- data/lib/diakonos/buffer/undo.rb +73 -0
- data/lib/diakonos/buffer-hash.rb +60 -0
- data/lib/diakonos/buffer-management.rb +59 -0
- data/lib/diakonos/buffer.rb +698 -0
- data/lib/diakonos/clipboard-klipper-dbus.rb +62 -0
- data/lib/diakonos/clipboard-klipper.rb +62 -0
- data/lib/diakonos/clipboard-osx.rb +59 -0
- data/lib/diakonos/clipboard-xclip.rb +60 -0
- data/lib/diakonos/clipboard.rb +47 -0
- data/lib/diakonos/config-file.rb +67 -0
- data/lib/diakonos/config.rb +381 -0
- data/lib/diakonos/core-ext/enumerable.rb +15 -0
- data/lib/diakonos/core-ext/hash.rb +60 -0
- data/lib/diakonos/core-ext/object.rb +6 -0
- data/lib/diakonos/core-ext/regexp.rb +6 -0
- data/lib/diakonos/core-ext/string.rb +122 -0
- data/lib/diakonos/ctag.rb +28 -0
- data/lib/diakonos/cursor.rb +27 -0
- data/lib/diakonos/display/format.rb +75 -0
- data/lib/diakonos/display.rb +336 -0
- data/lib/diakonos/extension-set.rb +49 -0
- data/lib/diakonos/extension.rb +34 -0
- data/lib/diakonos/finding.rb +40 -0
- data/lib/diakonos/functions/basics.rb +34 -0
- data/lib/diakonos/functions/bookmarking.rb +61 -0
- data/lib/diakonos/functions/buffers.rb +489 -0
- data/lib/diakonos/functions/clipboard.rb +70 -0
- data/lib/diakonos/functions/cursor.rb +264 -0
- data/lib/diakonos/functions/grepping.rb +83 -0
- data/lib/diakonos/functions/indentation.rb +71 -0
- data/lib/diakonos/functions/readline.rb +93 -0
- data/lib/diakonos/functions/search.rb +179 -0
- data/lib/diakonos/functions/selection.rb +98 -0
- data/lib/diakonos/functions/sessions.rb +78 -0
- data/lib/diakonos/functions/shell.rb +250 -0
- data/lib/diakonos/functions/tags.rb +65 -0
- data/lib/diakonos/functions/text-manipulation.rb +196 -0
- data/lib/diakonos/functions-deprecated.rb +77 -0
- data/lib/diakonos/functions.rb +292 -0
- data/lib/diakonos/grep.rb +98 -0
- data/lib/diakonos/help.rb +47 -0
- data/lib/diakonos/hooks.rb +13 -0
- data/lib/diakonos/installation.rb +19 -0
- data/lib/diakonos/interaction-handler.rb +216 -0
- data/lib/diakonos/interaction.rb +52 -0
- data/lib/diakonos/key-map.rb +62 -0
- data/lib/diakonos/keying.rb +442 -0
- data/lib/diakonos/line-mover.rb +42 -0
- data/lib/diakonos/list.rb +59 -0
- data/lib/diakonos/logging.rb +27 -0
- data/lib/diakonos/mode.rb +17 -0
- data/lib/diakonos/mouse.rb +18 -0
- data/lib/diakonos/number-fitter.rb +11 -0
- data/lib/diakonos/range.rb +31 -0
- data/lib/diakonos/readline/functions.rb +82 -0
- data/lib/diakonos/readline.rb +222 -0
- data/lib/diakonos/search.rb +58 -0
- data/lib/diakonos/sessions.rb +257 -0
- data/lib/diakonos/sized-array.rb +48 -0
- data/lib/diakonos/text-mark.rb +19 -0
- data/lib/diakonos/vendor/fuzzy_file_finder.rb +365 -0
- data/lib/diakonos/version.rb +25 -0
- data/lib/diakonos/window.rb +43 -0
- data/lib/diakonos.rb +592 -0
- metadata +160 -66
@@ -0,0 +1,442 @@
|
|
1
|
+
module Diakonos
|
2
|
+
module Keying
|
3
|
+
|
4
|
+
KEYSTRINGS = [
|
5
|
+
"ctrl+space", # 0
|
6
|
+
"ctrl+a", # 1
|
7
|
+
"ctrl+b", # 2
|
8
|
+
"ctrl+c", # 3
|
9
|
+
"ctrl+d", # 4
|
10
|
+
"ctrl+e", # 5
|
11
|
+
"ctrl+f", # 6
|
12
|
+
"ctrl+g", # 7
|
13
|
+
nil, # 8
|
14
|
+
"tab", # 9
|
15
|
+
"ctrl+j", # 10
|
16
|
+
"ctrl+k", # 11
|
17
|
+
"ctrl+l", # 12
|
18
|
+
"enter", # 13
|
19
|
+
"ctrl+n", # 14
|
20
|
+
"ctrl+o", # 15
|
21
|
+
"ctrl+p", # 16
|
22
|
+
"ctrl+q", # 17
|
23
|
+
"ctrl+r", # 18
|
24
|
+
"ctrl+s", # 19
|
25
|
+
"ctrl+t", # 20
|
26
|
+
"ctrl+u", # 21
|
27
|
+
"ctrl+v", # 22
|
28
|
+
"ctrl+w", # 23
|
29
|
+
"ctrl+x", # 24
|
30
|
+
"ctrl+y", # 25
|
31
|
+
"ctrl+z", # 26
|
32
|
+
"esc", # 27
|
33
|
+
nil, # 28
|
34
|
+
nil, # 29
|
35
|
+
nil, # 30
|
36
|
+
nil, # 31
|
37
|
+
"space", # 32
|
38
|
+
] + (33..126).map(&:chr) + [
|
39
|
+
"backspace" # 127
|
40
|
+
]
|
41
|
+
|
42
|
+
def self.keycodes_for( str )
|
43
|
+
retval = case str.downcase
|
44
|
+
when "down"
|
45
|
+
Curses::KEY_DOWN
|
46
|
+
when "up"
|
47
|
+
Curses::KEY_UP
|
48
|
+
when "left"
|
49
|
+
Curses::KEY_LEFT
|
50
|
+
when "right"
|
51
|
+
Curses::KEY_RIGHT
|
52
|
+
when "home"
|
53
|
+
Curses::KEY_HOME
|
54
|
+
when "end"
|
55
|
+
Curses::KEY_END
|
56
|
+
when "insert", "ins"
|
57
|
+
Curses::KEY_IC
|
58
|
+
when "delete", "del"
|
59
|
+
Curses::KEY_DC
|
60
|
+
when "backspace"
|
61
|
+
::Diakonos::BACKSPACE
|
62
|
+
when "tab"
|
63
|
+
9
|
64
|
+
when "pageup", "page-up"
|
65
|
+
Curses::KEY_PPAGE
|
66
|
+
when "pagedown", "page-down"
|
67
|
+
Curses::KEY_NPAGE
|
68
|
+
when "enter", "return"
|
69
|
+
::Diakonos::ENTER
|
70
|
+
when "numpad7", "keypad7", "kp-7"
|
71
|
+
Curses::KEY_A1
|
72
|
+
when "numpad9", "keypad9", "kp-9"
|
73
|
+
Curses::KEY_A3
|
74
|
+
when "numpad5", "keypad5", "kp-5"
|
75
|
+
Curses::KEY_B2
|
76
|
+
when "numpad1", "keypad1", "kp-1"
|
77
|
+
Curses::KEY_C1
|
78
|
+
when "numpad3", "keypad3", "kp-3"
|
79
|
+
Curses::KEY_C3
|
80
|
+
when "escape", "esc"
|
81
|
+
::Diakonos::ESCAPE
|
82
|
+
when "space"
|
83
|
+
32
|
84
|
+
when "ctrl+space"
|
85
|
+
0
|
86
|
+
when "find"
|
87
|
+
Curses::KEY_FIND
|
88
|
+
when "select"
|
89
|
+
Curses::KEY_SELECT
|
90
|
+
when "suspend"
|
91
|
+
Curses::KEY_SUSPEND
|
92
|
+
when /^f(\d\d?)$/
|
93
|
+
Curses::KEY_F0 + $1.to_i
|
94
|
+
when /^ctrl\+[a-gi-z]$/
|
95
|
+
str.downcase[ -1 ].ord - 96
|
96
|
+
when /^ctrl\+h$/
|
97
|
+
::Diakonos::CTRL_H
|
98
|
+
when /^alt\+(.)$/
|
99
|
+
[ ::Diakonos::ESCAPE, $1[ 0 ].ord ]
|
100
|
+
when /^ctrl\+alt\+(.)$/, /^alt\+ctrl\+(.)$/
|
101
|
+
[ ::Diakonos::ESCAPE, str.downcase[ -1 ].ord - 96 ]
|
102
|
+
when /^keycode(\d+)$/
|
103
|
+
$1.to_i
|
104
|
+
when /^.$/
|
105
|
+
str[ 0 ].ord
|
106
|
+
end
|
107
|
+
Array( retval )
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.key_string_for( num )
|
111
|
+
retval = KEYSTRINGS[ num ]
|
112
|
+
if retval.nil?
|
113
|
+
retval = case num
|
114
|
+
when Curses::KEY_DOWN
|
115
|
+
"down"
|
116
|
+
when Curses::KEY_UP
|
117
|
+
"up"
|
118
|
+
when Curses::KEY_LEFT
|
119
|
+
"left"
|
120
|
+
when Curses::KEY_RIGHT
|
121
|
+
"right"
|
122
|
+
when Curses::KEY_HOME
|
123
|
+
"home"
|
124
|
+
when Curses::KEY_END
|
125
|
+
"end"
|
126
|
+
when Curses::KEY_IC
|
127
|
+
"insert"
|
128
|
+
when Curses::KEY_DC
|
129
|
+
"delete"
|
130
|
+
when Curses::KEY_PPAGE
|
131
|
+
"page-up"
|
132
|
+
when Curses::KEY_NPAGE
|
133
|
+
"page-down"
|
134
|
+
when Curses::KEY_A1
|
135
|
+
"numpad7"
|
136
|
+
when Curses::KEY_A3
|
137
|
+
"numpad9"
|
138
|
+
when Curses::KEY_B2
|
139
|
+
"numpad5"
|
140
|
+
when Curses::KEY_C1
|
141
|
+
"numpad1"
|
142
|
+
when Curses::KEY_C3
|
143
|
+
"numpad3"
|
144
|
+
when Curses::KEY_FIND
|
145
|
+
"find"
|
146
|
+
when Curses::KEY_SELECT
|
147
|
+
"select"
|
148
|
+
when Curses::KEY_SUSPEND
|
149
|
+
"suspend"
|
150
|
+
when Curses::KEY_F0..(Curses::KEY_F0 + 24)
|
151
|
+
"f" + ( num - Curses::KEY_F0 ).to_s
|
152
|
+
when CTRL_H
|
153
|
+
"ctrl+h"
|
154
|
+
when Curses::KEY_RESIZE
|
155
|
+
"resize"
|
156
|
+
when RESIZE2
|
157
|
+
"resize2"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
if retval.nil? && num.class == Integer
|
161
|
+
retval = "keycode#{num}"
|
162
|
+
end
|
163
|
+
retval
|
164
|
+
end
|
165
|
+
|
166
|
+
UTF_8_2_BYTE_BEGIN = 0xc2
|
167
|
+
UTF_8_2_BYTE_END = 0xdf
|
168
|
+
UTF_8_3_BYTE_BEGIN = 0xe0
|
169
|
+
UTF_8_3_BYTE_END = 0xef
|
170
|
+
UTF_8_4_BYTE_BEGIN = 0xf0
|
171
|
+
UTF_8_4_BYTE_END = 0xf4
|
172
|
+
end
|
173
|
+
|
174
|
+
class Diakonos
|
175
|
+
def keychain_str_for( array )
|
176
|
+
chain_str = ""
|
177
|
+
array.each do |key|
|
178
|
+
key_str = Keying.key_string_for( key )
|
179
|
+
if key_str
|
180
|
+
chain_str << key_str + " "
|
181
|
+
else
|
182
|
+
chain_str << key.to_s + " "
|
183
|
+
end
|
184
|
+
end
|
185
|
+
chain_str.strip
|
186
|
+
end
|
187
|
+
|
188
|
+
def capture_keychain( c, context )
|
189
|
+
if c == ENTER
|
190
|
+
@capturing_keychain = false
|
191
|
+
buffer_current.delete_selection
|
192
|
+
str = keychain_str_for( context )
|
193
|
+
buffer_current.insert_string str
|
194
|
+
cursor_right( Buffer::STILL_TYPING, str.length )
|
195
|
+
else
|
196
|
+
keychain_pressed = context.concat [ c ]
|
197
|
+
|
198
|
+
function_and_args = @modes[ 'edit' ].keymap.get_leaf( keychain_pressed )
|
199
|
+
|
200
|
+
if function_and_args
|
201
|
+
function, args = function_and_args
|
202
|
+
end
|
203
|
+
|
204
|
+
partial_keychain = @modes[ 'edit' ].keymap.get_node( keychain_pressed )
|
205
|
+
if partial_keychain
|
206
|
+
set_iline( "Part of existing keychain: " + keychain_str_for( keychain_pressed ) + "..." )
|
207
|
+
else
|
208
|
+
set_iline keychain_str_for( keychain_pressed ) + "..."
|
209
|
+
end
|
210
|
+
process_keystroke keychain_pressed
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def capture_mapping( c, context )
|
215
|
+
if c == ENTER
|
216
|
+
@capturing_mapping = false
|
217
|
+
buffer_current.delete_selection
|
218
|
+
set_iline
|
219
|
+
else
|
220
|
+
keychain_pressed = context.concat [ c ]
|
221
|
+
|
222
|
+
function_and_args = @modes[ 'edit' ].keymap.get_leaf( keychain_pressed )
|
223
|
+
|
224
|
+
if function_and_args
|
225
|
+
function, args = function_and_args
|
226
|
+
set_iline "#{keychain_str_for( keychain_pressed )} -> #{function}( #{args} )"
|
227
|
+
else
|
228
|
+
partial_keychain = @modes[ 'edit' ].keymap.get_node( keychain_pressed )
|
229
|
+
if partial_keychain
|
230
|
+
set_iline( "Several mappings start with: " + keychain_str_for( keychain_pressed ) + "..." )
|
231
|
+
process_keystroke keychain_pressed
|
232
|
+
else
|
233
|
+
set_iline "There is no mapping for " + keychain_str_for( keychain_pressed )
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def typeable?( char )
|
240
|
+
char > 31 && char < 255 && char != BACKSPACE
|
241
|
+
end
|
242
|
+
|
243
|
+
# @param [Integer] c The first byte of a UTF-8 byte sequence
|
244
|
+
# @return [String] nil if c is not the beginning of a multi-byte sequence
|
245
|
+
def utf_8_bytes_to_char(c, mode)
|
246
|
+
if Keying::UTF_8_2_BYTE_BEGIN <= c && c <= Keying::UTF_8_2_BYTE_END
|
247
|
+
# 2-byte character
|
248
|
+
byte_array = [c, @modes[mode].window.getch.ord]
|
249
|
+
elsif Keying::UTF_8_3_BYTE_BEGIN <= c && c <= Keying::UTF_8_3_BYTE_END
|
250
|
+
# 3-byte character
|
251
|
+
byte_array = [
|
252
|
+
c,
|
253
|
+
@modes[mode].window.getch.ord,
|
254
|
+
@modes[mode].window.getch.ord,
|
255
|
+
]
|
256
|
+
elsif Keying::UTF_8_4_BYTE_BEGIN <= c && c <= Keying::UTF_8_4_BYTE_END
|
257
|
+
# 4-byte character
|
258
|
+
byte_array = [
|
259
|
+
c,
|
260
|
+
@modes[mode].window.getch.ord,
|
261
|
+
@modes[mode].window.getch.ord,
|
262
|
+
@modes[mode].window.getch.ord,
|
263
|
+
]
|
264
|
+
else
|
265
|
+
return nil
|
266
|
+
end
|
267
|
+
|
268
|
+
byte_array.pack('C*').force_encoding('utf-8')
|
269
|
+
end
|
270
|
+
|
271
|
+
# @param [Integer] c The ordinal (number) of a character
|
272
|
+
# @param [String] mode
|
273
|
+
# @return [Boolean] true iff c began a UTF-8 byte sequence
|
274
|
+
def handle_utf_8(c, mode)
|
275
|
+
utf_8_char = utf_8_bytes_to_char(c, mode)
|
276
|
+
if utf_8_char
|
277
|
+
self.type_character utf_8_char, mode
|
278
|
+
true
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
# Handle paste from a GUI (like x.org). i.e. Shift-Insert
|
283
|
+
def handle_gui_paste(mode)
|
284
|
+
s = ""
|
285
|
+
ch = nil
|
286
|
+
|
287
|
+
loop do
|
288
|
+
ch = nil
|
289
|
+
begin
|
290
|
+
Timeout::timeout(0.02) do
|
291
|
+
ch = @modes[mode].window.getch
|
292
|
+
end
|
293
|
+
rescue Timeout::Error => e
|
294
|
+
break
|
295
|
+
end
|
296
|
+
break if ch.nil?
|
297
|
+
|
298
|
+
c = ch.ord
|
299
|
+
utf_8_char = self.utf_8_bytes_to_char(c, mode)
|
300
|
+
|
301
|
+
if utf_8_char
|
302
|
+
s << utf_8_char
|
303
|
+
elsif self.typeable?(c)
|
304
|
+
s << c
|
305
|
+
elsif c == ENTER && mode == 'edit'
|
306
|
+
s << "\n"
|
307
|
+
else
|
308
|
+
break
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
if ! s.empty?
|
313
|
+
case mode
|
314
|
+
when 'edit'
|
315
|
+
buffer_current.paste s, Buffer::TYPING
|
316
|
+
when 'input'
|
317
|
+
@readline.paste s
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
if ch
|
322
|
+
process_keystroke( [], mode, ch )
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
# context is an array of characters (bytes) which are keystrokes previously
|
327
|
+
# typed (in a chain of keystrokes)
|
328
|
+
def process_keystroke( context = [], mode = 'edit', ch = nil )
|
329
|
+
ch ||= @modes[ mode ].window.getch
|
330
|
+
return if ch.nil?
|
331
|
+
|
332
|
+
if ch == Curses::KEY_MOUSE
|
333
|
+
handle_mouse_event
|
334
|
+
return
|
335
|
+
end
|
336
|
+
|
337
|
+
c = ch.ord
|
338
|
+
|
339
|
+
self.handle_utf_8(c, mode) and return
|
340
|
+
|
341
|
+
if @capturing_keychain
|
342
|
+
capture_keychain c, context
|
343
|
+
elsif @capturing_mapping
|
344
|
+
capture_mapping c, context
|
345
|
+
else
|
346
|
+
|
347
|
+
if context.empty? && typeable?( c )
|
348
|
+
self.type_character ch, mode
|
349
|
+
self.handle_gui_paste(mode)
|
350
|
+
return
|
351
|
+
end
|
352
|
+
|
353
|
+
keychain_pressed = context.concat [ c ]
|
354
|
+
|
355
|
+
function_and_args = (
|
356
|
+
@modes[mode].keymap_after[@function_last].get_leaf( keychain_pressed ) ||
|
357
|
+
@modes[mode].keymap.get_leaf( keychain_pressed )
|
358
|
+
)
|
359
|
+
|
360
|
+
if function_and_args
|
361
|
+
function, args = function_and_args
|
362
|
+
@function_last = function
|
363
|
+
|
364
|
+
if mode != 'input' && ! @settings[ "context.combined" ]
|
365
|
+
set_iline
|
366
|
+
end
|
367
|
+
|
368
|
+
if args
|
369
|
+
to_eval = "#{function}( #{args} )"
|
370
|
+
else
|
371
|
+
to_eval = function
|
372
|
+
end
|
373
|
+
|
374
|
+
if @macro_history
|
375
|
+
@macro_history.push to_eval
|
376
|
+
end
|
377
|
+
|
378
|
+
begin
|
379
|
+
if buffer_current.search_area? && ! ( /^(?:find|readline)/ === to_eval )
|
380
|
+
buffer_current.clear_search_area
|
381
|
+
end
|
382
|
+
eval to_eval, nil, "eval"
|
383
|
+
@functions_last << to_eval unless to_eval == "repeat_last"
|
384
|
+
if ! @there_was_non_movement
|
385
|
+
@there_was_non_movement = !( /^((cursor|page|scroll)_?(up|down|left|right)|find|seek)/i === to_eval )
|
386
|
+
end
|
387
|
+
rescue Exception => e
|
388
|
+
debug_log e.message
|
389
|
+
debug_log e.backtrace.join( "\n\t" )
|
390
|
+
show_exception e
|
391
|
+
end
|
392
|
+
else
|
393
|
+
partial_keychain = @modes[ mode ].keymap.get_node( keychain_pressed )
|
394
|
+
if partial_keychain
|
395
|
+
if mode != 'input'
|
396
|
+
set_iline( keychain_str_for( keychain_pressed ) + "..." )
|
397
|
+
end
|
398
|
+
process_keystroke keychain_pressed, mode
|
399
|
+
elsif mode != 'input'
|
400
|
+
set_iline "Nothing assigned to #{keychain_str_for( keychain_pressed )}"
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
def type_character( c, mode = 'edit' )
|
407
|
+
if @macro_history
|
408
|
+
@macro_history.push "type_character #{c.inspect}, #{mode.inspect}"
|
409
|
+
end
|
410
|
+
@there_was_non_movement = true
|
411
|
+
|
412
|
+
case mode
|
413
|
+
when 'edit'
|
414
|
+
buffer_current.delete_selection Buffer::DONT_DISPLAY
|
415
|
+
buffer_current.insert_string c
|
416
|
+
cursor_right Buffer::STILL_TYPING
|
417
|
+
if c =~ @indent_triggers[buffer_current.language]
|
418
|
+
buffer_current.parsed_indent cursor_eol: true
|
419
|
+
end
|
420
|
+
when 'input'
|
421
|
+
if ! @readline.numbered_list?
|
422
|
+
@readline.paste c
|
423
|
+
else
|
424
|
+
if(
|
425
|
+
showing_list? &&
|
426
|
+
( (48..57).include?( c.ord ) || (97..122).include?( c.ord ) )
|
427
|
+
)
|
428
|
+
line = list_buffer.to_a.select { |l|
|
429
|
+
l =~ /^#{c} /
|
430
|
+
}[ 0 ]
|
431
|
+
|
432
|
+
if line
|
433
|
+
@readline.list_sync line
|
434
|
+
@readline.finish
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Diakonos
|
2
|
+
class LineMover
|
3
|
+
def initialize(buffer:)
|
4
|
+
@buffer = buffer
|
5
|
+
end
|
6
|
+
|
7
|
+
def move_selected_lines(direction:)
|
8
|
+
case direction
|
9
|
+
when :up
|
10
|
+
from_row = start_row-1
|
11
|
+
return if from_row < 0
|
12
|
+
to_row = end_row-1
|
13
|
+
selection_delta = 0
|
14
|
+
when :down
|
15
|
+
from_row = end_row
|
16
|
+
to_row = start_row
|
17
|
+
return if to_row > @buffer.lines.count - 2
|
18
|
+
selection_delta = @buffer.selecting? ? 1 : 0
|
19
|
+
end
|
20
|
+
|
21
|
+
@buffer.take_snapshot Buffer::TYPING
|
22
|
+
@buffer.lines.insert(
|
23
|
+
to_row,
|
24
|
+
@buffer.lines.delete_at(from_row)
|
25
|
+
)
|
26
|
+
if @buffer.selecting?
|
27
|
+
@buffer.set_selection to_row+selection_delta, 0, from_row+1+selection_delta, 0
|
28
|
+
@buffer.anchor_selection to_row+selection_delta
|
29
|
+
end
|
30
|
+
@buffer.go_to_line from_row+selection_delta
|
31
|
+
@buffer.set_modified
|
32
|
+
end
|
33
|
+
|
34
|
+
private def start_row
|
35
|
+
@buffer.selection_mark&.start_row || @buffer.current_row
|
36
|
+
end
|
37
|
+
|
38
|
+
private def end_row
|
39
|
+
@buffer.selection_mark&.end_row || @buffer.last_row+1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Diakonos
|
2
|
+
|
3
|
+
class Diakonos
|
4
|
+
attr_reader :list_buffer
|
5
|
+
|
6
|
+
def open_list_buffer
|
7
|
+
@list_buffer = open_file( @list_filename )
|
8
|
+
end
|
9
|
+
|
10
|
+
def close_list_buffer( opts = {} )
|
11
|
+
close_buffer @list_buffer, opts
|
12
|
+
@list_buffer = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def showing_list?
|
16
|
+
@list_buffer
|
17
|
+
end
|
18
|
+
|
19
|
+
def list_item_selected?
|
20
|
+
@list_buffer && @list_buffer.selecting?
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_list_item
|
24
|
+
if @list_buffer
|
25
|
+
@list_buffer.set_selection_current_line
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def select_list_item
|
30
|
+
if @list_buffer
|
31
|
+
line = @list_buffer.set_selection_current_line
|
32
|
+
display_buffer @list_buffer
|
33
|
+
line
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def previous_list_item
|
38
|
+
if @list_buffer
|
39
|
+
cursor_up
|
40
|
+
@list_buffer[ @list_buffer.current_row ]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def next_list_item
|
45
|
+
if @list_buffer
|
46
|
+
cursor_down
|
47
|
+
@list_buffer[ @list_buffer.current_row ]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def with_list_file
|
52
|
+
File.open( @list_filename, "w" ) do |f|
|
53
|
+
yield f
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Diakonos
|
2
|
+
|
3
|
+
class Diakonos
|
4
|
+
|
5
|
+
def log( string )
|
6
|
+
@log.puts string
|
7
|
+
@log.flush
|
8
|
+
end
|
9
|
+
|
10
|
+
def debug_log( string )
|
11
|
+
@debug.puts( Time.now.strftime( "[%a %H:%M:%S] #{string}" ) )
|
12
|
+
@debug.flush
|
13
|
+
end
|
14
|
+
|
15
|
+
def log_backtrace
|
16
|
+
begin
|
17
|
+
raise Exception
|
18
|
+
rescue Exception => e
|
19
|
+
e.backtrace[ 1..-1 ].each do |x|
|
20
|
+
debug_log x
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Diakonos
|
2
|
+
class Mode
|
3
|
+
attr_reader :keymap, :keymap_after, :window
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@keymap = Hash.new.extend( KeyMap )
|
7
|
+
# keys of @keymap_after are Strings of Diakonos functions
|
8
|
+
@keymap_after = Hash.new { |h,k|
|
9
|
+
h[k] = Hash.new.extend( KeyMap )
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def window=( w )
|
14
|
+
@window = w
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Diakonos
|
2
|
+
class Diakonos
|
3
|
+
def handle_mouse_event
|
4
|
+
event = Curses::getmouse
|
5
|
+
return if event.nil?
|
6
|
+
|
7
|
+
if event.bstate & Curses::BUTTON1_CLICKED > 0
|
8
|
+
buffer_current.cursor_to(
|
9
|
+
buffer_current.top_line + event.y,
|
10
|
+
buffer_current.left_column + event.x,
|
11
|
+
Buffer::DO_DISPLAY
|
12
|
+
)
|
13
|
+
else
|
14
|
+
$diakonos.debug_log "button state = #{'0x%x' % event.bstate}, "
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Diakonos
|
2
|
+
class Range
|
3
|
+
attr_reader :start_row, :start_col, :end_row, :end_col
|
4
|
+
attr_writer :end_row, :end_col
|
5
|
+
|
6
|
+
def initialize( start_row, start_col, end_row, end_col )
|
7
|
+
@start_row, @start_col, @end_row, @end_col = start_row, start_col, end_row, end_col
|
8
|
+
end
|
9
|
+
|
10
|
+
def contains?(row, col)
|
11
|
+
if row == @start_row
|
12
|
+
@start_col <= col
|
13
|
+
elsif row == @end_row
|
14
|
+
col < @end_col
|
15
|
+
else
|
16
|
+
@start_row < row && row < @end_row
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module RangeDelegator
|
22
|
+
def start_row; @range.start_row; end
|
23
|
+
def end_row; @range.end_row; end
|
24
|
+
def start_col; @range.start_col; end
|
25
|
+
def end_col; @range.end_col; end
|
26
|
+
|
27
|
+
def contains?(row, col)
|
28
|
+
@range.contains?(row, col)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|