Is there anyway (internal or via a plugin) to prevent marks to be overridden ? I mean a way so you can't set a mark if it's already used (I'm thinking especially of global marks).
I'm thinking of adding them in my vimrc or session, but I would prefer another way.
Update
Don't send me a script to do it. I can do it myself, my question was more if there is a hidden way in VIM to do it or if I had to write a script myself. The answer is apparently no.
Thanks anyway to people who开发者_如何学Go already sent me a script. I'll use them to write my own one (as the scripts sent are not exactly what I want)
You may remap the m
with custom function:
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()
This function will prevent you from remapping mark. That is how it works:
- We define a dictionary, which keys contain already set marks (actually we could use a list, but dictionary should be a bit faster).
- We define a function that:
- Pick next symbol. As
getchar
may return either a string or a character number, we must convert it back to string. - Checks whether we are going to set a mark (you can have mark with name
a
, but not with name%
). If you try to set mark%
, it would be ignored by vim, so no need to keep useless keys. And no need to prevent you from usingm'
,m[
andm]
since we cannot prevent redefining them by vim itself. - Checks whether mark in question was already set by this function, throws a error if it was.
- Returns text
mC
, whereC
is your mark name.
- Pick next symbol. As
- We define a mapping that uses this function returned value as
{rhs}
.
Note that this will not prevent somebody from redefining this mark by normal!
(but not normal
without a bang) command, nnoremap
(but not nmap
) mapping or something similar.
UPDATE: Modified version of 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()
You can prevent marks from being changed while you run a specific command. See :lockmarks.
There isn't a way to prevent them from being overridden, but you could use a function that asks for the mark to use, informs you if that's already used, and prompts for another mark.
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>
精彩评论