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?

Rich Churcher
  • 201
  • 2
  • 6

1 Answers1

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()}'

Jake Grossman
  • 1,643
  • 1
  • 4
  • 16
  • 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'. – Rich Churcher Nov 03 '20 at 07:16