原插件下载地址如下:
https://github.com/name5566/vim-bookmark/blob/master/README.md
Vim bookmark 是一个 Vim 的书签插件。此插件的特点:
- 相对于 Vim marks 来说,Vim bookmark(书签)可见
- 支持多个 Buffer 间相互跳转
- 关闭 Vim 时自动保存现有书签
- 书签组的支持
但最主要的问题是我要管理多个工程.在每个工程中我都希望能有大写字母的书签.比如定义M书签为main()函数的开始.它的书签是无名书签,如能结合大写字母书签来使用就更好了.
我主要在Linux下使用.做了下面的改进.
一:更改gvim的启动脚本,加入了删除~/.viminfo的功能.因为我的Gvim7.4版本上无论使用:wv或:wv!来保存viminfo文件都会发生将书签与其它工程书签合并的现象.
二:增加一个sh脚本.与插件配合使用,使保存本工程的viminfo中只保存大写字母书签.(此步可省略)
三:修改插件内容如下:主要功能是保存工程时,将大写字母书签保存.读工程时先读大写字母书签.
" Name: Vim bookmark
" Author: Name5566 <name5566@gmail.com>
" pre Version: 0.3.0
" Version:1.01 2019-07-27 10:26
" https://github.com/name5566/vim-bookmark/blob/master/README.md
" 使用V命令列表或切换环境组
" 2018-11-04 20:05 王贺忠修改在Exvim中不能设置全局变量
" let g:vbookmark_bookmarkSaveFile = '/vimbookmark'
" 增加了读写viminfo文件的功能
" 2018-11-07 10:12 调试成功每个Group 都有自己的大写字母文件标记 切换viminfo文件实现
" 2018-11-07 10:12 使用awk 脚本删除没用的跳转列表,使得每个文件长度都小于1K /bin/rp_vi.sh
" 下面是rp_vi.sh的具体内容
" #!/bin/bash
" #使用说明:repair viminfo
" # 2019-07-27 09:25 删除书签0-9 \047表示'
" # 2019-07-26 17:14
" #1、在Viminfo中只保存文件标记后面的内容,不再保存跳转列表
" #2、chmod 777 ./%
" #3、:! ./%
" awk -v var1="/vb_vi" 'BEGIN{
" getline<var1
" printf("# 文件标记:") > "/vb_vi_1"
" while(getline<var1)
" {
" if($0 == "# 文件标记:"){
" break
" }
" }
" while(getline<var1)
" {
" if(NF == 4 && $1 != "\0470"){
" printf("\n") >> "/vb_vi_1"
" printf($0) >> "/vb_vi_1"
" }
" else
" break;
" }
" }'
" #rm -rf /vb_vi
" 2019-07-27 10:21 修改gvim.sh脚本,防止合并viminfo,
" #!/bin/bash
" rm -rf /root/.viminfo
" cwd=$(pwd)
" cwd=/opt/exvim
" escape_cwd=$(printf "%q" "${cwd}")
" echo $cwd
" echo $escape_cwd
" gvim \
" -u "${cwd}/.vimrc" \
" --cmd "let g:exvim_custom_path='${cwd}'" \
" --cmd "set runtimepath=${escape_cwd}/vimfiles,\$VIMRUNTIME,${escape_cwd}/vimfiles/after" \
" ${1:+"$@"}
if exists('loaded_vbookmark')
finish
endif
let loaded_vbookmark = 1
let s:savedCpo = &cpo
set cpo&vim
"""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Sign
"""""""""""""""""""""""""""""""""""""""""""""""""""""""
exec 'sign define vbookmark_sign text=>> texthl=Visual'
function! s:Vbookmark_placeSign(id, file, lineNo)
exec 'sign place ' . a:id
\ . ' line=' . a:lineNo
\ . ' name=vbookmark_sign'
\ . ' file=' . a:file
endfunction
function! s:Vbookmark_unplaceSign(id, file)
exec 'sign unplace ' . a:id
\ . ' file=' . a:file
endfunction
function! s:Vbookmark_jumpSign(id, file)
exec 'sign jump ' . a:id
\ . ' file=' . a:file
endfunction
" I don't like this implementation
function! s:Vbookmark_getSignId(line)
let savedZ = @z
redir @z
silent! exec 'sign place buffer=' . winbufnr(0)
redir END
let output = @z
let @z = savedZ
let match = matchlist(output, ' \S\+=' . a:line . ' id=\(\d\+\)')
if empty(match)
return -1
else
return match[1]
endif
endfun
"""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Bookmark
"""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:Vbookmark_initVariables()
let s:vbookmark_groups = []
let s:vbookmark_curGroupIndex = s:Vbookmark_addGroup('default')
endfunction
function! s:Vbookmark_isSignIdExist(id)
let group = s:vbookmark_groups[s:vbookmark_curGroupIndex]
for mark in group.marks
if mark.id == a:id
return 1
endif
endfor
return 0
endfunction
function! s:Vbookmark_generateSignId()
if !exists('s:vbookmark_signSeed')
let s:vbookmark_signSeed = 201210
endif
while s:Vbookmark_isSignIdExist(s:vbookmark_signSeed)
let s:vbookmark_signSeed += 1
endwhile
return s:vbookmark_signSeed
endfunction
function! s:Vbookmark_adjustCurGroupIndex()
let size = len(s:vbookmark_groups)
let s:vbookmark_curGroupIndex = s:vbookmark_curGroupIndex % size
if s:vbookmark_curGroupIndex < 0
let s:vbookmark_curGroupIndex += size
endif
endfunction
function! s:Vbookmark_adjustCurMarkIndex()
let group = s:vbookmark_groups[s:vbookmark_curGroupIndex]
let size = len(group.marks)
let group.index = group.index % size
if group.index < 0
let group.index += size
endif
endfunction
function! s:Vbookmark_setBookmark(line)
let id = s:Vbookmark_generateSignId()
let file = expand("%:p")
if file == ''
echo "No valid file name"
return
endif
call s:Vbookmark_placeSign(id, file, a:line)
let group = s:vbookmark_groups[s:vbookmark_curGroupIndex]
call add(group.marks, {'id': id, 'file': file, 'line': a:line})
endfunction
function! s:Vbookmark_unsetBookmark(id)
let marks = s:vbookmark_groups[s:vbookmark_curGroupIndex].marks
let i = 0
let size = len(marks)
while i < size
let mark = marks[i]
if mark.id == a:id
call s:Vbookmark_unplaceSign(mark.id, mark.file)
call remove(marks, i)
call s:Vbookmark_adjustCurMarkIndex()
break
endif
let i += 1
endwhile
endfunction
function! s:Vbookmark_refreshSign(file)
let marks = s:vbookmark_groups[s:vbookmark_curGroupIndex].marks
for mark in marks
if mark.file == a:file
call s:Vbookmark_placeSign(mark.id, mark.file, mark.line)
endif
endfor
endfunction
function! s:Vbookmark_jumpBookmark(method)
let group = s:vbookmark_groups[s:vbookmark_curGroupIndex]
if empty(group.marks)
echo "No bookmarks found"
return
endif
if a:method == 'next'
let group.index += 1
elseif a:method == 'prev'
let group.index -= 1
endif
call s:Vbookmark_adjustCurMarkIndex()
let mark = group.marks[group.index]
try
call s:Vbookmark_jumpSign(mark.id, mark.file)
catch
if !filereadable(mark.file)
call remove(group.marks, group.index)
call s:Vbookmark_adjustCurMarkIndex()
call s:Vbookmark_jumpBookmark(a:method)
return
endif
exec 'e ' . mark.file
call s:Vbookmark_refreshSign(mark.file)
call s:Vbookmark_jumpSign(mark.id, mark.file)
endtry
endfunction
function! s:Vbookmark_placeAllSign()
let marks = s:vbookmark_groups[s:vbookmark_curGroupIndex].marks
for mark in marks
try
call s:Vbookmark_placeSign(mark.id, mark.file, mark.line)
catch
endtry
endfor
endfunction
function! s:Vbookmark_unplaceAllSign()
let marks = s:vbookmark_groups[s:vbookmark_curGroupIndex].marks
for mark in marks
try
call s:Vbookmark_unplaceSign(mark.id, mark.file)
catch
endtry
endfor
endfunction
function! s:Vbookmark_clearAllBookmark()
call s:Vbookmark_unplaceAllSign()
call s:Vbookmark_initVariables()
endfunction
function! s:Vbookmark_addGroup(name)
call add(s:vbookmark_groups, {'name': a:name, 'marks': [], 'index': -1})
return len(s:vbookmark_groups) - 1
endfunction
function! s:Vbookmark_removeGroup(name)
if len(s:vbookmark_groups) <= 1
echo "Cann't remove the last bookmark group"
return
endif
let curGroupName = s:vbookmark_groups[s:vbookmark_curGroupIndex].name
if curGroupName =~ '^' . a:name
call s:Vbookmark_unplaceAllSign()
call remove(s:vbookmark_groups, s:vbookmark_curGroupIndex)
call s:Vbookmark_adjustCurGroupIndex()
call s:Vbookmark_placeAllSign()
echo 'Remove the current bookmark group ' . curGroupName
\ . '. Open the bookmark group ' . s:vbookmark_groups[s:vbookmark_curGroupIndex].name
return
endif
let i = 0
let size = len(s:vbookmark_groups)
while i < size
let group = s:vbookmark_groups[i]
if group.name =~ '^' . a:name
call remove(s:vbookmark_groups, i)
if i < s:vbookmark_curGroupIndex
let s:vbookmark_curGroupIndex -= 1
endif
echo 'Remove the bookmark group ' . group.name
return
endif
let i += 1
endwhile
echo 'No bookmark group ' . a:name . ' found'
endfunction
function! s:Vbookmark_openGroup(name)
if s:vbookmark_groups[s:vbookmark_curGroupIndex].name =~ '^' . a:name
return 1
endif
let i = 0
let size = len(s:vbookmark_groups)
while i < size
let group = s:vbookmark_groups[i]
if group.name =~ '^' . a:name
call s:Vbookmark_unplaceAllSign()
let s:vbookmark_curGroupIndex = i
call s:Vbookmark_placeAllSign()
echo 'Open the bookmark group ' . group.name
let output = "cp /b/whzwiki/个人/vbgroup/" . s:vbookmark_groups[s:vbookmark_curGroupIndex].name . " /vb_vi"
call system(output)
delmarks A-Z
if filereadable("/vb_vi")
rviminfo! /vb_vi
endif
return 1
endif
let i += 1
endwhile
return 0
endfunction
function! s:Vbookmark_listGroup()
let i = 0
let size = len(s:vbookmark_groups)
while i < size
let output = ' '
if i == s:vbookmark_curGroupIndex
let output = '* '
endif
let output .= s:vbookmark_groups[i].name
echo output
let i += 1
endwhile
endfunction
function! s:Vbookmark_saveAllBookmark()
if !exists('g:vbookmark_bookmarkSaveFile')
let g:vbookmark_bookmarkSaveFile = '/vimbookmark'
" return
end
let output = "rm -rf /vb_vi"
call system(output)
wviminfo! /vb_vi
call system("rp_vi.sh")
call system("mkdir -p /b/whzwiki/个人/vbgroup/")
let output = "mv -f /vb_vi_1 /b/whzwiki/个人/vbgroup/" . s:vbookmark_groups[s:vbookmark_curGroupIndex].name
call system(output)
call system("rm -rf /viminfo")
let outputGroups = 'let g:__vbookmark_groups__ = ['
for group in s:vbookmark_groups
let outputGroups .= '{"name": "' . group.name . '", "index": ' . group.index . ', "marks": ['
for mark in group.marks
let outputGroups .= '{"id": ' . mark.id . ', "file": "' . escape(mark.file, ' \') . '", "line": ' . mark.line . '},'
endfor
let outputGroups .= ']},'
endfor
let outputGroups .= ']'
let outputCurGroupIndex = "let g:__vbookmark_curGroupIndex__ = " . s:vbookmark_curGroupIndex
call writefile([outputGroups, outputCurGroupIndex], g:vbookmark_bookmarkSaveFile)
endfunction
autocmd VimLeave * call s:Vbookmark_saveAllBookmark()
function! s:Vbookmark_loadAllBookmark()
delmarks A-Z
if !exists('g:vbookmark_bookmarkSaveFile')
let g:vbookmark_bookmarkSaveFile = '/vimbookmark'
end
if filereadable("ss")
" rviminfo ss
endif
if !exists('g:vbookmark_bookmarkSaveFile') || !filereadable(g:vbookmark_bookmarkSaveFile)
return
end
try
exec 'source ' . g:vbookmark_bookmarkSaveFile
catch
echo "Bookmark save file is broken"
return
endtry
if !exists('g:__vbookmark_groups__') || type(g:__vbookmark_groups__) != 3
\ || !exists('g:__vbookmark_curGroupIndex__') || type(g:__vbookmark_curGroupIndex__) != 0
echo "Bookmark save file is invalid"
return
end
echo
let s:vbookmark_groups = deepcopy(g:__vbookmark_groups__)
let s:vbookmark_curGroupIndex = g:__vbookmark_curGroupIndex__
call s:Vbookmark_placeAllSign()
unlet g:__vbookmark_groups__
unlet g:__vbookmark_curGroupIndex__
call s:Vbookmark_openGroup("default")
let output = "cp /b/whzwiki/个人/vbgroup/" . s:vbookmark_groups[s:vbookmark_curGroupIndex].name . " /vb_vi"
call system(output)
if filereadable("/vb_vi")
rviminfo! /vb_vi
endif
endfunction
autocmd VimEnter * call s:Vbookmark_loadAllBookmark()
call s:Vbookmark_initVariables()
"""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Interface
"""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:VbookmarkToggle()
let line = line('.')
let id = s:Vbookmark_getSignId(line)
if id == -1
call s:Vbookmark_setBookmark(line)
else
call s:Vbookmark_unsetBookmark(id)
endif
endfunction
function! s:VbookmarkNext()
call s:Vbookmark_jumpBookmark('next')
endfunction
function! s:VbookmarkPrevious()
call s:Vbookmark_jumpBookmark('prev')
endfunction
function! s:VbookmarkClearAll()
call s:Vbookmark_clearAllBookmark()
endfunction
function! s:VbookmarkGroup(name)
if a:name == ''
call s:Vbookmark_listGroup()
elseif !s:Vbookmark_openGroup(a:name)
call s:Vbookmark_unplaceAllSign()
let s:vbookmark_curGroupIndex = s:Vbookmark_addGroup(a:name)
echo 'Add a new bookmark group ' . a:name
endif
marks
endfunction
function! s:VbookmarkGroupRemove(name)
let name = a:name
if name == ''
let name = s:vbookmark_groups[s:vbookmark_curGroupIndex].name
endif
call s:Vbookmark_removeGroup(name)
endfunction
if !exists(':VbookmarkToggle')
command -nargs=0 VbookmarkToggle :call s:VbookmarkToggle()
endif
if !exists(':VbookmarkNext')
command -nargs=0 VbookmarkNext :call s:VbookmarkNext()
endif
if !exists(':VbookmarkPrevious')
command -nargs=0 VbookmarkPrevious :call s:VbookmarkPrevious()
endif
if !exists(':VbookmarkClearAll')
command -nargs=0 VbookmarkClearAll :call s:VbookmarkClearAll()
endif
if !exists(':VbookmarkSaveAll')
command -nargs=0 VbookmarkSaveAll :call s:Vbookmark_saveAllBookmark()
endif
if !exists(':VbookmarkGroup')
command -nargs=? V :call s:VbookmarkGroup(<q-args>)
endif
if !exists(':VbookmarkGroupRemove')
command -nargs=? VbookmarkGroupRemove :call s:VbookmarkGroupRemove(<q-args>)
endif
if !exists('g:vbookmark_disableMapping')
nnoremap <silent> mn :VbookmarkToggle<CR>
nnoremap <silent> mm :VbookmarkNext<CR>
nnoremap <silent> mp :VbookmarkPrevious<CR>
nnoremap <silent> mc :VbookmarkClearAll<CR>
endif
let &cpo = s:savedCpo