@@ -17,7 +17,6 @@ class AbstractEdits(object):
17
17
'line' : 'hello world' ,
18
18
'cursor_offset' : 5 ,
19
19
'cut_buffer' : 'there' ,
20
- 'indent' : 4 ,
21
20
}
22
21
23
22
def __contains__ (self , key ):
@@ -28,15 +27,22 @@ def __contains__(self, key):
28
27
else :
29
28
return True
30
29
31
- def add (self , key , func ):
30
+ def add (self , key , func , overwrite = False ):
32
31
if key in self :
33
- raise ValueError ('key %r already has a mapping' % (key ,))
32
+ if overwrite :
33
+ del self [key ]
34
+ else :
35
+ raise ValueError ('key %r already has a mapping' % (key ,))
34
36
params = inspect .getargspec (func )[0 ]
35
37
args = dict ((k , v ) for k , v in self .default_kwargs .items () if k in params )
36
38
r = func (** args )
37
39
if len (r ) == 2 :
40
+ if hasattr (func , 'kills' ):
41
+ raise ValueError ('function %r returns two values, but has a kills attribute' % (func ,))
38
42
self .simple_edits [key ] = func
39
43
elif len (r ) == 3 :
44
+ if not hasattr (func , 'kills' ):
45
+ raise ValueError ('function %r returns three values, but has no kills attribute' % (func ,))
40
46
self .cut_buffer_edits [key ] = func
41
47
else :
42
48
raise ValueError ('return type of function %r not recognized' % (func ,))
@@ -52,11 +58,20 @@ def call(self, key, **kwargs):
52
58
args = dict ((k , v ) for k , v in kwargs .items () if k in params )
53
59
return func (** args )
54
60
61
+ def call_without_cut (self , key , ** kwargs ):
62
+ """Looks up the function and calls it, returning only line and cursor offset"""
63
+ r = self .call_for_two (key , ** kwargs )
64
+ return r [:2 ]
65
+
55
66
def __getitem__ (self , key ):
56
67
if key in self .simple_edits : return self .simple_edits [key ]
57
68
if key in self .cut_buffer_edits : return self .cut_buffer_edits [key ]
58
69
raise KeyError ("key %r not mapped" % (key ,))
59
70
71
+ def __delitem__ (self , key ):
72
+ if key in self .simple_edits : del self .simple_edits [key ]
73
+ elif key in self .cut_buffer_edits : del self .cut_buffer_edits [key ]
74
+ else : raise KeyError ("key %r not mapped" % (key ,))
60
75
61
76
class UnconfiguredEdits (AbstractEdits ):
62
77
"""Maps key to edit functions, and bins them by what parameters they take.
@@ -104,7 +119,8 @@ def __init__(self, simple_edits, cut_buffer_edits, awaiting_config, config, key_
104
119
self .simple_edits = dict (simple_edits )
105
120
self .cut_buffer_edits = dict (cut_buffer_edits )
106
121
for attr , func in awaiting_config .items ():
107
- super (ConfiguredEdits , self ).add (key_dispatch [getattr (config , attr )], func )
122
+ for key in key_dispatch [getattr (config , attr )]:
123
+ super (ConfiguredEdits , self ).add (key , func , overwrite = True )
108
124
109
125
def add_config_attr (self , config_attr , func ):
110
126
raise NotImplementedError ("Config already set on this mapping" )
@@ -117,6 +133,14 @@ def add(self, key, func):
117
133
# Because the edits.on decorator runs the functions, functions which depend
118
134
# on other functions must be declared after their dependencies
119
135
136
+ def kills_behind (func ):
137
+ func .kills = 'behind'
138
+ return func
139
+
140
+ def kills_ahead (func ):
141
+ func .kills = 'ahead'
142
+ return func
143
+
120
144
@edit_keys .on ('<Ctrl-b>' )
121
145
@edit_keys .on ('<LEFT>' )
122
146
def left_arrow (cursor_offset , line ):
@@ -183,22 +207,29 @@ def delete_from_cursor_back(cursor_offset, line):
183
207
return 0 , line [cursor_offset :]
184
208
185
209
@edit_keys .on ('<Esc+d>' ) # option-d
210
+ @kills_ahead
186
211
def delete_rest_of_word (cursor_offset , line ):
187
212
m = re .search (r'\w\b' , line [cursor_offset :])
188
213
if not m :
189
- return cursor_offset , line
190
- return cursor_offset , line [:cursor_offset ] + line [m .start ()+ cursor_offset + 1 :]
214
+ return cursor_offset , line , ''
215
+ return (cursor_offset , line [:cursor_offset ] + line [m .start ()+ cursor_offset + 1 :],
216
+ line [cursor_offset :m .start ()+ cursor_offset + 1 ])
191
217
192
218
@edit_keys .on ('<Ctrl-w>' )
193
219
@edit_keys .on (config = 'clear_word_key' )
220
+ @kills_behind
194
221
def delete_word_to_cursor (cursor_offset , line ):
195
222
matches = list (re .finditer (r'\s\S' , line [:cursor_offset ]))
196
223
start = matches [- 1 ].start ()+ 1 if matches else 0
197
- return start , line [:start ] + line [cursor_offset :]
224
+ return start , line [:start ] + line [cursor_offset :], line [ start : cursor_offset ]
198
225
199
226
@edit_keys .on ('<Esc+y>' )
200
- def yank_prev_prev_killed_text (cursor_offset , line ):
201
- return cursor_offset , line #TODO Not implemented
227
+ def yank_prev_prev_killed_text (cursor_offset , line , cut_buffer ): #TODO not implemented - just prev
228
+ return cursor_offset + len (cut_buffer ), line [:cursor_offset ] + cut_buffer + line [cursor_offset :]
229
+
230
+ @edit_keys .on (config = 'yank_from_buffer_key' )
231
+ def yank_prev_killed_text (cursor_offset , line , cut_buffer ):
232
+ return cursor_offset + len (cut_buffer ), line [:cursor_offset ] + cut_buffer + line [cursor_offset :]
202
233
203
234
@edit_keys .on ('<Ctrl-t>' )
204
235
def transpose_character_before_cursor (cursor_offset , line ):
@@ -223,21 +254,24 @@ def uppercase_next_word(cursor_offset, line):
223
254
return cursor_offset , line #TODO Not implemented
224
255
225
256
@edit_keys .on ('<Ctrl-k>' )
257
+ @kills_ahead
226
258
def delete_from_cursor_forward (cursor_offset , line ):
227
- return cursor_offset , line [:cursor_offset ]
259
+ return cursor_offset , line [:cursor_offset ], line [ cursor_offset :]
228
260
229
261
@edit_keys .on ('<Esc+c>' )
230
262
def titlecase_next_word (cursor_offset , line ):
231
263
return cursor_offset , line #TODO Not implemented
232
264
233
265
@edit_keys .on ('<Esc+BACKSPACE>' )
234
266
@edit_keys .on ('<Meta-BACKSPACE>' )
267
+ @kills_behind
235
268
def delete_word_from_cursor_back (cursor_offset , line ):
236
269
"""Whatever my option-delete does in bash on my mac"""
237
270
if not line :
238
271
return cursor_offset , line
239
272
starts = [m .start () for m in list (re .finditer (r'\b\w' , line )) if m .start () < cursor_offset ]
240
273
if starts :
241
- return starts [- 1 ], line [:starts [- 1 ]] + line [cursor_offset :]
242
- return cursor_offset , line
274
+ return starts [- 1 ], line [:starts [- 1 ]] + line [cursor_offset :], line [starts [- 1 ]:cursor_offset ]
275
+ return cursor_offset , line , ''
276
+
243
277
0 commit comments