Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collapse directories in zsh prompt in a unique way

Tags:

prompt

zsh

pwd

Is there a way to collapse the current working directory in the zsh prompt in a unique way, so that I could copy and paste it to another terminal, hit TAB and get the original path?

Let's say we have following directories:

/adam/devl
/alice/devl
/alice/docs
/bob/docs

If the prompt is programmed to show the first characters, and I'm in /b/d, then it is unique. On the other hand, /a/d is not unique, so I would need /ad/d, /al/de and /al/do. And even /ali/… as soon as the user alex appears.

Is it possible to hack this directly in zsh or do I need to write a script, that finds the shortest unique beginning of each parent directory?

Thank you for your ideas!

like image 821
eumiro Avatar asked Jul 23 '17 09:07

eumiro


People also ask

How do I change zsh prompt on Mac?

To make any change to the default zsh prompt, you'll have to add relevant values for the prompt to appear differently than the default. It'll be blank if you're accessing it for the first time. You can add a new line with the text PROMPT='...' and include relevant values in the ellipses.

Does zsh have PS1?

zsh uses the same shell variable PS1 to store the default prompt.

How do I customize my zsh prompt?

To customize the ZSH prompt, we need to modify the prompt= variable inside the . zshrc file. We can populate the prompt variable with various placeholders, which will alter how the ZSH prompt appears.

How do I show the current working directory in zsh?

This is documented in the Zsh manual under Prompt Expansion, right at the end of the page. %d %/ Current working directory. If an integer follows the ‘%’, it specifies a number of trailing components of the current working directory to show %~ As %d and %/, but if the current working directory starts with $HOME, that part is replaced by a ‘~’.

How to increase the maximum prompt length in zsh?

Using %< yields a far more predictable maximum prompt length. For example, to left-truncate the path element with tilde expansion ( %~) to 15 characters, replacing removed characters with .., you can do something like this: This is documented in the Zsh manual under Prompt Expansion, right at the end of the page.

How do I set the PS1 variable in zsh?

For Zsh, we will use ~/.zshrc to set the PS1 variable. This file is loaded at the beginning of every shell session, so it will ensure our configuration is respected for all sessions and not just the current one. Every shell has a default prompt string, and we can view the raw source by echoing the PS1 variable (e.g. echo $PS1 ).


1 Answers

I'm not aware that zsh has a built-in function of this sort, but it should be pretty easy to script without resorting to a single subshell or slow pipe:

#!/bin/zsh

paths=(${(s:/:)PWD})

cur_path='/'
cur_short_path='/'
for directory in ${paths[@]}
do
  cur_dir=''
  for (( i=0; i<${#directory}; i++ )); do
    cur_dir+="${directory:$i:1}"
    matching=("$cur_path"/"$cur_dir"*/)
    if [[ ${#matching[@]} -eq 1 ]]; then
      break
    fi
  done
  cur_short_path+="$cur_dir/"
  cur_path+="$directory/"
done

printf %q "${cur_short_path: : -1}"
echo

This script will output the shortest path needed for auto-completion to work.

You can throw it in your .zshrc as a function and then run it from any directory.

function spwd {
  paths=(${(s:/:)PWD})

  cur_path='/'
  cur_short_path='/'
  for directory in ${paths[@]}
  do
    cur_dir=''
    for (( i=0; i<${#directory}; i++ )); do
      cur_dir+="${directory:$i:1}"
      matching=("$cur_path"/"$cur_dir"*/)
      if [[ ${#matching[@]} -eq 1 ]]; then
        break
      fi
    done
    cur_short_path+="$cur_dir/"
    cur_path+="$directory/"
  done

  printf %q "${cur_short_path: : -1}"
  echo
}

Here's a video of it in action:

https://asciinema.org/a/0TyL8foqvQ8ec5ZHS3c1mn5LH

Or if you prefer, some sample output:

~/t $ ls
adam  alice  bob  getshortcwd.zsh

~/t $ ls adam
devl

~/t $ ls alice
devl  docs

~/t $ spwd
/h/v/t

~/t $ cd adam/devl

~/t/adam/devl $ spwd
/h/v/t/ad/d

~/t/adam/devl $ cd ../../alice/devl

~/t/alice/devl $ spwd
/h/v/t/al/de

~/t/alice/devl $ cd ../docs

~/t/alice/docs $ spwd
/h/v/t/al/do

~/t/alice/docs $ `spwd` [TAB]
~/t/alice/docs $ /h/v/t/al/do [TAB]
~/t/alice/docs $ /home/vsimonian/t/alice/docs
like image 176
Adaline Simonian Avatar answered Oct 24 '22 08:10

Adaline Simonian