简体   繁体   中英

Shortened path relative to git repository in terminal prompt with zsh

GOAL

I'm trying to create a shortened path for my terminal prompt that is relative to the repository in which I'm in. Similar to what I already have for my root & home directory shown below.

The last directory shown in the following terminal prompts' paths is always the current working directory.

root:

/ %
/rootDir %
/rootDir/dir1/dir2 %
/rootDir/.../dir2/dir3 %
/rootDir/.../dir3/dir4 %

home:

~ %
~/dir1/dir2 %
~/.../dir2/dir3 %
~/.../dir3/dir4 %

And I'm trying to figure a way to have it work the same way when I'm in a repository. Where the repository is the "root" instead of the actual root or home being the "root" of the path.
repository:

|repo %
|repo/dir1/dir2 %
|repo/.../dir2/dir3 %
|repo/.../dir3/dir4 %

WHAT I'VE DONE

my.zshrc code:

autoload -Uz vcs_info
zstyle ':vcs_info:git:*' formats '|%r'
zstyle ':vcs_info:git:*' check-for-changes true

setopt PROMPT_SUBST

precmd()
{
    vcs_info
    if [ -d .git ];
    then
        PROMPT='${vcs_info_msg_0_}'
    elif $(git rev-parse > /dev/null 2>&1);
    then
        PROMPT='${vcs_info_msg_0_}/%c'
    else
        PROMPT='%(4~|%-1~/.../%2~|%3~)'
    fi

    PROMPT+=' %# '
}

The solution for the path when in the root or home directory is pretty simple:

PROMPT='%(4~|%-1~/.../%2~|%3~)'

This checks the length of the path from the working directory to the which ever is the closest, root or home and displays one of two different paths depending on how many directories long the relative path is.

I couldn't figure out a way to modify this for the repository however. As I have it now it uses an if..else which checks whether my working directory is the "root" of the repo or if I'm further inside of the repo. And use these to either display just the name of the repo or the name and the current working directory. To make it work like with the root & home directories however I would need to have the current length between the repo and working directory or some other simpler solution which I might have missed.

Finally got around to this again. I ended up working out a solution that does the intended:

autoload -Uz vcs_info
zstyle ':vcs_info:git:*' formats '|%r'
zstyle ':vcs_info:git:*' check-for-changes true

setopt PROMPT_SUBST

precmd()
{
    vcs_info

# in git repo
    if [[ -n $(git rev-parse --git-dir 2> /dev/null) ]]; then

    # in root of git repo
        if [ -d .git ];
        then
            PROMPT='${vcs_info_msg_0_}'

    # in first subfolder of git repo
        elif [ -d ../.git ];
        then
            PROMPT='${vcs_info_msg_0_}/%c'

    # in second subfolder of git repo
        elif [ -d ../../.git ];
        then
            PROMPT='${vcs_info_msg_0_}/%2c'

    # in deeper subfolder of git repo
        else
            PROMPT='${vcs_info_msg_0_}/.../%2c'
        fi

# not in git repo
    else
        PROMPT='%(4~|%-1~/.../%2~|%3~)'
    fi

    PROMPT+=' %# '
}

Not the most elegant of hacks but not being very familiar with the syntax this is what I came up with.

Now the function checks the working directory's relative position to the.git file that is found at the root of every git repository. To reduce the amount of checks done by the function it firstly has an if statement that checks whether the current directory is anywhere inside of a git repository. If not, the previous solution from the original post for the home and root paths is used instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM