Skip to content

Commit

Permalink
Improved cursor-motion handling
Browse files Browse the repository at this point in the history
Made it modular so that more commands can be added in the future.
  • Loading branch information
subnut committed Dec 14, 2020
1 parent 24675ba commit 5cd95bd
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 51 deletions.
79 changes: 40 additions & 39 deletions autoload/smoothie.vim
Original file line number Diff line number Diff line change
Expand Up @@ -331,64 +331,65 @@ function smoothie#backwards()
endfunction

""
" Smoothie equivalent to gg.
function smoothie#gg()
let s:cursor_movement = v:true
let s:ctrl_f_invoked = v:false
if !g:smoothie_enabled || mode(1) =~# 'o' && mode(1) =~? 'no'
" If in operator pending mode, disable vim-smoothie and force the movement
" to be line-wise, because gg was originally linewise.
" Uses the normal non-smooth version of gg.
exe 'normal! ' . (mode(1) ==# 'no' ? 'V' : '') . v:count . 'gg'
return
endif
" gg behaves like a jump-command so, append current position to the jumplist
" but before that, set the target, because v:count and v:count1 will be lost
let l:target = v:count1
let l:target = (l:target > line('$') ? line('$') : l:target)
let l:target = (foldclosed(l:target) != -1 ? foldclosed(l:target) : l:target)
if foldclosed('.') == l:target
let s:cursor_movement = v:false
return
endif
execute "normal! m'"
call s:update_target(s:calculate_screen_lines(line('.'), l:target))
" suspend further commands till the destination is reached
" see point (3) of https://github.com/psliwka/vim-smoothie/issues/1#issuecomment-560158642
while line('.') != l:target
exe 'sleep ' . g:smoothie_update_interval . ' m'
endwhile
let s:cursor_movement = v:false " reset s:cursor_movement to false
if &startofline " :help 'startofline'
call cursor(line('.'), match(getline('.'),'\S')+1)
" Smoothie equivalent for G and gg
" NOTE: I have also added - movement to dempnstrate how to add more new
" movements in the future
function smoothie#cursor_movement(movement)
let l:movements = {
\'gg': {
\'target_expr': 'v:count1',
\'startofline': &startofline,
\'jump_commmand': v:true,
\},
\'G' : {
\'target_expr': "(v:count ? v:count : line('$'))",
\'startofline': &startofline,
\'jump_commmand': v:true,
\},
\'-' : {
\'target_expr': "line('.') - v:count1",
\'startofline': v:true,
\'jump_commmand': v:false,
\},
\}
if !has_key(l:movements, a:movement)
return 1
endif
call s:do_vertical_cursor_movement(a:movement, l:movements[a:movement])
endfunction

""
" Smoothie equivalent to G.
function smoothie#G()
" absolutely similar to smoothie#gg()
" refer to that for explanation of steps
" Helper function to preform cursor movements
function s:do_vertical_cursor_movement(movement, properties)
let s:cursor_movement = v:true
let s:ctrl_f_invoked = v:false
" If in operator pending mode, disable vim-smoothie and use the normal
" non-smoothie version of the movement
if !g:smoothie_enabled || mode(1) =~# 'o' && mode(1) =~? 'no'
exe 'normal! ' . (mode(1) ==# 'no' ? 'V' : '') . v:count . 'G'
" If in operator-pending mode, prefer the movement to be linewise
exe 'normal! ' . (mode(1) ==# 'no' ? 'V' : '') . v:count . a:movement
return
endif
let l:target = (v:count ? v:count : line('$'))
let l:target = eval(a:properties['target_expr'])
let l:target = (l:target > line('$') ? line('$') : l:target)
let l:target = (foldclosed(l:target) != -1 ? foldclosed(l:target) : l:target)
if foldclosed('.') == l:target
let s:cursor_movement = v:false
return
endif
execute "normal! m'"
" if this is a jump command, append current position to the jumplist
if a:properties['jump_commmand']
execute "normal! m'"
endif
call s:update_target(s:calculate_screen_lines(line('.'), l:target))
" suspend further commands till the destination is reached
" see point (3) of https://github.com/psliwka/vim-smoothie/issues/1#issuecomment-560158642
while line('.') != l:target
exe 'sleep ' . g:smoothie_update_interval . ' m'
endwhile
let s:cursor_movement = v:false
if &startofline
let s:cursor_movement = v:false " reset s:cursor_movement to false
if a:properties['startofline']
" move cursor to the first non-blank character of the line
call cursor(line('.'), match(getline('.'),'\S')+1)
endif
endfunction
Expand Down
24 changes: 12 additions & 12 deletions plugin/smoothie.vim
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ if !has('float') || !has('timers')
endif

if has('nvim') || has('patch-8.2.1978')
noremap <silent> <Plug>(SmoothieDownwards) <cmd>call smoothie#downwards() <CR>
noremap <silent> <Plug>(SmoothieUpwards) <cmd>call smoothie#upwards() <CR>
noremap <silent> <Plug>(SmoothieForwards) <cmd>call smoothie#forwards() <CR>
noremap <silent> <Plug>(SmoothieBackwards) <cmd>call smoothie#backwards() <CR>
noremap <silent> <Plug>(Smoothie_gg) <cmd>call smoothie#gg() <CR>
noremap <silent> <Plug>(Smoothie_G) <cmd>call smoothie#G() <CR>
noremap <silent> <Plug>(SmoothieDownwards) <cmd>call smoothie#downwards() <CR>
noremap <silent> <Plug>(SmoothieUpwards) <cmd>call smoothie#upwards() <CR>
noremap <silent> <Plug>(SmoothieForwards) <cmd>call smoothie#forwards() <CR>
noremap <silent> <Plug>(SmoothieBackwards) <cmd>call smoothie#backwards() <CR>
noremap <silent> <Plug>(Smoothie_gg) <cmd>call smoothie#cursor_movement('gg') <CR>
noremap <silent> <Plug>(Smoothie_G) <cmd>call smoothie#cursor_movement('G') <CR>
if !get(g:, 'smoothie_no_default_mappings', v:false)
silent! map <unique> <C-D> <Plug>(SmoothieDownwards)
Expand All @@ -25,12 +25,12 @@ if has('nvim') || has('patch-8.2.1978')
silent! map <unique> <PageUp> <Plug>(SmoothieBackwards)
endif
else
nnoremap <silent> <Plug>(SmoothieDownwards) :<C-U>call smoothie#downwards() <CR>
nnoremap <silent> <Plug>(SmoothieUpwards) :<C-U>call smoothie#upwards() <CR>
nnoremap <silent> <Plug>(SmoothieForwards) :<C-U>call smoothie#forwards() <CR>
nnoremap <silent> <Plug>(SmoothieBackwards) :<C-U>call smoothie#backwards() <CR>
nnoremap <silent> <Plug>(Smoothie_gg) :<C-U>call smoothie#gg() <CR>
nnoremap <silent> <Plug>(Smoothie_G) :<C-U>call smoothie#G() <CR>
nnoremap <silent> <Plug>(SmoothieDownwards) :<C-U>call smoothie#downwards() <CR>
nnoremap <silent> <Plug>(SmoothieUpwards) :<C-U>call smoothie#upwards() <CR>
nnoremap <silent> <Plug>(SmoothieForwards) :<C-U>call smoothie#forwards() <CR>
nnoremap <silent> <Plug>(SmoothieBackwards) :<C-U>call smoothie#backwards() <CR>
nnoremap <silent> <Plug>(Smoothie_gg) :<C-U>call smoothie#cursor_movement('gg') <CR>
nnoremap <silent> <Plug>(Smoothie_G) :<C-U>call smoothie#cursor_movement('G') <CR>
if !get(g:, 'smoothie_no_default_mappings', v:false)
silent! nmap <unique> <C-D> <Plug>(SmoothieDownwards)
Expand Down

0 comments on commit 5cd95bd

Please sign in to comment.