Created
June 4, 2014 16:08
-
-
Save afazio/81b68f60e9566d80da27 to your computer and use it in GitHub Desktop.
ZSH prompt for Git and Ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## ~/.zshrc | |
# ... | |
# Load extensions from ~/.zsh/func/ directory | |
zgitinit | |
railsdir | |
# Setup basic prompt: | |
if [[ "$TERM" != "dumb" ]]; then | |
PROMPT="%B%m%b%# " | |
RPROMPT="[%h:%2.]" | |
else | |
PROMPT="%m%# " | |
fi | |
export BASE_PROMPT=$PROMPT | |
# Set precmd_functions to be a global array | |
typeset -ga precmd_functions | |
# Setup git prompt: | |
# Check git status of current directory and change prompt as necessary | |
git_precmd () { | |
local p=$BASE_PROMPT # strip last space off | |
[[ -n $NO_GIT || -n $NOGIT ]] && { | |
export PROMPT=$p | |
return 1 | |
} | |
(zgit_isgit && zgit_issubdirtracked) || { | |
export PROMPT=$p | |
return 1 | |
} | |
zgit_isworktreeclean || p="${p}${PR_RED}!${PR_NO_COLOR}" | |
zgit_hasuntracked && p="${p}${PR_RED}?${PR_NO_COLOR}" | |
zgit_isindexclean || p="${p}${PR_GREEN}+${PR_NO_COLOR}" | |
zgit_hasstash && p="${p}${PR_YELLOW}s${PR_NO_COLOR}" | |
zgit_isahead 2>/dev/null && p="${p}${PR_BLUE}>${PR_NO_COLOR}" | |
[[ $(zgit_branch) != "master" ]] && p="${p}${PR_BLUE}*${PR_NO_COLOR}" | |
if [[ $p != $BASE_PROMPT ]]; then | |
PROMPT="$p " | |
else | |
PROMPT="$BASE_PROMPT${PR_GREEN}=${PR_NO_COLOR} " | |
fi | |
export PROMPT | |
export GIT_PROMPT=$PROMPT | |
} | |
precmd_functions+='git_precmd' | |
# Setup railsdir extension | |
railsdir_precmd () { | |
local p=$BASE_PROMPT | |
if [[ -n $GIT_PROMPT ]]; then | |
p=$GIT_PROMPT | |
fi | |
is_rails_app_dir || { | |
export PROMPT=$p | |
return 1 | |
} | |
get_rails_env >/dev/null | |
get_ruby_version >/dev/null | |
color= | |
case $RAILS_ENV in; | |
"local") color="";; | |
"test") color="";; | |
"development") color="${PR_YELLOW}";; | |
*) color="${PR_RED}";; | |
esac | |
p="${p}[${PR_GREEN}${RUBY_VERSION}${PR_NO_COLOR}:${color}$RAILS_ENV${PR_NO_COLOR}] " | |
PROMPT=$p | |
export PROMPT | |
} | |
precmd_functions+=railsdir_precmd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- mode: sh -*- | |
## ~/.zsh/func/railsdir | |
typeset -ga __AJF_AVAILABLE_RAILS_ENVS | |
function is_rails_app_dir { | |
# If no directory provided, use pwd | |
[[ -z $1 ]] && 1=$(pwd) | |
# Does this look like a rails app? | |
if [[ -e "$1/Rakefile" && \ | |
-d "$1/app" && \ | |
-d "$1/config" && \ | |
-f "$1/config/environment.rb" && \ | |
-f "$1/config/routes.rb" ]]; then | |
# Set this variable to a list of available rails envs supported by | |
# this application. | |
if is_mac; then | |
__AJF_AVAILABLE_RAILS_ENVS=($(ls -1 "$1/config/environments/" | grep '\.rb$' | xargs basename | sed 's/\.rb//')) | |
else | |
__AJF_AVAILABLE_RAILS_ENVS=($(find config/environments -name '*.rb' -printf '%f\n' | sed 's/\.rb//')) | |
fi | |
export __AJF_AVAILABLE_RAILS_ENVS | |
# We are in a rails application. Return true | |
return 0 | |
fi | |
## The current directory doesn't look like a rails application. Let's | |
## keep checking parent directories until we either find that we are in | |
## a rails application or we hit the root directory (/) | |
if [[ "$1" == "/" ]]; then | |
# We've made it to the root directory. exit | |
return 1 # Return false | |
else | |
# Otherwise, check the parent directory | |
is_rails_app_dir $1:h | |
return $? | |
fi | |
} | |
function get_rails_env { | |
typeset -g RAILS_ENV >/dev/null | |
[[ -z $RAILS_ENV ]] && { | |
if [[ ${__AJF_AVAILABLE_RAILS_ENVS[(i)local]} -le ${#__AJF_AVAILABLE_RAILS_ENVS} ]]; then | |
export RAILS_ENV=local | |
else | |
export RAILS_ENV=development | |
fi | |
} | |
echo -n $RAILS_ENV | |
} | |
function get_ruby_version { | |
typeset -g RUBY_VERSION >/dev/null | |
if which rvm >/dev/null; then | |
export RUBY_VERSION=$(rvm current | cut -d- -f 2) | |
else | |
export RUBY_VERSION=$(ruby --version | cut -d' ' -f 2) | |
fi | |
echo -n $RUBY_VERSION | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- sh -*- | |
## ~/.zsh/func/zgitinit | |
## Load with `autoload -U zgitinit; zgitinit' | |
## | |
typeset -gA zgit_info | |
zgit_info=() | |
zgit_chpwd_hook() { | |
zgit_info_update | |
} | |
zgit_preexec_hook() { | |
if [[ $2 == git\ * ]] || [[ $2 == *\ git\ * ]]; then | |
zgit_precmd_do_update=1 | |
fi | |
} | |
zgit_precmd_hook() { | |
if [ $zgit_precmd_do_update ]; then | |
unset zgit_precmd_do_update | |
zgit_info_update | |
fi | |
} | |
zgit_info_update() { | |
zgit_info=() | |
local gitdir="$(git rev-parse --git-dir 2>/dev/null)" | |
if [[ $? -ne 0 ]] || [[ -z $gitdir ]] || [[ $gitdir == "." ]]; then | |
return | |
fi | |
zgit_info[dir]=$gitdir | |
zgit_info[bare]=$(git rev-parse --is-bare-repository) | |
} | |
zgit_isgit() { | |
if [[ -z "$zgit_info[dir]" ]]; then | |
return 1 | |
else | |
return 0 | |
fi | |
} | |
zgit_isbare() { | |
zgit_isgit || return | |
if [[ $zgit_info[bare] = "true" ]]; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
zgit_head() { | |
zgit_isgit || return 1 | |
if [[ -z $zgit_info[head] ]]; then | |
local name | |
name=$(git symbolic-ref -q HEAD) | |
if [[ $? -eq 0 ]]; then | |
if [[ $name == refs/(heads|tags)/* ]]; then | |
name=${name#refs/(heads|tags)/} | |
fi | |
else | |
name=$(git name-rev --name-only --no-undefined --always HEAD) | |
if [ $? -ne 0 ]; then | |
return 1 | |
elif [[ $name == remotes/* ]]; then | |
name=${name#remotes/} | |
fi | |
fi | |
zgit_info[head]=$name | |
fi | |
echo $zgit_info[head] | |
} | |
zgit_isahead() { | |
zgit_isgit || return 1 | |
ahead=$(git status | grep "Your branch is ahead of") | |
[[ -n $ahead ]] && return 0 | |
return 1 | |
} | |
zgit_branch() { | |
zgit_isgit || return 1 | |
zgit_isbare && return 1 | |
if [ -z "$zgit_info[branch]" ]; then | |
local branch=$(git symbolic-ref HEAD 2>/dev/null) | |
if [ $? -eq 0 ]; then | |
branch=${branch##*/} | |
else | |
branch=$(git name-rev --name-only --always HEAD) | |
fi | |
zgit_info[branch]=$branch | |
fi | |
echo $zgit_info[branch] | |
return 0 | |
} | |
zgit_tracking_remote() { | |
zgit_isgit || return 1 | |
zgit_isbare && return 1 | |
local branch | |
if [ -n "$1" ]; then | |
branch=$1 | |
elif [ -z "$zgit_info[branch]" ]; then | |
branch=$(zgit_branch) | |
[ $? -ne 0 ] && return 1 | |
else | |
branch=$zgit_info[branch] | |
fi | |
local k="tracking_$branch" | |
local remote | |
if [ -z "$zgit_info[$k]" ]; then | |
remote=$(git config branch.$branch.remote) | |
zgit_info[$k]=$remote | |
fi | |
echo $zgit_info[$k] | |
return 0 | |
} | |
zgit_tracking_merge() { | |
zgit_isgit || return 1 | |
zgit_isbare && return 1 | |
local branch | |
if [ -z "$zgit_info[branch]" ]; then | |
branch=$(zgit_branch) | |
[ $? -ne 0 ] && return 1 | |
else | |
branch=$zgit_info[branch] | |
fi | |
local remote=$(zgit_tracking_remote $branch) | |
[ $? -ne 0 ] && return 1 | |
if [ -n "$remote" ]; then # tracking branch | |
local merge=$(git config branch.$branch.merge) | |
if [ $remote != "." ]; then | |
merge=$remote/$(basename $merge) | |
fi | |
echo $merge | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
zgit_isindexclean() { | |
zgit_isgit || return 1 | |
if git diff --quiet --cached 2>/dev/null; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
zgit_isworktreeclean() { | |
zgit_isgit || return 1 | |
if git diff --quiet 2>/dev/null; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
zgit_issubdirtracked() { | |
local d="$(git rev-parse --git-dir)" | |
local ds p="$(pwd)" | |
[[ $d == ".git" ]] && return 0; | |
ds=$(git ls-tree --name-only HEAD | head -n 1) | |
[[ -n $ds ]] && return 0; | |
d=$d:h | |
ds=$(cd $d; git ls-tree -r --full-name --name-only HEAD) | |
for directory in $ds; do | |
if [[ $ds == $p ]]; then | |
return 0; | |
fi | |
done | |
return 1; | |
} | |
zgit_hasuntracked() { | |
zgit_isgit || return 1 | |
local -a flist | |
flist=($(git ls-files --others --exclude-standard)) | |
if [ $#flist -gt 0 ]; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
zgit_hasunmerged() { | |
zgit_isgit || return 1 | |
local -a flist | |
flist=($(git ls-files -u)) | |
if [ $#flist -gt 0 ]; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
zgit_hasstash() { | |
zgit_isgit || return 1 | |
local s | |
s=$(git stash list) | |
if [[ -n $s ]]; then | |
return 0; | |
fi | |
return 1; | |
} | |
zgit_svnhead() { | |
zgit_isgit || return 1 | |
local commit=$1 | |
if [ -z "$commit" ]; then | |
commit='HEAD' | |
fi | |
git show --raw $commit | \ | |
grep git-svn-id | \ | |
sed -re 's/^\s*git-svn-id: .*@([0-9]+).*$/\1/' | |
} | |
zgit_rebaseinfo() { | |
zgit_isgit || return 1 | |
dotest=$zgit_info[dir]/.dotest-merge | |
if ! [ -d $dotest ]; then | |
if [ -d .dotest ]; then | |
dotest=.dotest | |
else | |
return 1 | |
fi | |
fi | |
zgit_info[dotest]=$dotest | |
zgit_info[rb_onto]=$(cat "$dotest/onto") | |
if [ -f "$dotest/orig-head" ]; then | |
zgit_info[rb_head]=$(cat "$dotest/orig-head") | |
elif [ -f "$dotest/head" ]; then | |
zgit_info[rb_head]=$(cat "$dotest/head") | |
fi | |
zgit_info[rb_head_name]=$(cat "$dotest/head-name") | |
return 0 | |
} | |
zgitinit() { | |
typeset -ga chpwd_functions | |
typeset -ga preexec_functions | |
typeset -ga precmd_functions | |
chpwd_functions+='zgit_chpwd_hook' | |
preexec_functions+='zgit_preexec_hook' | |
precmd_functions+='zgit_precmd_hook' | |
} | |
zgitinit | |
zgit_info_update | |
# vim:set ft=zsh: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment