给每个工程都分配一组大写字母书签,vim-bookmark的改进

原插件下载地址如下:

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

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值