summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTuowen Zhao <ztuowen@gmail.com>2021-01-18 13:16:40 -0700
committerTuowen Zhao <ztuowen@gmail.com>2021-01-18 13:16:40 -0700
commitc6e754a3119b7273a57f0cfed38e85303662d26b (patch)
treec50ae3c6b0271ec88e964d3a57199ea37e63bf0b
parentfb45741fc1dbd40dd2be72bc35a28c6ee8f3f7a5 (diff)
parentefcbd9f3480a28ec69c607c46adcbfd8d230ac9f (diff)
downloadzsh-c6e754a3119b7273a57f0cfed38e85303662d26b.tar.gz
zsh-c6e754a3119b7273a57f0cfed38e85303662d26b.tar.bz2
zsh-c6e754a3119b7273a57f0cfed38e85303662d26b.zip
Merge remote-tracking branch 'origin/master'
-rw-r--r--.github/CODEOWNERS3
-rw-r--r--lib/cli.zsh36
-rw-r--r--lib/functions.zsh2
-rw-r--r--lib/git.zsh4
-rw-r--r--lib/termsupport.zsh2
-rw-r--r--plugins/archlinux/archlinux.plugin.zsh4
-rw-r--r--plugins/brew/README.md22
-rw-r--r--plugins/brew/brew.plugin.zsh2
-rw-r--r--plugins/colorize/colorize.plugin.zsh2
-rw-r--r--plugins/debian/debian.plugin.zsh4
-rw-r--r--plugins/docker/_docker15
-rwxr-xr-xplugins/genpass/genpass-xkcd2
-rw-r--r--plugins/git-prompt/git-prompt.plugin.zsh12
-rw-r--r--plugins/git-prompt/gitstatus.py20
-rw-r--r--plugins/git/README.md1
-rw-r--r--plugins/git/git.plugin.zsh1
-rw-r--r--plugins/grc/README.md28
-rw-r--r--plugins/grc/grc.plugin.zsh49
-rw-r--r--plugins/jake-node/jake-node.plugin.zsh2
-rw-r--r--plugins/last-working-dir/README.md28
-rw-r--r--plugins/last-working-dir/last-working-dir.plugin.zsh14
-rw-r--r--plugins/macports/_port1
-rw-r--r--plugins/nvm/README.md8
-rw-r--r--plugins/term_tab/README16
-rw-r--r--plugins/term_tab/term_tab.plugin.zsh41
-rw-r--r--plugins/universalarchive/README.md46
-rw-r--r--plugins/universalarchive/_universalarchive6
-rw-r--r--plugins/universalarchive/universalarchive.plugin.zsh70
-rw-r--r--plugins/vi-mode/README.md84
-rw-r--r--plugins/vi-mode/vi-mode.plugin.zsh117
-rw-r--r--plugins/zbell/README.md30
-rw-r--r--plugins/zbell/zbell.plugin.zsh83
-rw-r--r--templates/zshrc.zsh-template2
-rw-r--r--themes/essembeh.zsh-theme60
-rwxr-xr-xtools/changelog.sh4
-rwxr-xr-xtools/upgrade.sh8
36 files changed, 648 insertions, 181 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index b091f5d89..e307e4be8 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,7 +1,8 @@
# Plugin owners
plugins/aws/ @maksyms
plugins/genpass/ @atoponce
-plugins/git-lfs/ @vietduc01100001
+plugins/git-lfs/ @hellovietduc
plugins/gitfast/ @felipec
plugins/sdk/ @rgoldberg
+plugins/universalarchive/ @Konfekt
plugins/wp-cli/ @joshmedeski
diff --git a/lib/cli.zsh b/lib/cli.zsh
index 92d447a8e..3346d3973 100644
--- a/lib/cli.zsh
+++ b/lib/cli.zsh
@@ -37,7 +37,7 @@ function _omz {
changelog) local -a refs
refs=("${(@f)$(command git for-each-ref --format="%(refname:short):%(subject)" refs/heads refs/tags)}")
_describe 'command' refs ;;
- plugin) subcmds=('list:List plugins')
+ plugin) subcmds=('info:Get plugin information' 'list:List plugins')
_describe 'command' subcmds ;;
pr) subcmds=('test:Test a Pull Request' 'clean:Delete all Pull Request branches')
_describe 'command' subcmds ;;
@@ -46,6 +46,8 @@ function _omz {
esac
elif (( CURRENT == 4 )); then
case "$words[2]::$words[3]" in
+ plugin::info) compadd "$ZSH"/plugins/*/README.md(.N:h:t) \
+ "$ZSH_CUSTOM"/plugins/*/README.md(.N:h:t) ;;
theme::use) compadd "$ZSH"/themes/*.zsh-theme(.N:t:r) \
"$ZSH_CUSTOM"/**/*.zsh-theme(.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::) ;;
esac
@@ -143,6 +145,7 @@ Usage: omz plugin <command> [options]
Available commands:
+ info <plugin> Get information of a plugin
list List all available Oh My Zsh plugins
EOF
@@ -155,6 +158,29 @@ EOF
_omz::plugin::$command "$@"
}
+function _omz::plugin::info {
+ if [[ -z "$1" ]]; then
+ echo >&2 "Usage: omz plugin info <plugin>"
+ return 1
+ fi
+
+ local readme
+ for readme in "$ZSH_CUSTOM/plugins/$1/README.md" "$ZSH/plugins/$1/README.md"; do
+ if [[ -f "$readme" ]]; then
+ (( ${+commands[less]} )) && less "$readme" || cat "$readme"
+ return 0
+ fi
+ done
+
+ if [[ -d "$ZSH_CUSTOM/plugins/$1" || -d "$ZSH/plugins/$1" ]]; then
+ _omz::log error "the '$1' plugin doesn't have a README file"
+ else
+ _omz::log error "'$1' plugin not found"
+ fi
+
+ return 1
+}
+
function _omz::plugin::list {
local -a custom_plugins builtin_plugins
custom_plugins=("$ZSH_CUSTOM"/plugins/*(-/N:t))
@@ -333,8 +359,8 @@ EOF
function _omz::theme::list {
local -a custom_themes builtin_themes
- custom_themes=("$ZSH_CUSTOM"/**/*.zsh-theme(.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::))
- builtin_themes=("$ZSH"/themes/*.zsh-theme(.N:t:r))
+ custom_themes=("$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::))
+ builtin_themes=("$ZSH"/themes/*.zsh-theme(-.N:t:r))
# If the command is being piped, print all found line by line
if [[ ! -t 1 ]]; then
@@ -391,7 +417,9 @@ function _omz::update {
# Restart the zsh session
if [[ $ret -eq 0 && "$1" != --unattended ]]; then
+ # Old zsh versions don't have ZSH_ARGZERO
+ local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}"
# Check whether to run a login shell
- [[ "$ZSH_ARGZERO" = -* ]] && exec -l "${ZSH_ARGZERO#-}" || exec "$ZSH_ARGZERO"
+ [[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh"
fi
}
diff --git a/lib/functions.zsh b/lib/functions.zsh
index 7beb62ad9..c4340f16c 100644
--- a/lib/functions.zsh
+++ b/lib/functions.zsh
@@ -1,7 +1,7 @@
function zsh_stats() {
fc -l 1 \
| awk '{ CMD[$2]++; count++; } END { for (a in CMD) print CMD[a] " " CMD[a]*100/count "% " a }' \
- | grep -v "./" | sort -nr | head -n20 | column -c3 -s " " -t | nl
+ | grep -v "./" | sort -nr | head -20 | column -c3 -s " " -t | nl
}
function uninstall_oh_my_zsh() {
diff --git a/lib/git.zsh b/lib/git.zsh
index 157c85062..c9363274c 100644
--- a/lib/git.zsh
+++ b/lib/git.zsh
@@ -51,7 +51,7 @@ function parse_git_dirty() {
FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}"
;;
esac
- STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -n1)
+ STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -1)
fi
if [[ -n $STATUS ]]; then
echo "$ZSH_THEME_GIT_PROMPT_DIRTY"
@@ -170,7 +170,7 @@ function git_prompt_status() {
'\?\? ' 'UNTRACKED'
'A ' 'ADDED'
'M ' 'ADDED'
- 'MM ' 'ADDED'
+ 'MM ' 'MODIFIED'
' M ' 'MODIFIED'
'AM ' 'MODIFIED'
' T ' 'MODIFIED'
diff --git a/lib/termsupport.zsh b/lib/termsupport.zsh
index 778f12bca..33451ef1f 100644
--- a/lib/termsupport.zsh
+++ b/lib/termsupport.zsh
@@ -10,7 +10,7 @@ function title {
emulate -L zsh
setopt prompt_subst
- [[ "$EMACS" == *term* ]] && return
+ [[ "$INSIDE_EMACS" == *term* ]] && return
# if $2 is unset use $1 as default
# if it is set and empty, leave it as is
diff --git a/plugins/archlinux/archlinux.plugin.zsh b/plugins/archlinux/archlinux.plugin.zsh
index c72e06dc2..32f09cef9 100644
--- a/plugins/archlinux/archlinux.plugin.zsh
+++ b/plugins/archlinux/archlinux.plugin.zsh
@@ -188,8 +188,8 @@ function pacdisowned() {
}
function pacmanallkeys() {
- curl -s https://www.archlinux.org/people/{developers,trustedusers}/ | \
- awk -F\" '(/pgp.mit.edu/) { sub(/.*search=0x/,""); print $1}' | \
+ curl -sL https://www.archlinux.org/people/{developers,trusted-users}/ | \
+ awk -F\" '(/keyserver.ubuntu.com/) { sub(/.*search=0x/,""); print $1}' | \
xargs sudo pacman-key --recv-keys
}
diff --git a/plugins/brew/README.md b/plugins/brew/README.md
index b714b7ac0..bf952bf01 100644
--- a/plugins/brew/README.md
+++ b/plugins/brew/README.md
@@ -10,17 +10,17 @@ plugins=(... brew)
## Aliases
-| Alias | Command | Description |
-|----------|------------------------------------------------------------- |---------------------------------------------------------------------|
-| `brewp` | `brew pin` | Pin a specified formula so that it's not upgraded. |
-| `brews` | `brew list -1` | List installed formulae or the installed files for a given formula. |
-| `brewsp` | `brew list --pinned` | List pinned formulae, or show the version of a given formula. |
-| `bubo` | `brew update && brew outdated` | Update Homebrew data, then list outdated formulae and casks. |
-| `bubc` | `brew upgrade && brew cleanup` | Upgrade outdated formulae and casks, then run cleanup. |
-| `bubu` | `bubo && bubc` | Do the last two operations above. |
-| `buf` | `brew upgrade --formula` | Upgrade only formulas (not casks). |
-| `bcubo` | `brew update && brew outdated --cask` | Update Homebrew data, then list outdated casks. |
-| `bcubc` | `brew cask reinstall $(brew outdated --cask) && brew cleanup` | Update outdated casks, then run cleanup. |
+| Alias | Command | Description |
+|----------|---------------------------------------|---------------------------------------------------------------------|
+| `brewp` | `brew pin` | Pin a specified formula so that it's not upgraded. |
+| `brews` | `brew list -1` | List installed formulae or the installed files for a given formula. |
+| `brewsp` | `brew list --pinned` | List pinned formulae, or show the version of a given formula. |
+| `bubo` | `brew update && brew outdated` | Update Homebrew data, then list outdated formulae and casks. |
+| `bubc` | `brew upgrade && brew cleanup` | Upgrade outdated formulae and casks, then run cleanup. |
+| `bubu` | `bubo && bubc` | Do the last two operations above. |
+| `buf` | `brew upgrade --formula` | Upgrade only formulas (not casks). |
+| `bcubo` | `brew update && brew outdated --cask` | Update Homebrew data, then list outdated casks. |
+| `bcubc` | `brew upgrade --cask && brew cleanup` | Update outdated casks, then run cleanup. |
## Completion
diff --git a/plugins/brew/brew.plugin.zsh b/plugins/brew/brew.plugin.zsh
index 30eb135bb..532dd9be7 100644
--- a/plugins/brew/brew.plugin.zsh
+++ b/plugins/brew/brew.plugin.zsh
@@ -6,4 +6,4 @@ alias bubc='brew upgrade && brew cleanup'
alias bubu='bubo && bubc'
alias buf='brew upgrade --formula'
alias bcubo='brew update && brew outdated --cask'
-alias bcubc='brew cask reinstall $(brew outdated --cask) && brew cleanup'
+alias bcubc='brew upgrade --cask && brew cleanup'
diff --git a/plugins/colorize/colorize.plugin.zsh b/plugins/colorize/colorize.plugin.zsh
index cb5ac36f5..8ea98f80a 100644
--- a/plugins/colorize/colorize.plugin.zsh
+++ b/plugins/colorize/colorize.plugin.zsh
@@ -96,7 +96,7 @@ colorize_less() {
# which assumes that his LESSOPEN has been executed.
local LESSCLOSE=""
- LESS="$LESS" LESSOPEN="$LESSOPEN" LESSCLOSE="$LESSCLOSE" less "$@"
+ LESS="$LESS" LESSOPEN="$LESSOPEN" LESSCLOSE="$LESSCLOSE" command less "$@"
}
if [ -t 0 ]; then
diff --git a/plugins/debian/debian.plugin.zsh b/plugins/debian/debian.plugin.zsh
index 68c6df1ae..108396784 100644
--- a/plugins/debian/debian.plugin.zsh
+++ b/plugins/debian/debian.plugin.zsh
@@ -66,7 +66,7 @@ if [[ $use_sudo -eq 1 ]]; then
alias di="sudo dpkg -i"
# Remove ALL kernel images and headers EXCEPT the one in use
- alias kclean='sudo aptitude remove -P ?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))'
+ alias kclean='sudo aptitude remove -P "?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))"'
# commands using su #########
@@ -105,7 +105,7 @@ else
alias di='su -lc "dpkg -i" root'
# Remove ALL kernel images and headers EXCEPT the one in use
- alias kclean='su -lc "aptitude remove -P ?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))" root'
+ alias kclean='su -lc "aptitude remove -P \"?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))\"" root'
fi
# Completion ################################################################
diff --git a/plugins/docker/_docker b/plugins/docker/_docker
index 10c19e233..7fe204313 100644
--- a/plugins/docker/_docker
+++ b/plugins/docker/_docker
@@ -624,7 +624,8 @@ __docker_container_subcommand() {
"($help)--entrypoint=[Overwrite the default entrypoint of the image]:entry point: "
"($help)*--env-file=[Read environment variables from a file]:environment file:_files"
"($help)*--expose=[Expose a port from the container without publishing it]: "
- "($help)*--group=[Set one or more supplementary user groups for the container]:group:_groups"
+ "($help)*--gpus=[GPU devices to add to the container ('all' to pass all GPUs)]:device: "
+ "($help)*--group-add=[Set one or more supplementary user groups for the container]:group:_groups"
"($help -h --hostname)"{-h=,--hostname=}"[Container host name]:hostname:_hosts"
"($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]"
"($help)--init[Run an init inside the container that forwards signals and reaps processes]"
@@ -750,6 +751,7 @@ __docker_container_subcommand() {
$opts_attach_exec_run_start \
"($help -d --detach)"{-d,--detach}"[Detached mode: leave the container running in the background]" \
"($help)*"{-e=,--env=}"[Set environment variables]:environment variable: " \
+ "($help)*--env-file=[Read environment variables from a file]:environment file:_files" \
"($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]" \
"($help)--privileged[Give extended Linux capabilities to the command]" \
"($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]" \
@@ -791,7 +793,7 @@ __docker_container_subcommand() {
"($help -f --follow)"{-f,--follow}"[Follow log output]" \
"($help -s --since)"{-s=,--since=}"[Show logs since this timestamp]:timestamp: " \
"($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \
- "($help)--tail=[Output the last K lines]:lines:(1 10 20 50 all)" \
+ "($help -n --tail)"{-n=,--tail=}"[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \
"($help -)*:containers:__docker_complete_containers" && ret=0
;;
(ls|list)
@@ -1018,6 +1020,7 @@ __docker_image_subcommand() {
"($help)*--shm-size=[Size of '/dev/shm' (format is '<number><unit>')]:shm size: " \
"($help)--squash[Squash newly built layers into a single new layer]" \
"($help -t --tag)*"{-t=,--tag=}"[Repository, name and tag for the image]: :__docker_complete_repositories_with_tags" \
+ "($help)--target=[Set the target build stage to build.]" \
"($help)*--ulimit=[ulimit options]:ulimit: " \
"($help)--userns=[Container user namespace]:user namespace:(host)" \
"($help -):path or URL:_directories" && ret=0
@@ -1958,6 +1961,8 @@ __docker_service_subcommand() {
opts_help=("(: -)--help[Print usage]")
opts_create_update=(
+ "($help)*--cap-add=[Add Linux capabilities]:capability: "
+ "($help)*--cap-drop=[Drop Linux capabilities]:capability: "
"($help)*--constraint=[Placement constraints]:constraint: "
"($help)--endpoint-mode=[Placement constraints]:mode:(dnsrr vip)"
"($help)*"{-e=,--env=}"[Set environment variables]:env: "
@@ -1970,6 +1975,7 @@ __docker_service_subcommand() {
"($help)*--label=[Service labels]:label: "
"($help)--limit-cpu=[Limit CPUs]:value: "
"($help)--limit-memory=[Limit Memory]:value: "
+ "($help)--limit-pids[Limit maximum number of processes (default 0 = unlimited)]"
"($help)--log-driver=[Logging driver for service]:logging driver:__docker_complete_log_drivers"
"($help)*--log-opt=[Logging driver options]:log driver options:__docker_complete_log_options"
"($help)*--mount=[Attach a filesystem mount to the service]:mount: "
@@ -2012,6 +2018,7 @@ __docker_service_subcommand() {
"($help)*--dns-option=[Set DNS options]:DNS option: " \
"($help)*--dns-search=[Set custom DNS search domains]:DNS search: " \
"($help)*--env-file=[Read environment variables from a file]:environment file:_files" \
+ "($help)*--group=[Set one or more supplementary user groups for the container]:group: _groups " \
"($help)--mode=[Service Mode]:mode:(global replicated)" \
"($help)--name=[Service name]:name: " \
"($help)*--placement-pref=[Add a placement preference]:pref:__docker_service_complete_placement_pref" \
@@ -2035,7 +2042,7 @@ __docker_service_subcommand() {
"($help)--no-task-ids[Do not include task IDs]" \
"($help)--no-trunc[Do not truncate output]" \
"($help)--since=[Show logs since timestamp]:timestamp: " \
- "($help)--tail=[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \
+ "($help -n --tail)"{-n=,--tail=}"[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \
"($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \
"($help -)1:service:__docker_complete_services" && ret=0
;;
@@ -2639,6 +2646,8 @@ __docker_subcommand() {
"($help)*--cluster-store-opt=[Cluster store options]:Cluster options:->cluster-store-options" \
"($help)--config-file=[Path to daemon configuration file]:Config File:_files" \
"($help)--containerd=[Path to containerd socket]:socket:_files -g \"*.sock\"" \
+ "($help)--containerd-namespace=[Containerd namespace to use]:containerd namespace:" \
+ "($help)--containerd-plugins-namespace=[Containerd namespace to use for plugins]:containerd namespace:" \
"($help)--data-root=[Root directory of persisted Docker data]:path:_directories" \
"($help -D --debug)"{-D,--debug}"[Enable debug mode]" \
"($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \
diff --git a/plugins/genpass/genpass-xkcd b/plugins/genpass/genpass-xkcd
index a486ccb40..ed0397138 100755
--- a/plugins/genpass/genpass-xkcd
+++ b/plugins/genpass/genpass-xkcd
@@ -43,7 +43,7 @@ fi
# Figure out how many words we need for 128 bits of security margin.
# Each word adds log2($#words) bits.
-local -i n=$((ceil(128. / log2($#words))))
+local -i n=$((ceil(128. / (log($#words) / log(2)))))
{
local c
diff --git a/plugins/git-prompt/git-prompt.plugin.zsh b/plugins/git-prompt/git-prompt.plugin.zsh
index da674af98..a4c952471 100644
--- a/plugins/git-prompt/git-prompt.plugin.zsh
+++ b/plugins/git-prompt/git-prompt.plugin.zsh
@@ -40,6 +40,8 @@ function update_current_git_vars() {
GIT_CONFLICTS=$__CURRENT_GIT_STATUS[5]
GIT_CHANGED=$__CURRENT_GIT_STATUS[6]
GIT_UNTRACKED=$__CURRENT_GIT_STATUS[7]
+ GIT_STASHED=$__CURRENT_GIT_STATUS[8]
+ GIT_CLEAN=$__CURRENT_GIT_STATUS[9]
}
git_super_status() {
@@ -63,9 +65,12 @@ git_super_status() {
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED%{${reset_color}%}"
fi
if [ "$GIT_UNTRACKED" -ne "0" ]; then
- STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED%{${reset_color}%}"
+ STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED$GIT_UNTRACKED%{${reset_color}%}"
fi
- if [ "$GIT_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then
+ if [ "$GIT_STASHED" -ne "0" ]; then
+ STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STASHED$GIT_STASHED%{${reset_color}%}"
+ fi
+ if [ "$GIT_CLEAN" -eq "1" ]; then
STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN"
fi
STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX"
@@ -83,7 +88,8 @@ ZSH_THEME_GIT_PROMPT_CONFLICTS="%{$fg[red]%}%{✖%G%}"
ZSH_THEME_GIT_PROMPT_CHANGED="%{$fg[blue]%}%{✚%G%}"
ZSH_THEME_GIT_PROMPT_BEHIND="%{↓%G%}"
ZSH_THEME_GIT_PROMPT_AHEAD="%{↑%G%}"
-ZSH_THEME_GIT_PROMPT_UNTRACKED="%{…%G%}"
+ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg[cyan]%}%{…%G%}"
+ZSH_THEME_GIT_PROMPT_STASHED="%{$fg_bold[blue]%}%{⚑%G%}"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[green]%}%{✔%G%}"
# Set the prompt.
diff --git a/plugins/git-prompt/gitstatus.py b/plugins/git-prompt/gitstatus.py
index bf3173614..786274a71 100644
--- a/plugins/git-prompt/gitstatus.py
+++ b/plugins/git-prompt/gitstatus.py
@@ -23,6 +23,18 @@ def get_tagname_or_hash():
return hash_
return None
+# Re-use method from https://github.com/magicmonty/bash-git-prompt to get stashs count
+def get_stash():
+ cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE)
+ so, se = cmd.communicate()
+ stash_file = '%s%s' % (so.decode('utf-8').rstrip(), '/logs/refs/stash')
+
+ try:
+ with open(stash_file) as f:
+ return sum(1 for _ in f)
+ except IOError:
+ return 0
+
# `git status --porcelain --branch` can collect all information
# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
@@ -68,6 +80,12 @@ for st in status:
elif st[0] != ' ':
staged.append(st)
+stashed = get_stash()
+if not changed and not staged and not conflicts and not untracked and not stashed:
+ clean = 1
+else:
+ clean = 0
+
out = ' '.join([
branch,
str(ahead),
@@ -76,5 +94,7 @@ out = ' '.join([
str(len(conflicts)),
str(len(changed)),
str(len(untracked)),
+ str(stashed),
+ str(clean)
])
print(out, end='')
diff --git a/plugins/git/README.md b/plugins/git/README.md
index b7f216813..029386267 100644
--- a/plugins/git/README.md
+++ b/plugins/git/README.md
@@ -136,6 +136,7 @@ plugins=(... git)
| grs | git restore |
| grset | git remote set-url |
| grss | git restore --source |
+| grst | git restore --staged |
| grt | cd "$(git rev-parse --show-toplevel \|\| echo .)" |
| gru | git reset -- |
| grup | git remote update |
diff --git a/plugins/git/git.plugin.zsh b/plugins/git/git.plugin.zsh
index e32136f15..2f97dbc92 100644
--- a/plugins/git/git.plugin.zsh
+++ b/plugins/git/git.plugin.zsh
@@ -236,6 +236,7 @@ alias grrm='git remote remove'
alias grs='git restore'
alias grset='git remote set-url'
alias grss='git restore --source'
+alias grst='git restore --staged'
alias grt='cd "$(git rev-parse --show-toplevel || echo .)"'
alias gru='git reset --'
alias grup='git remote update'
diff --git a/plugins/grc/README.md b/plugins/grc/README.md
index dfda41466..515e87640 100644
--- a/plugins/grc/README.md
+++ b/plugins/grc/README.md
@@ -10,28 +10,6 @@ plugins=(... grc)
## Commands
-The following commands are wrapped by `grc` so that their output is automatically colored:
-
-- `cc`
-- `configure`
-- `cvs`
-- `df`
-- `diff`
-- `dig`
-- `gcc`
-- `gmake`
-- `ifconfig`
-- `iwconfig`
-- `last`
-- `ldap`
-- `make`
-- `mount`
-- `mtr`
-- `netstat`
-- `ping`
-- `ping6`
-- `ps`
-- `traceroute`
-- `traceroute6`
-- `wdiff`
-- `whois`
+The plugin sources the bundled alias generator from the installation, available at `/etc/grc.zsh`.
+The complete list of wrapped commands may vary depending on the installed version of `grc`, look
+at the file mentioned above (`/etc/grc.zsh`) to see which commands are wrapped.
diff --git a/plugins/grc/grc.plugin.zsh b/plugins/grc/grc.plugin.zsh
index 6a52ec568..b709b9e02 100644
--- a/plugins/grc/grc.plugin.zsh
+++ b/plugins/grc/grc.plugin.zsh
@@ -1,44 +1,17 @@
-# Adapted from: https://github.com/garabik/grc/blob/master/grc.zsh
+#!/usr/bin/env zsh
-if [[ "$TERM" = dumb ]] || (( ! $+commands[grc] )); then
- return
-fi
-
-# Supported commands
-cmds=(
- cc
- configure
- cvs
- df
- diff
- dig
- gcc
- gmake
- ifconfig
- iwconfig
- last
- ldap
- make
- mount
- mtr
- netstat
- ping
- ping6
- ps
- traceroute
- traceroute6
- wdiff
- whois
+# common grc.zsh paths
+files=(
+ /etc/grc.zsh # default
+ /usr/local/etc/grc.zsh # homebrew
)
-# Set alias for supported commands
-for cmd in $cmds; do
- if (( $+commands[$cmd] )); then
- eval "function $cmd {
- grc --colour=auto \"${commands[$cmd]}\" \"\$@\"
- }"
+# verify the file is readable and source it
+for file in $files; do
+ if [[ -r "$file" ]]; then
+ source "$file"
+ break
fi
done
-# Clean up variables
-unset cmds cmd
+unset file files
diff --git a/plugins/jake-node/jake-node.plugin.zsh b/plugins/jake-node/jake-node.plugin.zsh
index 3b692f899..c2dad28af 100644
--- a/plugins/jake-node/jake-node.plugin.zsh
+++ b/plugins/jake-node/jake-node.plugin.zsh
@@ -6,7 +6,7 @@
# Inspiration : https://weblog.rubyonrails.org/2006/3/9/fast-rake-task-completion-for-zsh
function _jake () {
- if [ -f Jakefile ]||[ -f jakefile ]; then
+ if [ -f Jakefile ] || [ -f jakefile ] || [ -f Jakefile.js ] || [ -f jakefile.js ]; then
compadd `jake -T | cut -d " " -f 2 | sed -E "s/.\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"`
fi
}
diff --git a/plugins/last-working-dir/README.md b/plugins/last-working-dir/README.md
index ced9e0370..b5cc55828 100644
--- a/plugins/last-working-dir/README.md
+++ b/plugins/last-working-dir/README.md
@@ -1,15 +1,33 @@
# last-working-dir plugin
Keeps track of the last used working directory and automatically jumps into it
-for new shells, unless:
+for new shells, unless the starting directory is not `$HOME`.
-- The plugin is already loaded.
-- The current `$PWD` is not `$HOME`.
-
-Also adds `lwd` function to jump to the last working directory.
+Also adds a `lwd` function to jump to the last working directory.
To use it, add `last-working-dir` to the plugins array in your zshrc file:
```zsh
plugins=(... last-working-dir)
```
+
+## Features
+
+### Use separate last-working-dir files with different SSH keys
+
+If the same user account is used by multiple users connecting via different SSH keys, you can
+configure SSH to map them to different `SSH_USER`s and the plugin will use separate lwd files
+for each one.
+
+Make sure that your SSH server allows environment variables. You can enable this feature
+within the `/etc/sshd/sshd_config` file:
+
+```
+PermitUserEnvironment yes
+```
+
+Then, add `environment="SSH_USER=<SSH_USERNAME>"` before the SSH keys in your `authorized_keys` file:
+
+```
+environment="SSH_USER=a.test@example.com" ssh-ed25519 AAAAC3Nz...
+```
diff --git a/plugins/last-working-dir/last-working-dir.plugin.zsh b/plugins/last-working-dir/last-working-dir.plugin.zsh
index fd21705ae..905a02a70 100644
--- a/plugins/last-working-dir/last-working-dir.plugin.zsh
+++ b/plugins/last-working-dir/last-working-dir.plugin.zsh
@@ -5,16 +5,18 @@ typeset -g ZSH_LAST_WORKING_DIRECTORY
autoload -U add-zsh-hook
add-zsh-hook chpwd chpwd_last_working_dir
chpwd_last_working_dir() {
- if [ "$ZSH_SUBSHELL" = 0 ]; then
- local cache_file="$ZSH_CACHE_DIR/last-working-dir"
- pwd >| "$cache_file"
- fi
+ # Don't run in subshells
+ [[ "$ZSH_SUBSHELL" -eq 0 ]] || return 0
+ # Add ".$SSH_USER" suffix to cache file if $SSH_USER is set and non-empty
+ local cache_file="$ZSH_CACHE_DIR/last-working-dir${SSH_USER:+.$SSH_USER}"
+ pwd >| "$cache_file"
}
# Changes directory to the last working directory
lwd() {
- local cache_file="$ZSH_CACHE_DIR/last-working-dir"
- [[ -r "$cache_file" ]] && cd "$(cat "$cache_file")"
+ # Add ".$SSH_USER" suffix to cache file if $SSH_USER is set and non-empty
+ local cache_file="$ZSH_CACHE_DIR/last-working-dir${SSH_USER:+.$SSH_USER}"
+ [[ -r "$cache_file" ]] && cd "$(cat "$cache_file")"
}
# Jump to last directory automatically unless:
diff --git a/plugins/macports/_port b/plugins/macports/_port
index 6a9ebe0c6..897598a46 100644
--- a/plugins/macports/_port
+++ b/plugins/macports/_port
@@ -43,6 +43,7 @@ subcmds=(
'provides'
'rdependents'
'rdeps'
+'reclaim'
'rpmpackage'
'search'
'selfupdate'
diff --git a/plugins/nvm/README.md b/plugins/nvm/README.md
index 749a43403..700613085 100644
--- a/plugins/nvm/README.md
+++ b/plugins/nvm/README.md
@@ -11,9 +11,11 @@ plugins=(... nvm)
## Settings
-- **`NVM_DIR`**: if you have installed nvm in a directory other than `$HOME/.nvm`, set and export `NVM_DIR`
- to be the directory where you installed nvm.
-
+If you installed nvm in a directory other than `$HOME/.nvm`, set and export `NVM_DIR` to be the directory
+where you installed nvm.
+
+These settings should go in your zshrc file, before Oh My Zsh is sourced:
+
- **`NVM_HOMEBREW`**: if you installed nvm via Homebrew, in a directory other than `/usr/local/opt/nvm`, you
can set `NVM_HOMEBREW` to be the directory where you installed it.
diff --git a/plugins/term_tab/README b/plugins/term_tab/README
new file mode 100644
index 000000000..316062e73
--- /dev/null
+++ b/plugins/term_tab/README
@@ -0,0 +1,16 @@
+
+term_tab - 'cwd' for all open zsh sessions
+******************************************
+
+What it does:
+*************
+This plugin allows to complete the 'cwd' of other Zsh sessions. Sounds
+complicated but is rather simple. E.g. if you have three zsh sessions open, in
+each session you are in a different folder, you can hit Ctrl+v in one session
+to show you the current working directory of the other open zsh sessions.
+
+How it works:
+*************
+* It uses 'pidof zsh' to determine all zsh PIDs
+* It reads procfs to get the current working directory of this session
+* Everything is fed into zsh's completion magic
diff --git a/plugins/term_tab/term_tab.plugin.zsh b/plugins/term_tab/term_tab.plugin.zsh
new file mode 100644
index 000000000..1b612df68
--- /dev/null
+++ b/plugins/term_tab/term_tab.plugin.zsh
@@ -0,0 +1,41 @@
+# Copyright (C) 2014 Julian Vetter <death.jester@web.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+function _term_list(){
+ local -a expl
+ local -au dirs
+
+ PREFIX="$IPREFIX$PREFIX"
+ IPREFIX=
+ SUFFIX="$SUFFIX$ISUFFIX"
+ ISUFFIX=
+
+ [[ -o magicequalsubst ]] && compset -P '*='
+
+ case $OSTYPE in
+ solaris*) dirs=( ${(M)${${(f)"$(pgrep -U $UID -x zsh|xargs pwdx)"}:#$$:*}%%/*} ) ;;
+ linux*) dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) ;;
+ esac
+ dirs=( ${(D)dirs} )
+
+ compstate[pattern_match]='*'
+ _wanted directories expl 'current directory from other shell' \
+ compadd -Q -M "r:|/=* r:|=*" -f -a dirs
+}
+
+zle -C term_list menu-complete _generic
+bindkey "^v" term_list
+zstyle ':completion:term_list::::' completer _term_list
diff --git a/plugins/universalarchive/README.md b/plugins/universalarchive/README.md
new file mode 100644
index 000000000..93a1bd9fc
--- /dev/null
+++ b/plugins/universalarchive/README.md
@@ -0,0 +1,46 @@
+# universalarchive plugin
+
+Lets you compress files by a command `ua <format> <files>`, supporting various
+compression formats (e.g. 7z, tar.gz, lzma, ...).
+
+To enable it, add `universalarchive` to the plugins array in your zshrc file:
+
+```zsh
+plugins=(... universalarchive)
+```
+
+## Usage
+
+Run `ua <format> <files>` to compress `<files>` into an archive file using `<format>`.
+For example:
+
+```sh
+ua xz *.html
+```
+
+this command will compress all `.html` files in directory `folder` into `folder.xz`.
+
+This plugin saves you from having to remember which command line arguments compress a file.
+
+## Supported compression formats
+
+| Extension | Description |
+|:-----------------|:-------------------------------|
+| `7z` | 7zip file |
+| `bz2` | Bzip2 file |
+| `gz` | Gzip file |
+| `lzma` | LZMA archive |
+| `lzo` | LZO archive |
+| `rar` | WinRAR archive |
+| `tar` | Tarball |
+| `tbz`/`tar.bz2` | Tarball with bzip2 compression |
+| `tgz`/`tar.gz` | Tarball with gzip compression |
+| `tlz`/`tar.lzma` | Tarball with lzma compression |
+| `txz`/`tar.xz` | Tarball with lzma2 compression |
+| `tZ`/`tar.Z` | Tarball with LZW compression |
+| `xz` | LZMA2 archive |
+| `Z` | Z archive (LZW) |
+| `zip` | Zip archive |
+| `zst` | Zstd archive |
+
+See [list of archive formats](https://en.wikipedia.org/wiki/List_of_archive_formats) for more information regarding the archive formats.
diff --git a/plugins/universalarchive/_universalarchive b/plugins/universalarchive/_universalarchive
new file mode 100644
index 000000000..17cfd782e
--- /dev/null
+++ b/plugins/universalarchive/_universalarchive
@@ -0,0 +1,6 @@
+#compdef ua
+
+_arguments \
+ "1:archive format:(7z bz2 gz lzma lzo rar tar tar.bz2 tar.gz tar.lzma tar.xz tar.Z tbz tgz tlz txz tZ xz Z zip zst)" \
+ "*:input files:_files" \
+&& return 0
diff --git a/plugins/universalarchive/universalarchive.plugin.zsh b/plugins/universalarchive/universalarchive.plugin.zsh
new file mode 100644
index 000000000..b287c22b2
--- /dev/null
+++ b/plugins/universalarchive/universalarchive.plugin.zsh
@@ -0,0 +1,70 @@
+function ua() {
+ local usage=\
+"Archive files and directories using a given compression algorithm.
+
+Usage: $0 <format> <files>
+Example: $0 tbz PKGBUILD
+
+Supported archive formats are:
+7z, bz2, gz, lzma, lzo, rar, tar, tbz (tar.bz2), tgz (tar.gz),
+tlz (tar.lzma), txz (tar.xz), tZ (tar.Z), xz, Z, zip, and zst."
+
+ if [[ $# -lt 2 ]]; then
+ print -u2 -- "$usage"
+ return 1
+ fi
+
+ local ext="$1"
+ local input="${2:a}"
+
+ shift
+
+ if [[ ! -e "$input" ]]; then
+ print -u2 -- "$input not found"
+ return 1
+ fi
+
+ # generate output file name
+ local output
+ if [[ $# -gt 1 ]]; then
+ output="${input:h:t}"
+ elif [[ -f "$input" ]]; then
+ output="${input:r:t}"
+ elif [[ -d "$input" ]]; then
+ output="${input:t}"
+ fi
+
+ # if output file exists, generate a random name
+ if [[ -f "${output}.${ext}" ]]; then
+ output=$(mktemp "${output}_XXX") && rm "$output" || return 1
+ fi
+
+ # add extension
+ output="${output}.${ext}"
+
+ # safety check
+ if [[ -f "$output" ]]; then
+ print -u2 -- "output file '$output' already exists. Aborting"
+ return 1
+ fi
+
+ case "$ext" in
+ 7z) 7z u "${output}" "${@}" ;;
+ bz2) bzip2 -vcf "${@}" > "${output}" ;;
+ gz) gzip -vcf "${@}" > "${output}" ;;
+ lzma) lzma -vc -T0 "${@}" > "${output}" ;;
+ lzo) lzop -vc "${@}" > "${output}" ;;
+ rar) rar a "${output}" "${@}" ;;
+ tar) tar -cvf "${output}" "${@}" ;;
+ tbz|tar.bz2) tar -cvjf "${output}" "${@}" ;;
+ tgz|tar.gz) tar -cvzf "${output}" "${@}" ;;
+ tlz|tar.lzma) XZ_OPT=-T0 tar --lzma -cvf "${output}" "${@}" ;;
+ txz|tar.xz) XZ_OPT=-T0 tar -cvJf "${output}" "${@}" ;;
+ tZ|tar.Z) tar -cvZf "${output}" "${@}" ;;
+ xz) xz -vc -T0 "${@}" > "${output}" ;;
+ Z) compress -vcf "${@}" > "${output}" ;;
+ zip) zip -rull "${output}" "${@}" ;;
+ zst) zstd -c -T0 "${@}" > "${output}" ;;
+ *) print -u2 -- "$usage"; return 1 ;;
+ esac
+}
diff --git a/plugins/vi-mode/README.md b/plugins/vi-mode/README.md
index 8519a5592..b59d5f279 100644
--- a/plugins/vi-mode/README.md
+++ b/plugins/vi-mode/README.md
@@ -1,34 +1,72 @@
-vi-mode
-=======
+# vi-mode plugin
+
This plugin increase `vi-like` zsh functionality.
+To use it, add `vi-mode` to the plugins array in your zshrc file:
+
+```zsh
+plugins=(... vi-mode)
+```
+
+## Settings
+
+- `VI_MODE_RESET_PROMPT_ON_MODE_CHANGE`: controls whether the prompt is redrawn when
+ switching to a different input mode. If this is unset, the mode indicator will not
+ be updated when changing to a different mode.
+ Set it to `true` to enable it. For example:
+
+ ```zsh
+ VI_MODE_RESET_PROMPT_ON_MODE_CHANGE=true
+ ```
+
+ The default value is unset, unless `vi_mode_prompt_info` is used, in which case it'll
+ automatically be set to `true`.
+
+- `VI_MODE_SET_CURSOR`: controls whether the cursor style is changed when switching
+ to a different input mode. Set it to `true` to enable it (default: unset):
+
+ ```zsh
+ VI_MODE_SET_CURSOR=true
+ ```
+
+- `MODE_INDICATOR`: controls the string displayed when the shell is in normal mode.
+ See [Mode indicator](#mode-indicator) for details.
+
+## Mode indicator
+
+*Normal mode* is indicated with a red `<<<` mark at the right prompt, when it
+hasn't been defined by theme.
+
+You can change this indicator by setting the `MODE_INDICATOR` variable. This setting
+supports Prompt Expansion sequences. For example:
+
+```zsh
+MODE_INDICATOR="%F{yellow}+%f"
+```
+
+You can also use the `vi_mode_prompt_info` function in your prompt, which will display
+this mode indicator.
+
+## Key bindings
+
Use `ESC` or `CTRL-[` to enter `Normal mode`.
+NOTE: some of these key bindings are set by zsh by default when using a vi-mode keymap.
-History
--------
+### History
- `ctrl-p` : Previous command in history
- `ctrl-n` : Next command in history
- `/` : Search backward in history
- `n` : Repeat the last `/`
+### Vim edition
-Mode indicators
----------------
-
-*Normal mode* is indicated with red `<<<` mark at the right prompt, when it
-wasn't defined by theme.
+- `vv` : Edit current command line in Vim
+NOTE: this used to be bound to `v`. That is now the default (`visual-mode`)
-Vim edition
------------
-
-- `v` : Edit current command line in Vim
-
-
-Movement
---------
+### Movement
- `$` : To the end of the line
- `^` : To the first non-blank character of the line
@@ -46,9 +84,7 @@ Movement
- `;` : Repeat latest f, t, F or T [count] times
- `,` : Repeat latest f, t, F or T in opposite direction
-
-Insertion
----------
+### Insertion
- `i` : Insert text before the cursor
- `I` : Insert text before the first character in the line
@@ -57,9 +93,7 @@ Insertion
- `o` : Insert new command line below the current one
- `O` : Insert new command line above the current one
-
-Delete and Insert
------------------
+### Delete and Insert
- `ctrl-h` : While in *Insert mode*: delete character before the cursor
- `ctrl-w` : While in *Insert mode*: delete word before the cursor
@@ -71,5 +105,5 @@ Delete and Insert
- `C` : Delete to the end of the line and start insert
- `r{char}` : Replace the character under the cursor with {char}
- `R` : Enter replace mode: Each character replaces existing one
-- `x` : Delete [count] characters under and after the cursor
-- `X` : Delete [count] characters before the cursor
+- `x` : Delete `count` characters under and after the cursor
+- `X` : Delete `count` characters before the cursor
diff --git a/plugins/vi-mode/vi-mode.plugin.zsh b/plugins/vi-mode/vi-mode.plugin.zsh
index c91ba05ba..7f14961ad 100644
--- a/plugins/vi-mode/vi-mode.plugin.zsh
+++ b/plugins/vi-mode/vi-mode.plugin.zsh
@@ -1,32 +1,73 @@
+# Control whether to force a redraw on each mode change.
+#
+# Resetting the prompt on every mode change can cause lag when switching modes.
+# This is especially true if the prompt does things like checking git status.
+#
+# Set to "true" to force the prompt to reset on each mode change.
+# Unset or set to any other value to do the opposite.
+#
+# The default is not to reset, unless we're showing the mode in RPS1.
+typeset -g VI_MODE_RESET_PROMPT_ON_MODE_CHANGE
+# Control whether to change the cursor style on mode change.
+#
+# Set to "true" to change the cursor on each mode change.
+# Unset or set to any other value to do the opposite.
+typeset -g VI_MODE_SET_CURSOR
+
+typeset -g VI_KEYMAP=main
+
+function _vi-mode-set-cursor-shape-for-keymap() {
+ [[ "$VI_MODE_SET_CURSOR" = true ]] || return
+
+ # https://vt100.net/docs/vt510-rm/DECSCUSR
+ local _shape=0
+ case "${1:-${VI_KEYMAP:-main}}" in
+ main) _shape=6 ;; # vi insert: line
+ viins) _shape=6 ;; # vi insert: line
+ isearch) _shape=6 ;; # inc search: line
+ command) _shape=6 ;; # read a command name
+ vicmd) _shape=2 ;; # vi cmd: block
+ visual) _shape=2 ;; # vi visual mode: block
+ viopp) _shape=0 ;; # vi operation pending: blinking block
+ *) _shape=0 ;;
+ esac
+ printf $'\e[%d q' "${_shape}"
+}
+
# Updates editor information when the keymap changes.
function zle-keymap-select() {
# update keymap variable for the prompt
- VI_KEYMAP=$KEYMAP
+ typeset -g VI_KEYMAP=$KEYMAP
- zle reset-prompt
- zle -R
+ if [[ "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:-}" = true ]]; then
+ zle reset-prompt
+ zle -R
+ fi
+ _vi-mode-set-cursor-shape-for-keymap "${VI_KEYMAP}"
}
-
zle -N zle-keymap-select
-function vi-accept-line() {
- VI_KEYMAP=main
- zle accept-line
+# These "echoti" statements were originally set in lib/key-bindings.zsh
+# Not sure the best way to extend without overriding.
+function zle-line-init() {
+ typeset -g VI_KEYMAP=main
+ (( ! ${+terminfo[smkx]} )) || echoti smkx
+ _vi-mode-set-cursor-shape-for-keymap "${VI_KEYMAP}"
}
+zle -N zle-line-init
-zle -N vi-accept-line
-
+function zle-line-finish() {
+ (( ! ${+terminfo[rmkx]} )) || echoti rmkx
+ _vi-mode-set-cursor-shape-for-keymap default
+}
+zle -N zle-line-finish
bindkey -v
-# use custom accept-line widget to update $VI_KEYMAP
-bindkey -M vicmd '^J' vi-accept-line
-bindkey -M vicmd '^M' vi-accept-line
-
-# allow v to edit the command line (standard behaviour)
+# allow vv to edit the command line (standard behaviour)
autoload -Uz edit-command-line
zle -N edit-command-line
-bindkey -M vicmd 'v' edit-command-line
+bindkey -M vicmd 'vv' edit-command-line
# allow ctrl-p, ctrl-n for navigate history (standard behaviour)
bindkey '^P' up-history
@@ -45,16 +86,56 @@ bindkey '^s' history-incremental-search-forward
bindkey '^a' beginning-of-line
bindkey '^e' end-of-line
+function wrap_clipboard_widgets() {
+ # NB: Assume we are the first wrapper and that we only wrap native widgets
+ # See zsh-autosuggestions.zsh for a more generic and more robust wrapper
+ local verb="$1"
+ shift
+
+ local widget
+ local wrapped_name
+ for widget in "$@"; do
+ wrapped_name="_zsh-vi-${verb}-${widget}"
+ if [ "${verb}" = copy ]; then
+ eval "
+ function ${wrapped_name}() {
+ zle .${widget}
+ printf %s \"\${CUTBUFFER}\" | clipcopy 2>/dev/null || true
+ }
+ "
+ else
+ eval "
+ function ${wrapped_name}() {
+ CUTBUFFER=\"\$(clippaste 2>/dev/null || echo \$CUTBUFFER)\"
+ zle .${widget}
+ }
+ "
+ fi
+ zle -N "${widget}" "${wrapped_name}"
+ done
+}
+
+wrap_clipboard_widgets copy vi-yank vi-yank-eol vi-backward-kill-word vi-change-whole-line vi-delete
+wrap_clipboard_widgets paste vi-put-{before,after}
+unfunction wrap_clipboard_widgets
+
# if mode indicator wasn't setup by theme, define default
-if [[ "$MODE_INDICATOR" == "" ]]; then
- MODE_INDICATOR="%{$fg_bold[red]%}<%{$fg[red]%}<<%{$reset_color%}"
+if [[ -z "$MODE_INDICATOR" ]]; then
+ MODE_INDICATOR='%B%F{red}<%b<<%f'
fi
function vi_mode_prompt_info() {
+ # If we're using the prompt to display mode info, and we haven't explicitly
+ # disabled "reset prompt on mode change", then set it here.
+ #
+ # We do that here instead of the `if` statement below because the user may
+ # set RPS1/RPROMPT to something else in their custom config.
+ : "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:=true}"
+
echo "${${VI_KEYMAP/vicmd/$MODE_INDICATOR}/(main|viins)/}"
}
# define right prompt, if it wasn't defined by a theme
-if [[ "$RPS1" == "" && "$RPROMPT" == "" ]]; then
+if [[ -z "$RPS1" && -z "$RPROMPT" ]]; then
RPS1='$(vi_mode_prompt_info)'
fi
diff --git a/plugins/zbell/README.md b/plugins/zbell/README.md
new file mode 100644
index 000000000..1c1c13546
--- /dev/null
+++ b/plugins/zbell/README.md
@@ -0,0 +1,30 @@
+# zbell plugin
+
+This plugin prints a bell character when a command finishes if it has been
+running for longer than a specified duration.
+
+To use it, add `zbell` to the plugins array in your zshrc file:
+
+```zsh
+plugins=(... zbell)
+```
+
+## Settings
+
+These settings need to be set in your zshrc file, before Oh My Zsh is sourced.
+
+- `zbell_duration`: duration in seconds after which to consider notifying
+ the end of a command. Default: 15 seconds.
+
+- `zbell_ignore`: if there are programs that you know run long that you
+ don't want to bell after, then add them to the `zbell_ignore` array.
+ By default, `$EDITOR` and `$PAGER` are ignored:
+
+ ```zsh
+ zbell_ignore=($EDITOR $PAGER)
+ ```
+
+## Author
+
+Adapted from an original version by [Jean-Philippe Ouellet](https://github.com/jpouellet).
+Made available under the ISC license.
diff --git a/plugins/zbell/zbell.plugin.zsh b/plugins/zbell/zbell.plugin.zsh
new file mode 100644
index 000000000..6d0416502
--- /dev/null
+++ b/plugins/zbell/zbell.plugin.zsh
@@ -0,0 +1,83 @@
+#!/usr/bin/env zsh
+
+# This script prints a bell character when a command finishes
+# if it has been running for longer than $zbell_duration seconds.
+# If there are programs that you know run long that you don't
+# want to bell after, then add them to $zbell_ignore.
+#
+# This script uses only zsh builtins so its fast, there's no needless
+# forking, and its only dependency is zsh and its standard modules
+#
+# Written by Jean-Philippe Ouellet <jpo@vt.edu>
+# Made available under the ISC license.
+
+# only do this if we're in an interactive shell
+[[ -o interactive ]] || return
+
+# get $EPOCHSECONDS. builtins are faster than date(1)
+zmodload zsh/datetime || return
+
+# make sure we can register hooks
+autoload -Uz add-zsh-hook || return
+
+# make sure we can do regexp replace
+autoload -Uz regexp-replace || return
+
+# initialize zbell_duration if not set
+(( ${+zbell_duration} )) || zbell_duration=15
+
+# initialize zbell_ignore if not set
+(( ${+zbell_ignore} )) || zbell_ignore=($EDITOR $PAGER)
+
+# initialize it because otherwise we compare a date and an empty string
+# the first time we see the prompt. it's fine to have lastcmd empty on the
+# initial run because it evaluates to an empty string, and splitting an
+# empty string just results in an empty array.
+zbell_timestamp=$EPOCHSECONDS
+
+# default notification function
+# $1: command
+# $2: duration in seconds
+zbell_notify() {
+ type notify-send > /dev/null && \
+ notify-send -i terminal "Command completed in ${2}s:" $1
+ print -n "\a"
+}
+
+# right before we begin to execute something, store the time it started at
+zbell_begin() {
+ zbell_timestamp=$EPOCHSECONDS
+ zbell_lastcmd=$1
+}
+
+# when it finishes, if it's been running longer than $zbell_duration,
+# and we dont have an ignored command in the line, then print a bell.
+zbell_end() {
+ local cmd_duration=$(( $EPOCHSECONDS - $zbell_timestamp ))
+ local ran_long=$(( $cmd_duration >= $zbell_duration ))
+
+ local zbell_lastcmd_tmp="$zbell_lastcmd"
+ regexp-replace zbell_lastcmd_tmp '^sudo ' ''
+
+ [[ $zbell_last_timestamp == $zbell_timestamp ]] && return
+
+ [[ $zbell_lastcmd_tmp == "" ]] && return
+
+ zbell_last_timestamp=$zbell_timestamp
+
+ local has_ignored_cmd=0
+ for cmd in ${(s:;:)zbell_lastcmd_tmp//|/;}; do
+ words=(${(z)cmd})
+ util=${words[1]}
+ if (( ${zbell_ignore[(i)$util]} <= ${#zbell_ignore} )); then
+ has_ignored_cmd=1
+ break
+ fi
+ done
+
+ (( ! $has_ignored_cmd && ran_long )) && zbell_notify $zbell_lastcmd $cmd_duration
+}
+
+# register the functions as hooks
+add-zsh-hook preexec zbell_begin
+add-zsh-hook precmd zbell_end
diff --git a/templates/zshrc.zsh-template b/templates/zshrc.zsh-template
index 307618104..65d5ea65b 100644
--- a/templates/zshrc.zsh-template
+++ b/templates/zshrc.zsh-template
@@ -45,6 +45,8 @@ ZSH_THEME="robbyrussell"
# ENABLE_CORRECTION="true"
# Uncomment the following line to display red dots whilst waiting for completion.
+# Caution: this setting can cause issues with multiline prompts (zsh 5.7.1 and newer seem to work)
+# See https://github.com/ohmyzsh/ohmyzsh/issues/5765
# COMPLETION_WAITING_DOTS="true"
# Uncomment the following line if you want to disable marking untracked files
diff --git a/themes/essembeh.zsh-theme b/themes/essembeh.zsh-theme
index 939bb7a4c..f34f36f8a 100644
--- a/themes/essembeh.zsh-theme
+++ b/themes/essembeh.zsh-theme
@@ -1,24 +1,14 @@
-# Theme with full path names and hostname
-# Handy if you work on different servers all the time;
-
-local return_code="%(?..%{$fg_bold[red]%}%? ↵%{$reset_color%})"
-
-function my_git_prompt_info() {
- ref=$(git symbolic-ref HEAD 2> /dev/null) || return
- GIT_STATUS=$(git_prompt_status)
- [[ -n $GIT_STATUS ]] && GIT_STATUS=" $GIT_STATUS"
- echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$GIT_STATUS$ZSH_THEME_GIT_PROMPT_SUFFIX"
-}
-
-# Colored prompt
-ZSH_THEME_COLOR_USER="green"
-ZSH_THEME_COLOR_HOST="green"
-ZSH_THEME_COLOR_PWD="yellow"
-test -n "$SSH_CONNECTION" && ZSH_THEME_COLOR_USER="red" && ZSH_THEME_COLOR_HOST="red"
-test `id -u` = 0 && ZSH_THEME_COLOR_USER="magenta" && ZSH_THEME_COLOR_HOST="magenta"
-PROMPT='%{$fg_bold[$ZSH_THEME_COLOR_USER]%}%n@%{$fg_bold[$ZSH_THEME_COLOR_HOST]%}%M%{$reset_color%}:%{$fg_bold[$ZSH_THEME_COLOR_PWD]%}%~%{$reset_color%} $(my_git_prompt_info)%(!.#.$) '
-RPS1="${return_code}"
+# My custom theme:
+# - single line
+# - quite simple by default: user@host:$PWD
+# - green for local shell as non root
+# - red for ssh shell as non root
+# - magenta for root sessions
+# - prefix with remote address for ssh shells
+# - prefix to detect docker containers or chroot
+# - git plugin to display current branch and status
+# git plugin
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg[cyan]%}("
ZSH_THEME_GIT_PROMPT_SUFFIX=") %{$reset_color%}"
ZSH_THEME_GIT_PROMPT_UNTRACKED="%%"
@@ -28,3 +18,33 @@ ZSH_THEME_GIT_PROMPT_RENAMED="~"
ZSH_THEME_GIT_PROMPT_DELETED="!"
ZSH_THEME_GIT_PROMPT_UNMERGED="?"
+function zsh_essembeh_gitstatus {
+ ref=$(git symbolic-ref HEAD 2> /dev/null) || return
+ GIT_STATUS=$(git_prompt_status)
+ if [[ -n $GIT_STATUS ]]; then
+ GIT_STATUS=" $GIT_STATUS"
+ fi
+ echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$GIT_STATUS$ZSH_THEME_GIT_PROMPT_SUFFIX"
+}
+
+# by default, use green for user@host and no prefix
+local ZSH_ESSEMBEH_COLOR="green"
+local ZSH_ESSEMBEH_PREFIX=""
+if [[ -n "$SSH_CONNECTION" ]]; then
+ # display the source address if connected via ssh
+ ZSH_ESSEMBEH_PREFIX="%{$fg[yellow]%}[$(echo $SSH_CONNECTION | awk '{print $1}')]%{$reset_color%} "
+ # use red color to highlight a remote connection
+ ZSH_ESSEMBEH_COLOR="red"
+elif [[ -r /etc/debian_chroot ]]; then
+ # prefix prompt in case of chroot
+ ZSH_ESSEMBEH_PREFIX="%{$fg[yellow]%}[chroot:$(cat /etc/debian_chroot)]%{$reset_color%} "
+elif [[ -r /.dockerenv ]]; then
+ # also prefix prompt inside a docker contrainer
+ ZSH_ESSEMBEH_PREFIX="%{$fg[yellow]%}[docker]%{$reset_color%} "
+fi
+if [[ $UID = 0 ]]; then
+ # always use magenta for root sessions, even in ssh
+ ZSH_ESSEMBEH_COLOR="magenta"
+fi
+PROMPT='${ZSH_ESSEMBEH_PREFIX}%{$fg[$ZSH_ESSEMBEH_COLOR]%}%n@%M%{$reset_color%}:%{%B$fg[yellow]%}%~%{$reset_color%b%} $(zsh_essembeh_gitstatus)%(!.#.$) '
+RPROMPT="%(?..%{$fg[red]%}%?%{$reset_color%})"
diff --git a/tools/changelog.sh b/tools/changelog.sh
index 8753212e9..836afef14 100755
--- a/tools/changelog.sh
+++ b/tools/changelog.sh
@@ -91,6 +91,8 @@ function parse-commit {
if [[ "$body" =~ "BREAKING CHANGE: (.*)" || \
"$subject" =~ '^[^ :\)]+\)?!: (.*)$' ]]; then
message="${match[1]}"
+ # remove CR characters (might be inserted in GitHub UI commit description form)
+ message="${message//$'\r'/}"
# skip next paragraphs (separated by two newlines or more)
message="${message%%$'\n\n'*}"
# ... and replace newlines with spaces
@@ -284,7 +286,7 @@ function display-release {
local hash subject
for hash message in ${(kv)breaking}; do
- echo " - $(fmt:hash) $(fmt:subject "${message}")"
+ echo " - $(fmt:hash) $(fmt:scope)$(fmt:subject "${message}")"
done | sort
echo
}
diff --git a/tools/upgrade.sh b/tools/upgrade.sh
index 4df7eb184..358242d0f 100755
--- a/tools/upgrade.sh
+++ b/tools/upgrade.sh
@@ -75,14 +75,10 @@ if git pull --rebase --stat origin master; then
# Display changelog with less if available, otherwise just print it to the terminal
if [[ "$1" = --interactive ]]; then
- if (( $+commands[less] )); then
- "$ZSH/tools/changelog.sh" HEAD "$last_commit" --text | LESS= command less -R
- else
- "$ZSH/tools/changelog.sh" HEAD "$last_commit"
- fi
+ "$ZSH/tools/changelog.sh" HEAD "$last_commit"
fi
- printf "${BLUE}%s \`${BOLD}%s${RESET}${BLUE}\`${RESET}\n" "You can see the changelog again with" "omz changelog"
+ printf "${BLUE}%s \`${BOLD}%s${RESET}${BLUE}\`${RESET}\n" "You can see the changelog with" "omz changelog"
fi
printf '%s %s__ %s %s %s %s %s__ %s\n' $RAINBOW $RESET