0

I display the current file name and path using:

let g:airline_section_c = '%{pathshorten(expand(''%:f''))}'

Which results in, for example:

/h/b/.c/n/init.vim

This keeps things tidy. However, it would be slightly more useful to have the containing folder name visible. So:

/h/b/.c/nvim/init.vim

The docs for pathshorten seem to suggest that this isn't configurable, and I haven't been able to think of a better solution short of writing my own. Does a viable alternative exist?

5

You could use pathshorten() on the results of expand('%:h') to shorten only the path up to the containing folder (the head). For a path of /home/dev/.vim/ftplugin/c.vim:

expand('%:h')              -> /home/dev/.vim/ftplugin
pathshorten(expand('%:h')) -> /h/d/.v/ftplugin

Then, you can use expand('%:t') to get just the tail of the path (in this example, c.vim) and concatenate with the shortened head:

pathshorten(expand('%:h')) . '/' . expand('%:t') -> /h/d/.v/ftplugin/c.vim

This will work 99% of the time, and you could stop there and probably never encounter the other 1%:

What if the only component of the path is the tail?


Take for instance the path /foo. The result of the above for this path would be //foo (due to the / concatenated between the shortened head / and the tail foo). This is a contrived example, sure, but for the sake of completeness you could check if expand('%:h') == '/' (indicative of our edge case) when adding the shortened head before the tail of the path. In this snippet, I'm using a conditional expression:

(expand('%:h') == '/' ? '' : pathshorten(expand('%:h'))) . '/' .  expand('%:t')

This will now correctly show the path /foo, covering our edge case.


This is kind of hard to understand at a glance though, especially within a statusline item with %{}. It may be better to move this to it's own function, where the logic can be expressed more clearly, as well as decluttering our variable assignment:

function! CondensedPath() abort
    if expand(':h') == '/'
        return '/' . expand('%:t')
    else
        return pathshorten(expand('%:h')) . '/' . expand('%:t')
    endif
endfunction

let g:airline_section_c='%{CondensedPath()}'
1
  • Outstanding answer, very thorough! I'll add for the sake of completeness that, had I consulted :h expand rather than :h pathshorten, that would've led me to the list of modifiers and :h for 'head'. Nov 3 '20 at 7:16

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.