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
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
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')
return pathshorten(expand('%:h')) . '/' . expand('%:t')