代码之家  ›  专栏  ›  技术社区  ›  mb14

VIM中的锁定标记

vim
  •  2
  • mb14  · 技术社区  · 14 年前

    是否仍有(内部或通过插件)防止标记被重写? 我的意思是,如果已经使用了就不能设置标记(我特别考虑全球标记)。

    我正在考虑将它们添加到我的VIMRC或会话中,但我更喜欢另一种方式。

    更新

    别给我发脚本来做。我可以自己去做,我的问题更多的是,如果维姆有一个隐藏的方法去做,或者我必须自己写一个脚本。答案显然是否定的。

    不管怎样,谢谢那些已经给我发了剧本的人。我将使用它们来编写自己的脚本(因为发送的脚本并不完全是我想要的)

    2 回复  |  直到 14 年前
        1
  •  5
  •   ZyX    14 年前

    你可以重新映射 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. 选择下一个符号。AS getchar 可以返回一个字符串或一个字符编号,我们必须将其转换回字符串。
      2. 检查我们是否要设置一个标记(您可以用名称标记 a ,但不带姓名 % )如果你试图设置标记 % ,它会被vim忽略,所以不需要保留无用的键。不需要阻止你使用 m' , m[ m] 因为我们不能阻止Vim自己重新定义它们。
      3. 检查有问题的标记是否已由该函数设置,如果已设置,则引发错误。
      4. 返回文本 mC 在哪里 C 是你的商标名。
    3. 我们将使用此函数返回值的映射定义为 {rhs} .

    请注意,这不会阻止某人通过以下方式重新定义此标记: 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()
    
        2
  •  3
  •   jamessan    14 年前

    运行特定命令时,可以防止更改标记。见 :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>