3

I have several projects I work on. Instead of setting aliases for each project's location, I would rather set it when I navigate to that specific directory. Each project is a git repo and I already have a mechanism that appends the current branch name to $PS1 when I navigate to it.

In my .bashrc, I call a function: parse_git_branch to append to command prompt:

case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h:\w\a\]$PS1\$(parse_git_branch) "
    ;;  
*)
;;  
esac

parse_git_branch is defined at the end of my .basrhc:

function parse_git_branch {
    GIT_BRANCH=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ \[\1\]/')
    if [[ -n $GIT_BRANCH ]];then
            source $HOME/bin/cur
    fi
    echo $GIT_BRANCH
}

if GIT_BRANCH isn't empty, I source a simple script ~/bin/cur which sets an alias for the pwd:

#!/bin/bash
echo "got here!"
shopt -s expand_aliases
alias current="cd $(pwd)"

When cur is sourced, the alias is not set. The debug message does display correctly however.

I believe this is because shell scripts run "outside" of my current environment. The alias is set when call source cur from the command line.

So, why is the alias not being set when called from "parse_git_branch" inside my .bashrc?

Thanks!

eggmatters
  • 1,130
  • 12
  • 28
  • What is the purpose of that alias? – Etan Reisner Sep 11 '14 at 19:59
  • When I navigate into a project directory, I want an alias created that will be able to allow me to navigate back. For example, I have a project located at "/home/eggmatters/webaps/www/html/foo" and another at "/home/eggmatters/webaps/www/html/bar". They are both git repos and parse_git branch appends my prompt with the branch name when I navigate into it. If I navigate out of the project, say to edit a server conf or whatever, I want to run a command to bring me back to the last project I was in. – eggmatters Sep 11 '14 at 20:16
  • Learn to use `pushd` it will make your life better. Also you can edit files without using `cd` to change to their directory. But I suppose that sort of makes sense... though I'd think using `git rev-parse --show-toplevel` in that alias would be more useful since it wouldn't take you to whatever random directory in the working directory you happened to have last been in, but . – Etan Reisner Sep 11 '14 at 20:20
  • Etan, respectfully, I don't think you understand the nature of the question. I want to indiscriminately track two events: entering a git repo (and storing it's directory on entry) and a request to enter back into that directory. Both of these commands are helpful tools but I still would have a problem *communicating* with the top-level shell current state from a subshell directive - $(). [code] git rev-parse --show-toplevel [/code] is a great idea in the cur script (as opposed to pwd) and pushd would only push the directory stack of the subshell. – eggmatters Sep 12 '14 at 15:32
  • I understand the question. The question has answers. I was discussing the utility of the alias on its own and was suggesting that the alias is a workaround for a problem with a more elegant solution, namely use the shell's dirstack for when you want to cd aside for a moment and be able to easily return to your previous location. But as this is offtopic and I've explained myself once again I think we can probably drop this conversation. – Etan Reisner Sep 12 '14 at 16:36

2 Answers2

2

Problem here is usage of $() that runs parse_git_branch in a subshell. As a result, alias current is not found in opened terminal because aliases are not visible by parent processes.

case "$TERM" in
  xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h:\w\a\]$PS1\$(parse_git_branch) "
    source $HOME/bin/cur
    ;;  
*)
;;

should work.

bart
  • 2,378
  • 2
  • 19
  • 21
0

Ok, I figured it out. The issue here isn't why I'm trying to do this. The issue lays in the fact that I'm trying to affect a parent shell environment from a subshell environment spawned from it (The $() command syntax bart spoke of.) So the workaround was to allow communication from both environments. For that, I simply used the filesystem. Here's what I did:

.bashrc didn't have to change much, but it didn't have to source anything either:

parse_git_branch {
  GIT_BRANCH=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ \[\1\]/')
  if [[ -n $GIT_BRANCH ]];then
        $HOME/bin/cur -p
  fi
  echo $GIT_BRANCH
}

I modified ~/bin/cur to simply write or read the fs, not attempt to modify any environments:

#!/bin/bash
put() {
  echo $(pwd) > $HOME/.tmpalias
}
get() {
  cat $HOME/.tmpalias
}

case "$1" in
 *p) 
   put
   ;;
 *g) 
   get 
   ;;  
esac

The cur script will either write or read from the file .tmpalias when called (I didn't bother with arguments and files etc since this is only called in two places.

Then I added the following to my .bash_aliases file:

alias current='cd $(cur -g)'

Voila! So I can expand this into an event trapping mechanism that can be invoked for any command I run.

eggmatters
  • 1,130
  • 12
  • 28