comparison vimrc @ 87:aefa231684d9

Add extra motions
author zegervdv <zegervdv@me.com>
date Fri, 01 Aug 2014 07:08:40 +0200
parents 8a5464ec3c29
children 3fdc762fe6bb
comparison
equal deleted inserted replaced
86:3a37086414bd 87:aefa231684d9
244 let fillcharcount = windowwidth - len(line) - len(foldedlinecount) 244 let fillcharcount = windowwidth - len(line) - len(foldedlinecount)
245 return line . '…' . repeat(" ",fillcharcount) . foldedlinecount . '…' . ' ' 245 return line . '…' . repeat(" ",fillcharcount) . foldedlinecount . '…' . ' '
246 endfunction " }}} 246 endfunction " }}}
247 set foldtext=MyFoldText() 247 set foldtext=MyFoldText()
248 248
249 " }}} 249 " Next and Last {{{
250 250 "
251 " Motion for "next/last object". "Last" here means "previous", not "final".
252 " Unfortunately the "p" motion was already taken for paragraphs.
253 "
254 " Next acts on the next object of the given type, last acts on the previous
255 " object of the given type. These don't necessarily have to be in the current
256 " line.
257 "
258 " Currently works for (, [, {, and their shortcuts b, r, B.
259 "
260 " Next kind of works for ' and " as long as there are no escaped versions of
261 " them in the string (TODO: fix that). Last is currently broken for quotes
262 " (TODO: fix that).
263 "
264 " Some examples (C marks cursor positions, V means visually selected):
265 "
266 " din' -> delete in next single quotes foo = bar('spam')
267 " C
268 " foo = bar('')
269 " C
270 "
271 " canb -> change around next parens foo = bar('spam')
272 " C
273 " foo = bar
274 " C
275 "
276 " vin" -> select inside next double quotes print "hello ", name
277 " C
278 " print "hello ", name
279 " VVVVVV
280
281 onoremap an :<c-u>call <SID>NextTextObject('a', '/')<cr>
282 xnoremap an :<c-u>call <SID>NextTextObject('a', '/')<cr>
283 onoremap in :<c-u>call <SID>NextTextObject('i', '/')<cr>
284 xnoremap in :<c-u>call <SID>NextTextObject('i', '/')<cr>
285
286 onoremap al :<c-u>call <SID>NextTextObject('a', '?')<cr>
287 xnoremap al :<c-u>call <SID>NextTextObject('a', '?')<cr>
288 onoremap il :<c-u>call <SID>NextTextObject('i', '?')<cr>
289 xnoremap il :<c-u>call <SID>NextTextObject('i', '?')<cr>
290
291
292 function! s:NextTextObject(motion, dir)
293 let c = nr2char(getchar())
294 let d = ''
295
296 if c ==# "b" || c ==# "(" || c ==# ")"
297 let c = "("
298 elseif c ==# "B" || c ==# "{" || c ==# "}"
299 let c = "{"
300 elseif c ==# "r" || c ==# "[" || c ==# "]"
301 let c = "["
302 elseif c ==# "'"
303 let c = "'"
304 elseif c ==# '"'
305 let c = '"'
306 else
307 return
308 endif
309
310 " Find the next opening-whatever.
311 execute "normal! " . a:dir . c . "\<cr>"
312
313 if a:motion ==# 'a'
314 " If we're doing an 'around' method, we just need to select around it
315 " and we can bail out to Vim.
316 execute "normal! va" . c
317 else
318 " Otherwise we're looking at an 'inside' motion. Unfortunately these
319 " get tricky when you're dealing with an empty set of delimiters because
320 " Vim does the wrong thing when you say vi(.
321
322 let open = ''
323 let close = ''
324
325 if c ==# "("
326 let open = "("
327 let close = ")"
328 elseif c ==# "{"
329 let open = "{"
330 let close = "}"
331 elseif c ==# "["
332 let open = "\\["
333 let close = "\\]"
334 elseif c ==# "'"
335 let open = "'"
336 let close = "'"
337 elseif c ==# '"'
338 let open = '"'
339 let close = '"'
340 endif
341
342 " We'll start at the current delimiter.
343 let start_pos = getpos('.')
344 let start_l = start_pos[1]
345 let start_c = start_pos[2]
346
347 " Then we'll find it's matching end delimiter.
348 if c ==# "'" || c ==# '"'
349 " searchpairpos() doesn't work for quotes, because fuck me.
350 let end_pos = searchpos(open)
351 else
352 let end_pos = searchpairpos(open, '', close)
353 endif
354
355 let end_l = end_pos[0]
356 let end_c = end_pos[1]
357
358 call setpos('.', start_pos)
359
360 if start_l == end_l && start_c == (end_c - 1)
361 " We're in an empty set of delimiters. We'll append an "x"
362 " character and select that so most Vim commands will do something
363 " sane. v is gonna be weird, and so is y. Oh well.
364 execute "normal! ax\<esc>\<left>"
365 execute "normal! vi" . c
366 elseif start_l == end_l && start_c == (end_c - 2)
367 " We're on a set of delimiters that contain a single, non-newline
368 " character. We can just select that and we're done.
369 execute "normal! vi" . c
370 else
371 " Otherwise these delimiters contain something. But we're still not
372 " sure Vim's gonna work, because if they contain nothing but
373 " newlines Vim still does the wrong thing. So we'll manually select
374 " the guts ourselves.
375 let whichwrap = &whichwrap
376 set whichwrap+=h,l
377
378 execute "normal! va" . c . "hol"
379
380 let &whichwrap = whichwrap
381 endif
382 endif
383 endfunction
384 " }}}
385 " }}}
251 " Vim Math plugin; make simple calculations {{{ 386 " Vim Math plugin; make simple calculations {{{
252 vmap <expr> ++ VMATH_YankAndAnalyse() 387 vmap <expr> ++ VMATH_YankAndAnalyse()
253 nmap ++ vip++ 388 nmap ++ vip++
254 " }}} 389 " }}}
255 " Airline configuration {{{ 390 " Airline configuration {{{