2
function! GitBranch()
  return system("git rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n'")
endfunction

function! StatuslineGit()
  let l:branchname = GitBranch()
  return strlen(l:branchname) > 0?'  '.l:branchname.' ':''
endfunction

set laststatus=2
set statusline+=%#PmenuSel#
set statusline+=%{StatuslineGit()}

I have the code above on .vimrc, which shows git branch status on statusline, it works well until I start scrolling to the top or bottom of the page, strange output appearing on my Konsole screen like this,

enter image description here

Anyone know why?

3

3 Answers 3

2

:help system() tells you about this:

system({expr} [, {input}])              *system()* *E677*
    [...]
    When prepended by |:silent| the terminal will not be set to
    cooked mode.  This is meant to be used for commands that do
    not need the user to type.  It avoids stray characters showing
    up on the screen which require |CTRL-L| to remove. >
        :silent let f = system('ls *.vim')

So call system() with silent seems to avoid this issue.

However, putting that aside, calling an external process on every statusline update doesn't seem like a very swell idea to begin with. Starting up an external process is slow and statusline is called very frequently when scrolling. Try adding :silent and you'll see that while it makes the stray characters go away, scrolling becomes unbearably slow as vim queues its input and wait for the system call to finish.

I'd recommend caching the external call in a g: variable and only making a real call every now and then, it's not like you'll be changing branch every second or so.

1
  • for the last solution, what exactly should I change? Commented Oct 8, 2020 at 8:28
2

Building uppon Lie Ryan's answer and the code provided above (it is described here) . Change your function parsing the git branch as follows:

let g:gitparsedbranchname = ' '
function! UpdateGitBranch()
  let l:string = system("git rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n'")
  let g:gitparsedbranchname = strlen(l:string) > 0?'['.l:string.']':''
endfunction

And change the display of the result in your status line:

set statusline+=%{g:gitparsedbranchname}

To update the vim variable g:gitparsedbranchname hook a function call to UpdateGitBranch() in a auto command group (see vim help: autocmd-groups as you do not want to have multiple listeners on one event (see vim help: autocommand-events).

E.g. if you want to update your git branch variable g:gitparsedbranchname on buffer writes, after buffer reads and buffer changes you can set it up like that (it depends on when you want to update the branch variable):

augroup UPDATE_GITBRANCH
  " clear old commands
  autocmd!

  " update git branch
  autocmd BufWritePre * :call UpdateGitBranch()
  autocmd BufReadPost * :call UpdateGitBranch()
  autocmd BufEnter * :call UpdateGitBranch()
augroup END

You can change the g: as you see fit to limit the scope of that variable (see: vim :help internal-variables).

Those changes fixed the issue with mouse escape codes being printed while using the function to get the git branch.


I for my part settled with the following (and the code snippet for the augroup):

let b:gitparsedbranchname = ' '
function! UpdateGitBranch()
  let l:string = system("git -C ".expand("%:p:h")." rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n'")
  let b:gitparsedbranchname = strlen(l:string) > 0?''.l:string.'':' '
endfunction
set laststatus=2
set statusline=
set statusline+=[%{b:gitparsedbranchname}]

This

  • sets the current git branch in my status line,
  • updates it after each write and
  • considers different git-directories of open files.

For git versions of 2.22 and above it might be easier to get the branch name and the system call can be changed for them (see: here).

0

^[ is a representation of <Esc>, the escape key. When you scroll up or down using your mouse or trackpad, your OS sends an escape code to the terminal. <Esc>OA and <Esc>OB are the escape codes for Up and Down. The escape codes for Right and Left are <Esc>OC and <Esc>OD.

Kinda annoying that you're seeing this instead of a more graceful failure to scroll, but such is life :)

4
  • is there a way to tell VIM to ignore it once it reach top and the bottom of the page? Commented Aug 28, 2020 at 1:19
  • @ThomasG.Lau I do not know of a way for this to happen. Vim shouldn’t even be displaying these, as far as I know. This is a very in-the-weeds issue to debug. Maybe a Jacky workaround will save you. Maybe you can try remapping - map <esc>OA <Up>. No idea if that’ll fix anything. Commented Aug 28, 2020 at 1:21
  • @ThomasG.Lau I wonder if it is Vin’s fault or your terminals fault. Does this issue only happen with vim for you? You must diagnose where the problem is then treat it accordingly. I am down to help you a little bit, but this probably isn’t the site to do this on :P Commented Aug 28, 2020 at 1:22
  • without the script above, VIM act normally, that's all I can tell you Commented Aug 28, 2020 at 1:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.