diff --git a/CHANGES b/CHANGES index 5e62f4d..ec4a9ad 100644 --- a/CHANGES +++ b/CHANGES @@ -1,15 +1,123 @@ +1.11 ????-??-?? + Bug fixes: + - OS X: sudo feature fixed + - OS X: battery level restored -1.9 2014-11-?? dolmen (Olivier Mengué) +1.10 2016-05-30 + Breaking changes: + - In themes, LP_COLORMAP_x variables are replaced by a single + LP_COLORMAP array variable. A warning will be displayed at startup + if your config still uses the old variables, but a compatibility + shim is active (will be removed in next release). + - Many LP_ENABLE_* settings are now static (their effect applies when + liquidprompt is loaded, and changing them at the prompt does nothing) + to more and more improve speed. + - zsh: option 'nopromptsubst' is enabled for security reasons. + This will unfortunately also affect evaluations of other prompt + contexts such as RPS1. + - Variables LP_SCREEN_TITLE_OPEN and LP_SCREEN_TITLE_CLOSE are now + removed to simplify the code (GitHub #371) + New features: + - Sudo: + * The color of the prompt mark is now dynamic and changes to + LP_COLOR_MARK_SUDO (default: bold red) as long as your sudo + credentials are cached (GitHub #335). + Requires sudo 1.7.0+. + This feature must be enabled with LP_ENABLE_SUDO=1 + Use 'sudo -K' to revoke your credentials early. + * This feature is disabled by default as there is no way to + detect if the user has sudo rights without triggering a security + alert that will annoy the sysadmin. + - Git: + * Show the number of commits behind the remote (GitHub #269) + * Show the rebasing/merging/cherry-picking state (GitHub #409) + - Add variable LP_TTYN: the basename of the terminal (GitHub #357) + - Add setting LP_ENABLE_FQDN to show the fully qualified domain name + of the host (GitHub #254, #277) + - LP_HOSTNAME_ALWAYS=-1 to always hide the hostname (GitHub #406) + - Run duration of the last command (LP_ENABLE_RUNTIME) is now also + supported on zsh (GitHub #404, #355) + - Python: add support for Conda (CONDA_DEFAULT_ENV) (GitHub #425) + Bug fixes: + - Use $XDG_CONFIG_HOME to locate the config (GitHub #415, #420, #425) + - Improved zsh integration (but most issues had no impact of the + user experience) + - Fix escaping of special chars from $PWD (well, almost, see GitHub + #389) and explicitely set the shell options we need (instead of + relying on the shell default settings) + - Git: + * Fix typo in git work directory detection + - Fossil: + * Fix on darwin (GitHub #390) + - LP_DISABLED_VCS_PATH is fixed on zsh (GitHub #423) + - Battery indicator: + * MacOS: many fixes to handle (all?) edge cases (GitHub #326) + We now have a pmset simulator to better detect regressions. + - Temperature indicator: + * The code using the 'sensors' command now uses the '-u' option + ("raw output") that is easier to parse. This format is at least + 7 years old. (GitHub #379, #380) + * We now try each backend (acpi/sensors) once to check it works + at startup and disable the feature if none works. + (GitHub #410, #319, #381, #387) + - CPU load indicator: + * Fix the scale that was incorrectly 0-200 (GitHub #391) + - Title: + * Fix terminal sequences that were sent in the title text (the + escaping algorithm is rewritten and now just correct). + - Terminal channel: + * Fix detection of tmux (GitHub #304, #377) + * Fix detection of local session on OS X (GitHub #407) + - Misc: + * Fix bash 3 compatibility (GitHub #313) + * Clear GREP_OPTIONS and skip 'grep' aliases (GitHub #372) + - Shortened path: + * Fix bugs when $PWD contains spaces or special chars (GitHub #369) + * Optimize implementation in case of LP_PATH_KEEP=-1 : LP_PWD + becomes static (related to GitHub #256, #336) + * Optimize implementation in case LP_ENABLE_SHORTEN_PATH=0 + * Optimize implementation in case LP_ENABLE_SHORTEN_PATH=0 on bash + with PROMPT_DIRTRIM + - Sample configuration files: + * example.bashrc: major fixes + - The last statement of liquidprompt did not return 0 (GitHub #360,#361) + - Analog clock: + * complete rewrite for speed and correctness (GitHub #365 and other + issues) + - Documentation: + * Many small fixes + - Move dist/ to contrib/dist/ as files there are unmaintained + - Fix title escapes in zsh inside tmux/screen (GitHub #370, #371) + + Thanks to Matt Fletcher (@MaffooBristol), Kevin Yap (@iKevinY), Sean + Hussey (@seanhussey), François Schmidts (@jaesivsm), Morgan Knicely + (@morganizeit), Daniel Serodio (@dserodio), Jonathan Giddy + (@jongiddy), Jeremy Clement (@jeremyclement), Panayiotis Kkolos + (@pkkolos), Arturo Borrero Gonzalez (@aborrero), Samuel Krieg + (@SamK), Brian May (@brianmay), Colin Lieberman (@colinlieberman), + @hegedus, Anthony Gelibert (@anthonygelibert), Anthony Ramine (@nox), + Erik M Jacobs (@thoraxe), Pedro Parracho (@berserck), Brad Beyenhof + (@augmentedfourth), Austen Adler (@stonewareslord), Hagen Graf + (@hcgraf), William P. Riley-Land (@wprl), Dave Rigby (@daverigby), + Ned Batchelder (@nedbat), Fabien Marty (@thefab), Alessio Garzi + (@Ozzyboshi), Roger Huang (@rhuang2014), Sebastian Bremicker + (@sebrem), Alex Prengere (@alexprengere), Philipp Grogg (@gro-gg), + Tener Hades (@tenerhades), Thomas Kühnel (@kuehnelth), Étienne Deparis + (@milouse), @Hotschke, Software Mechanic (@softwaremechanic), Simon + McVittie (@smcv)... + ... for their patches or bug reports. + +1.9 2014-11-12 dolmen (Olivier Mengué) Bug fixes: - Battery indicator: - * General fixes (Github #264) - * MacOS: fix for computers without battery (like iMacs) (Github + * General fixes (GitHub #264) + * MacOS: fix for computers without battery (like iMacs) (GitHub #319) * Optimize colormap - Temperature indicator: * Linux: Add a guard against any future l10n of the 'acpi' command - * Linux: Fix for negative temperature values (Github #308) + * Linux: Fix for negative temperature values (GitHub #308) - CPU load: * Darwin/BSD: quoting fixes - Hostname: @@ -17,41 +125,41 @@ * Simplify chroot detection - VCS: - Git: - * Use --porcelain for "git status" (Github #270) - * Minir optimization (Github #266) + * Use --porcelain for "git status" (GitHub #270) + * Minir optimization (GitHub #266) - Fossil: - * Cleanup and fixes (Github #274 and others) + * Cleanup and fixes (GitHub #274 and others) - Subversion: - * Fix branch/tag name extraction (Github #117, #237, #293) + * Fix branch/tag name extraction (GitHub #117, #237, #293) - Bazar: * Fix branch name extraction - * zsh fixes (Github #303) + * zsh fixes (GitHub #303) - Mercurial: * General cleanup for speed and fixes - * Disabled "hg outgoing" because it is slow (Github #217) + * Disabled "hg outgoing" because it is slow (GitHub #217) - Shortened path: * Bash: Fix quoting for PROMPT_DIRTRIM - Prompt mark: * Simplify implementation of LP_MARK_DEFAULT - Jobs: * Refactoring - * Fix when screen/tmux are not installed (Github #304) + * Fix when screen/tmux are not installed (GitHub #304) - Analog clock: - * Fix hour for 12AM and 12PM (Github #273) + * Fix hour for 12AM and 12PM (GitHub #273) - Misc: * bash: save and set 'promptvars' - * bash: workaround broken pattern substitution in bash 4.2 (Github + * bash: workaround broken pattern substitution in bash 4.2 (GitHub #289, #294, #302) * zsh: fix restoration of the original (pre-liquidprompt) prompt - * Fix tmux detection (Github #279) - * Save IFS (Github #267) - * Fix $TERM check (Github #291) + * Fix tmux detection (GitHub #279) + * Save IFS (GitHub #267) + * Fix $TERM check (GitHub #291) * Various quoting fixes * Apply some shellcheck.com suggestions - * Many, many optimizations (Github #267) + * Many, many optimizations (GitHub #267) New features: - - Add vcsh support (Github #148, #287) - - Add support for Software Collections (Github #299, #300) + - Add vcsh support (GitHub #148, #287) + - Add support for Software Collections (GitHub #299, #300) Thanks to Anthony Gelibert, Frédéric Mahé, Panayiotis Kkolos, Étienne Deparis, François Schmidts, Linus Wallgren, Alexander Belaev, Bartosz diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e43b309..db117e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,21 +6,11 @@ Contributing a patch The public stable branch for end users is `master`. -The main branch for development is `develop`. This is on top of this branch -that you must write your patches. - -Any pull request built on top of `master` instead of `develop` -is additional merge work for maintainers, and you want to avoid this if you -aim for quick integration of your work. - -If you wrote your patch on the wrong branch the maintainers may choose to close -the pull request and ask you to rewrite it on top of the current `develop`. - How to do the right thing? -------------------------- - $ git clone -b develop -o upstream git://github.com/nojhan/liquidprompt.git + $ git clone -o upstream git://github.com/nojhan/liquidprompt.git $ cd liquidprompt # Run liquidprompt and check that your issue is still on that branch @@ -41,14 +31,14 @@ How to do the right thing? # Check that your local repo is up to date $ git fetch - # Rebase your work on the latest state of `develop` - $ git rebase upstream/develop + # Rebase your work on the latest state of `master` + $ git rebase upstream/master # Push your commits $ git push github fix/my-fix - $ git push github fix/my-feature + $ git push github feature/my-feature - # Create the pull request on GitHub. Check that Github chose the `develop` + # Create the pull request on GitHub. Check that Github chose the `master` # branch as the starting point for your branch. @@ -75,8 +65,8 @@ How to make a good pull request? For example use triple backquotes for code blocks. -Never, ever, merge the branches `develop` or `master` of the main repo into one -of your own branches. Instead, always rebase your own work on top the `develop` +Never, ever, merge the branches `master` of the main repo into one +of your own branches. Instead, always rebase your own work on top the `master` branch. How my patch will be applied? @@ -88,7 +78,7 @@ pull requests. If your patch is accepted it will be applied either: - by "merging" your branch -- by cherry-picking your commit on top of the `develop` branch. This makes the +- by cherry-picking your commit on top of the `master` branch. This makes the history linear, and so easier to track. In any case, your authorship will be preserved in the commit. @@ -101,7 +91,7 @@ between pings: 1 week, 2 weeks, then every month. If a stable version is released while your pull request has still not been merged on any working branch of the main repo, it would be helpful to ease -the maitainer's work by rebasing your branch on top of the latest `develop` +the maitainer's work by rebasing your branch on top of the latest `master` and push it again to your GitHub repo. Be careful (for example create a branch or a tag before your rebase) because your may lose all your work in that process. diff --git a/README.md b/README.md index f60d88c..9d952b0 100644 --- a/README.md +++ b/README.md @@ -173,8 +173,9 @@ prompt-building process: * `LP_ENABLE_SCREEN_TITLE`, if you want to use the prompt as your screen window's title * `LP_ENABLE_SSH_COLORS`, if you want different colors for hosts you SSH into * `LP_ENABLE_RUNTIME`, if you want to display the runtime of the last command +* `LP_ENABLE_SUDO`, if you want the prompt mark to change color while you have password-less root access +* `LP_ENABLE_FQDN`, if you want the display of the fully qualified domain name * `LP_ENABLE_TIME`, if you want to display the time at which the prompt was shown -* `LP_ENABLE_OHMYGIT`, if you want to enable [Oh My Git](https://github.com/arialdomartini/oh-my-git) * `LP_TIME_ANALOG`, if you want to show the time using an analog clock instead of numeric values Note that if required commands are not installed, enabling the corresponding @@ -240,6 +241,7 @@ Available features: * `LP_ERR` last error code * `LP_MARK` prompt mark * `LP_TITLE` the prompt as a window's title escaped sequences +* LP_TTYN the terminal basename * `LP_BRACKET_OPEN` and `LP_BRACKET_CLOSE`, brackets enclosing the user+path part For example, if you just want to have a prompt displaying the user and the @@ -258,7 +260,8 @@ To erase your new formatting, just bind `LP_PS1` to a null string: ## Themes You can change the colors and special characters of some parts of Liquid Prompt -by sourcing your favorite theme file (`*.theme`) in the configuration file. +by sourcing your favorite theme file (`*.theme`) in the configuration file. See +[`liquid.theme`](liquid.theme) for an example of the default Liquid Prompt theme. ### Colors @@ -285,6 +288,7 @@ Set the variable to a null string (`""`) if you do not want color. * Prompt mark * `LP_COLOR_MARK` as user * `LP_COLOR_MARK_ROOT` as root + * `LP_COLOR_MARK_SUDO` when you did `sudo` and your credentials are still cached (use `sudo -K` to revoke them) * `LP_MARK_PREFIX="\n"` put the prompt on the second line * Current user * `LP_COLOR_USER_LOGGED` user who logged in @@ -332,8 +336,6 @@ Set the variable to a null string (`""`) if you do not want color. * `LP_MARK_BRACKET_CLOSE` (default: "]") marks around the main part of the prompt * `LP_TITLE_OPEN` (default: "\e]0;") escape character opening a window's title * `LP_TITLE_CLOSE` (default: "\a") escape character closing a window's title -* `LP_SCREEN_TITLE_OPEN` (default: "\033k") escape character opening screen window's title -* `LP_SCREEN_TITLE_CLOSE` (default: "\033\134") escape character closing screen window's title ## Known Limitations and Bugs @@ -344,14 +346,15 @@ version 3](LICENSE). * Does not display the number of commits to be pushed in Mercurial repositories. * Browsing very large Subversion repositories may dramatically slow down the display of Liquid Prompt (use `LP_DISABLED_VCS_PATH` to avoid that). -* Subversion repositories cannot display commits to be pushed; this is a - limitation of the Subversion versioning model. +* Subversion repositories cannot display commits to be pushed because + that's not how Subversion works * The proxy detection only uses the `$http_proxy` environment variable. * The window's title escape sequence may not work properly on some terminals (like `xterm-256`). * The analog clock requires a Unicode-aware terminal and at least a sufficiently complete font on your system. The [Symbola](http://users.teilar.gr/~g1951d/) - font, designed by Georges Douros, is known to work well. + font, designed by Georges Douros, is known to work well. On Debian or Ubuntu + install try the `fonts-symbola` or `ttf-ancient-fonts` package. ## Authors diff --git a/contrib/README b/contrib/README new file mode 100644 index 0000000..e5143b3 --- /dev/null +++ b/contrib/README @@ -0,0 +1,12 @@ + +liquidprompt/contrib Policy +--------------------------- + +This directory contains files that have been contributed by contributors +but that the core liquidprompt maintainers don't take care. +So they are probably outdated, maybe of poor quality (because the maintainers +do not have the knowledge to properly review them). + +So use them at your own risks, and don't fill issues about them, just send +patches. + diff --git a/contrib/dist/archlinux-aur/PKGBUILD b/contrib/dist/archlinux-aur/PKGBUILD new file mode 100644 index 0000000..75158be --- /dev/null +++ b/contrib/dist/archlinux-aur/PKGBUILD @@ -0,0 +1,40 @@ +# Maintainer: Julien Pecqueur (JPEC) +pkgname=liquidprompt-git +pkgver=20130314 +pkgrel=3 +pkgdesc="An intelligent and non intrusive prompt for bash and zsh" +url="https://github.com/nojhan/liquidprompt" +arch=('any') +license=('AGPLv3') +optdepends=('screen' 'acpi') +makedepends=('git') +md5sums=('SKIP') +install=liquidprompt.install +_gitroot="git://github.com/nojhan/liquidprompt.git" +_gitname="liquidprompt" + +build() { + cd ${srcdir}/ + msg "Connecting to the GIT server...." + if [[ -d ${srcdir}/${_gitname} ]] ; then + cd ${_gitname} + git reset --hard + git pull origin + msg "The local files are updated..." + else + msg "Cloning git repo..." + git clone ${_gitroot} + cd ${_gitname} + fi + git reset --hard + msg "GIT checkout done." +} + +package() { + cd "${srcdir}/${_gitname}" + # install files + install -Dm755 liquidprompt "$pkgdir/usr/bin/liquidprompt" + install -Dm644 liquidpromptrc-dist "$pkgdir/etc/liquidpromptrc" +} + +# vim:set ts=2 sw=2 et: diff --git a/contrib/dist/archlinux-aur/liquidprompt.install b/contrib/dist/archlinux-aur/liquidprompt.install new file mode 100644 index 0000000..80cf376 --- /dev/null +++ b/contrib/dist/archlinux-aur/liquidprompt.install @@ -0,0 +1,4 @@ +post_install() { + echo "Use 'source liquidprompt' to enable the prompt." +} + diff --git a/contrib/dist/debian/create_deb.sh b/contrib/dist/debian/create_deb.sh new file mode 100755 index 0000000..daf559e --- /dev/null +++ b/contrib/dist/debian/create_deb.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +echo "Creating Debian's package..." +nano ./liquidprompt/DEBIAN/control + +echo "Copying files..." +cp ../../liquidprompt ./liquidprompt/usr/bin/liquidprompt +cp ../../liquidpromptrc-dist ./liquidprompt/etc/liquidpromptrc +chmod a+x ./liquidprompt/usr/bin/liquidprompt + +echo "Building liquidprompt.deb..." +dpkg-deb -b liquidprompt + +echo "Deleting files..." +rm -f ./liquidprompt/etc/* +rm -f ./liquidprompt/usr/bin/* + +echo "Done !" diff --git a/contrib/dist/debian/liquidprompt/DEBIAN/control b/contrib/dist/debian/liquidprompt/DEBIAN/control new file mode 100644 index 0000000..95ee5ce --- /dev/null +++ b/contrib/dist/debian/liquidprompt/DEBIAN/control @@ -0,0 +1,11 @@ +Package: liquidprompt +Version: 1.3-0 +Section: base +Priority: optional +Architecture: all +Depends: bash +Recommends: acpi +Suggests: git, screen, tmux +Maintainer: Julien Pecqueur +Description: A slick adaptative prompt for Bash and Zsh. +Homepage: http://github.com/nojhan/liquidprompt diff --git a/example.bashrc b/example.bashrc index 227f647..6f5c508 100644 --- a/example.bashrc +++ b/example.bashrc @@ -7,17 +7,19 @@ # Use the system config if it exists if [ -f /etc/bashrc ]; then - . /etc/bashrc # --> Read /etc/bashrc, if present. + . /etc/bashrc # --> Read /etc/bashrc, if present. +elif [ -f /etc/bash.bashrc ]; then + . /etc/bash.bashrc # --> Read /etc/bash.bashrc, if present. fi +# The following lines are only for interactive shells +[[ $- = *i* ]] || return + # Use Bash completion, if installed if [ -f /etc/bash_completion ]; then . /etc/bash_completion fi -# If you have your own config for Liquid Prompt, edit and uncomment this line: -# source /path/to/liquidpromptrc - # Use Liquid Prompt -source ~/.liquidprompt +source ~/liquidprompt/liquidprompt diff --git a/liquid.ps1 b/liquid.ps1 index ca6fde4..bca782d 100644 --- a/liquid.ps1 +++ b/liquid.ps1 @@ -17,6 +17,7 @@ # LP_ERR last error code # LP_MARK prompt mark # LP_TIME current time +# LP_TTYN number of current terminal (useful in title for quick switching) # LP_RUNTIME runtime of last command # LP_MARK_PREFIX user-defined prompt mark prefix (helpful if you want 2-line prompts) # LP_PS1_PREFIX user-defined general-purpose prefix (default set a generic prompt as the window title) diff --git a/liquid.theme b/liquid.theme index 1d897f4..1c8aa28 100644 --- a/liquid.theme +++ b/liquid.theme @@ -73,6 +73,7 @@ LP_COLOR_ERR="$PURPLE" # Prompt mark LP_COLOR_MARK="$BOLD" # as user LP_COLOR_MARK_ROOT="$BOLD_RED" # as root +LP_COLOR_MARK_SUDO="$BOLD_RED" # when sudo credentials are cached # Current user LP_COLOR_USER_LOGGED="" # user who logged in @@ -92,10 +93,11 @@ LP_COLOR_WRITE="$GREEN" # have write permission LP_COLOR_NOWRITE="$RED" # do not have write permission # VCS -LP_COLOR_UP="$GREEN" # repository is up to date / a push have been made -LP_COLOR_COMMITS="$YELLOW" # some commits have not been pushed -LP_COLOR_CHANGES="$RED" # there is some changes to commit -LP_COLOR_DIFF="$PURPLE" # number of lines impacted by current changes +LP_COLOR_UP="$GREEN" # repository is up to date / a push have been made +LP_COLOR_COMMITS="$YELLOW" # some commits have not been pushed +LP_COLOR_COMMITS_BEHIND="$BOLD_RED" # some commits have not been pushed +LP_COLOR_CHANGES="$RED" # there is some changes to commit +LP_COLOR_DIFF="$PURPLE" # number of lines impacted by current changes # Battery LP_COLOR_CHARGING_ABOVE="$GREEN" # charging and above threshold @@ -115,17 +117,19 @@ LP_COLOR_VIRTUALENV="$CYAN" # Runtime LP_COLOR_RUNTIME="$YELLOW" -# Color maps (battery and load levels) +# Color map (for battery and load levels, and temperature) # Range from 0 (nothing special) to 9 (alert) -LP_COLORMAP_0="" -LP_COLORMAP_1="$GREEN" -LP_COLORMAP_2="$BOLD_GREEN" -LP_COLORMAP_3="$YELLOW" -LP_COLORMAP_4="$BOLD_YELLOW" -LP_COLORMAP_5="$RED" -LP_COLORMAP_6="$BOLD_RED" -LP_COLORMAP_7="$WARN_RED" -LP_COLORMAP_8="$CRIT_RED" -LP_COLORMAP_9="$DANGER_RED" +LP_COLORMAP=( + "" + "$GREEN" + "$BOLD_GREEN" + "$YELLOW" + "$BOLD_YELLOW" + "$RED" + "$BOLD_RED" + "$WARN_RED" + "$CRIT_RED" + "$DANGER_RED" +) # vim: set et sts=4 sw=4 tw=120 ft=sh: diff --git a/liquidprompt b/liquidprompt index 5d1c096..24069ea 100755 --- a/liquidprompt +++ b/liquidprompt @@ -46,7 +46,7 @@ # Rolf Morel # "Shorten path" refactoring and fixes # Thomas Debesse # Fix columns use. # Yann 'Ze' Richard # Do not fail on missing commands. -# Austen Adler # ZSH RPS1, ZSH runtime +# Austen Adler # ZSH runtime # See the README.md file for a summary of features. @@ -54,9 +54,9 @@ test -z "$TERM" -o "x$TERM" = xdumb && return # Check for recent enough version of bash. -if test -n "$BASH_VERSION" -a -n "$PS1" ; then +if test -n "${BASH_VERSION-}" -a -n "$PS1" ; then bash=${BASH_VERSION%.*}; bmajor=${bash%.*}; bminor=${bash#*.} - if [[ $bmajor -lt 3 ]] || [[ $bmajor -eq 3 && $bminor -lt 2 ]]; then + if (( bmajor < 3 || ( bmajor == 3 && bminor < 2 ) )); then unset bash bmajor bminor return fi @@ -67,35 +67,72 @@ if test -n "$BASH_VERSION" -a -n "$PS1" ; then _LP_SHELL_zsh=false _LP_OPEN_ESC="\[" _LP_CLOSE_ESC="\]" + _LP_USER_SYMBOL="\u" _LP_HOST_SYMBOL="\h" + _LP_FQDN_SYMBOL="\H" _LP_TIME_SYMBOL="\t" _LP_MARK_SYMBOL='\$' - _LP_FIRST_INDEX=0 _LP_PWD_SYMBOL="\\w" - _LP_PERCENT='%' # percent must be escaped on zsh + _LP_DIR_SYMBOL="\\W" + + _LP_FIRST_INDEX=0 + _LP_PERCENT='%' # must be escaped on zsh + _LP_BACKSLASH='\\' # must be escaped on bash + + # Escape the given strings + # Must be used for all strings injected in PS1 that may comes from remote sources, + # like $PWD, VCS branch names... + _lp_escape() + { + echo -nE "${1//\\/\\\\}" + } + # Disable the DEBUG trap used by the RUNTIME feature # (in case we are reloading LP in the same shell after disabling # the feature in .liquidpromptrc) # FIXME this doesn't seem to work :( - [[ -n "$LP_ENABLE_RUNTIME" ]] && trap - DEBUG -elif test -n "$ZSH_VERSION" ; then + [[ -n "${LP_ENABLE_RUNTIME-}" ]] && trap - DEBUG +elif test -n "${ZSH_VERSION-}" ; then _LP_SHELL_bash=false _LP_SHELL_zsh=true _LP_OPEN_ESC="%{" _LP_CLOSE_ESC="%}" + _LP_USER_SYMBOL="%n" _LP_HOST_SYMBOL="%m" + _LP_FQDN_SYMBOL="%M" _LP_TIME_SYMBOL="%*" _LP_MARK_SYMBOL='%(!.#.%%)' + _LP_PWD_SYMBOL="%~" + _LP_DIR_SYMBOL="%1~" + _LP_FIRST_INDEX=1 _LP_PERCENT='%%' - _LP_PWD_SYMBOL="%~" + _LP_BACKSLASH="\\" + + _lp_escape() + { + arg="${1//\\/\\\\}" + echo -nE "${arg//\%/$_LP_PERCENT}" + } + + # For ZSH, autoload required functions + autoload -Uz add-zsh-hook + + # Disable previous hooks as options that set them + # may have changed + { + add-zsh-hook -d precmd _lp_set_prompt + add-zsh-hook -d preexec _lp_runtime_before + add-zsh-hook -d precmd _lp_runtime_after + } >/dev/null else echo "liquidprompt: shell not supported" >&2 return fi + # Store $2 (or $?) as a true/false value in variable named $1 # $? is propagated # _lp_bool foo 5 @@ -105,10 +142,10 @@ fi _lp_bool() { local res=${2:-$?} - if [[ $res = 0 ]]; then - eval $1=true - else + if (( res )); then eval $1=false + else + eval $1=true fi return $res } @@ -149,29 +186,25 @@ _LP_SED_EXTENDED=r case "$LP_OS" in Linux) _lp_cpu_load () { - local load eol - read load eol < /proc/loadavg - echo "$load" + local eol + read lp_cpu_load eol < /proc/loadavg } ;; FreeBSD|Darwin|OpenBSD) _lp_cpu_load () { - local bol load eol + local bol eol # If you have problems with syntax coloring due to the following # line, do this: ln -s liquidprompt liquidprompt.bash # and edit liquidprompt.bash - read bol load eol <<<"$( LANG=C sysctl -n vm.loadavg )" - echo "$load" + read bol lp_cpu_load eol <<<"$( LANG=C sysctl -n vm.loadavg )" } ;; SunOS) _lp_cpu_load () { - LANG=C uptime | awk '{print substr($10,0,length($10))}' + read lp_cpu_load <<<"$( LANG=C uptime | awk '{print substr($10,0,length($10))}' )" } esac -# Reset so all PWD dependent variables are computed after loading -unset LP_OLD_PWD ################# # CONFIGURATION # @@ -259,7 +292,8 @@ _lp_source_config() local hash=$(( 1 + $(hostname | cksum | cut -d " " -f 1) % 6 )) LP_COLOR_HOST_HASH="${_LP_OPEN_ESC}$(ti_setaf $hash)${_LP_CLOSE_ESC}" - unset ti_sgr0 ti_bold ti_setaf ti_setab + unset ti_sgr0 ti_bold + unset -f ti_setaf ti_setab # Default values (globals) @@ -277,10 +311,6 @@ _lp_source_config() LP_RPS1=${LP_RPS1:-""} LP_PS1_PREFIX=${LP_PS1_PREFIX:-""} LP_PS1_POSTFIX=${LP_PS1_POSTFIX:-""} - LP_TITLE_OPEN=${LP_TITLE_OPEN:-"\e]0;"} - LP_TITLE_CLOSE=${LP_TITLE_CLOSE:-"\a"} - LP_SCREEN_TITLE_OPEN=${LP_SCREEN_TITLE_OPEN:-"\033k"} - LP_SCREEN_TITLE_CLOSE=${LP_SCREEN_TITLE_CLOSE:-"\033\134"} LP_ENABLE_PERM=${LP_ENABLE_PERM:-1} LP_ENABLE_SHORTEN_PATH=${LP_ENABLE_SHORTEN_PATH:-1} @@ -290,8 +320,8 @@ _lp_source_config() LP_ENABLE_LOAD=${LP_ENABLE_LOAD:-1} LP_ENABLE_BATT=${LP_ENABLE_BATT:-1} LP_ENABLE_GIT=${LP_ENABLE_GIT:-1} - LP_ENABLE_OHMYGIT=${LP_ENABLE_OHMYGIT:-0} LP_ENABLE_SVN=${LP_ENABLE_SVN:-1} + LP_ENABLE_OHMYGIT=${LP_ENABLE_OHMYGIT:-0} LP_ENABLE_VCSH=${LP_ENABLE_VCSH:-1} LP_ENABLE_FOSSIL=${LP_ENABLE_FOSSIL:-1} LP_ENABLE_HG=${LP_ENABLE_HG:-1} @@ -304,7 +334,9 @@ _lp_source_config() LP_ENABLE_TITLE=${LP_ENABLE_TITLE:-0} LP_ENABLE_SCREEN_TITLE=${LP_ENABLE_SCREEN_TITLE:-0} LP_ENABLE_SSH_COLORS=${LP_ENABLE_SSH_COLORS:-0} + LP_ENABLE_FQDN=${LP_ENABLE_FQDN:-0} # LP_DISABLED_VCS_PATH="${LP_DISABLED_VCS_PATH}" + LP_ENABLE_SUDO=${LP_ENABLE_SUDO:-0} LP_MARK_DEFAULT="${LP_MARK_DEFAULT:-$_LP_MARK_SYMBOL}" LP_MARK_BATTERY="${LP_MARK_BATTERY:-"⌁"}" @@ -335,19 +367,21 @@ _lp_source_config() LP_COLOR_ERR=${LP_COLOR_ERR:-$PURPLE} LP_COLOR_MARK=${LP_COLOR_MARK:-$BOLD} LP_COLOR_MARK_ROOT=${LP_COLOR_MARK_ROOT:-$BOLD_RED} + LP_COLOR_MARK_SUDO=${LP_COLOR_MARK_SUDO:-$LP_COLOR_MARK_ROOT} 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_USER_ROOT=${LP_COLOR_USER_ROOT:-$BOLD_YELLOW} LP_COLOR_HOST=${LP_COLOR_HOST:-""} LP_COLOR_SSH=${LP_COLOR_SSH:-$BLUE} LP_COLOR_SU=${LP_COLOR_SU:-$BOLD_YELLOW} LP_COLOR_TELNET=${LP_COLOR_TELNET:-$WARN_RED} - LP_COLOR_X11_ON=${LP_COLOR_X11:-$GREEN} - LP_COLOR_X11_OFF=${LP_COLOR_X11:-$YELLOW} + LP_COLOR_X11_ON=${LP_COLOR_X11_ON:-$GREEN} + LP_COLOR_X11_OFF=${LP_COLOR_X11_OFF:-$YELLOW} 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_COMMITS_BEHIND=${LP_COLOR_COMMITS_BEHIND:-$BOLD_RED} LP_COLOR_CHANGES=${LP_COLOR_CHANGES:-$RED} LP_COLOR_DIFF=${LP_COLOR_DIFF:-$PURPLE} LP_COLOR_CHARGING_ABOVE=${LP_COLOR_CHARGING_ABOVE:-$GREEN} @@ -359,70 +393,119 @@ _lp_source_config() LP_COLOR_RUNTIME=${LP_COLOR_RUNTIME:-$YELLOW} LP_COLOR_VIRTUALENV=${LP_COLOR_VIRTUALENV:-$CYAN} - 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} + if [[ -z "${LP_COLORMAP-}" ]]; then + LP_COLORMAP=( + "" # 0 + "$GREEN" # 1 + "$BOLD_GREEN" # 2 + "$YELLOW" # 3 + "$BOLD_YELLOW" # 4 + "$RED" # 5 + "$BOLD_RED" # 6 + "$WARN_RED" # 7 + "$CRIT_RED" # 8 + "$DANGER_RED" # 9 + ) + fi # Debugging flags LP_DEBUG_TIME=${LP_DEBUG_TIME:-0} + + local configfile + # Default config file may be the XDG standard ~/.config/liquidpromptrc, # but heirloom dotfile has priority. - local configfile - if [[ -f "/etc/liquidpromptrc" ]] - then + if [[ -f "$HOME/.liquidpromptrc" ]]; then + configfile="$HOME/.liquidpromptrc" + else + local first + local search + # trailing ":" is so that ${search#*:} always removes something + search="${XDG_CONFIG_HOME:-"$HOME/.config"}:${XDG_CONFIG_DIRS:-/etc/xdg}:" + while [[ -n "$search" ]]; do + first="${search%%:*}" + search="${search#*:}" + if [[ -f "$first/liquidpromptrc" ]]; then + configfile="$first/liquidpromptrc" + break + fi + done + fi + + if [[ -n "$configfile" ]]; then + source "$configfile" + elif [[ -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" + + # Delete this code in version 1.11 + if [[ -n "${LP_COLORMAP_1-}" ]]; then + echo "liquidprompt: LP_COLORMAP_x variables are deprecated. Update your theme to use LP_COLORMAP array." >&2 + LP_COLORMAP=( + "$LP_COLORMAP_0" + "$LP_COLORMAP_1" + "$LP_COLORMAP_2" + "$LP_COLORMAP_3" + "$LP_COLORMAP_4" + "$LP_COLORMAP_5" + "$LP_COLORMAP_6" + "$LP_COLORMAP_7" + "$LP_COLORMAP_8" + "$LP_COLORMAP_9" + ) + unset LP_COLORMAP_0 LP_COLORMAP_1 LP_COLORMAP_2 LP_COLORMAP_3 LP_COLORMAP_4 \ + LP_COLORMAP_5 LP_COLORMAP_6 LP_COLORMAP_7 LP_COLORMAP_8 LP_COLORMAP_9 fi } # do source config files _lp_source_config -unset _lp_source_config +unset -f _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_FOSSIL" = 1 ]] && { command -v fossil >/dev/null || LP_ENABLE_FOSSIL=0 ; } -[[ "$LP_ENABLE_HG" = 1 ]] && { command -v hg >/dev/null || LP_ENABLE_HG=0 ; } -[[ "$LP_ENABLE_BZR" = 1 ]] && { command -v bzr > /dev/null || LP_ENABLE_BZR=0 ; } -case "$LP_OS" in - Darwin) [[ "$LP_ENABLE_BATT" = 1 ]] && { command -v pmset >/dev/null || LP_ENABLE_BATT=0 ; };; - *) [[ "$LP_ENABLE_BATT" = 1 ]] && { (command -v upower||command -v acpi) >/dev/null || LP_ENABLE_BATT=0 ; };; -esac -command -v screen >/dev/null ; _lp_bool _LP_ENABLE_SCREEN $? -command -v tmux >/dev/null ; _lp_bool _LP_ENABLE_TMUX $? -$_LP_ENABLE_SCREEN || $_LP_ENABLE_TMUX ; _lp_bool _LP_ENABLE_DETACHED_SESSIONS $? +# Disable feature if the tool is not installed +_lp_require_tool() +{ + (( LP_ENABLE_$1 )) && { command -v $2 >/dev/null || eval LP_ENABLE_$1=0 ; } +} + +_lp_require_tool GIT git +_lp_require_tool SVN svn +_lp_require_tool FOSSIL fossil +_lp_require_tool HG hg +_lp_require_tool BZR bzr + +if [[ "$LP_OS" = Darwin ]]; then + _lp_require_tool BATT pmset +else + _lp_require_tool BATT acpi +fi + +unset -f _lp_require_tool + +if (( LP_ENABLE_JOBS )); then + typeset -i _LP_ENABLE_DETACHED_SESSION _LP_ENABLE_SCREEN _LP_ENABLE_TMUX + command -v screen >/dev/null ; _LP_ENABLE_SCREEN=!$? + command -v tmux >/dev/null ; _LP_ENABLE_TMUX=!$? + (( _LP_ENABLE_DETACHED_SESSIONS = ( _LP_ENABLE_SCREEN || _LP_ENABLE_TMUX ) )) +fi + +# Use standard path symbols inside Midnight Commander +[[ -n "${MC_SID-}" ]] && LP_ENABLE_SHORTEN_PATH=0 # If we are running in a terminal multiplexer, brackets are colored if [[ "$TERM" == screen* ]]; then LP_BRACKET_OPEN="${LP_COLOR_IN_MULTIPLEXER}${LP_MARK_BRACKET_OPEN}${NO_COL}" LP_BRACKET_CLOSE="${LP_COLOR_IN_MULTIPLEXER}${LP_MARK_BRACKET_CLOSE}${NO_COL}" (( LP_ENABLE_TITLE = LP_ENABLE_TITLE && LP_ENABLE_SCREEN_TITLE )) - LP_TITLE_OPEN="$LP_SCREEN_TITLE_OPEN" - LP_TITLE_CLOSE="$LP_SCREEN_TITLE_CLOSE" + LP_TITLE_OPEN="$(printf '\033k')" + # "\e\" but on bash \ must be escaped + LP_TITLE_CLOSE="$(printf '\033%s' "$_LP_BACKSLASH")" else LP_BRACKET_OPEN="${LP_MARK_BRACKET_OPEN}" LP_BRACKET_CLOSE="${LP_MARK_BRACKET_CLOSE}" + LP_TITLE_OPEN="$(printf '\e]0;')" + LP_TITLE_CLOSE="$(printf '\a')" fi [[ "_$TERM" == _linux* ]] && LP_ENABLE_TITLE=0 @@ -431,7 +514,7 @@ fi # will update an icon of the directory displayed in the title of the terminal # window. # See http://hints.macworld.com/article.php?story=20110722211753852 -if [[ "$TERM_PROGRAM" == Apple_Terminal ]] && command -v update_terminal_cwd >/dev/null; then +if [[ "${TERM_PROGRAM-}" == Apple_Terminal ]] && command -v update_terminal_cwd >/dev/null; then _LP_TERM_UPDATE_DIR=update_terminal_cwd # Remove "update_terminal_cwd; " that has been add by Apple in /et/bashrc. # See issue #196 @@ -443,43 +526,61 @@ fi # Default value for LP_PERM when LP_ENABLE_PERM is 0 LP_PERM=: # without color +# Same as bash '\l', but inlined as a constant as the value will not change +# during the shell's life +LP_TTYN="$(basename -- "$(tty)" 2>/dev/null)" -# Escape the given strings -# Must be used for all strings that may comes from remote sources, -# like VCS branch names -_lp_escape() -{ - printf "%q" "$*" -} ############### # Who are we? # ############### +command -v _lp_sudo_check >/dev/null && unset -f _lp_sudo_check # Yellow for root, bold if the user is not the login one, else no color. -if [[ "$EUID" -ne "0" ]] ; then # if user is not root +if (( EUID != 0 )); then # if user is not root # if user is not login user - if [[ ${USER} != "$(logname 2>/dev/null || echo "$LOGNAME")" ]]; then + if [[ "${USER}" != "$(logname 2>/dev/null || echo "$LOGNAME")" ]]; then LP_USER="${LP_COLOR_USER_ALT}${_LP_USER_SYMBOL}${NO_COL}" + elif (( LP_USER_ALWAYS )); then + LP_USER="${LP_COLOR_USER_LOGGED}${_LP_USER_SYMBOL}${NO_COL}" else - if [[ "${LP_USER_ALWAYS}" -ne "0" ]] ; then - LP_USER="${LP_COLOR_USER_LOGGED}${_LP_USER_SYMBOL}${NO_COL}" - else - LP_USER="" - fi + LP_USER="" + fi + # "sudo -n" is only supported from sudo 1.7.0 + if (( LP_ENABLE_SUDO )) \ + && command -v sudo >/dev/null \ + && LC_MESSAGES=C sudo -V | GREP_OPTIONS= \grep -qE '^Sudo version (1(\.([789]\.|[1-9][0-9])|[0-9])|[2-9])' + then + LP_COLOR_MARK_NO_SUDO="$LP_COLOR_MARK" + # Test the code with the commands: + # sudo id # sudo, enter your credentials + # sudo -K # revoke your credentials + _lp_sudo_check() + { + if sudo -n true 2>/dev/null; then + LP_COLOR_MARK=$LP_COLOR_MARK_SUDO + else + LP_COLOR_MARK=$LP_COLOR_MARK_NO_SUDO + fi + } fi else # root! LP_USER="${LP_COLOR_USER_ROOT}${_LP_USER_SYMBOL}${NO_COL}" LP_COLOR_MARK="${LP_COLOR_MARK_ROOT}" LP_COLOR_PATH="${LP_COLOR_PATH_ROOT}" # Disable VCS info for all paths - if [[ "$LP_ENABLE_VCS_ROOT" != 1 ]]; then + if (( ! LP_ENABLE_VCS_ROOT )); then LP_DISABLED_VCS_PATH=/ LP_MARK_DISABLED="$_LP_MARK_SYMBOL" fi fi +# Empty _lp_sudo_check if root or sudo disabled +if ! command -v _lp_sudo_check >/dev/null; then + _lp_sudo_check() { :; } +fi + ################# # Where are we? # @@ -487,15 +588,16 @@ fi _lp_connection() { - if [[ -n "$SSH_CLIENT$SSH2_CLIENT$SSH_TTY" ]] ; then + if [[ -n "${SSH_CLIENT-}${SSH2_CLIENT-}${SSH_TTY-}" ]]; then echo ssh else + # tmux: see GH #304 # TODO check on *BSD - local sess_src="$(who am i | sed -n 's/.*(\(.*\))/\1/p')" + local whoami="$(LANG=C who am i)" local sess_parent="$(ps -o comm= -p $PPID 2> /dev/null)" - if [[ -z "$sess_src" || "$sess_src" = ":"* ]] ; then + if [[ x"$whoami" != *'('* || x"$whoami" = *'(:'* || x"$whoami" = *'(tmux'* ]]; then echo lcl # Local - elif [[ "$sess_parent" = "su" || "$sess_parent" = "sudo" ]] ; then + elif [[ "$sess_parent" = "su" || "$sess_parent" = "sudo" ]]; then echo su # Remote su/sudo else echo tel # Telnet @@ -509,42 +611,55 @@ _lp_connection() # The connection is not expected to change from inside the shell, so we # build this just once LP_HOST="" -[[ -r /etc/debian_chroot ]] && LP_HOST="($(< /etc/debian_chroot))" -# If we are connected with a X11 support -if [[ -n "$DISPLAY" ]]; then - LP_HOST="${LP_COLOR_X11_ON}${LP_HOST}@${NO_COL}" -else - LP_HOST="${LP_COLOR_X11_OFF}${LP_HOST}@${NO_COL}" +# Only process hostname elements if we haven't turned them off +if (( LP_HOSTNAME_ALWAYS != -1 )); then + + [[ -r /etc/debian_chroot ]] && LP_HOST="($(< /etc/debian_chroot))" + + # Which host symbol should we use? + if (( LP_ENABLE_FQDN )); then + LP_HOST_SYMBOL="${_LP_FQDN_SYMBOL}" + else + LP_HOST_SYMBOL="${_LP_HOST_SYMBOL}" + fi + + # If we are connected with a X11 support + if [[ -n "$DISPLAY" ]]; then + LP_HOST="${LP_COLOR_X11_ON}${LP_HOST}@${NO_COL}" + else + LP_HOST="${LP_COLOR_X11_OFF}${LP_HOST}@${NO_COL}" + fi + + case "$(_lp_connection)" in + lcl) + if (( LP_HOSTNAME_ALWAYS )); then + LP_HOST+="${LP_COLOR_HOST}${_LP_HOST_SYMBOL}${NO_COL}" + else + # FIXME do we want to display the chroot if local? + LP_HOST="" # no hostname if local + fi + ;; + ssh) + # If we want a different color for each host + (( LP_ENABLE_SSH_COLORS )) && LP_COLOR_SSH="$LP_COLOR_HOST_HASH" + LP_HOST+="${LP_COLOR_SSH}${_LP_HOST_SYMBOL}${NO_COL}" + ;; + su) + LP_HOST+="${LP_COLOR_SU}${_LP_HOST_SYMBOL}${NO_COL}" + ;; + tel) + LP_HOST+="${LP_COLOR_TELNET}${_LP_HOST_SYMBOL}${NO_COL}" + ;; + *) + LP_HOST+="${_LP_HOST_SYMBOL}" # defaults to no color + ;; + esac + fi -case "$(_lp_connection)" in -lcl) - if [[ "${LP_HOSTNAME_ALWAYS}" -eq "0" ]] ; then - # FIXME do we want to display the chroot if local? - LP_HOST="" # no hostname if local - else - LP_HOST="${LP_HOST}${LP_COLOR_HOST}${_LP_HOST_SYMBOL}${NO_COL}" - fi - ;; -ssh) - # If we want a different color for each host - [[ "$LP_ENABLE_SSH_COLORS" -eq 1 ]] && LP_COLOR_SSH="$LP_COLOR_HOST_HASH" - LP_HOST="${LP_HOST}${LP_COLOR_SSH}${_LP_HOST_SYMBOL}${NO_COL}" - ;; -su) - LP_HOST="${LP_HOST}${LP_COLOR_SU}${_LP_HOST_SYMBOL}${NO_COL}" - ;; -tel) - LP_HOST="${LP_HOST}${LP_COLOR_TELNET}${_LP_HOST_SYMBOL}${NO_COL}" - ;; -*) - LP_HOST="${LP_HOST}${_LP_HOST_SYMBOL}" # defaults to no color - ;; -esac - # Useless now, so undefine -unset _lp_connection +unset -f _lp_connection _lp_get_home_tilde_collapsed() @@ -561,27 +676,26 @@ _lp_get_home_tilde_collapsed() _lp_shorten_path() { - if [[ "$LP_ENABLE_SHORTEN_PATH" != 1 ]] ; then - LP_PWD="$LP_PATH_DEFAULT" - if $_LP_SHELL_bash; then - [[ -n "$PROMPT_DIRTRIM" ]] && _lp_set_dirtrim - fi + if (( ! LP_ENABLE_SHORTEN_PATH )); then + # We are not supposed to come here often as this case is already + # optimized at install time + LP_PWD="${LP_COLOR_PATH}${LP_PATH_DEFAULT}$NO_COL" return fi - local ret="" + local ret= local p="$(_lp_get_home_tilde_collapsed)" local mask="${LP_MARK_SHORTEN_PATH}" local -i max_len=$(( ${COLUMNS:-80} * LP_PATH_LENGTH / 100 )) - if [[ ${LP_PATH_KEEP} == -1 ]]; then + if (( LP_PATH_KEEP == -1 )); then # only show the current directory, excluding any parent dirs ret="${p##*/}" # discard everything up to and including the last slash [[ "${ret}" == "" ]] && ret="/" # if in root directory elif (( ${#p} <= max_len )); then ret="${p}" - elif [[ ${LP_PATH_KEEP} == 0 ]]; then + elif (( LP_PATH_KEEP == 0 )); then # len is over max len, show as much of the tail as is allowed ret="${p##*/}" # show at least complete current directory p="${p:0:${#p} - ${#ret}}" @@ -589,7 +703,7 @@ _lp_shorten_path() else # len is over max len, show at least LP_PATH_KEEP leading dirs and # current directory - local tmp=${p//\//} + local tmp="${p//\//}" local -i delims=$(( ${#p} - ${#tmp} )) for (( dir=0; dir < LP_PATH_KEEP; dir++ )); do @@ -598,12 +712,12 @@ _lp_shorten_path() local left="${p#*/}" local name="${p:0:${#p} - ${#left}}" p="${left}" - ret="${ret}${name%/}/" + ret+="${name%/}/" done if (( delims <= LP_PATH_KEEP )); then # no dirs between LP_PATH_KEEP leading dirs and current dir - ret="${ret}${p##*/}" + ret+="${p##*/}" else local base="${p##*/}" @@ -613,18 +727,35 @@ _lp_shorten_path() local -i len_left=$(( max_len - ${#ret} - ${#base} - ${#mask} )) - ret="${ret}${mask}${p:${#p} - ${len_left}}${base}" + ret+="${mask}${p:${#p} - ${len_left}}${base}" fi fi # Escape special chars - if $_LP_SHELL_bash; then - LP_PWD="${ret//\\/\\\\}" - else # zsh - LP_PWD="${ret//\%/%%}" - fi + LP_PWD="${LP_COLOR_PATH}$(_lp_escape "$ret")$NO_COL" } -# In Bash shells, PROMPT_DIRTRIM is the number of directory to keep at the end +if (( LP_ENABLE_SHORTEN_PATH )); then + if (( LP_PATH_KEEP == -1 )); then + # _lp_shorten_path becomes a noop + _lp_shorten_path() + { + : + } + # Will never change + LP_PWD="${LP_COLOR_PATH}${_LP_DIR_SYMBOL}$NO_COL" + fi +else + # Will never change + LP_PWD="${LP_COLOR_PATH}${LP_PATH_DEFAULT}$NO_COL" + + if $_LP_SHELL_bash && [[ -n "$PROMPT_DIRTRIM" ]]; then + unset -f _lp_shorten_path + alias _lp_shorten_path=_lp_set_dirtrim + fi +fi + + +# In Bash shells, PROMPT_DIRTRIM is the number of directories to keep at the end # of the displayed path (if "\w" is present in the PS1 var). # Liquid Prompt can calculate this number under two conditions, path shortening # must be disabled and PROMPT_DIRTRIM must be already set. @@ -662,32 +793,32 @@ _lp_set_dirtrim() { # - attached stopped jobs (suspended with Ctrl-Z) _lp_jobcount_color() { - [[ "$LP_ENABLE_JOBS" != 1 ]] && return + (( LP_ENABLE_JOBS )) || return - local m_stop="z" - local m_run="&" - local ret + local ret="" + local -i r s - if $_LP_ENABLE_DETACHED_SESSIONS; then + # Count detached sessions + if (( _LP_ENABLE_DETACHED_SESSIONS )); then local -i detached=0 - #$_LP_ENABLE_SCREEN && let detached=$(screen -ls 2> /dev/null | \grep -c '[Dd]etach[^)]*)$') - $_LP_ENABLE_TMUX && let detached+=$(tmux list-sessions 2> /dev/null | \grep -cv 'attached') - (( detached > 0 )) && ret="${ret}${LP_COLOR_JOB_D}${detached}d${NO_COL}" + (( _LP_ENABLE_SCREEN )) && detached=$(screen -ls 2> /dev/null | \grep -c '[Dd]etach[^)]*)$') + (( _LP_ENABLE_TMUX )) && detached+=$(tmux list-sessions 2> /dev/null | \grep -cv 'attached') + (( detached > 0 )) && ret+="${LP_COLOR_JOB_D}${detached}d${NO_COL}" fi - local running=$(( $(jobs -r | wc -l) )) - if [[ $running != 0 ]] ; then - [[ -n "$ret" ]] && ret="${ret}/" - ret="${ret}${LP_COLOR_JOB_R}${running}${m_run}${NO_COL}" + # Count running jobs + if (( r = $(jobs -r | wc -l) )); then + [[ -n "$ret" ]] && ret+='/' + ret+="${LP_COLOR_JOB_R}${r}&${NO_COL}" fi - local stopped=$(( $(jobs -s | wc -l) )) - if [[ $stopped != 0 ]] ; then - [[ -n "$ret" ]] && ret="${ret}/" - ret="${ret}${LP_COLOR_JOB_Z}${stopped}${m_stop}${NO_COL}" + # Count stopped jobs + if (( s = $(jobs -s | wc -l) )); then + [[ -n "$ret" ]] && ret+='/' + ret+="${LP_COLOR_JOB_Z}${s}z${NO_COL}" fi - echo -n "$ret" + echo -nE "$ret" } @@ -699,6 +830,7 @@ _lp_jobcount_color() _lp_are_vcs_enabled() { [[ -z "$LP_DISABLED_VCS_PATH" ]] && return 0 + $_LP_SHELL_zsh && setopt local_options && setopt sh_word_split local path local IFS=: for path in $LP_DISABLED_VCS_PATH; do @@ -712,9 +844,9 @@ _lp_are_vcs_enabled() # Get the branch name of the current directory _lp_git_branch() { - [[ "$LP_ENABLE_GIT" != 1 ]] && return + (( LP_ENABLE_GIT )) || return - \git rev-parse --inside-work-tree >/dev/null 2>&1 || return + \git rev-parse --is-inside-work-tree >/dev/null 2>&1 || return local branch # Recent versions of Git support the --short option for symbolic-ref, but @@ -728,6 +860,21 @@ _lp_git_branch() fi } + +# Display additional information if HEAD is in merging, rebasing +# or cherry-picking state +_lp_git_head_status() { + local gitdir + gitdir="$(\git rev-parse --git-dir 2>/dev/null)" + if [[ -f "${gitdir}/MERGE_HEAD" ]]; then + echo " MERGING" + elif [[ -d "${gitdir}/rebase-apply" || -d "${gitdir}/rebase-merge" ]]; then + echo " REBASING" + elif [[ -f "${gitdir}/CHERRY_PICK_HEAD" ]]; then + echo " CHERRY-PICKING" + 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 @@ -736,14 +883,15 @@ _lp_git_branch() # Add the number of pending commits and the impacted lines. _lp_git_branch_color() { - [[ "$LP_ENABLE_GIT" != 1 ]] && return + (( LP_ENABLE_GIT )) || return local branch branch="$(_lp_git_branch)" - if [[ -n "$branch" ]] ; then + if [[ -n "$branch" ]]; then local end - end="$NO_COL" + end="${LP_COLOR_CHANGES}$(_lp_git_head_status)${NO_COL}" + if LC_ALL=C \git status --porcelain 2>/dev/null | \grep -Eq '^\?\?'; then end="$LP_COLOR_CHANGES$LP_MARK_UNTRACKED$end" fi @@ -755,14 +903,23 @@ _lp_git_branch_color() local remote remote="$(\git config --get branch.${branch}.remote 2>/dev/null)" - local -i has_commit - has_commit=0 + local has_commit="" + local commit_ahead + local commit_behind if [[ -n "$remote" ]]; then local remote_branch remote_branch="$(\git config --get branch.${branch}.merge)" if [[ -n "$remote_branch" ]]; then - has_commit="$(\git rev-list --count ${remote_branch/refs\/heads/refs\/remotes\/$remote}..HEAD 2>/dev/null)" - [[ -z "$has_commit" ]] && has_commit=0 + remote_branch=${remote_branch/refs\/heads/refs\/remotes\/$remote} + commit_ahead="$(\git rev-list --count $remote_branch..HEAD 2>/dev/null)" + commit_behind="$(\git rev-list --count HEAD..$remote_branch 2>/dev/null)" + if [[ "$commit_ahead" -ne "0" && "$commit_behind" -ne "0" ]]; then + has_commit="${LP_COLOR_COMMITS}+$commit_ahead${NO_COL}/${LP_COLOR_COMMITS_BEHIND}-$commit_behind${NO_COL}" + elif [[ "$commit_ahead" -ne "0" ]]; then + has_commit="${LP_COLOR_COMMITS}$commit_ahead${NO_COL}" + elif [[ "$commit_behind" -ne "0" ]]; then + has_commit="${LP_COLOR_COMMITS_BEHIND}-$commit_behind${NO_COL}" + fi fi fi @@ -770,20 +927,20 @@ _lp_git_branch_color() local shortstat # only to check for uncommitted changes shortstat="$(LC_ALL=C \git diff --shortstat HEAD 2>/dev/null)" - if [[ -n "$shortstat" ]] ; then + if [[ -n "$shortstat" ]]; then local u_stat # shorstat of *unstaged* changes u_stat="$(LC_ALL=C \git diff --shortstat 2>/dev/null)" u_stat=${u_stat/*changed, /} # removing "n file(s) changed" local i_lines # inserted lines - if [[ "$u_stat" = *insertion* ]] ; then + if [[ "$u_stat" = *insertion* ]]; then i_lines=${u_stat/ inser*} else i_lines=0 fi local d_lines # deleted lines - if [[ "$u_stat" = *deletion* ]] ; then + if [[ "$u_stat" = *deletion* ]]; then d_lines=${u_stat/*\(+\), } d_lines=${d_lines/ del*/} else @@ -793,21 +950,23 @@ _lp_git_branch_color() local has_lines has_lines="+$i_lines/-$d_lines" - if [[ "$has_commit" -gt "0" ]] ; then + if [[ -n "$has_commit" ]]; 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})" + ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$has_lines${NO_COL},$has_commit)" else ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$has_lines${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})" + elif [[ -n "$has_commit" ]]; then + # some commit(s) to push + if [[ "$commit_behind" -gt "0" ]]; then + ret="${LP_COLOR_COMMITS_BEHIND}${branch}${NO_COL}($has_commit)" else - ret="${LP_COLOR_UP}${branch}" # nothing to commit or push + ret="${LP_COLOR_COMMITS}${branch}${NO_COL}($has_commit)" fi + else + ret="${LP_COLOR_UP}${branch}" # nothing to commit or push fi - echo -ne "$ret$end" + echo -nE "$ret$end" fi } @@ -829,7 +988,7 @@ _lp_upwards_find() # Get the branch name of the current directory _lp_hg_branch() { - [[ "$LP_ENABLE_HG" != 1 ]] && return + (( LP_ENABLE_HG )) || return # First do a simple search to avoid having to invoke hg -- at least on my # machine, the python startup causes a noticeable hitch when changing @@ -842,7 +1001,7 @@ _lp_hg_branch() local branch branch="$(hg branch 2>/dev/null)" - [[ $? -eq 0 ]] && _lp_escape "$branch" + (( $? == 0 )) && _lp_escape "$branch" } # Set a color depending on the branch state: @@ -851,12 +1010,12 @@ _lp_hg_branch() # - TODO: yellow if there is some commits not pushed _lp_hg_branch_color() { - [[ "$LP_ENABLE_HG" != 1 ]] && return + (( LP_ENABLE_HG )) || return local branch local ret branch="$(_lp_hg_branch)" - if [[ -n "$branch" ]] ; then + if [[ -n "$branch" ]]; then local has_untracked has_untracked= @@ -873,8 +1032,8 @@ _lp_hg_branch_color() commits=0 # Check if there is some uncommitted stuff - if [[ -z "$(hg status --quiet -n)" ]] ; then - if (( commits > 0 )) ; then + if [[ -z "$(hg status --quiet -n)" ]]; then + if (( commits > 0 )); then # some commit(s) to push ret="${LP_COLOR_COMMITS}${branch}${NO_COL}(${LP_COLOR_COMMITS}$commits${NO_COL})${has_untracked}${NO_COL}" else @@ -885,14 +1044,14 @@ _lp_hg_branch_color() local has_lines # Parse the last line of the diffstat-style output has_lines="$(hg diff --stat 2>/dev/null | sed -n '$ s!^.*, \([0-9]*\) .*, \([0-9]*\).*$!+\1/-\2!p')" - if (( commits > 0 )) ; then + if (( commits > 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}$commits${NO_COL})${has_untracked}${NO_COL}" else ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$has_lines${NO_COL})${has_untracked}${NO_COL}" # changes to commit fi fi - echo -ne "$ret" + echo -nE "$ret" fi } @@ -902,20 +1061,21 @@ _lp_hg_branch_color() # For the first level of the repository, gives the repository name _lp_svn_branch() { - [[ "$LP_ENABLE_SVN" != 1 ]] && return - local root - local url + (( LP_ENABLE_SVN )) || return + + local root= + local url= eval "$(LANG=C LC_ALL=C svn info 2>/dev/null | sed -n 's/^URL: \(.*\)/url="\1"/p;s/^Repository Root: \(.*\)/root="\1"/p' )" - [[ -z "$root" ]] && return + [[ -z "${root-}" ]] && return # Make url relative to root url="${url:${#root}}" - if [[ "$url" == */trunk* ]] ; then + if [[ "$url" == */trunk* ]]; then echo -n trunk - elif [[ "$url" == */branches/?* ]] ; then + elif [[ "$url" == */branches/?* ]]; then url="${url##*/branches/}" _lp_escape "${url%/*}" - elif [[ "$url" == */tags/?* ]] ; then + elif [[ "$url" == */tags/?* ]]; then url="${url##*/tags/}" _lp_escape "${url%/*}" else @@ -925,24 +1085,24 @@ _lp_svn_branch() # Set a color depending on the branch state: # - green if the repository is clean -# (use $LP_SVN_STATUS_OPTS to define what that means with +# (use $LP_SVN_STATUS_OPTIONS to define what that means with # the --depth option of 'svn status') # - 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 + (( LP_ENABLE_SVN )) || return local branch branch="$(_lp_svn_branch)" - if [[ -n "$branch" ]] ; then + if [[ -n "$branch" ]]; then local changes - changes=$(( $(svn status $LP_SVN_STATUS_OPTIONS | \grep -c -v "?") )) - if [[ $changes -eq 0 ]] ; then - echo "${LP_COLOR_UP}${branch}${NO_COL}" + changes=$(( $(svn status ${LP_SVN_STATUS_OPTIONS-} | \grep -c -v "?") )) + if (( changes == 0 )); then + echo -nE "${LP_COLOR_UP}${branch}${NO_COL}" else - echo "${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$changes${NO_COL})" # changes to commit + echo -nE "${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_DIFF}$changes${NO_COL})" # changes to commit fi fi } @@ -953,15 +1113,13 @@ _lp_svn_branch_color() # Get the tag name of the current directory _lp_fossil_branch() { - [[ "$LP_ENABLE_FOSSIL" != 1 ]] && return + (( LP_ENABLE_FOSSIL )) || return local branch - branch=$(fossil status 2>/dev/null | sed -n "s/tags:[ ]*\(\w*\)$/\1/Ip") - if [ -n "$branch" ]; then - echo "$branch" - else - if fossil info &>/dev/null ; then - echo "no-tag" - fi + branch=$(fossil status 2>/dev/null | sed -n -$_LP_SED_EXTENDED 's/^tags:\s+(\w*)$/\1/p') + if [[ -n "$branch" ]]; then + echo -nE "$branch" + elif fossil info &>/dev/null ; then + echo -n "no-tag" fi } @@ -975,12 +1133,12 @@ _lp_fossil_branch() # - when files are DELETED _lp_fossil_branch_color() { - [[ "$LP_ENABLE_FOSSIL" != 1 ]] && return + (( LP_ENABLE_FOSSIL )) || return local branch branch="$(_lp_fossil_branch)" - if [ -n "$branch" ]; then + if [[ -n "$branch" ]]; then local -i C2E # Modified files (added or edited) local C2A # Extras files local ret @@ -1002,16 +1160,14 @@ _lp_fossil_branch_color() if [[ "$branch" = "no-tag" ]]; then # Warning, your branch has no tag name ! branch="${LP_COLOR_COMMITS}$branch${NO_COL}$ret${LP_COLOR_COMMITS}$C2A${NO_COL}" + elif (( C2E == 0 )); then + # All is up-to-date + branch="${LP_COLOR_UP}$branch$C2A${NO_COL}" else - if (( C2E == 0 )); then - # All is up-to-date - branch="${LP_COLOR_UP}$branch$C2A${NO_COL}" - else - # There're some changes to commit - branch="${LP_COLOR_CHANGES}$branch${NO_COL}$ret${LP_COLOR_CHANGES}$C2A${NO_COL}" - fi + # There're some changes to commit + branch="${LP_COLOR_CHANGES}$branch${NO_COL}$ret${LP_COLOR_CHANGES}$C2A${NO_COL}" fi - echo "$branch" + echo -nE "$branch" fi } @@ -1020,7 +1176,7 @@ _lp_fossil_branch_color() # Get the branch name of the current directory _lp_bzr_branch() { - [[ "$LP_ENABLE_BZR" != 1 ]] && return + (( LP_ENABLE_BZR )) || return # First do a simple search to avoid having to invoke bzr -- at least on my # machine, the python startup causes a noticeable hitch when changing @@ -1032,7 +1188,7 @@ _lp_bzr_branch() local branch branch="$(bzr nick 2> /dev/null)" - [[ $? -ne 0 ]] && return + (( $? != 0 )) && return _lp_escape "$branch" } @@ -1045,7 +1201,7 @@ _lp_bzr_branch() # Add the number of pending commits and the impacted lines. _lp_bzr_branch_color() { - [[ "$LP_ENABLE_BZR" != 1 ]] && return + (( LP_ENABLE_BZR )) || return # First do a simple search to avoid having to invoke bzr -- at least on my # machine, the python startup causes a noticeable hitch when changing @@ -1057,7 +1213,7 @@ _lp_bzr_branch_color() local output output="$(bzr version-info --check-clean --custom --template='{branch_nick} {revno} {clean}' 2> /dev/null)" - [[ $? -ne 0 ]] && return + (( $? != 0 )) && return $_LP_SHELL_zsh && setopt local_options && setopt sh_word_split local tuple tuple=($output) @@ -1065,16 +1221,17 @@ _lp_bzr_branch_color() local branch=${tuple[_LP_FIRST_INDEX+0]} local revno=${tuple[_LP_FIRST_INDEX+1]} local clean=${tuple[_LP_FIRST_INDEX+2]} + local ret= - if [[ -n "$branch" ]] ; then - if [[ "$clean" -eq 0 ]] ; then + if [[ -n "$branch" ]]; then + if (( clean == 0 )); then ret="${LP_COLOR_CHANGES}${branch}${NO_COL}(${LP_COLOR_COMMITS}$revno${NO_COL})" else ret="${LP_COLOR_UP}${branch}${NO_COL}(${LP_COLOR_COMMITS}$revno${NO_COL})" fi fi - echo -ne "$ret" + echo -nE "$ret" } @@ -1101,107 +1258,49 @@ case "$LP_OS" in Linux) _lp_battery() { - [[ "$LP_ENABLE_BATT" != 1 ]] && return 4 - bat=$(upower -i /org/freedesktop/UPower/devices/battery_BAT1|grep percentage|awk '{print $2}'|sed 's/%//') + (( LP_ENABLE_BATT )) || return 4 + local acpi + acpi="$(acpi --battery 2>/dev/null)" + # Extract the battery load value in percent + # First, remove the beginning of the line... + local bat="${acpi#Battery *, }" + bat="${bat%%%*}" # remove everything starting at '%' - if [[ -z "${bat}" ]] ; then - # not battery level found + if [[ -z "${bat}" ]]; then + # no battery level found return 4 - + fi + echo -nE "$bat" # discharging - elif [[ $(upower -i /org/freedesktop/UPower/devices/battery_BAT1|grep state|awk '{print $2}') == "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 - + if [[ "$acpi" == *"Discharging"* ]]; then + # under => 0, above => 1 + return $(( bat > LP_BATTERY_THRESHOLD )) # 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 + # under => 2, above => 3 + return $(( 1 + ( bat > LP_BATTERY_THRESHOLD ) )) fi -# [[ "$LP_ENABLE_BATT" != 1 ]] && return 4 -# local acpi -# acpi="$(acpi --battery 2>/dev/null)" -# # Extract the battery load value in percent -# # First, remove the beginning of the line... -# local bat="${acpi#Battery *, }" -# bat="${bat%%%*}" # remove everything starting at '%' -# -# 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 } ;; Darwin) _lp_battery() { - [[ "$LP_ENABLE_BATT" != 1 ]] && return 4 - local pmset="$(pmset -g batt | sed -n -e '/InternalBattery/p')" - local bat="$(cut -f2 <<<"$pmset")" - bat="${bat%%%*}" - case "$pmset" in - *charged* | "") + (( LP_ENABLE_BATT )) || return 4 + local percent batt_status + eval "$(pmset -g batt | sed -n 's/^ -InternalBattery[^ ]*[ ]\([0-9]*[0-9]\)%; \([^;]*\).*$/percent=\1 batt_status='\'\\2\'/p)" + case "$batt_status" in + charged | "") return 4 ;; - *discharging*) - if [[ ${bat} -le $LP_BATTERY_THRESHOLD ]] ; then - # under threshold - echo -n "${bat}" - return 0 - else - # above threshold - echo -n "${bat}" - return 1 - fi + discharging) + echo -nE "$percent" + # under => 0, above => 1 + return $(( percent > LP_BATTERY_THRESHOLD )) ;; - *) - if [[ ${bat} -le $LP_BATTERY_THRESHOLD ]] ; then - # under threshold - echo -n "${bat}" - return 2 - else - # above threshold - echo -n "${bat}" - return 3 - fi + *) # "charging", "AC attached" + echo -nE "$percent" + # under => 2, above => 3 + return $(( 1 + ( percent > LP_BATTERY_THRESHOLD ) )) ;; esac } @@ -1216,103 +1315,74 @@ esac # a red ⌁ if the battery is discharging and above threshold _lp_battery_color() { - [[ "$LP_ENABLE_BATT" != 1 ]] && return + (( LP_ENABLE_BATT )) || return local mark=$LP_MARK_BATTERY local chargingmark=$LP_MARK_ADAPTER - local bat - local ret + local -i bat ret bat="$(_lp_battery)" ret=$? - if [[ $ret == 4 || $bat == 100 ]] ; then + if (( ret == 4 || bat == 100 )); then # no battery support or battery full: nothing displayed - return - elif [[ $ret == 3 && $bat != 100 ]] ; then + : + 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 + echo -nE "${LP_COLOR_CHARGING_ABOVE}$chargingmark${NO_COL}" + elif (( ret == 2 )); then # charging but under threshold # yellow ⏚ - echo -ne "${LP_COLOR_CHARGING_UNDER}$chargingmark${NO_COL}" - return - elif [[ $ret == 1 ]] ; then + echo -nE "${LP_COLOR_CHARGING_UNDER}$chargingmark${NO_COL}" + elif (( ret == 1 )); then # discharging but above threshold # yellow ⌁ - echo -ne "${LP_COLOR_DISCHARGING_ABOVE}$mark${NO_COL}" - return - + echo -nE "${LP_COLOR_DISCHARGING_ABOVE}$mark${NO_COL}" # discharging and under threshold - elif [[ "$bat" != "" ]] ; then - ret="${LP_COLOR_DISCHARGING_UNDER}${mark}${NO_COL}" + else + local res + res="${LP_COLOR_DISCHARGING_UNDER}${mark}${NO_COL}" - if [[ "$LP_PERCENTS_ALWAYS" -eq "1" ]]; then + if (( LP_PERCENTS_ALWAYS )); then + local -i idx if (( bat <= 0 )); then - ret="${ret}${LP_COLORMAP_0}" + idx=0 elif (( bat <= 5 )); then # 5 - ret="${ret}${LP_COLORMAP_9}" + idx=9 elif (( bat <= 10 )); then # 5 - ret="${ret}${LP_COLORMAP_8}" + idx=8 elif (( bat <= 20 )); then # 10 - ret="${ret}${LP_COLORMAP_7}" + idx=7 elif (( bat <= 30 )); then # 10 - ret="${ret}${LP_COLORMAP_6}" + idx=6 elif (( bat <= 40 )); then # 10 - ret="${ret}${LP_COLORMAP_5}" + idx=5 elif (( bat <= 50 )); then # 10 - ret="${ret}${LP_COLORMAP_4}" + idx=4 elif (( bat <= 65 )); then # 15 - ret="${ret}${LP_COLORMAP_3}" + idx=3 elif (( bat <= 80 )); then # 15 - ret="${ret}${LP_COLORMAP_2}" + idx=2 elif (( bat < 100 )); then # 20 - ret="${ret}${LP_COLORMAP_1}" + idx=1 else # >= 100 - ret="${ret}${LP_COLORMAP_0}" + idx=0 fi - ret="${ret}${bat}$_LP_PERCENT" + res+="${LP_COLORMAP[idx+_LP_FIRST_INDEX]}${bat}$_LP_PERCENT${NO_COL}" fi # LP_PERCENTS_ALWAYS - echo -ne "${ret}${NO_COL}" - fi # ret + echo -nE "${res}" + fi } _lp_color_map() { # Default scale: 0..100 # Custom scale: 0..$2 - local -i scale value + local -i scale idx scale=${2:-100} - # Transform the value to a 0..100 scale - value=100*$1/scale - if (( value < 50 )); then - if (( value < 30 )); then - if (( value < 10 )); then - echo -ne "${LP_COLORMAP_0}" - elif (( value < 20 )); then - echo -ne "${LP_COLORMAP_1}" - else # 40..59 - echo -ne "${LP_COLORMAP_2}" - fi - elif (( value < 40 )); then - echo -ne "${LP_COLORMAP_3}" - else # 80..99 - echo -ne "${LP_COLORMAP_4}" - fi - elif (( value < 80 )); then - if (( value < 60 )); then - echo -ne "${LP_COLORMAP_5}" - elif (( value < 70 )); then - echo -ne "${LP_COLORMAP_6}" - else - echo -ne "${LP_COLORMAP_7}" - fi - elif (( value < 90 )) ; then - echo -ne "${LP_COLORMAP_8}" - else # (( value >= 90 )) - echo -ne "${LP_COLORMAP_9}" - fi + # Transform the value to a 0..${#COLOR_MAP} scale + idx=_LP_FIRST_INDEX+100*$1/scale/${#LP_COLORMAP[*]} + echo -nE "${LP_COLORMAP[idx]}" } ########################### @@ -1323,49 +1393,56 @@ _LP_RUNTIME_LAST_SECONDS=$SECONDS _lp_runtime() { - [[ "$LP_ENABLE_RUNTIME" != 1 ]] && return - if [[ $_LP_RUNTIME_SECONDS -ge $LP_RUNTIME_THRESHOLD ]] + if (( LP_ENABLE_RUNTIME && _LP_RUNTIME_SECONDS >= LP_RUNTIME_THRESHOLD )) then - echo -ne "${LP_COLOR_RUNTIME}" + echo -nE "${LP_COLOR_RUNTIME}" # display runtime seconds as days, hours, minutes, and seconds - [[ "$_LP_RUNTIME_SECONDS" -ge 86400 ]] && echo -ne $((_LP_RUNTIME_SECONDS / 86400))d - [[ "$_LP_RUNTIME_SECONDS" -ge 3600 ]] && echo -ne $((_LP_RUNTIME_SECONDS % 86400 / 3600))h - [[ "$_LP_RUNTIME_SECONDS" -ge 60 ]] && echo -ne $((_LP_RUNTIME_SECONDS % 3600 / 60))m - echo -ne $((_LP_RUNTIME_SECONDS % 60))s - echo -ne "${NO_COL}" + (( _LP_RUNTIME_SECONDS >= 86400 )) && echo -n $((_LP_RUNTIME_SECONDS / 86400))d + (( _LP_RUNTIME_SECONDS >= 3600 )) && echo -n $((_LP_RUNTIME_SECONDS % 86400 / 3600))h + (( _LP_RUNTIME_SECONDS >= 60 )) && echo -n $((_LP_RUNTIME_SECONDS % 3600 / 60))m + echo -n $((_LP_RUNTIME_SECONDS % 60))"s${NO_COL}" fi + : } -_lp_reset_runtime() -{ - # Compute number of seconds since program was started - _LP_RUNTIME_SECONDS=$((SECONDS - _LP_RUNTIME_LAST_SECONDS)) - - # If no proper command was executed (i.e., someone pressed enter without entering a command), - # reset the runtime counter - [ "$_LP_RUNTIME_COMMAND_EXECUTED" != 1 ] && _LP_RUNTIME_LAST_SECONDS=$SECONDS && _LP_RUNTIME_SECONDS=0 - - # A proper command has been executed if the last command was not related to Liquid Prompt - [ "$BASH_COMMAND" = _lp_set_prompt ] - _LP_RUNTIME_COMMAND_EXECUTED=$? -} - -if [ "$LP_ENABLE_RUNTIME" = 1 ] -then - if "$_LP_SHELL_zsh"; then - precmd() { - if [ $timer ]; then - export _LP_RUNTIME_SECONDS=$(($SECONDS - $timer)) - unset timer - fi +if (( LP_ENABLE_RUNTIME )); then + if $_LP_SHELL_zsh; then + _lp_runtime_before() { + _LP_RUNTIME_LAST_SECONDS=$SECONDS + } + _lp_runtime_after() { + if [[ -n "$_LP_RUNTIME_LAST_SECONDS" ]]; then + (( _LP_RUNTIME_SECONDS=SECONDS-_LP_RUNTIME_LAST_SECONDS )) + unset _LP_RUNTIME_LAST_SECONDS + fi } - preexec() { - export timer=${timer:-$SECONDS} - } + add-zsh-hook preexec _lp_runtime_before + add-zsh-hook precmd _lp_runtime_after else - # _lp_reset_runtime gets called whenever bash executes a command - trap '_lp_reset_runtime' DEBUG + _lp_runtime_before() + { + # For debugging + #echo "XXX $BASH_COMMAND" + + # If the previous command was just the refresh of the prompt, + # reset the counter + if (( _LP_RUNTIME_SKIP )); then + _LP_RUNTIME_SECONDS=-1 _LP_RUNTIME_LAST_SECONDS=$SECONDS + else + # Compute number of seconds since program was started + (( _LP_RUNTIME_SECONDS=SECONDS-_LP_RUNTIME_LAST_SECONDS )) + fi + + # If the command to run is the prompt, we'll have to ignore it + [[ "$BASH_COMMAND" != "$PROMPT_COMMAND" ]] + _LP_RUNTIME_SKIP=$? + } + + _LP_RUNTIME_SKIP=0 + # _lp_runtime_before gets called just before bash executes a command, + # including $PROMPT_COMMAND + trap _lp_runtime_before DEBUG fi fi @@ -1383,19 +1460,22 @@ _lp_load_color() # Then we have to choose the values at which the colours switch, with # anything past yellow being pretty important. - [[ "$LP_ENABLE_LOAD" != 1 ]] && return + (( LP_ENABLE_LOAD )) || return - local tmp="$(_lp_cpu_load)" - tmp=${tmp/./} # Remove '.' - tmp=${tmp#0} # Remove leading '0' - tmp=${tmp#0} # Remove leading '0', again (ex: 0.09) - local -i load=${tmp:-0}/$_lp_CPUNUM + local lp_cpu_load + # Get value (OS-specific) into lp_cpu_load + _lp_cpu_load + + lp_cpu_load=${lp_cpu_load/./} # Remove '.' + lp_cpu_load=${lp_cpu_load#0} # Remove leading '0' + lp_cpu_load=${lp_cpu_load#0} # Remove leading '0', again (ex: 0.09) + local -i load=${lp_cpu_load:-0}/$_lp_CPUNUM if (( load > LP_LOAD_THRESHOLD )); then - local ret="$(_lp_color_map $load 200)${LP_MARK_LOAD}" + local ret="$(_lp_color_map $load)${LP_MARK_LOAD}" - if [[ "$LP_PERCENTS_ALWAYS" == 1 ]]; then - ret="${ret}${load}${_LP_PERCENT}" + if (( LP_PERCENTS_ALWAYS )); then + ret+="${load}${_LP_PERCENT}" fi echo -nE "${ret}${NO_COL}" fi @@ -1405,49 +1485,77 @@ _lp_load_color() # System temperature # ###################### -_lp_temp_sensors() -{ - # Return the hottest system temperature we get through the sensors command - local i - for i in $(sensors | - sed -n -r "s/^(CPU|SYS|MB|Core|temp).*: *\+([0-9]*)\..°.*/\2/p"); do - [[ $i -gt $temperature ]] && temperature=$i - done -} - -_lp_temp_acpi() -{ - local i - for i in $(LANG=C acpi -t | sed 's/.* \(-\?[0-9]*\)\.[0-9]* degrees C$/\1/p'); do - [[ $i -gt $temperature ]] && temperature=$i - done -} - # Will set _LP_TEMP_FUNCTION so the temperature monitoring feature use an -# available command. _LP_TEMP_FUNCTION should return only a numeric value -if [[ "$LP_ENABLE_TEMP" = 1 ]]; then - if command -v acpi >/dev/null; then - _LP_TEMP_FUNCTION=_lp_temp_acpi - elif command -v sensors >/dev/null; then - _LP_TEMP_FUNCTION=_lp_temp_sensors - # elif command -v the_command_you_want_to_use; then - # _LP_TEMP_FUNCTION=your_function - else - LP_ENABLE_TEMP=0 - fi +# available command. +if (( LP_ENABLE_TEMP )); then + + # Backends for TEMP. Each backend must return the result in $temperature. + + # Implementation using lm-sensors + _lp_temp_sensors() + { + # Return the hottest system temperature we get through the sensors command + # Only the integer part is retained + local -i i + for i in $(sensors -u | + sed -n 's/^ temp[0-9][0-9]*_input: \([0-9]*\)\..*$/\1/p'); do + (( $i > ${temperature:-0} )) && temperature=i + done + } + + # Implementation using 'acpi -t' + _lp_temp_acpi() + { + local -i i + # Only the integer part is retained + for i in $(LANG=C acpi -t | + sed 's/.* \(-\?[0-9]*\)\.[0-9]* degrees C$/\1/p'); do + (( $i > ${temperature:-0} )) && temperature=i + done + } + + # Dynamic selection of backend + _lp_temp_detect() + { + local -i temperature + local cmd + + # Global variable + unset _LP_TEMP_FUNCTION + + for cmd + do + command -v $cmd >/dev/null || continue + + _LP_TEMP_FUNCTION=_lp_temp_$cmd + # Check that we can retrieve temperature at least once + $_LP_TEMP_FUNCTION 2>/dev/null + # If $temperature is set, success! + [[ -n "$temperature" ]] && return 0 + unset -f $_LP_TEMP_FUNCTION + unset _LP_TEMP_FUNCTION + done + return 1 + } + + # Try each _lp_temp method + # If no function worked, disable the feature + _lp_temp_detect acpi sensors || LP_ENABLE_TEMP=0 + unset -f _lp_temp_detect fi -_lp_temperature() { - # Will display the numeric value as we got it through the _LP_TEMP_FUNCTION - # and colorize it through _lp_color_map. - [[ "$LP_ENABLE_TEMP" != 1 ]] && return - local temperature +# Will display the numeric value as we get through the _LP_TEMP_FUNCTION +# and colorize it through _lp_color_map. +_lp_temperature() +{ + (( LP_ENABLE_TEMP )) || return + + local -i temperature temperature=0 $_LP_TEMP_FUNCTION - if [[ $temperature -ge $LP_TEMP_THRESHOLD ]]; then - echo -ne "${LP_MARK_TEMP}$(_lp_color_map $temperature 120)$temperature°${NO_COL}" - fi + (( temperature >= LP_TEMP_THRESHOLD )) && \ + echo -nE "${LP_MARK_TEMP}$(_lp_color_map $temperature 120)$temperature°${NO_COL}" } ########## @@ -1455,23 +1563,30 @@ _lp_temperature() { ########## -# Sed expression using extended regexp to remove shell codes around terminal -# escape sequences -_LP_CLEAN_ESC="$(printf "s,%q|%q,,g" "$_LP_OPEN_ESC" "$_LP_CLOSE_ESC")" +# Sed expression using extended regexp to match terminal +# escape sequences with their wrappers +if $_LP_SHELL_bash; then + _LP_CLEAN_ESC='\\\[([^\]+|\\[^]])*\\\]' +else + _LP_CLEAN_ESC='%\{([^%]+|%[^}])*%\}' +fi # Remove all colors and escape characters of the given string and return a pure text _lp_as_text() { - # Remove colors from the computed prompt - echo -n "$1" | sed -$_LP_SED_EXTENDED "s/\x1B\[[0-9;]*[mK]//g;$_LP_CLEAN_ESC" + # Remove all terminal sequences that we wrapped with $_LP_OPEN_ESC and + # $_LP_CLOSE_ESC. + echo -nE "$1" | sed -$_LP_SED_EXTENDED "s,$_LP_CLEAN_ESC,,g" } _lp_title() { - [[ "$LP_ENABLE_TITLE" != "1" ]] && return + (( LP_ENABLE_TITLE )) || return # Get the current computed prompt as pure text - echo -n "${_LP_OPEN_ESC}${LP_TITLE_OPEN}$(_lp_as_text "$1")${LP_TITLE_CLOSE}${_LP_CLOSE_ESC}" + echo -nE "${_LP_OPEN_ESC}${LP_TITLE_OPEN}" + _lp_as_text "$1" + echo -nE "${LP_TITLE_CLOSE}${_LP_CLOSE_ESC}" } # Set the prompt mark to ± if git, to ☿ if mercurial, to ‡ if subversion @@ -1490,75 +1605,76 @@ _lp_smart_mark() disabled) mark="$LP_MARK_DISABLED" ;; *) mark="$LP_MARK_DEFAULT" ;; esac - echo -ne "${LP_COLOR_MARK}${mark}${NO_COL}" + echo -nE "${mark}${NO_COL}" } # insert a space on the right _lp_sr() { - [[ -n "$1" ]] && echo -n "$1 " + [[ -n "$1" ]] && echo -nE "$1 " } # insert a space on the left _lp_sl() { - [[ -n "$1" ]] && echo -n " $1" + [[ -n "$1" ]] && echo -nE " $1" } # insert two space, before and after _lp_sb() { - [[ -n "$1" ]] && echo -n " $1 " + [[ -n "$1" ]] && echo -nE " $1 " } ################### # CURRENT TIME # ################### -_lp_time_analog() -{ - # get the date as "hours(12) minutes" in a single call - # make a bash array with it - local -a d - d=( $(date "+%I %M") ) - # separate hours and minutes - local -i hour=${d[_LP_FIRST_INDEX+0]#0} # no leading 0 - local -i min=${d[_LP_FIRST_INDEX+1]#0} - # The targeted unicode characters are the "CLOCK FACE" ones - # They are located in the codepages between: - # U+1F550 (ONE OCLOCK) and U+1F55B (TWELVE OCLOCK), for the plain hours - # U+1F55C (ONE-THIRTY) and U+1F567 (TWELVE-THIRTY), for the thirties - # +# LP_TIME is set colored, with a space on the right side +if (( LP_ENABLE_TIME )); then + if (( LP_TIME_ANALOG )); then + typeset -i _LP_CLOCK_PREV=-1 + # The targeted unicode characters are the "CLOCK FACE" ones + # They are located in the codepages between: + # U+1F550 (ONE OCLOCK) and U+1F55B (TWELVE OCLOCK), for the plain hours + # U+1F55C (ONE-THIRTY) and U+1F567 (TWELVE-THIRTY), for the thirties + # Generated with: + # perl -C -E 'say join("", map {chr(0x1F550+$_)." ".chr(0x1F55C+$_)." "} 0..11)' + _LP_CLOCK=(🕐 🕜 🕑 🕝 🕒 🕞 🕓 🕟 🕔 🕠 🕕 🕡 🕖 🕢 🕗 🕣 🕘 🕤 🕙 🕥 🕚 🕦 🕛 🕧 ) - local -a plain - plain=(🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚 🕛 ) - local -a half - half=(🕜 🕝 🕞 🕟 🕠 🕡 🕢 🕣 🕤 🕥 🕦 🕧 ) - - # "date %I" returns a number between 1 and 12 and we want 12 to be 0. - local -i hi=$(( hour % 12)) - - # add a space for correct alignment - if (( min < 15 )) ; then - echo -n "${plain[hi]} " - elif (( min < 45 )) ; then - echo -n "${half[hi]} " + _lp_time() + { + # %I: "00".."12" %M: "00".."59" + # Bash interprets a '0' prefix as octal + # so we have to clean that + local hhmm="$(date "+hh=%I mm=%M")" + # hh: 1..12 mm: 0..59 + local -i hh mm clock + eval ${hhmm//=0/=} # Line split for zsh + # clock: 0 .. 25 + # 1:00..1:14 -> 0 + # 1:15..1:44 -> 1 + # 1:45..2:15 -> 2 + # ... + # 12:15..12:44 -> 23 + # 12:45..12:59 -> 0 + if (( ( clock=((hh*60+mm-45)/30)%24 ) != _LP_CLOCK_PREV )); then + # There is a space just after the clock char because the glyph + # width is twice usual glyphs + LP_TIME="${LP_COLOR_TIME}${_LP_CLOCK[clock+_LP_FIRST_INDEX]} ${NO_COL} " + _LP_CLOCK_PREV=clock + fi + } else - echo -n "${plain[hi+1]} " + # Never changes + LP_TIME="${LP_COLOR_TIME}${_LP_TIME_SYMBOL}${NO_COL} " + _lp_time() { : ; } fi -} +else + LP_TIME="" + _lp_time() { : ; } +fi -_lp_time() -{ - [[ "$LP_ENABLE_TIME" != 1 ]] && return - if [[ "$LP_TIME_ANALOG" != 1 ]]; then - echo -n "${LP_COLOR_TIME}${_LP_TIME_SYMBOL}${NO_COL}" - else - echo -n "${LP_COLOR_TIME}" - _lp_time_analog - echo -n "${NO_COL}" - fi -} ######################## # Construct the prompt # @@ -1579,37 +1695,39 @@ _lp_set_prompt() # Reset IFS to its default value to avoid strange behaviors # (in case the user is playing with the value at the prompt) local IFS="$_LP_IFS" + local GREP_OPTIONS= - # execute the old prompt - if $_LP_SHELL_bash; then - eval "$LP_OLD_PROMPT_COMMAND" - else # zsh - eval "${${LP_OLD_PROMPT_COMMAND#*$'\n'}%$'\n'*}" - fi + # bash: execute the old prompt hook + eval "$LP_OLD_PROMPT_COMMAND" # left of main prompt: space at right LP_JOBS="$(_lp_sr "$(_lp_jobcount_color)")" LP_TEMP="$(_lp_sr "$(_lp_temperature)")" LP_LOAD="$(_lp_sr "$(_lp_load_color)")" LP_BATT="$(_lp_sr "$(_lp_battery_color)")" - LP_TIME="$(_lp_sr "$(_lp_time)")" + _lp_time + _lp_sudo_check # in main prompt: no space - if [[ "$LP_ENABLE_PROXY,$http_proxy" = 1,?* ]] ; then + if [[ "$LP_ENABLE_PROXY,${http_proxy-}" = 1,?* ]]; then LP_PROXY="$LP_COLOR_PROXY$LP_MARK_PROXY$NO_COL" else LP_PROXY= fi # Display the current Python virtual environment, if available - if [[ "$LP_ENABLE_VIRTUALENV,$VIRTUAL_ENV" = 1,?* ]] ; then - LP_VENV=" [${LP_COLOR_VIRTUALENV}${VIRTUAL_ENV##*/}${NO_COL}]" + if [[ "$LP_ENABLE_VIRTUALENV,${VIRTUAL_ENV-}${CONDA_DEFAULT_ENV-}" = 1,?* ]]; then + if [[ -n "${VIRTUAL_ENV-}" ]]; then + LP_VENV=" [${LP_COLOR_VIRTUALENV}${VIRTUAL_ENV##*/}${NO_COL}]" + else + LP_VENV=" [${LP_COLOR_VIRTUALENV}${CONDA_DEFAULT_ENV##*/}${NO_COL}]" + fi else LP_VENV= fi # Display the current software collections enabled, if available - if [[ "$LP_ENABLE_SCLS,$X_SCLS" = 1,?* ]] ; then + if [[ "$LP_ENABLE_SCLS,${X_SCLS-}" = 1,?* ]]; then LP_SCLS=" [${LP_COLOR_VIRTUALENV}${X_SCLS%"${X_SCLS##*[![:space:]]}"}${NO_COL}]" else LP_SCLS= @@ -1618,7 +1736,7 @@ _lp_set_prompt() LP_RUNTIME=$(_lp_sl "$(_lp_runtime)") # if change of working directory - if [[ "$LP_OLD_PWD" != "LP:$PWD" ]]; then + if [[ "${LP_OLD_PWD-}" != "LP:$PWD" ]]; then # Update directory icon for MacOS X $_LP_TERM_UPDATE_DIR @@ -1629,7 +1747,7 @@ _lp_set_prompt() # LP_PERM: shows a ":" # - colored in green if user has write permission on the current dir # - colored in red if not - if [[ "$LP_ENABLE_PERM" = 1 ]]; then + if (( LP_ENABLE_PERM )); then if [[ -w "${PWD}" ]]; then LP_PERM="${LP_COLOR_WRITE}:${NO_COL}" else @@ -1644,7 +1762,7 @@ _lp_set_prompt() LP_VCS_TYPE="git" if [[ -n "$LP_VCS" ]]; then # If this is a vcsh repository - if [[ -n "$VCSH_DIRECTORY" ]]; then + if [[ -n "${VCSH_DIRECTORY-}" ]]; then LP_VCS_TYPE="git-vcsh" fi # If this is a git-svn repository @@ -1677,7 +1795,7 @@ _lp_set_prompt() LP_VCS_TYPE="disabled" fi - if [[ -z "$LP_VCS_TYPE" ]] ; then + if [[ -z "$LP_VCS_TYPE" ]]; then LP_VCS="" else LP_VCS="$(_lp_sl "${LP_VCS}")" @@ -1686,9 +1804,6 @@ _lp_set_prompt() # end of the prompt line: double spaces LP_MARK="$(_lp_sr "$(_lp_smart_mark $LP_VCS_TYPE)")" - # The color is different if user is root - LP_PWD="${LP_COLOR_PATH}${LP_PWD}${NO_COL}" - LP_OLD_PWD="LP:$PWD" # if do not change of working directory but... @@ -1704,7 +1819,7 @@ _lp_set_prompt() esac fi - if [[ -f "$LP_PS1_FILE" ]]; then + if [[ -f "${LP_PS1_FILE-}" ]]; then source "$LP_PS1_FILE" fi @@ -1713,22 +1828,23 @@ _lp_set_prompt() if [[ -z "$LP_PS1" ]] ; then # add title, host, and permissions colon PS1="${LP_PS1_PREFIX}${LP_JOBS}${LP_BRACKET_OPEN}${LP_USER}${LP_HOST}${LP_PERM}" - # Add current directory, software collections, virtual enviornment, and proxy PS1="${PS1}${LP_PWD}${LP_BRACKET_CLOSE}${LP_SCLS}${LP_VENV}${LP_PROXY}" - # Add VCS infos # If root, the info has not been collected unless LP_ENABLE_VCS_ROOT # is set. - PS1="${PS1}${LP_VCS}" + PS1+="${LP_VCS}" # add return code and prompt mark - PS1="${PS1}${LP_RUNTIME}${LP_ERR}${LP_MARK_PREFIX}${LP_MARK}${LP_PS1_POSTFIX}" + PS1+="${LP_RUNTIME}${LP_ERR}${LP_MARK_PREFIX}${LP_COLOR_MARK}${LP_MARK}${LP_PS1_POSTFIX}" # "invisible" parts # Get the current prompt on the fly and make it a title LP_TITLE="$(_lp_title "$PS1")" + # Insert it in the prompt + PS1="${LP_TITLE}${PS1}" + # Insert it in the prompt PS1="${LP_TITLE}${PS1}" [[ $LP_ENABLE_OHMYGIT = 1 ]] && PS1="$(build_prompt)$PS1" @@ -1766,14 +1882,6 @@ _lp_set_prompt() # Insert it in the prompt PS1="${LP_TITLE}${PS1}" [[ $LP_ENABLE_OHMYGIT = 1 ]] && PS1="$(build_prompt)$PS1" - - # 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 - [[ $LP_ENABLE_OHMYGIT = 1 ]] && PS1="$(build_prompt)$PS1" fi fi } @@ -1786,32 +1894,56 @@ prompt_tag() # Activate Liquid Prompt prompt_on() { + # Reset so all PWD dependent variables are computed after loading + LP_OLD_PWD="" + # if Liquid Prompt has not been already set - if [[ -z "$LP_OLD_PS1" ]] ; then + if [[ -z "${LP_OLD_PS1-}" ]]; then LP_OLD_PS1="$PS1" if $_LP_SHELL_bash; then LP_OLD_PROMPT_COMMAND="$PROMPT_COMMAND" - LP_OLD_SHOPT="$(shopt -p promptvars)" + _LP_OLD_SHOPT="$(shopt -p promptvars)" else # zsh - LP_OLD_PROMPT_COMMAND="$(whence -f precmd)" + LP_OLD_PROMPT_COMMAND="" + _LP_ZSH_PROMPT_THEME="" + if [[ -n "$prompt_theme" && "$prompt_theme" != off ]]; then + _LP_ZSH_PROMPT_THEME="$prompt_theme" + # Disable the prompt to disable its precmd hook + prompt off + fi + _LP_OLD_SETOPT=() + # Dump option names: echo ${(ko)options} + for o in promptpercent promptbang promptsubst + do + if [[ "${options[$o]}" = on ]]; then + _LP_OLD_SETOPT+=$o + else + _LP_OLD_SETOPT+=no$o + fi + done fi fi if $_LP_SHELL_bash; then - shopt -s promptvars + # Disable parameter/command expansion from PS1 + shopt -u promptvars PROMPT_COMMAND=_lp_set_prompt - [[ "$LP_DEBUG_TIME" == 1 ]] && PROMPT_COMMAND="time $PROMPT_COMMAND" + (( LP_DEBUG_TIME )) && PROMPT_COMMAND="time $PROMPT_COMMAND" || true else # zsh - # That doesn't seem to work: no time output - #if [[ "$LP_DEBUG_TIME" == 1 ]]; then - # function precmd { + [[ -n "$_LP_ZSH_HOOK" ]] && add-zsh-hook -d precmd $_LP_ZSH_HOOK + # Set options that affect PS1 evaluation + # Disable parameter/command expansion; enable percent expansion + setopt promptpercent nopromptbang nopromptsubst + # 'time' doesn't seem to work on shell functions: no time output + #if (( LP_DEBUG_TIME )); then + # _lp_main_precmd() { # local TIMEFMT='Liquid Prompt build time: %*E' # time _lp_set_prompt # } + # _LP_ZSH_HOOK=_lp_main_precmd #else - function precmd { - _lp_set_prompt - } + _LP_ZSH_HOOK=_lp_set_prompt #fi + add-zsh-hook precmd $_LP_ZSH_HOOK fi } @@ -1820,28 +1952,29 @@ prompt_off() { PS1=$LP_OLD_PS1 if $_LP_SHELL_bash; then - eval "$LP_OLD_SHOPT" + eval "$_LP_OLD_SHOPT" PROMPT_COMMAND="$LP_OLD_PROMPT_COMMAND" else # zsh - precmd() { : ; } - eval "$LP_OLD_PROMPT_COMMAND" + add-zsh-hook -d precmd $_LP_ZSH_HOOK + setopt ${_LP_OLD_SETOPT} + (( ${#_LP_ZSH_PROMPT_THEME} )) && prompt $_LP_ZSH_PROMPT_THEME fi } # Use an empty prompt: just the \$ mark prompt_OFF() { - PS1="\$ " + PS1="$_LP_MARK_SYMBOL " if $_LP_SHELL_bash; then shopt -u promptvars PROMPT_COMMAND="$LP_OLD_PROMPT_COMMAND" else # zsh - precmd() { : ; } - eval "$LP_OLD_PROMPT_COMMAND" + add-zsh-hook -d precmd $_LP_ZSH_HOOK + setopt promptpercent nopromptbang nopromptsubst fi } # By default, sourcing liquidprompt will activate Liquid Prompt prompt_on -# vim: set et sts=4 sw=4 tw=120 ft=bash syn=sh: +# vim: set et sts=4 sw=4 tw=120 ft=sh: diff --git a/liquidpromptrc-dist b/liquidpromptrc-dist index 866a598..aa56c20 100644 --- a/liquidpromptrc-dist +++ b/liquidpromptrc-dist @@ -35,8 +35,12 @@ LP_PATH_KEEP=2 # Do you want to display the hostname, even if not connected through network? # Defaults to 0 (do not display hostname when locally connected) # set to 1 if you want to always see the hostname +# set to -1 if you want to never see the hostname LP_HOSTNAME_ALWAYS=0 +# Use the FQDN instead of the short hostname if the hostname is displayed +LP_ENABLE_FQDN=0 + # Do you want to display the user, even if the user is the same as the one logged in? # Defaults to 1 (always display the user) # set to 0 if you want to hide the logged user (it will always display different users) @@ -71,6 +75,11 @@ LP_ENABLE_LOAD=1 # Recommended value is 1 LP_ENABLE_BATT=1 +# Do you want to use the 'sudo credentials' feature? +# Be warned that this may pollute the syslog if you don't have sudo +# credentials, and the sysadmin will hate you. +LP_ENABLE_SUDO=0 + # Do you want to use VCS features with the root account? # Recommended value is 0 LP_ENABLE_VCS_ROOT=0 diff --git a/pmset-simulator b/pmset-simulator new file mode 100644 index 0000000..ccd2e2d --- /dev/null +++ b/pmset-simulator @@ -0,0 +1,48 @@ + +# Simulator for "pmset -g batt" for testing the implementation of +# battery display on MacOS X + +pmset() +{ + case "$pmset_sim" in + iMac|no-battery) + # https://github.com/nojhan/liquidprompt/issues/315 + cat <