################################################################################ # LIQUID PROMPT # An intelligent and non intrusive prompt for bash and zsh ################################################################################ # Licensed under the AGPL version 3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . ########### # AUTHORS # ########### # nojhan # Main author. # Aurelien Requiem # Major clean refactoring, variable path length, error codes, several bugfixes. # Joris Dedieu # Portability framework, FreeBSD support, bugfixes. # Ludovic Rousseau # Lot of bugfixes. # Yann 'Ze' Richard # Do not fail on missing commands. # François Schmidts # Simpler SSH_IP acquiring method. # Thomas Debesse # Fix columns use. # Florian Le Frioux # Use ± mark when root in VCS dir. # Luc Didry # Zsh port # Olivier Mengué # Major optimizations on host parsing # See the README.md file for a summary of features. # Check for recent enough version of bash. if test -n "$BASH_VERSION" -a -n "$PS1" -a -n "$TERM" ; then bash=${BASH_VERSION%.*}; bmajor=${bash%.*}; bminor=${bash#*.} if [[ $bmajor -lt 3 ]] || [[ $bmajor -eq 3 && $bminor -lt 2 ]]; then unset bash bmajor bminor return fi unset bash bmajor bminor _LP_WORKING_SHELL=bash _LP_OPEN_ESC="\[" _LP_CLOSE_ESC="\]" _LP_USER_SYMBOL="\u" _LP_HOST_SYMBOL="\h" elif test -n "$ZSH_VERSION" ; then _LP_WORKING_SHELL=zsh _LP_OPEN_ESC="%{" _LP_CLOSE_ESC="%}" _LP_USER_SYMBOL="%n" _LP_HOST_SYMBOL="%m" else echo "liquidprompt: shell not supported" >&2 return fi ############### # OS specific # ############### # LP_OS detection, default to Linux case $(uname) in FreeBSD) LP_OS=FreeBSD ;; DragonFly) LP_OS=FreeBSD ;; Darwin) LP_OS=FreeBSD ;; SunOS) LP_OS=SunOS ;; *) LP_OS=Linux ;; esac # Colors declarations if [[ "$LP_OS" == "FreeBSD" ]] ; then BOLD="${_LP_OPEN_ESC}$(tput md)${_LP_CLOSE_ESC}" BLACK="${_LP_OPEN_ESC}$(tput AF 0)${_LP_CLOSE_ESC}" BOLD_GRAY="${_LP_OPEN_ESC}$(tput md ; tput AF 0)${_LP_CLOSE_ESC}" WHITE="${_LP_OPEN_ESC}$(tput AF 7)${_LP_CLOSE_ESC}" BOLD_WHITE="${_LP_OPEN_ESC}$(tput md ; tput AF 7)${_LP_CLOSE_ESC}" RED="${_LP_OPEN_ESC}$(tput AF 1)${_LP_CLOSE_ESC}" BOLD_RED="${_LP_OPEN_ESC}$(tput md ; tput AF 1)${_LP_CLOSE_ESC}" WARN_RED="${_LP_OPEN_ESC}$(tput AF 0 ; tput setab 1)${_LP_CLOSE_ESC}" CRIT_RED="${_LP_OPEN_ESC}$(tput md; tput AF 7 ; tput setab 1)${_LP_CLOSE_ESC}" DANGER_RED="${_LP_OPEN_ESC}$(tput md; tput AF 3 ; tput setab 1)${_LP_CLOSE_ESC}" GREEN="${_LP_OPEN_ESC}$(tput AF 2)${_LP_CLOSE_ESC}" BOLD_GREEN="${_LP_OPEN_ESC}$(tput md ; tput AF 2)${_LP_CLOSE_ESC}" YELLOW="${_LP_OPEN_ESC}$(tput AF 3)${_LP_CLOSE_ESC}" BOLD_YELLOW="${_LP_OPEN_ESC}$(tput md ; tput AF 3)${_LP_CLOSE_ESC}" BLUE="${_LP_OPEN_ESC}$(tput AF 4)${_LP_CLOSE_ESC}" BOLD_BLUE="${_LP_OPEN_ESC}$(tput md ; tput AF 4)${_LP_CLOSE_ESC}" PURPLE="${_LP_OPEN_ESC}$(tput AF 5)${_LP_CLOSE_ESC}" PINK="${_LP_OPEN_ESC}$(tput md ; tput AF 5)${_LP_CLOSE_ESC}" CYAN="${_LP_OPEN_ESC}$(tput AF 6)${_LP_CLOSE_ESC}" BOLD_CYAN="${_LP_OPEN_ESC}$(tput md ; tput AF 6)${_LP_CLOSE_ESC}" NO_COL="${_LP_OPEN_ESC}$(tput me)${_LP_CLOSE_ESC}" else # default to Linux BOLD="${_LP_OPEN_ESC}$(tput bold)${_LP_CLOSE_ESC}" BLACK="${_LP_OPEN_ESC}$(tput setaf 0)${_LP_CLOSE_ESC}" BOLD_GRAY="${_LP_OPEN_ESC}$(tput bold ; tput setaf 0)${_LP_CLOSE_ESC}" WHITE="${_LP_OPEN_ESC}$(tput setaf 7)${_LP_CLOSE_ESC}" BOLD_WHITE="${_LP_OPEN_ESC}$(tput bold ; tput setaf 7)${_LP_CLOSE_ESC}" RED="${_LP_OPEN_ESC}$(tput setaf 1)${_LP_CLOSE_ESC}" BOLD_RED="${_LP_OPEN_ESC}$(tput bold ; tput setaf 1)${_LP_CLOSE_ESC}" WARN_RED="${_LP_OPEN_ESC}$(tput setaf 0 ; tput setab 1)${_LP_CLOSE_ESC}" CRIT_RED="${_LP_OPEN_ESC}$(tput bold; tput setaf 7 ; tput setab 1)${_LP_CLOSE_ESC}" DANGER_RED="${_LP_OPEN_ESC}$(tput bold; tput setaf 3 ; tput setab 1)${_LP_CLOSE_ESC}" GREEN="${_LP_OPEN_ESC}$(tput setaf 2)${_LP_CLOSE_ESC}" BOLD_GREEN="${_LP_OPEN_ESC}$(tput bold ; tput setaf 2)${_LP_CLOSE_ESC}" YELLOW="${_LP_OPEN_ESC}$(tput setaf 3)${_LP_CLOSE_ESC}" BOLD_YELLOW="${_LP_OPEN_ESC}$(tput bold ; tput setaf 3)${_LP_CLOSE_ESC}" BLUE="${_LP_OPEN_ESC}$(tput setaf 4)${_LP_CLOSE_ESC}" BOLD_BLUE="${_LP_OPEN_ESC}$(tput bold ; tput setaf 4)${_LP_CLOSE_ESC}" PURPLE="${_LP_OPEN_ESC}$(tput setaf 5)${_LP_CLOSE_ESC}" PINK="${_LP_OPEN_ESC}$(tput bold ; tput setaf 5)${_LP_CLOSE_ESC}" CYAN="${_LP_OPEN_ESC}$(tput setaf 6)${_LP_CLOSE_ESC}" BOLD_CYAN="${_LP_OPEN_ESC}$(tput bold ; tput setaf 6)${_LP_CLOSE_ESC}" NO_COL="${_LP_OPEN_ESC}$(tput sgr0)${_LP_CLOSE_ESC}" fi # Get cpu count case "$LP_OS" in Linux) _lp_CPUNUM=$( nproc 2>/dev/null || grep -c '^[Pp]rocessor' /proc/cpuinfo ) ;; FreeBSD) _lp_CPUNUM=$( sysctl -n hw.ncpu ) ;; SunOS) _lp_CPUNUM=$( kstat -m cpu_info | grep -c "module: cpu_info" ) ;; esac # get current load case "$LP_OS" in Linux) _lp_cpu_load () { local load eol read load eol < /proc/loadavg echo "$load" } ;; FreeBSD) _lp_cpu_load () { local bol load eol read bol load eol < $<( LANG=C sysctl -n vm.loadavg ) echo "$load" } ;; SunOS) _lp_cpu_load () { LANG=C uptime | awk '{print substr($10,0,length($10))}' } esac ################# # CONFIGURATION # ################# # Note: configuration is called _after_ colors declarations, because of themes. # Default values LP_BATTERY_THRESHOLD=${LP_BATTERY_THRESHOLD:-75} LP_LOAD_THRESHOLD=${LP_LOAD_THRESHOLD:-60} LP_PATH_LENGTH=${LP_PATH_LENGTH:-35} LP_PATH_KEEP=${LP_PATH_KEEP:-2} LP_HOSTNAME_ALWAYS=${LP_HOSTNAME_ALWAYS:-0} LP_PS1=${LP_PS1:-""} LP_ENABLE_PERM=${LP_ENABLE_PERM:-1} LP_ENABLE_SHORTEN_PATH=${LP_ENABLE_SHORTEN_PATH:-1} LP_ENABLE_PROXY=${LP_ENABLE_PROXY:-1} LP_ENABLE_JOBS=${LP_ENABLE_JOBS:-1} LP_ENABLE_LOAD=${LP_ENABLE_LOAD:-1} LP_ENABLE_BATT=${LP_ENABLE_BATT:-1} LP_ENABLE_GIT=${LP_ENABLE_GIT:-1} LP_ENABLE_SVN=${LP_ENABLE_SVN:-1} LP_ENABLE_HG=${LP_ENABLE_HG:-1} LP_MARK_BATTERY=${LP_MARK_BATTERY:-"⌁"} LP_MARK_ADAPTER=${LP_MARK_ADAPTER:-"⏚"} LP_MARK_LOAD=${LP_MARK_LOAD:-"⌂"} LP_MARK_PROXY=${LP_MARK_PROXY:-"↥"} LP_MARK_HG=${LP_MARK_HG:-"☿"} LP_MARK_SVN=${LP_MARK_SVN:-"‡"} LP_MARK_GIT=${LP_MARK_GIT:-"±"} LP_MARK_UNTRACKED=${LP_MARK_UNTRACKED:-"*"} LP_COLOR_PATH=${LP_COLOR_PATH:-$BOLD_WHITE} LP_COLOR_PATH_ROOT=${LP_COLOR_PATH_ROOT:-$BOLD_YELLOW} LP_COLOR_PROXY=${LP_COLOR_PROXY:-$BOLD_BLUE} LP_COLOR_JOB_D=${LP_COLOR_JOB_D:-$YELLOW} LP_COLOR_JOB_R=${LP_COLOR_JOB_R:-$BOLD_YELLOW} LP_COLOR_JOB_Z=${LP_COLOR_JOB_Z:-$BOLD_YELLOW} LP_COLOR_ERR=${LP_COLOR_ERR:-$PURPLE} LP_COLOR_MARK=${LP_COLOR_MARK:-$BOLD_WHITE} LP_COLOR_MARK_ROOT=${LP_COLOR_MARK_ROOT:-$BOLD_RED} LP_COLOR_USER_LOGGED=${LP_COLOR_USER_LOGGED:-""} LP_COLOR_USER_ALT=${LP_COLOR_USER_ALT:-$BOLD} LP_COLOR_USER_ROOT=${_ROOT:-$BOLD_YELLOW} LP_COLOR_HOST=${LP_COLOR_HOST:-""} LP_COLOR_SSH=${LP_COLOR_SSH:-$BOLD_CYAN} LP_COLOR_TELNET=${LP_COLOR_TELNET:-$WARN_RED} LP_COLOR_WRITE=${LP_COLOR_WRITE:-$GREEN} LP_COLOR_NOWRITE=${LP_COLOR_NOWRITE:-$RED} LP_COLOR_UP=${LP_COLOR_UP:-$GREEN} LP_COLOR_COMMITS=${LP_COLOR_COMMITS:-$YELLOW} LP_COLOR_CHANGES=${LP_COLOR_CHANGES:-$RED} LP_COLOR_DIFF=${LP_COLOR_DIFF:-$PURPLE} LP_COLOR_CHARGING_ABOVE=${LP_COLOR_CHARGING_ABOVE:-$GREEN} LP_COLOR_CHARGING_UNDER=${LP_COLOR_CHARGING_UNDER:-$YELLOW} LP_COLOR_DISCHARGING_ABOVE=${LP_COLOR_DISCHARGING_ABOVE:-$YELLOW} LP_COLOR_DISCHARGING_UNDER=${LP_COLOR_DISCHARGING_UNDER:-$RED} LP_COLORMAP_0=${LP_COLORMAP_0:-""} LP_COLORMAP_1=${LP_COLORMAP_1:-$GREEN} LP_COLORMAP_2=${LP_COLORMAP_2:-$BOLD_GREEN} LP_COLORMAP_3=${LP_COLORMAP_3:-$YELLOW} LP_COLORMAP_4=${LP_COLORMAP_4:-$BOLD_YELLOW} LP_COLORMAP_5=${LP_COLORMAP_5:-$RED} LP_COLORMAP_6=${LP_COLORMAP_6:-$BOLD_RED} LP_COLORMAP_7=${LP_COLORMAP_7:-$WARN_RED} LP_COLORMAP_8=${LP_COLORMAP_8:-$CRIT_RED} LP_COLORMAP_9=${LP_COLORMAP_9:-$DANGER_RED} # Default config file may be the XDG standard ~/.config/liquidpromptrc, # but heirloom dotfile has priority. _lp_source_config() { local configfile if [[ -f "/etc/liquidpromptrc" ]] then source "/etc/liquidpromptrc" fi if [[ -f "$HOME/.liquidpromptrc" ]] then configfile="$HOME/.liquidpromptrc" elif [[ -z "$XDG_HOME_DIR" ]] then configfile="$HOME/.config/liquidpromptrc" else configfile="$XDG_HOME_DIR/liquidpromptrc" fi if [[ -f "$configfile" ]] then source "$configfile" fi } # do source config files _lp_source_config # Disable features if the tool is not installed [[ "$LP_ENABLE_GIT" = 1 ]] && { command -v git >/dev/null || LP_ENABLE_GIT=0 ; } [[ "$LP_ENABLE_SVN" = 1 ]] && { command -v svn >/dev/null || LP_ENABLE_SVN=0 ; } [[ "$LP_ENABLE_HG" = 1 ]] && { command -v hg >/dev/null || LP_ENABLE_HG=0 ; } [[ "$LP_ENABLE_BATT" = 1 ]] && { command -v acpi >/dev/null || LP_ENABLE_BATT=0 ; } ############### # Who are we? # ############### # Yellow for root, bold if the user is not the login one, else no color. _lp_user() { local user # if user is not root if [[ "$EUID" -ne "0" ]] ; then # if user is not login user if [[ ${USER} != "$(logname 2>/dev/null)" ]]; then user="${LP_COLOR_USER_ALT}${_LP_USER_SYMBOL}${NO_COL}" else user="${LP_COLOR_USER_LOGGED}${_LP_USER_SYMBOL}${NO_COL}" fi else user="${LP_COLOR_USER_ROOT}${_LP_USER_SYMBOL}${NO_COL}" fi echo -ne $user } ################# # Where are we? # ################# _lp_connection() { if [[ -n "$SSH_CLIENT$SSH2_CLIENT" ]] ; then echo ssh else # TODO check on *BSD local sess_src=$(who am i | sed -n 's/.*(\(.*\))/\1/p') if [[ -z "$sess_src" || "$sess_src" = :0.0 || "$sess_src" == :0 ]] ; then echo lcl # Local else echo tel # Telnet fi fi } # Put the hostname if not locally connected # color it in cyan within SSH, and a warning red if within telnet # else diplay the host without color # The connection is not expected to change from inside the shell, so we # build this just once case "$(_lp_connection)" in lcl) if [[ "$LP_HOSTNAME_ALWAYS" != 1 ]] ; then LP_HOST="${NO_COL}" # no hostname if local else LP_HOST="${NO_COL}@${LP_COLOR_HOST}${_LP_HOST_SYMBOL}${NO_COL}" fi ;; ssh) LP_HOST="${NO_COL}@${LP_COLOR_SSH}${_LP_HOST_SYMBOL}${NO_COL}" ;; tel) LP_HOST="${NO_COL}@${LP_COLOR_TELNET}${_LP_HOST_SYMBOL}${NO_COL}" ;; *) LP_HOST="${NO_COL}@${_LP_HOST_SYMBOL}" # defaults to no color ;; esac # Useless now, so undefine unset _lp_connection # put an arrow if an http proxy is set _lp_proxy() { if [[ $LP_ENABLE_PROXY == 0 ]] ; then echo -n '' return fi if [[ ! -z "$http_proxy" ]] ; then echo -ne $LP_PROXY_MARK fi } # BASH/ZSH function that shortens # a very long path for display by removing # the left most parts and replacing them # with a leading ... # # the first argument is the path # # the second argument is the maximum allowed # length including the '/'s and ... # http://hbfs.wordpress.com/2009/09/01/short-pwd-in-bash-prompts/ # # + keep some left part of the path if asked _lp_shorten_path() { if [[ $LP_ENABLE_SHORTEN_PATH == 0 ]] ; then echo $(echo "$1" | sed -e "s|$HOME|~|") return fi # the character that will replace the part of the path that is masked local mask=" … " # index of the directory to keep from the root (starts at 0 whith bash, 1 with zsh) local keep=$((LP_PATH_KEEP-1)) if [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then keep=$LP_PATH_KEEP fi local len_percent=$2 local p=$(echo "$1" | sed -e "s|$HOME|~|") local len="${#p}" local max_len=$((${COLUMNS:-80}*$len_percent/100)) local mask_len="${#mask}" local slashes=0 if [[ "$_LP_WORKING_SHELL" == "bash" ]]; then if [[ "$len" -gt "$max_len" ]] then # finds all the '/' in # the path and stores their # positions # local pos=() for ((i=0;i $slashes ]] ; then i=$slashes fi while [[ "$((len-pos[i]))" -gt "$((max_len-mask_len))" ]] do i=$((i+1)) done # let us check if it's OK to # print the whole thing # if [[ "${pos[i]}" -eq "0" ]] then # the path is shorter than # the maximum allowed length, # so no need for ... # echo "$p" elif [[ "${pos[i]}" = "$len" ]] then # constraints are broken because # the maximum allowed size is smaller # than the last part of the path, plus # ' … ' # echo "${p:0:((${pos[${keep}]}+1))}${mask}${p:((len-max_len+mask_len))}" else # constraints are satisfied, at least # some parts of the path, plus ' … ', are # shorter than the maximum allowed size # echo "${p:0:((${pos[${keep}]}+1))}${mask}${p:pos[i]}" fi else echo "$p" fi elif [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then if [[ "$len" -gt "$max_len" ]]; then echo "%-${keep}~%${max_len}<${mask}<%~%<<" else echo "%~" fi fi } # Display a ":" # colored in green if user have write permission on the current directory # colored in red if it have not. _lp_permissions_color() { if [[ $LP_ENABLE_PERM == 0 ]]; then echo ":" # without color else if [[ -w "${PWD}" ]]; then echo "${LP_COLOR_WRITE}:${NO_COL}" else echo "${LP_COLOR_NOWRITE}:${NO_COL}" fi fi } ################ # Related jobs # ################ # Either attached running jobs (started with $ myjob &) # or attached stopped jobs (suspended with Ctrl-Z) # or detached screens sessions running on the host _lp_jobcount_color() { if [[ $LP_ENABLE_JOBS == 0 ]] ; then echo -n '' return fi local running=$(( $(jobs -r | wc -l) )) local stopped=$(( $(jobs -s | wc -l) )) local screens=$(screen -ls 2> /dev/null | grep -c Detach ) local m_detached="d" local m_stop="z" local m_run="&" local rep # d/&/z if [[ $screens != "0" && $running != "0" && $stopped != "0" ]] ; then rep="${NO_COL}${LP_COLOR_JOB_D}${screens}${m_detached}${NO_COL}/${LP_COLOR_JOB_R}${running}${m_run}${NO_COL}/${LP_COLOR_JOB_Z}${stopped}${m_stop}${NO_COL}" # _/&/_ elif [[ $screens == "0" && $running != "0" && $stopped == "0" ]] ; then rep="${NO_COL}${LP_COLOR_JOB_R}${running}${m_run}${NO_COL}" # _/_/z elif [[ $screens == "0" && $running == "0" && $stopped != "0" ]] ; then rep="${NO_COL}${LP_COLOR_JOB_Z}${stopped}${m_stop}${NO_COL}" # d/_/_ elif [[ $screens != "0" && $running == "0" && $stopped == "0" ]] ; then rep="${NO_COL}${LP_COLOR_JOB_D}${screens}${m_detached}${NO_COL}" # d/&/_ elif [[ $screens != "0" && $running != "0" && $stopped == "0" ]] ; then rep="${NO_COL}${LP_COLOR_JOB_D}${screens}${m_detached}${NO_COL}/${LP_COLOR_JOB_R}${running}${m_run}${NO_COL}" # d/_/z elif [[ $screens != "0" && $running == "0" && $stopped != "0" ]] ; then rep="${NO_COL}${LP_COLOR_JOB_D}${screens}${m_detached}${NO_COL}/${LP_COLOR_JOB_Z}${stopped}${m_stop}${NO_COL}" # _/&/z elif [[ $screens == "0" && $running != "0" && $stopped != "0" ]] ; then rep="${NO_COL}${LP_COLOR_JOB_R}${running}${m_run}${NO_COL}/${LP_COLOR_JOB_Z}${stopped}${m_stop}${NO_COL}" fi echo -ne "$rep" } # Display the return value of the last command, if different from zero _lp_return_value() { if [[ "$1" -ne "0" ]] then echo -ne "$1" fi } ###################### # VCS branch display # ###################### # GIT # # Get the branch name of the current directory _lp_git_branch() { [[ "$LP_ENABLE_GIT" == 1 ]] || return if git rev-parse --git-dir >/dev/null 2>&1 && [[ ! -z "$(git branch)" ]] ; then echo -n "$(git branch 2>/dev/null | sed -n '/^\*/s/^\* //p;')" fi } # Set a color depending on the branch state: # - green if the repository is up to date # - yellow if there is some commits not pushed # - red if there is changes to commit # # Add the number of pending commits and the impacted lines. _lp_git_branch_color() { [[ "$LP_ENABLE_GIT" == 1 ]] || return local branch branch=$(_lp_git_branch) if [[ ! -z "$branch" ]] ; then local GD git diff --quiet >/dev/null 2>&1 GD=$? local GDC git diff --cached --quiet >/dev/null 2>&1 GDC=$? local has_untracked has_untracked=$(git status 2>/dev/null | grep '\(# Untracked\)') if [[ -z "$has_untracked" ]] ; then has_untracked="" else has_untracked="$LP_MARK_UNTRACKED" fi local has_commit has_commit=$(git rev-list --no-merges --count origin/${branch}..${branch} 2>/dev/null) if [[ -z "$has_commit" ]] ; then has_commit=0 fi if [[ "$GD" -eq 1 || "$GDC" -eq "1" ]] ; then local has_line has_lines=$(git diff --numstat | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("+%d/-%d\n", plus, minus)}') if [[ "$has_commit" -gt "0" ]] ; then # Changes to commit and commits to push ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$has_lines${NO_COL},${LP_COLOR_COMMITS}$has_commit${NO_COL})${LP_COLOR_CHANGES}${has_untracked}${NO_COL}" else ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$has_lines${NO_COL})${LP_COLOR_CHANGES}${has_untracked}${NO_COL}" # changes to commit fi else if [[ "$has_commit" -gt "0" ]] ; then # some commit(s) to push ret="${LP_COLOR_COMMITS}${branch}${NO_COL}(${LP_COLOR_COMMITS}$has_commit${NO_COL})${LP_COLOR_COMMITS}${has_untracked}${NO_COL}" else ret="${LP_COLOR_UP}${branch}${has_untracked}${NO_COL}" # nothing to commit or push fi fi echo -ne "$ret" fi } # MERCURIAL # # Get the branch name of the current directory _lp_hg_branch() { [[ "$LP_ENABLE_HG" == 1 ]] || return local branch branch="$(hg branch 2>/dev/null)" if [[ $? -eq 0 ]] && [[ ! -z "$(hg branch)" ]] ; then echo -n "$(hg branch)" fi } # Set a color depending on the branch state: # - green if the repository is up to date # - red if there is changes to commit # - TODO: yellow if there is some commits not pushed _lp_hg_branch_color() { [[ "$LP_ENABLE_HG" == 1 ]] || return local branch local ret branch=$(_lp_hg_branch) if [[ ! -z "$branch" ]] ; then if [[ $(( $(hg status --quiet -n | wc -l) )) = 0 ]] ; then ret="${LP_COLOR_UP}${branch}${NO_COL}" else ret="${LP_COLOR_CHANGES}${branch}${NO_COL}" # changes to commit fi echo -ne "$ret" fi } # SUBVERSION # # Get the branch name of the current directory # For the first level of the repository, gives the repository name _lp_svn_branch() { [[ "$LP_ENABLE_SVN" == 1 ]] || return local infos local ret infos=$(svn info --xml 2>/dev/null) ret=$? if [[ $ret -eq 0 ]] ; then local root root=$(echo "$infos" | awk -v FS=">|/ { print $2 }') local subrep subrep=$(echo "$infos" | awk -v FS=">|/ { print $2 }') if [[ "$subrep" == *"url>"* ]] ; then echo -n $root else local branch branch=$(basename $subrep) echo -n $branch fi fi } # Set a color depending on the branch state: # - green if the repository is up to date # - red if there is changes to commit # Note that, due to subversion way of managing changes, # informations are only displayed for the CURRENT directory. _lp_svn_branch_color() { [[ "$LP_ENABLE_SVN" == 1 ]] || return local branch branch=$(_lp_svn_branch) if [[ ! -z "$branch" ]] ; then local commits commits=$(( $(svn status | grep -v "?" -c) )) if [[ $commits = 0 ]] ; then local ret ret="${LP_COLOR_UP}${branch}${NO_COL}" else ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_COMMITS}$commits${NO_COL})" # changes to commit fi echo -ne "$ret" fi } ################## # Battery status # ################## # Get the battery status in percent # returns 0 (and battery level) if battery is discharging and under threshold # returns 1 (and battery level) if battery is discharging and above threshold # returns 2 (and battery level) if battery is charging but under threshold # returns 3 (and battery level) if battery is charging and above threshold # returns 4 if no battery support _lp_battery() { [[ "$LP_ENABLE_BATT" == 1 ]] || return local acpi acpi="$(acpi --battery 2>/dev/null)" local bat bat=$( echo $acpi | sed "s/^Battery .*, \([0-9]*\)%.*$/\1/") if [[ -z "${bat}" ]] ; then # not battery level found return 4 # discharging elif [[ "$acpi" == *"Discharging"* ]] ; then if [[ ${bat} -le $LP_BATTERY_THRESHOLD ]] ; then # under threshold echo -n "${bat}" return 0 else # above threshold echo -n "${bat}" return 1 fi # charging else if [[ ${bat} -le $LP_BATTERY_THRESHOLD ]] ; then # under threshold echo -n "${bat}" return 2 else # above threshold echo -n "${bat}" return 3 fi fi } # Compute a gradient of background/foreground colors depending on the battery status # Display: # a green ⏚ if the battery is charging and above threshold # a yellow ⏚ if the battery is charging and under threshold # a yellow ⌁ if the battery is discharging but above threshold # a red ⌁ if the battery is discharging and above threshold _lp_battery_color() { if [[ $LP_ENABLE_BATT == 0 ]] ; then echo -n '' return fi local mark=$LP_BATTERY_MARK local chargingmark=$LP_ADAPTER_MARK local bat local ret bat=$(_lp_battery) ret=$? if [[ $ret == 4 || $bat == 100 ]] ; then # no battery support or battery full: nothing displayed return elif [[ $ret == 3 && $bat != 100 ]] ; then # charging and above threshold and not 100% # green ⏚ echo -ne "${LP_COLOR_CHARGING_ABOVE}$chargingmark${NO_COL}" return elif [[ $ret == 2 ]] ; then # charging but under threshold # yellow ⏚ echo -ne "${LP_COLOR_CHARGING_UNDER}$chargingmark${NO_COL}" return elif [[ $ret == 1 ]] ; then # discharging but above threshold # yellow ⌁ echo -ne "${LP_COLOR_DISCHARGING_ABOVE}$mark${NO_COL}" return # discharging and under threshold elif [[ "$bat" != "" ]] ; then local ret ret="${LP_COLOR_DISCHARGING_UNDER}${mark}${NO_COL}" if [[ ${bat} -le 100 ]] && [[ ${bat} -gt 80 ]] ; then # -20 ret="${ret}${LP_COLORMAP_1}" elif [[ ${bat} -le 80 ]] && [[ ${bat} -gt 65 ]] ; then # -15 ret="${ret}${LP_COLORMAP_2}" elif [[ ${bat} -le 65 ]] && [[ ${bat} -gt 50 ]] ; then # -15 ret="${ret}${LP_COLORMAP_3}" elif [[ ${bat} -le 50 ]] && [[ ${bat} -gt 40 ]] ; then # -10 ret="${ret}${LP_COLORMAP_4}" elif [[ ${bat} -le 40 ]] && [[ ${bat} -gt 30 ]] ; then # … ret="${ret}${LP_COLORMAP_5}" elif [[ ${bat} -le 30 ]] && [[ ${bat} -gt 20 ]] ; then ret="${ret}${LP_COLORMAP_6}" elif [[ ${bat} -le 20 ]] && [[ ${bat} -gt 10 ]] ; then ret="${ret}${LP_COLORMAP_7}" elif [[ ${bat} -le 10 ]] && [[ ${bat} -gt 5 ]] ; then ret="${ret}${LP_COLORMAP_8}" elif [[ ${bat} -le 5 ]] && [[ ${bat} -gt 0 ]] ; then ret="${ret}${LP_COLORMAP_9}" else # for debugging purpose ret="${ret}${LP_COLORMAP_0}" fi if [[ "$_LP_WORKING_SHELL" == "bash" ]]; then echo -ne "${ret}${bat}%${NO_COL}" elif [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then echo -ne "${ret}${bat}%%${NO_COL}" fi fi } ############### # System load # ############### # Compute a gradient of background/forground colors depending on the battery status _lp_load_color() { # Colour progression is important ... # bold gray -> bold green -> bold yellow -> bold red -> # black on red -> bold white on red # # Then we have to choose the values at which the colours switch, with # anything past yellow being pretty important. if [[ $LP_ENABLE_LOAD == 0 ]] ; then echo -n '' return fi local load load="$(_lp_cpu_load | sed 's/\.//g;s/^0*//g' )" let "load=${load:-0}/$_lp_CPUNUM" if [[ $load -ge $LP_LOAD_THRESHOLD ]] then local ret ret="${LP_MARK_LOAD}${NO_COL}" if [[ $load -ge 0 ]] && [[ $load -lt 20 ]] ; then ret="${ret}${LP_COLORMAP_0}" elif [[ $load -ge 20 ]] && [[ $load -lt 40 ]] ; then ret="${ret}${LP_COLORMAP_1}" elif [[ $load -ge 40 ]] && [[ $load -lt 60 ]] ; then ret="${ret}${LP_COLORMAP_2}" elif [[ $load -ge 60 ]] && [[ $load -lt 80 ]] ; then ret="${ret}${LP_COLORMAP_3}" elif [[ $load -ge 80 ]] && [[ $load -lt 100 ]] ; then ret="${ret}${LP_COLORMAP_4}" elif [[ $load -ge 100 ]] && [[ $load -lt 120 ]] ; then ret="${ret}${LP_COLORMAP_5}" elif [[ $load -ge 120 ]] && [[ $load -lt 140 ]] ; then ret="${ret}${LP_COLORMAP_6}" elif [[ $load -ge 140 ]] && [[ $load -lt 160 ]] ; then ret="${ret}${LP_COLORMAP_7}" elif [[ $load -ge 160 ]] && [[ $load -lt 180 ]] ; then ret="${ret}${LP_COLORMAP_8}" elif [[ $load -ge 180 ]] ; then ret="${ret}${LP_COLORMAP_9}" else ret="${ret}${LP_COLORMAP_0}" fi if [[ "$_LP_WORKING_SHELL" == "bash" ]]; then ret="${ret}$load%${NO_COL}" elif [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then ret="${ret}$load%%${NO_COL}" fi echo -ne "${ret}" fi } ########## # DESIGN # ########## # Set the prompt mark to ± if git, to ☿ if mercurial, to ‡ if subversion # to # if root and else $ _lp_smart_mark() { local COL COL=${LP_COLOR_MARK} if [[ "$EUID" -eq "0" ]] ; then COL=${LP_COLOR_MARK_ROOT} fi local mark mark="\\\$" if [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then mark="%(!.#.%%)" fi if [[ ! -z $(_lp_git_branch) ]] ; then mark=$LP_MARK_GIT elif [[ ! -z $(_lp_hg_branch) ]] ; then mark=$LP_MARK_HG elif [[ ! -z $(_lp_svn_branch) ]] ; then mark=$LP_MARK_SVN fi echo -ne "${COL}${mark}${NO_COL}" } # insert a space on the right _lp_sr() { if [[ ! -z "$1" ]] ; then echo -n "$1 " fi } # insert a space on the left _lp_sl() { if [[ ! -z "$1" ]] ; then echo -n " $1" fi } # insert two space, before and after _lp_sb() { if [[ ! -z "$1" ]] ; then echo -n " $1 " fi } ######################## # Construct the prompt # ######################## _lp_set_bash_prompt() { # as this get the last returned code, it should be called first LP_ERR="${LP_COLOR_ERR}$(_lp_sl $(_lp_return_value $?))${NO_COL}" # execute the old prompt $LP_OLD_PROMPT_COMMAND # left of main prompt: space at right LP_JOBS=$(_lp_sr "$(_lp_jobcount_color)") LP_LOAD=$(_lp_sr "$(_lp_load_color)") LP_BATT=$(_lp_sr "$(_lp_battery_color)") # in main prompt: no space LP_USER=$(_lp_user) # LP_HOST is a global set at load time LP_PERM=$(_lp_permissions_color) LP_PWD=$(_lp_shorten_path "$PWD" $LP_PATH_LENGTH) LP_PROXY="${LP_COLOR_PROXY}$(_lp_proxy)${NO_COL}" # right of main prompt: space at left LP_GIT=$(_lp_sl "$(_lp_git_branch_color)") LP_HG=$(_lp_sl "$(_lp_hg_branch_color)") LP_SVN=$(_lp_sl "$(_lp_svn_branch_color)") # end of the prompt line: double spaces LP_MARK=$(_lp_sb "$(_lp_smart_mark)") # Different path color if root if [[ "$EUID" -ne "0" ]] ; then LP_PWD="${LP_COLOR_PATH}${LP_PWD}${NO_COL}" else LP_PWD="${LP_COLOR_PATH_ROOT}${LP_PWD}${NO_COL}" fi if [[ -z $LP_PS1 ]] ; then # add jobs, load and battery PS1="${LP_BATT}${LP_LOAD}${LP_JOBS}" # add user, host and permissions colon PS1="${PS1}[${LP_USER}${LP_HOST}${LP_PERM}" # if not root if [[ "$EUID" -ne "0" ]] then # path in foreground color PS1="${PS1}${LP_PWD}]${LP_PROXY}" # add VCS infos PS1="${PS1}${LP_GIT}${LP_HG}${LP_SVN}" else # path in yellow PS1="${PS1}${LP_PWD}]${LP_PROXY}" # do not add VCS infos fi # add return code and prompt mark PS1="${PS1}${LP_ERR}${LP_MARK}" # Glue the bash prompt always go to the first column. # Avoid glitches after interrupting a command with Ctrl-C # Does not seem to be necessary anymore? #PS1="\[\033[G\]${PS1}${NO_COL}" else PS1=$LP_PS1 fi } # Activate the liquid prompt prompt_on() { # if liquidprompt has not been already set if [[ -z "$LP_LIQUIDPROMPT" ]] ; then LP_OLD_PS1="$PS1" if [[ "$_LP_WORKING_SHELL" == "bash" ]]; then LP_OLD_PROMPT_COMMAND="$PROMPT_COMMAND" elif [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then LP_OLD_PROMPT_COMMAND="$precmd" fi fi if [[ "$_LP_WORKING_SHELL" == "bash" ]]; then PROMPT_COMMAND=_lp_set_bash_prompt elif [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then function precmd { _lp_set_bash_prompt } fi # Keep in mind that LP has been sourced # (to avoid recursive prompt command). LP_LIQUIDPROMPT=1 } # Come back to the old prompt prompt_off() { PS1=$LP_OLD_PS1 if [[ "$_LP_WORKING_SHELL" == "bash" ]]; then PROMPT_COMMAND=$LP_OLD_PROMPT_COMMAND elif [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then precmd=$LP_OLD_PROMPT_COMMAND fi } # Use an empty prompt: just the \$ mark prompt_OFF() { PS1="\$ " if [[ "$_LP_WORKING_SHELL" == "bash" ]]; then PROMPT_COMMAND=$LP_OLD_PROMPT_COMMAND elif [[ "$_LP_WORKING_SHELL" == "zsh" ]]; then precmd=$LP_OLD_PROMPT_COMMAND fi } # By default, sourcing liquidprompt.bash will activate the liquid prompt prompt_on # Cleaning of variable that are not needed at runtime unset LP_OS # vim: set et sts=4 sw=4 tw=120 ft=sh: