Vim: 在lightline状态栏中显示当前的git分支(无需安装fugitive插件)

6
我正在使用lightline.vim,希望能够显示当前的git分支。目前,我是通过vim-fugitive来实现的,但我并不使用这个插件,除了在状态栏中显示git分支外。
我的问题是:
有没有一种方法可以在不使用fugitive的情况下在状态栏中显示git分支?
我尝试创建一个自定义函数,将其挂钩到lightline上。该函数使用system vimscript函数获取当前的git分支。它运行得很好,除了每次按键时刷新状态栏,这破坏了其他所有内容并使vim无法使用。基本上,git分支是在每次按键时使用system函数获取的...
那么这不是一个可行的解决方案。我“可以”创建一个全局变量来判断是否已经获取了git分支,并且如果已经获取,则防止自定义函数再次获取分支名称。然后,每次MacVim失去焦点时重新获取分支名称(不确定如何在终端vim中做到这一点)。但这并不理想...请问有什么解决这个问题的想法吗?

Powerline 还是 Lightline? - romainl
4个回答

26

我创造了一个插件,专注于你所需的功能。

https://github.com/itchyny/vim-gitbranch

你可以使用gitbranch#name()函数获取分支名称。

这段代码非常简短,你只需要一分钟就能读完。


哇!看起来很棒啊!我要去看看!谢谢! - Robert Audi
刚刚用了这个!和vim-airline一起使用效果非常好! - aashah7
@aashah7,请问您能展示一下如何使用vim-airline吗? - AniketGM

4

是的,使用全局变量是最好的选择。

不太明显的部分是如何/何时更新该变量的值。 autocmd 似乎是最明显的选择,但挂钩到什么事件呢? BufEnter 看起来是一个不错的起点。

现在,既然你不使用 fugitive,那么你如何切换分支呢?在 Vim 外面吗?在 Vim 的命令行上吗?

如果你在 Vim 的命令行上执行它,:!git checkout foo,你可以编写一个命令,将分支名称作为参数传递以执行正确的 shell 命令,并一次性更改 g:git_branch 的值,甚至不需要使用 autocmd

如果你在 Vim 外部执行它(<C-z>:sh,另一个终端窗口或 tmux 面板,GUI 应用程序...),你需要找到一种可靠的方法来通知 Vim 进行更改,或者使用带有 autocmdsystem() 调用。


我只在vim之外(从命令行)使用git。如我的问题所述,我已经考虑了autocmd + system()解决方案。但我想知道是否有更“自动化”的解决方案。也就是说,当我改变git分支时,它会自动更新lightline。使用fugitive,这就是正在发生的事情。我查看了fugitive的源代码,但我很难理解这个功能是如何实现的... - Robert Audi
4
逃犯不更新lightline:逃犯暴露了一个检索和缓存分支名称的函数,然后在lightline中使用该函数。您可以在lightline文档中查看其操作方式。解析 system('git branch') 的输出以更新全局变量(或更好的是缓冲区本地变量)最实用的解决方案。找到正确的方法来更新该变量是关键。简单的autocmd听起来不错。 - romainl
好的,你说服了我。我会实现这个解决方案,并随着时间的推移不断完善它。感谢你的回答。 - Robert Audi

2
将以下代码写入 .vimrc 文件中。
    let gitBranch=system("git rev-parse --abbrev-ref HEAD")
    set laststatus=2
    set statusline=%F%m%r%h%w\ [POS=%04l,%04v]\ [%p%%]\ [LEN=%L]
    execute "set statusline +=" . gitBranch


分支名称只有在关闭并重新打开vim时才会刷新。 - Ignacio Ambía

0
我曾经有同样的问题,但我只是想在我的.vimrc文件中添加几行代码,而不是安装一个插件。在阅读了其他答案并进行了一些尝试和错误之后,我最终得到了以下解决方案:
" ~/.vimrc

fun! GitBranch(file)
    let l:dir = fnamemodify(system('readlink -f ' . a:file), ':h')
    let l:cmd = 'git -C ' . l:dir . ' branch --show-current 2>/dev/null'
    let b:git_current_branch = trim(system(l:cmd))
endfun

augroup GitBranch
    autocmd!
    autocmd BufEnter,ShellCmdPost,FileChangedShellPost * call GitBranch(expand('%'))
augroup END

set rulerformat=%32(%=%{b:git_current_branch}%=%8l,%-6(%c%V%)%=%4p%%%)


我把分支名称放在标尺上,因为我不使用lightline或者状态栏,但是rulerformat的语法和statusline完全相同,所以应该很容易找到lightline设置statusline的地方,并进行必要的修改。
我的屏幕底部显示如下:
".vimrc" 135 lines --39%--                                         master      53,11      39%

关键部分是%{b:git_current_branch},其中b:git_current_branch是每个缓冲区本地的变量,所以在切换缓冲区时不会发生冲突。 GitBranch函数将获取当前缓冲区文件的当前分支名称,即使它位于不同的目录中,在此过程中还会跟随符号链接。
当您切换缓冲区时,分支名称会更新,并且在vim内执行shell命令(例如:!git switch:!git checkout等)后,以及在vim外更改分支(在W11: Warning ... has changed提示之后)。
如果缓冲区中的文件不在git目录中,则该变量为空,并且没有错误;分支名称只是消失了。如果文件在git目录中但未被跟踪,则仍然会得到分支名称,但如果这不是您想要的结果,您可以通过在GitBranch中添加一些额外的system()调用来更改它。
这适用于Linux上的vim 8,但我认为Mac可能有不同的readlink命令,而对于Windows我一无所知。

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