I'm currently learning Vimscript, but I'm stuck at a particular problem.

I'm creating a statusline which shows the full path (~) of the file currently displayed in the buffer. Instead of just using %F, I'm creating two separate highlight groups to show the difference between the cwd and the active file. Example:


My current solution:

let file = fnamemodify(expand("%:p"), ":~")
let pwd = system('print -P %~')

hi pwd guifg=#FFFFFF
hi file guifg=#FFF093 gui=bold

set statusline=
set statusline+=%#pwd#[%{pwd}/
set statusline+=%#file#%{file[len(pwd):]}

This works …until you switch files, and nothing updates, which makes sense given the above code. I'm just not sure to continue from here. I've tried to wrap the variables inside autocommands for different buffer events, but that doesn't help. Neither does assigning fnamemodify or system directly to the statusline, as that gives an error when trying to source my vimrc



Ben Knoble has suggested a function returning a string, and that the statusline should simply call that function. This works with the exception of highlight groups now being outputted as just plain strings

hi pwd guifg=#BADA55
hi file guifg=#FFF093 gui=bold

function! SetStatusLine()
    \ "%#pwd#" . system('print -P %~') .
    \ "%#file#" . fnamemodify(expand("%:p"), ":~")[len(system('print -P %~')):]

set statusline=%{SetStatusLine()}

The statusline now updates as it should, but highlight groups don't work. My statsline currently shows the following:


Close! Any other ideas?

Update 2

…Minor brainfart, you just use multiple functions for each highlight group. It works now!

  • 1
    Have you tried pulling the whole thing into a function and assigning statusline to evaluate that function? – D. Ben Knoble Aug 16 '18 at 13:02
  • I have not. Do you have a small, dumbed down example of such a function? – Audun Olsen Aug 16 '18 at 13:19
  • 1
    Hm, the 4 lines just above your assignment of statusline would be a good example actually (short and simple). Then you would probably return the string that comprises the statusline you want. This is how e.g. airline controls the statusline. – D. Ben Knoble Aug 16 '18 at 13:32
  • I did as you suggested, and I'm closer! The problem now is highlight groups not working, hmmm.. Updated original post with the new code. – Audun Olsen Aug 16 '18 at 14:25
  • 1
    You should self-answer with the solution that worked for you; that way others can benefit. – D. Ben Knoble Aug 16 '18 at 16:24

Finally got it going thanks to some simple functions!

hi pwd guifg=#BADA55
hi file guifg=#FFF093 gui=bold
hi line guifg=#FFFFFF
hi statuslinenc gui=none
hi statusline gui=none

function! SetStatusLinePath()
     return system('print -P %~')[:-2] . "/"

function! SetStatusLineFile()
     return fnamemodify(expand("%:p"), ":~")[len(system('print -P %~')):]

set statusline=–––⎜
set statusline+=%#pwd#%{SetStatusLinePath()}
set statusline+=%#file#%{SetStatusLineFile()}
set statusline+=%#line#⎟

Here's a picture of my statusline as of now, just to visually show what I was trying to accomplish.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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