Skip to content

Instantly share code, notes, and snippets.

@afazio
Created June 4, 2014 16:08

Revisions

  1. afazio created this gist Jun 4, 2014.
    81 changes: 81 additions & 0 deletions .zshrc
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    ## ~/.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
    65 changes: 65 additions & 0 deletions railsdir
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    # -*- 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
    }
    273 changes: 273 additions & 0 deletions zgitinit
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,273 @@
    # -*- 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: