Skip to content

Instantly share code, notes, and snippets.

@gregbugaj
Last active December 26, 2023 20:23
Show Gist options
  • Save gregbugaj/3b9a6587e46e876963599505e9dfd484 to your computer and use it in GitHub Desktop.
Save gregbugaj/3b9a6587e46e876963599505e9dfd484 to your computer and use it in GitHub Desktop.

Extended GIT Information in bash PS1

This will generate shell similar to this :

Multiline version:

┌──┤ greg: ~/dev/discovery/discovery-agent │ master  ≡  !1 +2 -2  ≡ 2 weeks ago
└── λ 

Format branch ≡ changes additons deletion ≡ last commit Example master ≡ !1 +2 -2 ≡ 2 weeks ago

Since we are intereseted in interactive shells only we will edit /etc/profile and add following

# GB mod


# Get branch name
parse_git_branch() {
    # git branch | grep -Po '(?<=\*\s)(.*)'
    local branch=$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ \1/')
    # When there is no initial commit, git branch will not return any branches, use a fallback method
    if [ -z "$branch" ]; then
         branch=$(git status | grep -iPo '(?<=On branch\s)(.*)')
    fi
    echo $branch
}

parse_git_status() {
    # changes to existing files
    # 0 = Changed Files, 1 = Additions, 2 = Deletions
    local gitstat=$(git diff --shortstat 2> /dev/null | grep -Po '\d')
    if [ -z "$gitstat" ]; then
	      gitstat="0 0 0"
    fi

    # replate \n with blanks
    gitstat=$(echo "$gitstat" | tr '\n' ' ')
    # untracted(??) or added(A) files
    local gitfiles=$(git status --untracked-files=all -s 2> /dev/null | grep -E '??|A' | wc -l)
    echo "$gitstat $gitfiles"
}

parse_git_hascommit() {
    val=$(git log 2> /dev/null | grep -iPo 'does not have')
    echo "result :: $val"
    if [ -z "$val" ]; then
      echo 0
      return 0
    fi

    echo 1
}

git_status_ps1() {
	green_light="\e[38;5;82m"
	red="\e[91m"
	blue="\e[34m"
	reset="\e[0m"

	inrepo=$(git rev-parse --is-inside-work-tree 2>/dev/null)
	if [ -z "$inrepo" ]; then
	   exit
        fi

	#hascommit=$(parse_git_hascommit)
	#echo "has :: $hascommit"i
	# can't get time unless we have a commit

        # capture error 'fatal: your current branch 'master' does not have any commits yet' and don't display time
	gittime=$(git log -1 --format=%cr 2> /dev/null)
        gitstat=$(parse_git_status)
	IFS=' ' read -r -a array <<< $gitstat

	if [ -z "${array[0]}" ]; then
		array[0]=0
		array[1]=0
		array[2]=0
	fi

	branch_color=$green_light
	if [ "${array[0]}" -gt "0" ]; then
	   branch_color=$red
	fi

	if [ -z "$gittime" ]; then
	   gittime="never"
	fi
        GIT_PS1="$branch_color$(parse_git_branch) $reset$green_light ~${array[3]}  !${array[0]} +${array[1]} $red-${array[2]} $reset$gittime"
	echo -e $GIT_PS1
}

# https://stackoverflow.com/questions/42481726/how-to-modify-conda-source-activate-ps1-behavior

# Disable conda's PS1 modification , disable virtualenv prompt change
export CONDA_CHANGEPS1=false
export VIRTUAL_ENV_DISABLE_PROMPT=1

# check if conda is activated

# vname=$(basename $CONDA_PROMPT_MODIFIER)
# vname=$(basename $CONDA_DEFAULT_ENV)
# echo "vname :: $vname"

parse_conda_env() {
    if [ ! -z "$CONDA_DEFAULT_ENV" ]; then
        echo $(basename "$CONDA_DEFAULT_ENV")
    fi
}

parse_virtual_env() {
    if [ ! -z "$VIRTUAL_ENV" ]; then
        echo $(basename "$VIRTUAL_ENV")
    fi
}

# echo "conda env :: $(parse_conda_env)"
# echo "virtual env :: $(parse_virtual_env)"

resolve_virtual_env() {
  # append both conda and virtual env to a single variable
  if [ ! -z "$(parse_conda_env)" ] && [ ! -z "$(parse_virtual_env)" ]; then
    echo "($(parse_conda_env), $(parse_virtual_env)"
  elif [ ! -z "$(parse_conda_env)" ]; then
    echo  "($(parse_conda_env))"
  elif [ ! -z "$(parse_virtual_env)" ]; then
    echo "($(parse_virtual_env))"
  fi

}

# https://github.com/arialdomartini/oh-my-git/blob/master/base.sh
# https://unix.stackexchange.com/questions/588600/in-this-0330132m-vt100-style-ansi-escape-sequences-what-is-the-01-and-the-m
# https://en.wikipedia.org/wiki/ANSI_escape_code
if [ ! -z $(resolve_virtual_env) ]; then
    PS1='┌──┤ \[\033[01;93m\]($(resolve_virtual_env)) \[\033[01;32m\]\u:\[\033[00m\] '
    PS1=$PS1'\[\033[01;34m\]\w\e[0m │ $(git_status_ps1)\n└──  λ '
else
    PS1='┌──┤  \[\033[01;32m\]\u:\[\033[00m\] '
    PS1=$PS1'\[\033[01;34m\]\w\e[0m │ $(git_status_ps1)\n└──  λ '
fi

PS1='┌──┤ \[\033[01;93m\]$(resolve_virtual_env) \[\033[01;32m\]\u:\[\033[00m\] '
PS1=$PS1'\[\033[01;34m\]\w\e[0m │ $(git_status_ps1)\n└──  λ '

#PS1='┌──┤ ($(resolve_virtual_env)) \[\033[01;32m\]\u:\[\033[00m\] '
# PS1=$PS1'\[\033[01;34m\]\w\e[0m │ $(git_status_ps1)\n└──  λ '

export PS1=$PS1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment