在VIM中锁定标记

时间:2010-08-02 11:38:20

标签: vim

无论如何(内部或通过插件)是否可以防止标记被覆盖? 我的意思是一种方式,所以如果它已经被使用你就不能设置标记(我特别考虑全局标记)。

我正在考虑在我的vimrc或会话中添加它们,但我更愿意采用其他方式。

更新

请勿向我发送脚本来执行此操作。我可以自己做,如果VIM中有隐藏的方法可以做到这一点,或者我自己必须编写脚本,那么我的问题就更多了。答案显然不是。

非常感谢那些已经发给我脚本的人。我将使用它们来编写我自己的(因为发送的脚本不是我想要的)

2 个答案:

答案 0 :(得分:5)

您可以使用自定义功能重新映射m

let s:marks={}
function s:SetMark()
    let m=getchar()
    if type(m)==type(0)
        let m=nr2char(m)
    endif
    if m=~#'^[a-zA-Z]$'
        if has_key(s:marks, m)
            throw "Mark ".m."is arleady set"
        endif
        let s:marks[m]=1
    endif
    return "m".m
endfunction
nnoremap <expr> m <SID>SetMark()

此功能将阻止您重新映射标记。这就是它的工作原理:

  1. 我们定义了一个字典,其中的键包含已设置的标记(实际上我们可以使用列表,但字典应该更快一些)。
  2. 我们定义一个函数:
    1. 选择下一个符号。由于getchar可能返回字符串或字符编号,因此我们必须将其转换回字符串。
    2. 检查我们是否要设置标记(您可以使用名称为a的标记,但不能使用名称%标记)。如果你试图设置标记%,它将被vim忽略,所以不需要保留无用的密钥。并且无需阻止您使用m'm[m],因为我们无法阻止您通过vim本身重新定义它们。
    3. 检查此功能是否已设置有问题的标记,如果是,则抛出错误。
    4. 返回文字mC,其中C是您的商标名称。
  3. 我们定义一个使用此函数返回值为{rhs}的映射。
  4. 请注意,这不会阻止某人通过normal!(但不是normal没有爆炸)命令重新定义此标记,nnoremap(但不是nmap)映射或类似的东西。

    更新:s的修改版本:SetMark:

    function s:SetMark()
        let m=getchar()
        if type(m)==type(0)
            let m=nr2char(m)
        endif
        if m=~#'^[A-Z]$'
            let pos=getpos("'".m)
            if pos[1]
                echohl Error
                echon "Mark ".m." is arleady set. Overwrite?"
                echohl None
                let c=getchar()
                if type(c)==type(0)
                    let c=nr2char(c)
                endif
                echo
                if c!=?'y'
                    return "<C-l>"
                endif
            endif
        endif
        return "m".m
    endfunction
    nnoremap <special><expr> m <SID>SetMark()
    

答案 1 :(得分:3)

您可以在运行特定命令时阻止更改标记。请参阅:lockmarks


没有办法阻止它们被覆盖,但您可以使用要求使用标记的功能,通知您是否已使用该标记,并提示输入其他标记。

fun! SetMark()
    let mark = ''
    while mark == ''
        call inputsave()
        let mark = input('Mark to set (Enter to cancel)? ')
        call inputrestore()
        if mark == ''
            return
        endif
        if mark !~# '^[A-Z]$'
            echohl Error
            echo "Invalid mark name.  Must be a capital letter."
            echohl None
            let mark = ''
            continue
        endif
        let pos = getpos("'" . mark)
        if pos[1] != 0 " Used mark
            let fname = fnamemodify(bufname(pos[0]), ':~:.')
            call inputsave()
            let yn = input('Mark already set for ' . fname . '. Overwrite? (y/n) ')
            call inputrestore()
            if yn !~? '^y'
                let mark = ''
            endif
        endif
    endwhile
    exe 'normal m' . mark
endfun
nnoremap <F2> :call SetMark()<CR>