【问题标题】:Preventing repeated use of hjkl movement keys in vim防止在vim中重复使用hjkl移动键
【发布时间】:2012-02-02 00:34:16
【问题描述】:

由于我经常不使用 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,或者我可以专注于我最初尝试做的任务,编辑文本,并且不假思索地发现自己使用更有效的编辑技术。

【问题讨论】:

  • 对于记录设置 mouse=a 允许您将 Up/Down 映射到 并且仍然有一个工作滚轮(如果您需要,也可以启用鼠标选择)。

标签: vim


【解决方案1】:

你太听别人的话了。只需使用您最喜欢的任何键来移动,而不要理会其他键。重新映射 hjkl 键有点麻烦,最好不要这样做,因为由于历史原因,它们在 vim 中是 hardcoded

【讨论】:

  • 我自己得出了结论,并提供了一个链接,以防有人对我为什么会有这种感觉感兴趣。由于某种深层的潜意识本能,我经常发现自己在等待进入文档的不同部分时按住 j 键,我想改掉这个习惯。但是听说重新映射 hjkl 键特别困难,这很有帮助,我可能只需要努力学习、练习和思考。
  • @Thomas - 好吧,如果您不想等待,可以使用 hjkl 键重新映射一些修饰键,以让您关闭整个屏幕。或类似的东西。 Vim 确实有很多移动选项。
  • 我(诚然是小事)的问题是,因为我可以一直按住 j 并等待,我不会有足够的动力去尝试其他事情。我想我可能会禁用 hjkl 几天(非生产性)。
  • @Thomas - 不要采取错误的方式,但是您在错误的事情上浪费了(!)太多时间。 hjkl 和使用箭头键都没有错,也没有(其他一些最适合您的变体)。 ...你不会从这一切中得到任何东西,除非你的工作只是整天上下移动文件。
【解决方案2】:

我发现有效的一件事是:noremap jj &lt;nop&gt;。 Vim 会延迟 j 动作,因为它认为你可能正在扩展它,这会减慢你的速度以尝试其他方式。您也不能再按住 j 键,因为它只会触发 nop。您仍然可以在紧急情况下使用该按钮,但它令人沮丧,以至于您在日常编辑中避免使用它。

【讨论】:

  • 作为一个全职 vim 用户,我认为这是解决 OP 避免按住移动键的愿望的最好也是迄今为止最简单的解决方案
  • 尝试这种方法,我认为它工作得很好,唯一让我烦恼的是,在向下移动多行时也会应用延迟,比如48j,我觉得没问题hjkl 的用法,但我想没有办法为它们设置单独的行为?
【解决方案3】:

编辑

在阅读了您的编辑和您的评论后,我提出了激进的解决方案:重新映射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)执行相同的操作,但在某些情况下逐字符/逐行移动很有用。在这种情况下,您会很高兴拥有+-&lt;Space&gt;

不过,我不太喜欢那种巴甫洛夫式的方法。我觉得它太残酷了,而且你实际上习惯这些奇怪的映射的风险似乎很高。

结束编辑

短版:

箭头键和hjkl 都不值得使用,因此您的重新映射最终毫无用处。一段时间后你会习惯 Vim 的动作和文本对象。在此期间使用你觉得更自然的东西。不要着急。它会来。自然而然。

加长版:

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

我不是打字员,我也不打算成为一名打字员:我使用hjkl 只是为了在插入模式下实际输入hjkl

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

但是有一个问题,当你输入jjjjjjjjjj或者按10次向下箭头键向下移动10行时:jjjjjjjjjjj显然和一样糟糕↓

“不要使用箭头键”这个愚蠢的口头禅只是隐藏森林的树:它重复得如此频繁,以至于它让你专注于无用的模式/反模式,而不是真正学习更强大的方法。

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

  • 0级将是

    jjjjjjjjjjj 然后进行所有必要的水平运动以达到您的目标。

    阅读上面的行,hjkl→ kbd> 辩论是绝对愚蠢的?

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

  • 1 级将是

    10j22l 向下 10 行并到达您的目标右侧 22 个字符。虽然打字少了很多,但您现在必须计算行数和字符数,这并不是特别好。

  • 2级将是

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

    嗯,这样好多了。

  • 3 级将是

    /#&lt;CR&gt; 直接跳转到你的目标(一个十六进制颜色值,和以前一样)。如果它高于你当前的位置,你会做?#&lt;CR&gt;

如果您是一名触控打字员,或者正在接受培训以成为一名打字员,那么争论就解决了:hjkl(或jkl;,有些人喜欢重新映射它们)快速而自然,您不需要箭头键如果不是,那么使用hjkl 优于 的好处最多最小。

转而关注eEbBwWfFtT/?} 和公司。一点一点。不要“强迫”自己。

【讨论】:

  • 我对这个问题的目标是超越 0 级 - 我绝对同意 hjkl 超过箭头键并不是真正的重点 - 我提到关闭箭头键作为提醒的常见示例不是使用几年前我开始使用 vim 时使用的技术。我现在想要一个类似的提醒,不要重复按 j,但不幸的是,重新绑定 hjkl 似乎比箭头键更难。
  • 好的,我喜欢你对过程的描述。我们的大脑似乎并没有以同样的方式工作;)。无论如何,我已经用提案编辑了我的答案。顺便说一句,我不想​​让“0 级”听起来带有贬义,希望你没有误会。
  • 很好,谢谢。我原以为我仍然需要使用 hjkl,但如果我直接跳到搜索导航,我想我不会,至少在短暂的培训期间。别担心,我没有否定“0 级”的东西——“启蒙水平”很有帮助。
  • 我现在使用这个解决方案 - 但我会做 nops 而不是将它们绑定到令人困惑的东西 - 这似乎太苛刻了。
【解决方案4】:

我想提出一个更符合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 联系以查看是否有更新/修复。

您可以放松水平运动的约束,或者 通过设置键/命令列表添加/删除其他动作 在您的~/.vimrc 中生效,g:keys_to_disable_if_not_preceded_by_count。 例如,以下仅对“j”和“k”强制执行以计数为前缀的运动:

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 对替代方法的满意度的回答,但我还是在这里添加了我的解决方案,以防有人正在寻找不同的东西。

【讨论】:

  • 这太棒了,我刚刚添加了它!如果您能在此处包含代码,那就太好了,但我对要点很满意。谢谢!
  • 我添加了代码,但保留了要点的链接,因为我将通过增强/修复来更新要点。
【解决方案5】:

我刚刚找到的一个非常特定于平台的解决方案,仅限 Mac:使用类似 vim 的东西(我只在 vim 模式下使用 PyCharm),打开 MacOS 键保持*,这使得按住 e 调出èéêëēėę 供您选择。这使得按住键永远不起作用!这真的很烦人除非你试图学会停止按住键!

如果我能弄清楚如何在我的终端仿真器(iTerm、Terminal.app 等)中使其工作,那么它可能在普通 vim 中工作?

*这会打开此功能,以防它被您禁用: defaults write -g ApplePressAndHoldEnabled -bool true

【讨论】:

    猜你喜欢
    • 2014-11-01
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 2011-11-08
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多