防止在vim中重复使用hjkl移动键

时间:2012-02-02 00:34:16

标签: vim

由于我经常不使用vim提供的优秀动作和文本对象,(以及"Holding down 'j' is a vim anti-pattern,")我希望vim帮助我训练使用这些而不是hjkl连续几次。

当我开始使用vim时,我很生气,我没有使用hjkl移动,而是使用箭头键。为了提醒我不要这样做,我重新设置了箭头键以防止自己使用它们 - 我知道使用主行进行导航将是一个更好的长期计划,所以我通过工作箭头减少了我会得到的积极强化密钥。

map <left> <nop>   
map <right> <nop>  
# I quickly removed nop's for up and down because using 
#  the mouse wheel to scroll is sometimes useful

我的.vimrc中不再需要这些映射,因为这非常有效,而且我很快就切换了,而不必有意识地这样做。以类似的方式,我现在也想切断我对基本运动键hjkl的重复使用。我想象的是这样的事情:

let g:last_mov_key = 'none'
let g:times_mov_key_repeated = 0
function! MovementKey(key)
    if (g:last_mov_key == a:key)
        let g:times_mov_key_repeated = g:times_mov_key_repeated + 1
    else
        let g:last_mov_key = a:key
        let g:times_mov_key_repeated = 0
    endif
    if g:times_mov_key_repeated > 3
        echo "Negative Reinforcement!"                             
    endif
endfunction

noremap j :call MovementKey('j')<CR>gj
noremap k :call MovementKey('k')<CR>gk
noremap h :call MovementKey('h')<CR>h
noremap l :call MovementKey('l')<CR>l

但是这会在视觉模式中中断,我想在其他大多数情况下,在某些事物中间使用vim命令行会在不应该的时候改变状态。我如何限制自己必须使用更复杂的动作?

编辑:问题在前两个答案后编辑,为清晰起见,段落重新排序。我想从vim超越romainl的“0级”获得一些帮助。到目前为止,答案建议我不要浪费我的时间,但如果我们假设我是学习技术的粉丝,我通过改变我的环境来改变我的习惯以改变激励措施呢?在这个模型中,我想完成一项任务,比如向下滚动页面,我会或多或少地随机尝试组合键,直到我完成任务。我脑中的多巴胺信号传导等将加强最终实现这一结果的作用。我可以专注于记住不使用hjkl,或者我可以专注于我最初尝试做的任务,编辑文本,而没有真正考虑它发现自己使用更有效的编辑技术。

5 个答案:

答案 0 :(得分:9)

你太聆听别人的意见了。只需使用您最喜欢的任何键移动,并留下其他键。重新映射hjkl密钥有点麻烦,最好不要这样做,因为由于历史原因它们在vim中hardcoded

答案 1 :(得分:6)

修改

在阅读完你的编辑后,你的评论是我提出的根本解决方案:重新映射hjkl来做超级讨厌的事情:

nnoremap h $
nnoremap l 0
nnoremap j gg
nnoremap k G
" and so on for other modes

hjkl被映射到与其原始行为极端相反的情况,基本上使它们完全无法使用。您也应该对其同义词(:h h:h j:h k:h l)执行相同的操作,以确保完整性,但有时会逐个字符/逐行线运动很有用。在这种情况下,您会很高兴+-<Space>

但是,我并不喜欢那种帕夫洛文法。我发现它太残酷了,你实际习惯这些怪异映射的风险似乎很高。

结束编辑

简短版:

箭头键和hjkl都不值得使用,因此您的重映射最终无用。过了一会儿,你会习惯Vim的动作和文本对象。在此期间使用对您来说更自然的感觉。不要急于求成。它会来。自然。

长版:

你是一名打字员吗?或者你打算学习触摸打字?

我不是一个触摸打字员而且我不打算成为一个:我只使用hjkl来实际在INSERT模式下输入hjkl

当我需要在没有特定“目标”的情况下在上方或下方移动1或2行时,我使用箭头键,当我需要向左或向右移动几个字母时,我使用箭头键。这样做并不可耻。

但是,当您键入jjjjjjjjjj或按下向下箭头键10次向下移动10行时会出现问题:jjjjjjjjjjj显然与 < KBD>↓

这个愚蠢的“不使用箭头键”的口号只是隐藏森林的树:它经常重复,它会让你专注于无用的模式/反模式而不是实际学习更强大的方式。

我不想解释美丽的Your problem with Vim is that you don't grok vi.,但你可以将其视为“启蒙水平”:

  • 等级0 将是

    jjjjjjjjjjj < kbd>↓ 然后所有必要的水平移动到达目标。

    阅读上面的一行,hjkl Vs →显而易见辩论绝对是愚蠢的?

    无论是使用一种方法还是另一种方法,最终都会使键盘垂直和水平移动以达到要编辑的值。多么浪费。浪费时间和精力迫使自己使用一种方法而不是另一种方法,因为两者都同样糟糕。

  • 等级1

    10j22l向下移动10行并向右移动目标22个字符。虽然输入的次数要少得多,但你现在必须计算线条和字符并不是特别好。

  • 等级2

    10jwww向下移动10行并向右移动目标3个单词 或10jf#向下移动10行并跳转到目标的第一个字母(十六进制颜色值)。

    嗯,那好多了。

  • 等级3 将是

    /#<CR>直接跳到目标(十六进制颜色值,如前所述)。如果它高于您当前的位置,您可以?#<CR>

如果你是一个触摸打字员,或者正在接受培训,那么辩论就会得到解决:hjkl(或jkl;,因为有些人喜欢重新映射它们)是快速而自然的,你不会需要箭头键,如果不是,使用hjkl优于 →< / kbd>至多是最小的。

专注于eEbBwWfFtT/?}和公司。一次一点。不要“强迫”自己。

答案 2 :(得分:4)

我发现有一件事是:noremap jj <nop>。 Vim会推迟j动作,因为它认为你可能会延长它,这会让你慢下来尝试别的东西。您也无法再按下j键,因为它只会触发nop。您仍然可以在紧急情况下使用该按钮,但令人沮丧的是让您在日常编辑中避免使用该按钮。

答案 3 :(得分:2)

我想提出一个更符合OP思维方式的解决方案。

我也决定阻止某些动作,如果没有计数之前是一个好主意,正如所讨论here。我也尝试过简单的直接重映射,但是在OP的描述中,这在许多情况下都不起作用。

但我确实最终提出了一种使用key maps that returned an expression的方法:

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", "gj", "gk"])
    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

请注意,为方便起见,此处包含代码,但我也会检查gist以查看是否有更新/修复。

你可以放松水平运动的约束,或者 通过设置键/命令列表来添加/删除其他动作 受g:keys_to_disable_if_not_preceded_by_count影响的~/.vimrc。 例如,以下仅对&#34; j&#34;强制执行以前计​​数为前缀的动作。和&#34; k&#34;:

let g:keys_to_disable_if_not_preceded_by_count = ["j", "k"]

此外,正如gist中所述,您可能会发现在~/.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

或安装插件行vim-numbers

即使这个问题(OP)已经回​​答OP对替代方法的满意度,但我在这里添加我的解决方案,以防任何人搜索不同的东西。

答案 4 :(得分:0)

我刚刚发现的一个非常特定于平台的解决方案,仅适用于Mac:使用类似vim的东西(我只能在vim模式下将其与PyCharm配合使用),打开MacOS密钥持有*,这使得按住 e 弹出èéêëēėę以供选择。这使得按住键永远无效!除非您想学会停止按住键,否则这真的很烦人!

如果我能弄清楚如何在我的终端仿真器(iTerm,Terminal.app等)中实现此功能,那么可以使它在正常vim中运行吗?

*如果您被禁用,它将打开此功能: defaults write -g ApplePressAndHoldEnabled -bool true