在vim中最喜欢的位置

10

Vim中是否有命令可以标记一个位置(文件路径、该文件中的行号),以便于以后可以轻松地跳转到那个位置?

这类似于NERDTree:Bookmark命令。您可以使用NERDTreeFromBookmark打开文件。我正在寻找相同的功能,但不同之处在于书签不仅是文件,还包括文件所在的行号。

谢谢


1
标签是我能想到的最接近的词。 - Michael Krelin - hacker
5个回答

20

你可以使用“mark”命令来创建书签,有两种类型的书签可以创建,本地和全局,你正在引用全局书签。

你可以输入“mP”来创建一个名为P的书签。注意大小写,大写表示它是一个全局书签。要跳转到该书签,请键入`P。

希望这可以帮到你

来源


1
我完全不知道它们是持久的 :) - Michael Krelin - hacker
@Eric LaForce 我必须重新打开这个问题,因为与 NERDTree 相比,这个解决方案存在缺点。书签只能是一个字母长,所以我必须记住这些字母。当我在 NERDTree 中使用书签时,它的行为更加优雅。我输入 NERDTreeFromBookmark,然后可以通过 <kbd>tab</kbd> 循环浏览我的字符串书签,例如从 prj_ 开始。标记的另一个缺点是我可以创建的书签数量有限。 - xralf
我会继续编辑您的问题,以包含这些额外的信息。我假设由于您正在将vim与NERDTree进行比较,因此您不想要任何插件,即您正在寻找一种本地的vim解决方案? - Eric LaForce
NERDTree的书签比标记更有效。我会开始一个赏金,如果没有更好的解决方案,我会接受这个。 - xralf
1
@MichaelKrelin-hacker,我错了,如果你使用:bd[elete],它们是持久的。文档:h bwipeout也这样说。 - Brady Trainor
显示剩余4条评论

6
viminfo设置可以包含选项!,使其将任何使用大写字母的全局变量存储在viminfo文件中。通过这种方式,您可以定义一个名为g:BOOKMARKS的变量,并将书签存储在其中。
以下是一些vimscript代码,您可以使用它来完成此操作:
set viminfo+=!

if !exists('g:BOOKMARKS')
  let g:BOOKMARKS = {}
endif

" Add the current [filename, cursor position] in g:BOOKMARKS under the given
" name
command! -nargs=1 Bookmark call s:Bookmark(<f-args>)
function! s:Bookmark(name)
  let file   = expand('%:p')
  let cursor = getpos('.')

  if file != ''
    let g:BOOKMARKS[a:name] = [file, cursor]
  else
    echom "No file"
  endif

  wviminfo
endfunction

" Delete the user-chosen bookmark
command! -nargs=1 -complete=custom,s:BookmarkNames DelBookmark call s:DelBookmark(<f-args>)
function! s:DelBookmark(name)
  if !has_key(g:BOOKMARKS, a:name)
    return
  endif

  call remove(g:BOOKMARKS, a:name)
  wviminfo
endfunction

" Go to the user-chosen bookmark
command! -nargs=1 -complete=custom,s:BookmarkNames GotoBookmark call s:GotoBookmark(<f-args>)
function! s:GotoBookmark(name)
  if !has_key(g:BOOKMARKS, a:name)
    return
  endif

  let [filename, cursor] = g:BOOKMARKS[a:name]

  exe 'edit '.filename
  call setpos('.', cursor)
endfunction

" Completion function for choosing bookmarks
function! s:BookmarkNames(A, L, P)
  return join(sort(keys(g:BOOKMARKS)), "\n")
endfunction

我不确定代码的可读性如何,但基本上,“Bookmark”命令接受一个单一的参数用作名称。它将当前的文件名和光标位置存储到“g:BOOKMARKS”字典中。您可以使用“GotoBookmark”命令加上书签名称来跳转到该书签。"DelBookmark"的工作方式相同,但会删除指定的书签。这两个功能都可以通过制表符自动完成。
另一种通过它们进行跳转的方法是使用此命令:
" Open all bookmarks in the quickfix window
command! CopenBookmarks call s:CopenBookmarks()
function! s:CopenBookmarks()
  let choices = []

  for [name, place] in items(g:BOOKMARKS)
    let [filename, cursor] = place

    call add(choices, {
          \ 'text':     name,
          \ 'filename': filename,
          \ 'lnum':     cursor[1],
          \ 'col':      cursor[2]
          \ })
  endfor

  call setqflist(choices)
  copen
endfunction

CopenBookmarks将在quickfix窗口中加载书签,这对我来说似乎是一个不错的界面。

这个解决方案与Eric的解决方案类似--它使用.viminfo文件,所以如果出现问题,您可能会丢失您的书签。如果您在一个vim实例中保存了书签,则它们不会立即在另一个实例中可用。

我不知道您对vimscript的熟悉程度如何,因此以防万一--要使用此功能,您可以将代码放在位于您的plugin vimfiles目录下的文件中,例如plugin/bookmarks.vim。应该完全足够。这里也有整个代码的gist:https://gist.github.com/1371174

编辑:略微更改了解决方案的接口。原始版本可以在gist历史记录中找到。


那听起来像是一个更好的接口。我并没有真正使用过NERDTree的书签功能,所以我选择了自己想出来的东西。无论如何,我已经更新了我的回复。顺便说一句,如果你遇到“类型不匹配”的错误,请尝试执行unlet g:BOOKMARKS。该变量现在是一个哈希表,而不是一个数组,由于它被持久化了,你可能会遇到这个问题。 - Andrew Radev
这个非常好用。到目前为止我还没有发现任何错误,而且它的表现正如我所希望的一样。非常感谢您应用您的脚本编程知识。 - xralf
重启电脑后书签消失,这很奇怪。 - xralf
很奇怪,我的书签在重新启动后似乎没有丢失。你使用的是什么操作系统?你的.viminfo文件是否放置在某个临时目录中(虽然可能性很小)? - Andrew Radev
我曾使用Xubuntu 10.04,现在改用Lubuntu 11.10,在重启后它可以正常工作。但我更愿意备份,因为我不知道.viminfo的工作原理以及是否可信。(顺便说一句,我问了一个问题,关于如何修改您的脚本以将书签保存到普通文件中) - xralf
显示剩余4条评论

1
" When editing a file, always jump to the last known cursor position.
" And open enough folds to make the cursor is not folded
" Don't do it when the position is invalid or when inside an event handler
" (happens when dropping a file on gvim).
autocmd BufWinEnter *
            \ if line("'\"") <= line("$") |
            \   exe "normal! g`\"" | exe "normal! zv" |
            \ endif

1

1

这并不能解决你所述的问题,但你可能会发现它有所帮助。

MRU.vim - 最近使用的文件插件

输入:MRU,你将得到一个漂亮的可搜索列表,列出了你最近使用的文件。在列表中选择一个并按回车键即可打开。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接