Skip to content

Instantly share code, notes, and snippets.

@jeetsukumaran
Last active January 25, 2019 12:06
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jeetsukumaran/96474ebbd00b874f0865 to your computer and use it in GitHub Desktop.
Save jeetsukumaran/96474ebbd00b874f0865 to your computer and use it in GitHub Desktop.
Disable Basic Motions if not Preceded By a Count
" Notes:
" (1) To enhance the ergonomics of this sufficiently to make it practical, at
" least, until your brain grows a new lobe dedicated to counting line offsets
" in the background while you work, you should either make sure you have
" something like the following in your `~/.vimrc`:
"
" set number
" if has('autocmd')
" augroup vimrc_linenumbering
" autocmd!
" autocmd WinLeave *
" \ if &number |
" \ set norelativenumber |
" \ endif
" autocmd BufWinEnter *
" \ if &number |
" \ set relativenumber |
" \ endif
" autocmd VimEnter *
" \ if &number |
" \ set relativenumber |
" \ endif
" augroup END
" endif
"
" or you have installed a plugin like
" (vim-numbers)[https://github.com/myusuf3/numbers.vim].
"
" (2) You might want to relax the constraint for horizontal motions, or
" add other motions. You can customize the list of motions by
" specifying the keys in the
" `g:keys_to_disable_if_not_preceded_by_count` variable. For example,
" the following only enforces count-prefixed motions for "j" and "k":
"
" let g:keys_to_disable_if_not_preceded_by_count = ["j", "k"]
function! DisableIfNonCounted(move) range
if v:count
return a:move
else
" You can make this do something annoying like:
" echoerr "Count required!"
" sleep 2
return ""
endif
endfunction
function! SetDisablingOfBasicMotionsIfNonCounted(on)
let keys_to_disable = get(g:, "keys_to_disable_if_not_preceded_by_count", ["j", "k", "l", "h"])
if a:on
for key in keys_to_disable
execute "noremap <expr> <silent> " . key . " DisableIfNonCounted('" . key . "')"
endfor
let g:keys_to_disable_if_not_preceded_by_count = keys_to_disable
let g:is_non_counted_basic_motions_disabled = 1
else
for key in keys_to_disable
try
execute "unmap " . key
catch /E31:/
endtry
endfor
let g:is_non_counted_basic_motions_disabled = 0
endif
endfunction
function! ToggleDisablingOfBasicMotionsIfNonCounted()
let is_disabled = get(g:, "is_non_counted_basic_motions_disabled", 0)
if is_disabled
call SetDisablingOfBasicMotionsIfNonCounted(0)
else
call SetDisablingOfBasicMotionsIfNonCounted(1)
endif
endfunction
command! ToggleDisablingOfNonCountedBasicMotions :call ToggleDisablingOfBasicMotionsIfNonCounted()
command! DisableNonCountedBasicMotions :call SetDisablingOfBasicMotionsIfNonCounted(1)
command! EnableNonCountedBasicMotions :call SetDisablingOfBasicMotionsIfNonCounted(0)
DisableNonCountedBasicMotions
@samuelsimoes
Copy link

@jeetsukumaran would be great if we could set some usage tolerance to use the "avoided keys without counting".

@portalgun
Copy link

portalgun commented Jul 7, 2017

This is great!
Here is your same come with a few lines to allow you to press just your keys just once, as to prevent bad habits (eg d1j instead of just dj).

let g:lastmove = 1
function! DisableIfNonCounted(move) range
    if g:lastmove != a:move
        let g:lastmove = a:move
        return a:move
    else
        if v:count
            let g:lastmove = a:move
            return a:move
        else
            " You can make this do something annoying like:
               " echoerr "Count required!"
               " sleep 2
            return ""
        endif
    endif
    let g:lastmove = a:move
endfunction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment