Don't understand german? Read or subscribe to my english-only feed.

Directory specific shell configuration with Zsh

Now being an official Debian developer I’ve the possibility to use $DEBEMAIL=mika@debian.org for my Debian packages. But whereas I want to use that for all my official Debian packages I still want to use $DEBEMAIL=mika@grml.org for my grml related packages. I’m a lazy sysadmin and don’t want to manually adjust my changelogs depending on the type of package (especially since this might be error-prone) so I needed a generic solution. Grml’s Zsh configuration (Debian package grml-etc-core >=0.3.71) provides a solution for Zsh (version 4.3.3 or later): based on directories you can set your own profiles. Demonstration:

% cd /grml/git-grml
chpwd(): Switching to profile: grml
% echo $DEBEMAIL
mika@grml.org
% cd /grml/git-debian
chpwd(): Switching to profile: debian
% echo $DEBEMAIL
mika@debian.org

The configuration is pretty simple:

# define profiles based on directories:
zstyle ':chpwd:profiles:/grml/git-grml(|/|/*)'       profile grml
zstyle ':chpwd:profiles:/grml/git-debian(|/|/*)'     profile debian
zstyle ':chpwd:profiles:/home/mika/Customers(|/|/*)' profile customers

# configuration for profile 'grml':
chpwd_profile_grml()
{
  [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
  print "chpwd(): Switching to profile: $profile"

  export DEBEMAIL=mika@grml.org
  export GIT_AUTHOR_EMAIL="mika@grml.org"
  export GIT_COMMITTER_EMAIL="mika@grml.org"
}

# configuration for profile 'debian':
chpwd_profile_debian()
{
  [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
  print "chpwd(): Switching to profile: $profile"

  export DEBEMAIL=mika@debian.org
  export GIT_AUTHOR_EMAIL="mika@debian.org"
  export GIT_COMMITTER_EMAIL="mika@debian.org"
}

# configuration for profile 'customers':
chpwd_profile_customers()
{
  [[ ${profile} == ${CHPWD_PROFILE} ]] && return 1
  print "chpwd(): Switching to profile: $profile"

  export TELEPHONE=[...]
  export MAIL=[...]
}

Kudos to Frank for implementing this lovely feature in grml’s zshrc. Look for chpwd_profiles() in grml’s zsh config for further documentation on this feature.

3 Responses to “Directory specific shell configuration with Zsh”

  1. pabs Says:

    You can do something similar in bash:


    set-git-email-address () {
    case "$PWD" in (/home/pabs/devel/debian/*)
    export GIT_AUTHOR_EMAIL=pabs@debian.org
    export GIT_COMMITTER_EMAIL=pabs@debian.org
    ;;
    (*)
    unset GIT_AUTHOR_EMAIL
    unset GIT_COMMITTER_EMAIL
    ;;
    esac
    }

    export PROMPT_COMMAND="set-git-email-address"

  2. Samat Says:

    Wow, amazing zsh feature I never knew about… definitely a +1 for reasons to switch to zsh.

    pabs: do you know how much slower setting PROMPT_COMMAND would be for bash?

  3. ft Says:

    @Samat: well, zsh doesn’t quite ship that feature, but it makes it possible
    to implement it in a few lines of code, like we did.

    About PROMPT_COMMAND: Yeah, you can do that. But PROMPT_COMMAND is far less
    suitable for that kind of action. The point of implementing this via zstyle
    based setup is, that we could provide a basic functionality that people can
    easily build the exact features they need on.

    And finally, a note about the version requirement, mika mentioned: That’s true
    for our setup. In order to keep our code structured, I decided to use the
    $chpwd_functions[] array – and that makes the code require zsh 4.3.3 or newer.

    If someone wants that feature in her/his zsh setup, you can just make
    chpwd_profiles() to your chpwd() function. When you do that, the code should
    work with zsh version 3.1.7 and newer (because of zstyle and ‘local -x’).