andsens / homeshick

git dotfiles synchronizer written in bash
MIT License
2.11k stars 145 forks source link

Add cd command to enter castle #30

Closed andsens closed 11 years ago

andsens commented 11 years ago

Add a homeshick cd CASTLE command so users can easily enter a castle and do git stuff. Not sure whether pushd should be used instead though? This way users can write popd to get back to where they were.

andsens commented 11 years ago

Balls, this is of course not possible. We can't change anything in the calling shell from the executing shell. Best we can do is echo the location of the castle, hmpf.

pdex commented 11 years ago

We can simulate popd/pushd with a subshell:

https://github.com/andsens/homeshick/pull/39#issuecomment-23518962

andsens commented 11 years ago

Your code from the PR is definitely worth considering:

#!/bin/bash

CASTLE="$HOME/.homesick/repos/$1"
if [[ -n "$1" && -d "$CASTLE" ]]; then
  export PS1="(Castle:`basename \"$CASTLE\"`)\n$PS1"
  cd $CASTLE
  $SHELL
fi
exit 0

I was thinking something along the lines of chrooting so people don't forget that they are in a subshell, but then you don't have git and it's generally just going to get messy.
I haven't tried this yet, when invoking the subshell do things like completion etc. still work? I assume everything is the same except for the prompt, correct?

pdex commented 11 years ago

ehhhhh, this method needs some tuning. I think your .bashrc, etc files aren't getting sourced when you call the subshell.

andsens commented 11 years ago

For zsh you can use ZDOTDIR=$HOME/.zshrc zsh and for bash bash --rcfile $HOME/.bashrc.

pdex commented 11 years ago

I guess $SHELL could be invoked with $HOMESHICK_SHELL_OPTS

andsens commented 11 years ago

I guess $SHELL could be invoked with $HOMESHICK_SHELL_OPTS

Why add complexity? The init file locations are constant, what would you need that variable for?

pdex commented 11 years ago

My thinking was you don't know which shell invoked homeshick.

On Thursday, August 29, 2013, Anders Ingemann wrote:

I guess $SHELL could be invoked with $HOMESHICK_SHELL_OPTS

Why add complexity? The init file locations are constant, what would you need that variable for?

— Reply to this email directly or view it on GitHubhttps://github.com/andsens/homeshick/issues/30#issuecomment-23530291 .

pdex commented 11 years ago

Or rather, you'd have to case each shell that could invoke homeshick.

On Thursday, August 29, 2013, Chris Keating wrote:

My thinking was you don't know which shell invoked homeshick.

On Thursday, August 29, 2013, Anders Ingemann wrote:

I guess $SHELL could be invoked with $HOMESHICK_SHELL_OPTS

Why add complexity? The init file locations are constant, what would you need that variable for?

— Reply to this email directly or view it on GitHubhttps://github.com/andsens/homeshick/issues/30#issuecomment-23530291 .

andsens commented 11 years ago

Well, there are quite a few shells, true. But really, if we support bash, sh, zsh, csh, dash and fish I think we're good. We can just use bash as a fallback for the rest. It's really just about the init file, it's not mission critical (ie. the feature can work without this).

pdex commented 11 years ago

Ok I'm going to refactor my PR into a proper homeshick command.

jjlin commented 11 years ago

You could potentially have the cd affect the current shell if you start out by sourcing a small helper script that does the cd (or similar operations where the helper is needed), and later passes control to the main script for anything else. This could add a fair amount of complexity since you'd probably need shell-specific helpers (well, one for the Bourne family and one for [t]csh, at least), but maybe there is some clever way to make this not too dirty. Just putting it out there...

andsens commented 11 years ago

I appreciate the input, though I am not entirely sure what you mean. Some pseudo-code maybe?

andsens commented 11 years ago

Your comment got me thinking, it's not a working solution, but I thought I'd throw it out ther.

You could technically achieve something similar to the storm command by making a homeshick dir CASTLE command, which echoes the path to a given castle and then have an alias alias homeshick_cd=cd $(homeshick dir)

This won't work of course because you can't really pass $1 into the $(homeshick dir) part. As far as I can see though, aliasing to cd would be the only way, since cd is a bash/zsh built-in and you can't emulate it by anything that spawns as a subprocess.

jjlin commented 11 years ago

Here's a very barebones implementation (saved in the file $HOME/.homesick/repos/homeshick/home/homeshick-helper.sh):

if [ "$1" = "cd" ]; then
   cd $HOME/.homesick/repos/$2
else
   $HOME/.homesick/repos/homeshick/home/.homeshick "$@"
fi

To make this work, you'd have to set this alias in bash:

alias homeshick="source $HOME/.homesick/repos/homeshick/home/homeshick-helper.sh"

The command homeshick cd homeshick would then go to the repo directory for homeshick.

Of course, you could rename things to taste, or use pushd instead of cd, or whatever. And you'd need another version of the helper for [t]csh or whatever other family of shells you'd like to support, which is where things start getting a bit more complicated. Actually, I had feared that there would be more logic to finding the repo directory, but I guess it's not too unreasonable to hardcode the expected location.

andsens commented 11 years ago

Ooooh, that is neat! I never thought of that! Now I also understand what you mean by complicated. hm, you could cover pretty much any bourne shell if you did this:

test "$1" -eq "cd" && cd $HOME/.homesick/repos/$2 || $HOME/.homesick/repos/homeshick/home/.homeshick "$@"

For C shells you simply change the $@ to $argv[*]. All you need are two scripts/aliases. @pdex what do you think? This would be much simpler and also get around the problem of having to source the init-file.

pdex commented 11 years ago

I don't understand how this is getting invoked. @jjlin are you proposing that the helper file be sourced every time you want to run homeshick? @jjlin Could you spike this out?

jjlin commented 11 years ago

@pdex Yes, that's exactly what would happen. The helper just implements the parts that the helper is needed for (currently, just the cd part). For anything else, it just forwards all the arguments to the main script, and then everything proceeds exactly as before. In fact, I think this scheme could be made such that if a user did not care to have the cd functionality, they could just ignore the helper and use the main script exactly as they do now. I'm not sure what you mean by "spike this out"?

pdex commented 11 years ago

Sorry, using work terminology (http://agiledictionary.com/209/spike/)

Basically I was saying I didn't understand how this was supposed to work and could you provide a Pull Request with what you had in mind.

jjlin commented 11 years ago

I might have time to do an implementation at some point in the next week or two, unless someone else wants to get to it first.

jjlin commented 11 years ago

I sent a PR with what I outlined above, with support for csh/tcsh and Bourne-family shells. I decided to keep things simple and just always do a cd -- you could just do a pushd . beforehand if you really cared, anyway.

One somewhat neat feature I thought of (but probably won't be implementing anytime soon) is to have the cd command handle the no-argument case by figuring out whether the current directory is part of a homeshick repo and if so, changing into it. So for example, if I were in ~/.emacs, then homeshick cd would figure out that it's part of my emacs repo and go there. If there's any ambiguity, then it could just bail out (maybe listing what the possibilities are first).

andsens commented 11 years ago

W00T W00T. Fixed!