Shorten path in bufname variable

Recently I’ve added new feature to my powerline.kak plugin. It allows user to select how to display the bufname in modeline. It has three options:

I think this can be really helpful, and I know that not everyone is using powerline.kak, and prefer a default modeline, so I’ve decided to share the script here:

declare-option -docstring "shorten the name of the buffer accordingly to the setting.
full  - do not shorten buffer name: '/full/path/file'.
short - display short path: '/f/p/file'.
name  - only show the file name: 'file'." \
str shorten_bufname_type "short"

declare-option -hidden str bufname
define-command -hidden shorten-bufname %{ set-option buffer bufname %sh{
    case "$kak_opt_shorten_bufname_type" in
            printf "%s\n" "${kak_bufname}" ;;
            printf "%s\n" "${kak_bufname}" | perl -pe 's:(?(?<=/)|(?<=^))([^\p{Letter}\p{Digit}]+.|[^/]).+?/:\1/:g' ;;
            printf "%s\n" "${kak_bufname##*/}" ;;

hook global WinDisplay .* shorten-bufname
hook global BufWritePost .* shorten-bufname
hook global BufSetOption shorten_bufname_type=.+ shorten-bufname

hook global WinCreate .* %{
    set-option window modelinefmt "%opt{bufname} %val{cursor_line}:%val{cursor_char_column} {{context_info}} {{mode_info}} - %val{client}@[%val{session}]"

I’ve altered it a bit, so it’s not 1 to 1 copy from the plugin (changed names), but it works exactly the same. I’ve used default modeline in the last hook so you have to modify the modeline to fit your needs.

The only disadvantage I’ve found so far is that I can’t track if pwd was changed. There’s no hook for that, and it seems that no option or variable either.

Nice work! Thanks for sharing.

In some IDEs there’s sometimes a behavior which is even more complex. Here’s an example tree:


At first, when src/componentA/index.js is opened in the editor, only index.js is shown as a bufname. Then, if src/componentB/index.js is opened, there’s an ambiguity, because both of them show the same bufname.
So in this case, the IDE decides to show longer bufnames for these 2 files: componentA/index.js and componentB/index.js. As soon as one of those files is closed, it reverts back to the simple index.js.

This scenario is a nice to have, but it’s out of the scope of the function you’re offering because it would have to scan for conflicts in the buflist.

1 Like

I’ve thought about this, but in a bit different way, e.g. show parts of path up until not matching symbol:
src/config/file src/custom/file would be shown as s/co/file and s/cu/file, but:

  • this is complex, and time to filter everything grows really fast because we have to do parsing for all buffers dir by dir and then char by char, until we find all differences.
  • most modern shells can understand ambiguous paths, such as s/c/index.js and provide completion if there’s several candidates, so this is fine:
  • in case of your example, such algorithm defeats the purpose, since path will be s/componentA/index.js if file with the same name is opened from componentB directory.