mirror of
https://github.com/robbyrussell/oh-my-zsh.git
synced 2026-09-21 18:46:06 +02:00
Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6421f8e104 | ||
|
|
0b50afdbfd | ||
|
|
157eb033f2 | ||
|
|
e7852049a5 | ||
|
|
7ce781ea37 | ||
|
|
def0f255c5 | ||
|
|
0ee67f0428 | ||
|
|
ec2901b7d0 | ||
|
|
1396cdd674 | ||
|
|
2ea948e05b | ||
|
|
6cd3a0baf6 | ||
|
|
fcf965912c | ||
|
|
c648271b6b | ||
|
|
53f663f3d8 | ||
|
|
e995678ca8 | ||
|
|
aea374f522 | ||
|
|
6553f90c45 | ||
|
|
9bf43f682c | ||
|
|
1b72d609b4 | ||
|
|
3258baa8b4 | ||
|
|
ee78d3aedd | ||
|
|
2b48fa42f9 | ||
|
|
be8da5c771 | ||
|
|
c6e66edee8 | ||
|
|
a1115e6eb8 | ||
|
|
24d629f7f1 | ||
|
|
d6f3106269 | ||
|
|
e6561f578f | ||
|
|
9bb15d681a | ||
|
|
ee2acd0e44 | ||
|
|
d5fa35e453 | ||
|
|
2c911e3f80 | ||
|
|
cd320b5506 | ||
|
|
e8b1cca662 | ||
|
|
8e5f198226 | ||
|
|
391cafc4cf | ||
|
|
3079e2f0b5 | ||
|
|
129de5a05f | ||
|
|
bd77419b2a | ||
|
|
d217d05374 | ||
|
|
c891b750b0 | ||
|
|
6aa16696d5 | ||
|
|
8d10cc9488 | ||
|
|
bf77e350e0 | ||
|
|
07351f99fc | ||
|
|
39334a08e9 | ||
|
|
cba369e090 | ||
|
|
0da7919339 | ||
|
|
992edcc17d | ||
|
|
78cbb3fe5e | ||
|
|
76ac9fcddc | ||
|
|
17bbf5fdac | ||
|
|
704f7d59d8 | ||
|
|
0b235c54de |
@@ -12,14 +12,14 @@ dependencies:
|
|||||||
plugins/gradle:
|
plugins/gradle:
|
||||||
repo: gradle/gradle-completion
|
repo: gradle/gradle-completion
|
||||||
branch: master
|
branch: master
|
||||||
version: 63578c9bc56134b80766e88957ba0239e6be2343
|
version: e7c881dbef7462bc35ad05328397e1582fe25cb8
|
||||||
precopy: |
|
precopy: |
|
||||||
set -e
|
set -e
|
||||||
find . ! -name _gradle ! -name LICENSE -delete
|
find . ! -name _gradle ! -name LICENSE -delete
|
||||||
plugins/history-substring-search:
|
plugins/history-substring-search:
|
||||||
repo: zsh-users/zsh-history-substring-search
|
repo: zsh-users/zsh-history-substring-search
|
||||||
branch: master
|
branch: master
|
||||||
version: 14c8d2e0ffaee98f2df9850b19944f32546fdea5
|
version: a0bdb0d47dbaba31dba2db7af8c48a5d9c74049a
|
||||||
precopy: |
|
precopy: |
|
||||||
set -e
|
set -e
|
||||||
rm -f zsh-history-substring-search.plugin.zsh
|
rm -f zsh-history-substring-search.plugin.zsh
|
||||||
@@ -30,7 +30,7 @@ dependencies:
|
|||||||
plugins/kube-ps1:
|
plugins/kube-ps1:
|
||||||
repo: jonmosco/kube-ps1
|
repo: jonmosco/kube-ps1
|
||||||
branch: master
|
branch: master
|
||||||
version: 04af46f7fe888ad287abcab6699b9bb10234bc3d
|
version: b4cd09ec8d4dc007173e28da40aeebf8eff8c87f
|
||||||
precopy: |
|
precopy: |
|
||||||
set -e
|
set -e
|
||||||
find . ! -name kube-ps1.sh ! -name LICENSE ! -name README.md -delete
|
find . ! -name kube-ps1.sh ! -name LICENSE ! -name README.md -delete
|
||||||
@@ -55,3 +55,46 @@ dependencies:
|
|||||||
set -e
|
set -e
|
||||||
test -e _zshz && mv -f _zshz _z
|
test -e _zshz && mv -f _zshz _z
|
||||||
test -e zsh-z.plugin.zsh && mv -f zsh-z.plugin.zsh z.plugin.zsh
|
test -e zsh-z.plugin.zsh && mv -f zsh-z.plugin.zsh z.plugin.zsh
|
||||||
|
plugins/zsh-autosuggestions:
|
||||||
|
repo: zsh-users/zsh-autosuggestions
|
||||||
|
branch: master
|
||||||
|
version: 85919cd1ffa7d2d5412f6d3fe437ebdbeeec4fc5
|
||||||
|
precopy: |
|
||||||
|
set -e
|
||||||
|
test -e README.md && mv -f README.md MANUAL.md
|
||||||
|
sed -i 's|\[INSTALL.md\](INSTALL.md)|[the Oh My Zsh plugin README](README.md)|' MANUAL.md
|
||||||
|
rm -f zsh-autosuggestions.plugin.zsh
|
||||||
|
mv -f zsh-autosuggestions.zsh zsh-autosuggestions.plugin.zsh
|
||||||
|
find . -depth -mindepth 1 \
|
||||||
|
! -path './LICENSE' \
|
||||||
|
! -path './MANUAL.md' \
|
||||||
|
! -path './src' \
|
||||||
|
! -path './src/*' \
|
||||||
|
! -path './zsh-autosuggestions.plugin.zsh' \
|
||||||
|
-delete
|
||||||
|
plugins/zsh-syntax-highlighting:
|
||||||
|
repo: zsh-users/zsh-syntax-highlighting
|
||||||
|
branch: master
|
||||||
|
version: 2fc57d63067c18b1100ecdbf684fa5baf49459d1
|
||||||
|
precopy: |
|
||||||
|
set -e
|
||||||
|
version=$(<.version)
|
||||||
|
test -e README.md && mv -f README.md MANUAL.md
|
||||||
|
sed -i 's|\[INSTALL.md\](INSTALL.md)|[the Oh My Zsh plugin README](README.md)|' MANUAL.md
|
||||||
|
rm -f zsh-syntax-highlighting.plugin.zsh
|
||||||
|
mv -f zsh-syntax-highlighting.zsh zsh-syntax-highlighting.plugin.zsh
|
||||||
|
mv -f COPYING.md LICENSE
|
||||||
|
sed -i "s|typeset -g ZSH_HIGHLIGHT_VERSION=.*|typeset -g ZSH_HIGHLIGHT_VERSION=$version|" zsh-syntax-highlighting.plugin.zsh
|
||||||
|
sed -i 's|typeset -g ZSH_HIGHLIGHT_REVISION=.*|typeset -g ZSH_HIGHLIGHT_REVISION=HEAD|' zsh-syntax-highlighting.plugin.zsh
|
||||||
|
find highlighters -type d -name test-data -prune -exec rm -rf {} +
|
||||||
|
find . -depth -mindepth 1 \
|
||||||
|
! -path './LICENSE' \
|
||||||
|
! -path './MANUAL.md' \
|
||||||
|
! -path './docs' \
|
||||||
|
! -path './docs/*' \
|
||||||
|
! -path './highlighters' \
|
||||||
|
! -path './highlighters/*' \
|
||||||
|
! -path './images' \
|
||||||
|
! -path './images/*' \
|
||||||
|
! -path './zsh-syntax-highlighting.plugin.zsh' \
|
||||||
|
-delete
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
contents: write # this is needed to push commits and branches
|
contents: write # this is needed to push commits and branches
|
||||||
steps:
|
steps:
|
||||||
- name: Harden the runner (Audit all outbound calls)
|
- name: Harden the runner (Audit all outbound calls)
|
||||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ charset-normalizer==3.5.1
|
|||||||
idna==3.19
|
idna==3.19
|
||||||
PyYAML==6.0.3
|
PyYAML==6.0.3
|
||||||
requests==2.34.2
|
requests==2.34.2
|
||||||
semver==3.0.4
|
semver==3.1.0
|
||||||
urllib3==2.7.0
|
urllib3==2.8.0
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
- macos-latest
|
- macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden the runner (Audit all outbound calls)
|
- name: Harden the runner (Audit all outbound calls)
|
||||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
- test
|
- test
|
||||||
steps:
|
steps:
|
||||||
- name: Harden the runner (Audit all outbound calls)
|
- name: Harden the runner (Audit all outbound calls)
|
||||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
if: github.repository == 'ohmyzsh/ohmyzsh'
|
if: github.repository == 'ohmyzsh/ohmyzsh'
|
||||||
steps:
|
steps:
|
||||||
- name: Harden the runner (Audit all outbound calls)
|
- name: Harden the runner (Audit all outbound calls)
|
||||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
if: github.repository == 'ohmyzsh/ohmyzsh'
|
if: github.repository == 'ohmyzsh/ohmyzsh'
|
||||||
steps:
|
steps:
|
||||||
- name: Harden the runner (Audit all outbound calls)
|
- name: Harden the runner (Audit all outbound calls)
|
||||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
- name: Authenticate as @ohmyzsh
|
- name: Authenticate as @ohmyzsh
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Harden the runner (Audit all outbound calls)
|
- name: Harden the runner (Audit all outbound calls)
|
||||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
@@ -60,6 +60,6 @@ jobs:
|
|||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
|
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ Twitter), and join us on [Discord](https://discord.gg/ohmyzsh).
|
|||||||
[](https://mstdn.social/@ohmyzsh)
|
[](https://mstdn.social/@ohmyzsh)
|
||||||
[](https://discord.gg/ohmyzsh)
|
[](https://discord.gg/ohmyzsh)
|
||||||
|
|
||||||
|
<a href="https://commitgoods.com/collections/oh-my-zsh?utm_source=github">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.shopify.com/s/files/1/0101/8752/files/commitgoods-badge-stacked-navy-dark.svg">
|
||||||
|
<img src="https://cdn.shopify.com/s/files/1/0101/8752/files/commitgoods-badge-stacked-navy.svg" height="28" alt="Official merch on commitgoods.com">
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Table of Contents</summary>
|
<summary>Table of Contents</summary>
|
||||||
|
|
||||||
@@ -466,6 +474,22 @@ zstyle ':omz:update' frequency 7
|
|||||||
zstyle ':omz:update' frequency 0
|
zstyle ':omz:update' frequency 0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, updates always pull the latest changes. If you'd rather let others kick the tires first
|
||||||
|
before an update reaches your machine, you can set a cooldown (in days). You'll still get everything —
|
||||||
|
just a little later:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Only apply updates that are at least 10 days old
|
||||||
|
zstyle ':omz:update' cooldown 10
|
||||||
|
```
|
||||||
|
|
||||||
|
`omz update` honors this setting. If you call `upgrade.sh` directly, pass the same
|
||||||
|
value with `-c`, because that script does not read your `.zshrc`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ZSH/tools/upgrade.sh -c 10
|
||||||
|
```
|
||||||
|
|
||||||
### Updates Verbosity
|
### Updates Verbosity
|
||||||
|
|
||||||
You can also limit the update verbosity with the following settings:
|
You can also limit the update verbosity with the following settings:
|
||||||
|
|||||||
+10
-1
@@ -738,6 +738,9 @@ function _omz::reload {
|
|||||||
|
|
||||||
# Old zsh versions don't have ZSH_ARGZERO
|
# Old zsh versions don't have ZSH_ARGZERO
|
||||||
local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}"
|
local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}"
|
||||||
|
# ZSH_ARGZERO is how zsh was invoked, not the path to it, so re-resolve
|
||||||
|
# anything that is not absolute via $PATH at exec time (see #13919)
|
||||||
|
[[ "${zsh#-}" != /* ]] && (( $+commands[zsh] )) && zsh="zsh"
|
||||||
# Check whether to run a login shell
|
# Check whether to run a login shell
|
||||||
[[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh"
|
[[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh"
|
||||||
}
|
}
|
||||||
@@ -903,8 +906,11 @@ function _omz::update {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Run update script
|
# Run update script
|
||||||
|
local verbose_mode cooldown_days
|
||||||
zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default
|
zstyle -s ':omz:update' verbose verbose_mode || verbose_mode=default
|
||||||
ZSH="$ZSH" command zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode || return $?
|
zstyle -s ':omz:update' cooldown cooldown_days || cooldown_days=0
|
||||||
|
[[ $cooldown_days == <-> ]] || cooldown_days=0
|
||||||
|
ZSH="$ZSH" command zsh -f "$ZSH/tools/upgrade.sh" -i -v $verbose_mode -c $cooldown_days || return $?
|
||||||
|
|
||||||
# Update last updated file
|
# Update last updated file
|
||||||
zmodload zsh/datetime
|
zmodload zsh/datetime
|
||||||
@@ -916,6 +922,9 @@ function _omz::update {
|
|||||||
if [[ "$(builtin cd -q "$ZSH"; git rev-parse HEAD)" != "$last_commit" ]]; then
|
if [[ "$(builtin cd -q "$ZSH"; git rev-parse HEAD)" != "$last_commit" ]]; then
|
||||||
# Old zsh versions don't have ZSH_ARGZERO
|
# Old zsh versions don't have ZSH_ARGZERO
|
||||||
local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}"
|
local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}"
|
||||||
|
# ZSH_ARGZERO is how zsh was invoked, not the path to it, so re-resolve
|
||||||
|
# anything that is not absolute via $PATH at exec time (see #13919)
|
||||||
|
[[ "${zsh#-}" != /* ]] && (( $+commands[zsh] )) && zsh="zsh"
|
||||||
# Check whether to run a login shell
|
# Check whether to run a login shell
|
||||||
[[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh"
|
[[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh"
|
||||||
fi
|
fi
|
||||||
|
|||||||
+19
-8
@@ -12,10 +12,16 @@ function __git_prompt_git() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _omz_git_prompt_info() {
|
function _omz_git_prompt_info() {
|
||||||
# If we are on a folder not tracked by git, get out.
|
# Get the git dir and the current branch name in one call. Outside a repo
|
||||||
# Otherwise, check for hide-info at global and local repository level
|
# there is no output. On a detached HEAD the branch is "HEAD". On an unborn
|
||||||
if ! __git_prompt_git rev-parse --git-dir &> /dev/null \
|
# branch git exits non-zero after printing the git dir.
|
||||||
|| [[ "$(__git_prompt_git config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then
|
local -a info
|
||||||
|
info=("${(@f)$(__git_prompt_git rev-parse --git-dir --abbrev-ref HEAD 2> /dev/null)}")
|
||||||
|
local unborn=$(( $? != 0 ))
|
||||||
|
[[ -n "$info[1]" ]] || return 0
|
||||||
|
|
||||||
|
# Check for hide-info at global and local repository level
|
||||||
|
if [[ "$(__git_prompt_git config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -23,11 +29,15 @@ function _omz_git_prompt_info() {
|
|||||||
# - the current branch name
|
# - the current branch name
|
||||||
# - the tag name if we are on a tag
|
# - the tag name if we are on a tag
|
||||||
# - the short SHA of the current commit
|
# - the short SHA of the current commit
|
||||||
local ref
|
# a git dir path may contain newlines, so the branch is the last line
|
||||||
ref=$(__git_prompt_git symbolic-ref --short HEAD 2> /dev/null) \
|
local ref="$info[-1]"
|
||||||
|| ref=$(__git_prompt_git describe --tags --exact-match HEAD 2> /dev/null) \
|
if (( unborn )); then
|
||||||
|
ref=$(__git_prompt_git symbolic-ref --short HEAD 2> /dev/null) || return 0
|
||||||
|
elif [[ "$ref" == HEAD ]]; then
|
||||||
|
ref=$(__git_prompt_git describe --tags --exact-match HEAD 2> /dev/null) \
|
||||||
|| ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) \
|
|| ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) \
|
||||||
|| return 0
|
|| return 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Use global ZSH_THEME_GIT_SHOW_UPSTREAM=1 for including upstream remote info
|
# Use global ZSH_THEME_GIT_SHOW_UPSTREAM=1 for including upstream remote info
|
||||||
local upstream
|
local upstream
|
||||||
@@ -244,7 +254,8 @@ function parse_git_dirty() {
|
|||||||
FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}"
|
FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -n 1)
|
# only non-emptiness matters, so keep one line instead of the whole list
|
||||||
|
__git_prompt_git status ${FLAGS} 2> /dev/null | read -r STATUS
|
||||||
fi
|
fi
|
||||||
if [[ -n $STATUS ]]; then
|
if [[ -n $STATUS ]]; then
|
||||||
echo "$ZSH_THEME_GIT_PROMPT_DIRTY"
|
echo "$ZSH_THEME_GIT_PROMPT_DIRTY"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ function chruby_prompt_info \
|
|||||||
azure_prompt_info \
|
azure_prompt_info \
|
||||||
tf_prompt_info \
|
tf_prompt_info \
|
||||||
conda_prompt_info \
|
conda_prompt_info \
|
||||||
|
go_prompt_info \
|
||||||
{
|
{
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -14,10 +14,16 @@ FX=(
|
|||||||
reverse "%{[07m%}" no-reverse "%{[27m%}"
|
reverse "%{[07m%}" no-reverse "%{[27m%}"
|
||||||
)
|
)
|
||||||
|
|
||||||
for color in {000..255}; do
|
# Build the tables with array operations instead of a 256-iteration loop
|
||||||
FG[$color]="%{[38;5;${color}m%}"
|
() {
|
||||||
BG[$color]="%{[48;5;${color}m%}"
|
setopt localoptions noksharrays
|
||||||
done
|
local -a codes fg bg
|
||||||
|
codes=({000..255})
|
||||||
|
fg=( "%{"$'\e'"[38;5;"${^codes}"m%}" )
|
||||||
|
bg=( "%{"$'\e'"[48;5;"${^codes}"m%}" )
|
||||||
|
FG=( ${codes:^fg} )
|
||||||
|
BG=( ${codes:^bg} )
|
||||||
|
}
|
||||||
|
|
||||||
# Show all 256 colors with color number
|
# Show all 256 colors with color number
|
||||||
function spectrum_ls() {
|
function spectrum_ls() {
|
||||||
|
|||||||
+8
-2
@@ -22,7 +22,8 @@ function title {
|
|||||||
print -Pn "\e]1;${1:q}\a" # set tab name
|
print -Pn "\e]1;${1:q}\a" # set tab name
|
||||||
;;
|
;;
|
||||||
screen*|tmux*)
|
screen*|tmux*)
|
||||||
print -Pn "\ek${1:q}\e\\" # set screen hardstatus
|
print -Pn "\e]2;${2:q}\e\\" # set tmux pane title
|
||||||
|
print -Pn "\ek${1:q}\e\\" # set screen hardstatus/tmux window name if `allow-rename` is on
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then
|
if [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then
|
||||||
@@ -31,7 +32,12 @@ function title {
|
|||||||
else
|
else
|
||||||
# Try to use terminfo to set the title if the feature is available
|
# Try to use terminfo to set the title if the feature is available
|
||||||
if (( ${+terminfo[fsl]} && ${+terminfo[tsl]} )); then
|
if (( ${+terminfo[fsl]} && ${+terminfo[tsl]} )); then
|
||||||
print -Pn "${terminfo[tsl]}$1${terminfo[fsl]}"
|
# Emit the capabilities with echoti so terminfo does its own parameter
|
||||||
|
# substitution: some terminals (vt320) take a column argument, and
|
||||||
|
# running prompt expansion over the capability string mangles it.
|
||||||
|
echoti tsl 0
|
||||||
|
print -Pn "$1"
|
||||||
|
echoti fsl
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -13,13 +13,40 @@ ZSH_THEME_RUBY_PROMPT_PREFIX="("
|
|||||||
ZSH_THEME_RUBY_PROMPT_SUFFIX=")"
|
ZSH_THEME_RUBY_PROMPT_SUFFIX=")"
|
||||||
|
|
||||||
|
|
||||||
|
# The command probes below fork a process each, and their result doesn't change
|
||||||
|
# from one shell to the next, so they're cached for a day (like lib/grep.zsh).
|
||||||
|
typeset -A __omz_probes
|
||||||
|
__omz_probe_cache="$ZSH_CACHE_DIR/appearance-probes"
|
||||||
|
__omz_probe_cached=("$__omz_probe_cache"(Nm-1))
|
||||||
|
[[ -z "$__omz_probe_cached" ]] || source "$__omz_probe_cache"
|
||||||
|
|
||||||
|
function __omz_test_cmd_args {
|
||||||
|
# Usage: __omz_test_cmd_args cmd args...
|
||||||
|
# Runs `cmd args... /dev/null` and remembers whether it succeeded, so a
|
||||||
|
# command needing two operands passes the first one itself:
|
||||||
|
# e.g. __omz_test_cmd_args gls --color -> gls --color /dev/null
|
||||||
|
# __omz_test_cmd_args diff --color /dev/null -> diff --color /dev/null /dev/null
|
||||||
|
local key="$*"
|
||||||
|
if (( ! ${+__omz_probes[$key]} )); then
|
||||||
|
command "$@" /dev/null &>/dev/null
|
||||||
|
__omz_probes[$key]=$?
|
||||||
|
if [[ -w "$ZSH_CACHE_DIR" ]]; then
|
||||||
|
print -r -- "__omz_probes=(" "${(@qqkv)__omz_probes}" ")" >| "$__omz_probe_cache"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return $__omz_probes[$key]
|
||||||
|
}
|
||||||
|
|
||||||
# Use diff --color if available
|
# Use diff --color if available
|
||||||
if command diff --color /dev/null{,} &>/dev/null; then
|
if __omz_test_cmd_args diff --color /dev/null; then
|
||||||
function diff {
|
function diff {
|
||||||
command diff --color "$@"
|
command diff --color "$@"
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Set up ls coloring. Done in a function so the early return below still
|
||||||
|
# reaches the cleanup at the end of this file.
|
||||||
|
() {
|
||||||
# Don't set ls coloring if disabled
|
# Don't set ls coloring if disabled
|
||||||
[[ "$DISABLE_LS_COLORS" != true ]] || return 0
|
[[ "$DISABLE_LS_COLORS" != true ]] || return 0
|
||||||
|
|
||||||
@@ -39,43 +66,39 @@ if [[ -z "$LS_COLORS" ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function test-ls-args {
|
|
||||||
# Usage: test-ls-args cmd args...
|
|
||||||
# e.g. test-ls-args gls --color
|
|
||||||
command "$@" /dev/null &>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find the option for using colors in ls, depending on the version
|
# Find the option for using colors in ls, depending on the version
|
||||||
case "$OSTYPE" in
|
case "$OSTYPE" in
|
||||||
netbsd*)
|
netbsd*)
|
||||||
# On NetBSD, test if `gls` (GNU ls) is installed (this one supports colors);
|
# On NetBSD, test if `gls` (GNU ls) is installed (this one supports colors);
|
||||||
# otherwise, leave ls as is, because NetBSD's ls doesn't support -G
|
# otherwise, leave ls as is, because NetBSD's ls doesn't support -G
|
||||||
test-ls-args gls --color && alias ls='gls --color=tty'
|
__omz_test_cmd_args gls --color && alias ls='gls --color=tty'
|
||||||
;;
|
;;
|
||||||
openbsd*)
|
openbsd*)
|
||||||
# On OpenBSD, `gls` (ls from GNU coreutils) and `colorls` (ls from base,
|
# On OpenBSD, `gls` (ls from GNU coreutils) and `colorls` (ls from base,
|
||||||
# with color and multibyte support) are available from ports.
|
# with color and multibyte support) are available from ports.
|
||||||
# `colorls` will be installed on purpose and can't be pulled in by installing
|
# `colorls` will be installed on purpose and can't be pulled in by installing
|
||||||
# coreutils (which might be installed for ), so prefer it to `gls`.
|
# coreutils (which might be installed for ), so prefer it to `gls`.
|
||||||
test-ls-args gls --color && alias ls='gls --color=tty'
|
__omz_test_cmd_args gls --color && alias ls='gls --color=tty'
|
||||||
test-ls-args colorls -G && alias ls='colorls -G'
|
__omz_test_cmd_args colorls -G && alias ls='colorls -G'
|
||||||
;;
|
;;
|
||||||
(darwin|freebsd)*)
|
(darwin|freebsd)*)
|
||||||
# This alias works by default just using $LSCOLORS
|
# This alias works by default just using $LSCOLORS
|
||||||
test-ls-args ls -G && alias ls='ls -G'
|
__omz_test_cmd_args ls -G && alias ls='ls -G'
|
||||||
# Only use GNU ls if installed and there are user defaults for $LS_COLORS,
|
# Only use GNU ls if installed and there are user defaults for $LS_COLORS,
|
||||||
# as the default coloring scheme is not very pretty
|
# as the default coloring scheme is not very pretty
|
||||||
zstyle -t ':omz:lib:theme-and-appearance' gnu-ls \
|
zstyle -t ':omz:lib:theme-and-appearance' gnu-ls \
|
||||||
&& test-ls-args gls --color \
|
&& __omz_test_cmd_args gls --color \
|
||||||
&& alias ls='gls --color=tty'
|
&& alias ls='gls --color=tty'
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if test-ls-args ls --color; then
|
if __omz_test_cmd_args ls --color; then
|
||||||
alias ls='ls --color=tty'
|
alias ls='ls --color=tty'
|
||||||
elif test-ls-args ls -G; then
|
elif __omz_test_cmd_args ls -G; then
|
||||||
alias ls='ls -G'
|
alias ls='ls -G'
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
unfunction test-ls-args
|
unfunction __omz_test_cmd_args
|
||||||
|
unset __omz_probes __omz_probe_cache __omz_probe_cached
|
||||||
|
|||||||
+39
-8
@@ -64,7 +64,7 @@ if [[ ! -w "$ZSH_CACHE_DIR" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Create cache and completions dir and add to $fpath
|
# Create cache and completions dir and add to $fpath
|
||||||
mkdir -p "$ZSH_CACHE_DIR/completions"
|
[[ -d "$ZSH_CACHE_DIR/completions" ]] || mkdir -p "$ZSH_CACHE_DIR/completions"
|
||||||
(( ${fpath[(Ie)$ZSH_CACHE_DIR/completions]} )) || fpath=("$ZSH_CACHE_DIR/completions" $fpath)
|
(( ${fpath[(Ie)$ZSH_CACHE_DIR/completions]} )) || fpath=("$ZSH_CACHE_DIR/completions" $fpath)
|
||||||
|
|
||||||
# Check for updates on initial load...
|
# Check for updates on initial load...
|
||||||
@@ -100,7 +100,28 @@ done
|
|||||||
# Figure out the SHORT hostname
|
# Figure out the SHORT hostname
|
||||||
if [[ "$OSTYPE" = darwin* ]]; then
|
if [[ "$OSTYPE" = darwin* ]]; then
|
||||||
# macOS's $HOST changes with dhcp, etc. Use LocalHostName if possible.
|
# macOS's $HOST changes with dhcp, etc. Use LocalHostName if possible.
|
||||||
SHORT_HOST=$(scutil --get LocalHostName 2>/dev/null) || SHORT_HOST="${HOST/.*/}"
|
# scutil costs a fork on every start, so remember its answer for a day
|
||||||
|
# (like lib/grep.zsh) and re-check sooner if $HOST changes.
|
||||||
|
__omz_host_cache="$ZSH_CACHE_DIR/localhostname"
|
||||||
|
__omz_host_cached=("$__omz_host_cache"(Nm-1))
|
||||||
|
__omz_host_key=
|
||||||
|
SHORT_HOST=
|
||||||
|
if [[ -n "$__omz_host_cached" ]]; then
|
||||||
|
if ! { read -r __omz_host_key && read -r SHORT_HOST } < "$__omz_host_cache"; then
|
||||||
|
__omz_host_key=
|
||||||
|
SHORT_HOST=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ "$__omz_host_key" != "$HOST" || -z "$SHORT_HOST" ]]; then
|
||||||
|
# only cache what scutil actually answered, so a transient failure
|
||||||
|
# doesn't pin the fallback name for a day
|
||||||
|
if SHORT_HOST=$(scutil --get LocalHostName 2>/dev/null) && [[ -n "$SHORT_HOST" ]]; then
|
||||||
|
[[ ! -w "$ZSH_CACHE_DIR" ]] || print -rl -- "$HOST" "$SHORT_HOST" >| "$__omz_host_cache"
|
||||||
|
else
|
||||||
|
SHORT_HOST="${HOST/.*/}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
unset __omz_host_cache __omz_host_cached __omz_host_key
|
||||||
else
|
else
|
||||||
SHORT_HOST="${HOST/.*/}"
|
SHORT_HOST="${HOST/.*/}"
|
||||||
fi
|
fi
|
||||||
@@ -114,9 +135,17 @@ fi
|
|||||||
zcompdump_revision="#omz revision: $(builtin cd -q "$ZSH"; git rev-parse HEAD 2>/dev/null)"
|
zcompdump_revision="#omz revision: $(builtin cd -q "$ZSH"; git rev-parse HEAD 2>/dev/null)"
|
||||||
zcompdump_fpath="#omz fpath: $fpath"
|
zcompdump_fpath="#omz fpath: $fpath"
|
||||||
|
|
||||||
|
# Check whether the zcompdump file carries the current OMZ metadata lines
|
||||||
|
_omz_compdump_has_metadata() {
|
||||||
|
local -a lines
|
||||||
|
[[ -r "$ZSH_COMPDUMP" ]] || return 1
|
||||||
|
lines=("${(@f)$(<"$ZSH_COMPDUMP")}")
|
||||||
|
(( ${lines[(Ie)$zcompdump_revision]} && ${lines[(Ie)$zcompdump_fpath]} ))
|
||||||
|
}
|
||||||
|
|
||||||
# Delete the zcompdump file if OMZ zcompdump metadata changed
|
# Delete the zcompdump file if OMZ zcompdump metadata changed
|
||||||
if ! command grep -q -Fx "$zcompdump_revision" "$ZSH_COMPDUMP" 2>/dev/null \
|
zcompdump_refresh=0
|
||||||
|| ! command grep -q -Fx "$zcompdump_fpath" "$ZSH_COMPDUMP" 2>/dev/null; then
|
if ! _omz_compdump_has_metadata; then
|
||||||
command rm -f "$ZSH_COMPDUMP"
|
command rm -f "$ZSH_COMPDUMP"
|
||||||
zcompdump_refresh=1
|
zcompdump_refresh=1
|
||||||
fi
|
fi
|
||||||
@@ -134,9 +163,8 @@ else
|
|||||||
compinit -u -d "$ZSH_COMPDUMP"
|
compinit -u -d "$ZSH_COMPDUMP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Append zcompdump metadata if missing
|
# Append zcompdump metadata if missing (compinit may have regenerated the file)
|
||||||
if (( $zcompdump_refresh )) \
|
if (( zcompdump_refresh )) || ! _omz_compdump_has_metadata; then
|
||||||
|| ! command grep -q -Fx "$zcompdump_revision" "$ZSH_COMPDUMP" 2>/dev/null; then
|
|
||||||
# Use `tee` in case the $ZSH_COMPDUMP filename is invalid, to silence the error
|
# Use `tee` in case the $ZSH_COMPDUMP filename is invalid, to silence the error
|
||||||
# See https://github.com/ohmyzsh/ohmyzsh/commit/dd1a7269#commitcomment-39003489
|
# See https://github.com/ohmyzsh/ohmyzsh/commit/dd1a7269#commitcomment-39003489
|
||||||
tee -a "$ZSH_COMPDUMP" &>/dev/null <<EOF
|
tee -a "$ZSH_COMPDUMP" &>/dev/null <<EOF
|
||||||
@@ -146,9 +174,12 @@ $zcompdump_fpath
|
|||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
unset zcompdump_revision zcompdump_fpath zcompdump_refresh
|
unset zcompdump_revision zcompdump_fpath zcompdump_refresh
|
||||||
|
unset -f _omz_compdump_has_metadata
|
||||||
|
|
||||||
# zcompile the completion dump file if the .zwc is older or missing.
|
# zcompile the completion dump file if the .zwc is older or missing.
|
||||||
if command mkdir "${ZSH_COMPDUMP}.lock" 2>/dev/null; then
|
# Test that first so the lock directory and zrecompile are skipped when it's fresh.
|
||||||
|
if [[ ! "${ZSH_COMPDUMP}.zwc" -nt "$ZSH_COMPDUMP" ]] \
|
||||||
|
&& command mkdir "${ZSH_COMPDUMP}.lock" 2>/dev/null; then
|
||||||
zrecompile -q -p "$ZSH_COMPDUMP"
|
zrecompile -q -p "$ZSH_COMPDUMP"
|
||||||
command rm -rf "$ZSH_COMPDUMP.zwc.old" "${ZSH_COMPDUMP}.lock"
|
command rm -rf "$ZSH_COMPDUMP.zwc.old" "${ZSH_COMPDUMP}.lock"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
# AppSignal CLI plugin
|
||||||
|
|
||||||
|
This plugin adds aliases, guard rails and completion for the
|
||||||
|
[AppSignal CLI](https://docs.appsignal.com/cli).
|
||||||
|
|
||||||
|
To use it, add `appsignal-cli` to the plugins array in your zshrc file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
plugins=(... appsignal-cli)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
[AppSignal CLI](https://docs.appsignal.com/cli) 2.1 or newer, installed and on
|
||||||
|
your `PATH`. The plugin does nothing if it is not:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
brew install appsignal/appsignal-cli/appsignal-cli
|
||||||
|
# or
|
||||||
|
curl -sSL https://github.com/appsignal/appsignal-cli/releases/latest/download/install.sh | sudo sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Most commands need `appsignal-cli auth login` first.
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
| Alias | Command | Description |
|
||||||
|
| :------ | :----------------------------- | :--------------------------------- |
|
||||||
|
| `asig` | `appsignal-cli` | The AppSignal CLI itself |
|
||||||
|
| `aslog` | `appsignal-cli logs tail` | Stream log lines as they arrive |
|
||||||
|
| `asinc` | `appsignal-cli incidents list` | List incidents for an application |
|
||||||
|
|
||||||
|
`aslog` and `asinc` complete like the commands they stand in for, so
|
||||||
|
`aslog --<TAB>` offers the flags of `appsignal-cli logs tail`.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
| :-------------- | :----------------------------------------------------------------- |
|
||||||
|
| `appsignal-cli` | Wraps the CLI to confirm before irreversible commands. See Settings |
|
||||||
|
|
||||||
|
## Completion
|
||||||
|
|
||||||
|
Every command completes with a description of what it does, at every level, and
|
||||||
|
so do their flags and allowed values: incident states and severities, sort
|
||||||
|
orders, log severities, trigger fields and comparison operators, output formats
|
||||||
|
and skill targets. `samples` and `sample` complete like `traces`, as they do in
|
||||||
|
the CLI itself.
|
||||||
|
|
||||||
|
`--org` completes offline from the `org` key of your project's
|
||||||
|
`.appsignal.toml` and of the global config.
|
||||||
|
|
||||||
|
The AppSignal CLI ships no completion generator of its own, so `_appsignal-cli`
|
||||||
|
is written from its command definitions and kept in this repository. It targets
|
||||||
|
AppSignal CLI 2.1.x.
|
||||||
|
|
||||||
|
## Settings
|
||||||
|
|
||||||
|
Set these with `zstyle` in your zshrc, before Oh My Zsh is sourced.
|
||||||
|
|
||||||
|
### Confirming destructive commands
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:appsignal-cli' confirm-destructive no
|
||||||
|
```
|
||||||
|
|
||||||
|
By default the plugin asks for confirmation before four operations that the CLI
|
||||||
|
itself performs without a prompt:
|
||||||
|
|
||||||
|
- `appsignal-cli logs metrics delete`
|
||||||
|
- `appsignal-cli logs triggers delete`
|
||||||
|
- `appsignal-cli triggers archive`, which also closes the trigger's alerts and
|
||||||
|
incidents
|
||||||
|
- `appsignal-cli incidents update --state CLOSED` when it names more than one
|
||||||
|
incident, since that flag accepts a comma-separated list
|
||||||
|
|
||||||
|
Nothing else is intercepted, and the prompt is skipped when stdin is not a
|
||||||
|
terminal, so scripts, pipelines and CI are unaffected. Set the style to `no` to
|
||||||
|
turn the prompt off entirely, or run `command appsignal-cli` for a single
|
||||||
|
invocation.
|
||||||
|
|
||||||
|
### Completing applications
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:appsignal-cli' dynamic-app-completion yes
|
||||||
|
```
|
||||||
|
|
||||||
|
Off by default. When enabled, `--app`, `--app-id` and `--environment` are
|
||||||
|
completed from `appsignal-cli apps list --output json`, showing each
|
||||||
|
application's name and environment next to its ID instead of making you copy
|
||||||
|
IDs by hand. It is opt-in because it runs the CLI and makes a network call when
|
||||||
|
you press <kbd>Tab</kbd>, and because it needs you to be authenticated. Results
|
||||||
|
are cached for five minutes.
|
||||||
|
|
||||||
|
### Disabling the aliases
|
||||||
|
|
||||||
|
This works for every Oh My Zsh plugin:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:appsignal-cli' aliases no
|
||||||
|
```
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
- `appsignal-cli` and the AppSignal Ruby gem's `appsignal` command are different
|
||||||
|
tools. The gem's command installs and diagnoses the agent inside your app;
|
||||||
|
this one queries your data. The plugin deliberately leaves `appsignal` alone,
|
||||||
|
so it keeps working in projects that use the gem.
|
||||||
|
- `appsignal-cli` is a shell function here. Run `command appsignal-cli` to reach
|
||||||
|
the binary directly.
|
||||||
|
- Most commands need exactly one of `--app-id` or `--app`. `--environment` only
|
||||||
|
narrows `--app`; it does nothing next to `--app-id`.
|
||||||
|
- `appsignal-cli project init` writes `.appsignal.toml`, and `auth login` then
|
||||||
|
stores OAuth tokens in it. Do not commit that file.
|
||||||
|
- `incidents delete-note`, `auth logout` and the `--clear-*` flags of
|
||||||
|
`logs metrics update` and `logs triggers update` are destructive too, but are
|
||||||
|
not prompted for: each affects a single note, login or field.
|
||||||
|
- `triggers create` and `triggers update` have their own `--format`, for the
|
||||||
|
format of the metric value. Everywhere else `--format` is a synonym for
|
||||||
|
`--output`.
|
||||||
|
- The CLI sends usage telemetry by default. `APPSIGNAL_CLI_TELEMETRY=0` turns it
|
||||||
|
off, and `APPSIGNAL_CLI_DEBUG=1` shows internal errors.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,108 @@
|
|||||||
|
# AppSignal CLI: completion, aliases and guard rails.
|
||||||
|
# https://docs.appsignal.com/cli
|
||||||
|
|
||||||
|
if (( ! $+commands[appsignal-cli] )); then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Does this invocation need confirming? Sets REPLY to the reason.
|
||||||
|
#
|
||||||
|
# The command path is collected from the leading bare words. Only the global
|
||||||
|
# flags may precede a subcommand, so the first other flag ends the path: that
|
||||||
|
# way an option value such as `--app "My App"` is never mistaken for one.
|
||||||
|
function _appsignal_cli_is_destructive() {
|
||||||
|
zstyle -T ':omz:plugins:appsignal-cli' confirm-destructive || return 1
|
||||||
|
|
||||||
|
# Nobody to answer: CI and pipelines are unaffected.
|
||||||
|
[[ -t 0 ]] || return 1
|
||||||
|
|
||||||
|
local -a args=("$@") path numbers
|
||||||
|
local arg state=""
|
||||||
|
integer i=1 n=$# path_done=0
|
||||||
|
|
||||||
|
while (( i <= n )); do
|
||||||
|
arg="$args[i]"
|
||||||
|
case "$arg" in
|
||||||
|
--) break ;;
|
||||||
|
--state=*) state="${arg#--state=}"; path_done=1 ;;
|
||||||
|
--state) state="$args[i+1]"; (( i++ )); path_done=1 ;;
|
||||||
|
--number=*) numbers+=(${(s:,:)${arg#--number=}}); path_done=1 ;;
|
||||||
|
# --number takes one or more values, comma-separated or repeated.
|
||||||
|
--number)
|
||||||
|
path_done=1
|
||||||
|
while (( i < n )) && [[ "$args[i+1]" != -* ]]; do
|
||||||
|
(( i++ ))
|
||||||
|
numbers+=(${(s:,:)args[i]})
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
# The output flag is global, so it can appear before the subcommand.
|
||||||
|
-o|--output|--format) (( i++ )) ;;
|
||||||
|
-o*|--output=*|--format=*) ;;
|
||||||
|
-*) path_done=1 ;;
|
||||||
|
*) (( path_done )) || path+=("$arg") ;;
|
||||||
|
esac
|
||||||
|
(( i++ ))
|
||||||
|
done
|
||||||
|
|
||||||
|
case "${(j: :)path[1,3]}" in
|
||||||
|
"logs metrics delete")
|
||||||
|
REPLY="deleting a log-derived metric cannot be undone."
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
"logs triggers delete")
|
||||||
|
REPLY="deleting a log-based trigger cannot be undone."
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
"triggers archive")
|
||||||
|
REPLY="archiving a trigger also closes its alerts and incidents."
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
"incidents update")
|
||||||
|
if [[ "${(U)state}" == CLOSED ]] && (( $#numbers > 1 )); then
|
||||||
|
REPLY="this closes $#numbers incidents at once."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Adds a confirmation prompt before irreversible operations. Everything else
|
||||||
|
# passes straight through, so `logs tail` keeps streaming and pipes stay clean.
|
||||||
|
function appsignal-cli() {
|
||||||
|
local REPLY
|
||||||
|
if _appsignal_cli_is_destructive "$@"; then
|
||||||
|
print -u2 -- "appsignal-cli: $REPLY"
|
||||||
|
if ! read -q "?Continue? [y/N] "; then
|
||||||
|
print -u2 -- ""
|
||||||
|
return 130
|
||||||
|
fi
|
||||||
|
print -u2 -- ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
command appsignal-cli "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Complete the aliases like the commands they stand in for.
|
||||||
|
if (( $+functions[compdef] )); then
|
||||||
|
_aslog() {
|
||||||
|
words=(appsignal-cli logs tail ${words[2,-1]})
|
||||||
|
(( CURRENT += 2 ))
|
||||||
|
_appsignal-cli
|
||||||
|
}
|
||||||
|
|
||||||
|
_asinc() {
|
||||||
|
words=(appsignal-cli incidents list ${words[2,-1]})
|
||||||
|
(( CURRENT += 2 ))
|
||||||
|
_appsignal-cli
|
||||||
|
}
|
||||||
|
|
||||||
|
compdef _appsignal-cli asig
|
||||||
|
compdef _aslog aslog
|
||||||
|
compdef _asinc asinc
|
||||||
|
fi
|
||||||
|
|
||||||
|
alias asig='appsignal-cli'
|
||||||
|
alias aslog='appsignal-cli logs tail'
|
||||||
|
alias asinc='appsignal-cli incidents list'
|
||||||
@@ -241,7 +241,7 @@ function aws_regions() {
|
|||||||
function aws_profiles() {
|
function aws_profiles() {
|
||||||
aws --no-cli-pager configure list-profiles 2> /dev/null && return
|
aws --no-cli-pager configure list-profiles 2> /dev/null && return
|
||||||
[[ -r "${AWS_CONFIG_FILE:-$HOME/.aws/config}" ]] || return 1
|
[[ -r "${AWS_CONFIG_FILE:-$HOME/.aws/config}" ]] || return 1
|
||||||
grep --color=never -Eo '\[.*\]' "${AWS_CONFIG_FILE:-$HOME/.aws/config}" | sed -E 's/^[[:space:]]*\[(profile)?[[:space:]]*([^[:space:]]+)\][[:space:]]*$/\2/g'
|
command grep -Eo '^[[:space:]]*\[[[:space:]]*(profile[[:space:]]+)?[^][:space:]]+[[:space:]]*\]' "${AWS_CONFIG_FILE:-$HOME/.aws/config}" | command sed -E 's/^[[:space:]]*\[[[:space:]]*(profile[[:space:]]+)?([^][:space:]]+)[[:space:]]*\]$/\2/'
|
||||||
}
|
}
|
||||||
|
|
||||||
function _aws_regions() {
|
function _aws_regions() {
|
||||||
|
|||||||
@@ -99,18 +99,21 @@ $ find . -type f 2>/dev/null
|
|||||||
## File extension aliases
|
## File extension aliases
|
||||||
|
|
||||||
These are special aliases that are triggered when a file name is passed as the command. For example,
|
These are special aliases that are triggered when a file name is passed as the command. For example,
|
||||||
if the pdf file extension is aliased to `acroread` (a popular Linux pdf reader), when running `file.pdf`
|
if the pdf file extension is aliased to `open_command`, running `file.pdf` opens that file with
|
||||||
that file will be open with `acroread`.
|
whatever application your system uses for PDFs.
|
||||||
|
|
||||||
### Reading Docs
|
### Reading Docs
|
||||||
|
|
||||||
|
These use `open_command`, which picks the right opener for your platform: `open` on macOS,
|
||||||
|
`xdg-open` on Linux, `cygstart` on Cygwin.
|
||||||
|
|
||||||
| Alias | Command | Description |
|
| Alias | Command | Description |
|
||||||
| ----- | ---------- | ---------------------------------- |
|
| ----- | -------------- | ----------------------------------------------- |
|
||||||
| pdf | `acroread` | Opens up a document using acroread |
|
| pdf | `open_command` | Opens up a .pdf file in your default viewer |
|
||||||
| ps | `gv` | Opens up a .ps file using gv |
|
| ps | `open_command` | Opens up a .ps file in your default viewer |
|
||||||
| dvi | `xdvi` | Opens up a .dvi file using xdvi |
|
| dvi | `open_command` | Opens up a .dvi file in your default viewer |
|
||||||
| chm | `xchm` | Opens up a .chm file using xchm |
|
| chm | `open_command` | Opens up a .chm file in your default viewer |
|
||||||
| djvu | `djview` | Opens up a .djvu file using djview |
|
| djvu | `open_command` | Opens up a .djvu file in your default viewer |
|
||||||
|
|
||||||
### Listing files inside a packed file
|
### Listing files inside a packed file
|
||||||
|
|
||||||
|
|||||||
@@ -71,12 +71,9 @@ if is-at-least 4.2.0; then
|
|||||||
_media_fts=(ape avi flv m4a mkv mov mp3 mpeg mpg ogg ogm rm wav webm)
|
_media_fts=(ape avi flv m4a mkv mov mp3 mpeg mpg ogg ogm rm wav webm)
|
||||||
for ft in $_media_fts; do alias -s $ft=mplayer; done
|
for ft in $_media_fts; do alias -s $ft=mplayer; done
|
||||||
|
|
||||||
#read documents
|
# read documents with the platform's default application
|
||||||
alias -s pdf=acroread
|
_doc_fts=(pdf ps dvi chm djvu)
|
||||||
alias -s ps=gv
|
for ft in $_doc_fts; do alias -s $ft=open_command; done
|
||||||
alias -s dvi=xdvi
|
|
||||||
alias -s chm=xchm
|
|
||||||
alias -s djvu=djview
|
|
||||||
|
|
||||||
#list what's inside packed file
|
#list what's inside packed file
|
||||||
alias -s zip="unzip -l"
|
alias -s zip="unzip -l"
|
||||||
|
|||||||
@@ -1,14 +1,33 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
emacsfun() {
|
emacsfun() {
|
||||||
local cmd frames
|
local cmd frames arg tty
|
||||||
|
|
||||||
# Build the Emacs Lisp command to check for suitable frames
|
# Build the Emacs Lisp command to check for suitable frames
|
||||||
# See https://www.gnu.org/software/emacs/manual/html_node/elisp/Frames.html#index-framep
|
# See https://www.gnu.org/software/emacs/manual/html_node/elisp/Frames.html#index-framep
|
||||||
case "$*" in
|
for arg in "$@"; do
|
||||||
*-t*|*--tty*|*-nw*) cmd="(memq 't (mapcar 'framep (frame-list)))" ;; # if != nil, there are tty frames
|
case "$arg" in
|
||||||
*) cmd="(delete 't (mapcar 'framep (frame-list)))" ;; # if != nil, there are graphical terminals (x, w32, ns)
|
-t|--tty|-nw) tty=1; break ;;
|
||||||
esac
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$tty" ]; then
|
||||||
|
cmd="(memq 't (mapcar 'framep (frame-list)))" # if != nil, there are tty frames
|
||||||
|
else
|
||||||
|
cmd="(delete 't (mapcar 'framep (frame-list)))" # if != nil, there are graphical terminals (x, w32, ns)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A tty frame needs the client to stay attached, so drop the --no-wait the
|
||||||
|
# `emacs` alias adds. Otherwise emacsclient returns at once and nothing opens.
|
||||||
|
if [ -n "$tty" ]; then
|
||||||
|
for arg do
|
||||||
|
shift
|
||||||
|
case "$arg" in
|
||||||
|
--no-wait) continue ;;
|
||||||
|
esac
|
||||||
|
set -- "$@" "$arg"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
# Check if there are suitable frames
|
# Check if there are suitable frames
|
||||||
frames="$(emacsclient -a '' -n -e "$cmd" 2>/dev/null |sed 's/.*\x07//g' )"
|
frames="$(emacsclient -a '' -n -e "$cmd" 2>/dev/null |sed 's/.*\x07//g' )"
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ plugins=(... git)
|
|||||||
| `glods` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset' --date=short` |
|
| `glods` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset' --date=short` |
|
||||||
| `glol` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'` |
|
| `glol` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'` |
|
||||||
| `glola` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset' --all` |
|
| `glola` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset' --all` |
|
||||||
|
| `glolm` | `git log $(git_main_branch) --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset'` |
|
||||||
| `glols` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset' --stat` |
|
| `glols` | `git log --graph --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset' --stat` |
|
||||||
| `glo` | `git log --oneline --decorate` |
|
| `glo` | `git log --oneline --decorate` |
|
||||||
| `glog` | `git log --oneline --decorate --graph` |
|
| `glog` | `git log --oneline --decorate --graph` |
|
||||||
@@ -254,6 +255,7 @@ receive further support.
|
|||||||
| `git_current_user_name` | Returns the `user.name` config value (Lives in `lib/git.zsh`) |
|
| `git_current_user_name` | Returns the `user.name` config value (Lives in `lib/git.zsh`) |
|
||||||
| `git_develop_branch` | Returns the name of the “development” branch: `dev`, `devel`, `development` if they exist, `develop` otherwise |
|
| `git_develop_branch` | Returns the name of the “development” branch: `dev`, `devel`, `development` if they exist, `develop` otherwise |
|
||||||
| `git_main_branch` | Returns the name of the main branch: `main` if it exists, `master` otherwise |
|
| `git_main_branch` | Returns the name of the main branch: `main` if it exists, `master` otherwise |
|
||||||
|
| `gbcopy` | Copies current branch name to clipboard |
|
||||||
| `grename <old> <new>` | Renames branch `<old>` to `<new>`, including on the origin remote |
|
| `grename <old> <new>` | Renames branch `<old>` to `<new>`, including on the origin remote |
|
||||||
| `gbda` | Deletes all merged branches |
|
| `gbda` | Deletes all merged branches |
|
||||||
| `gbds` | Deletes all squash-merged branches (**Note: performance degrades with number of branches**) |
|
| `gbds` | Deletes all squash-merged branches (**Note: performance degrades with number of branches**) |
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ function git_main_branch() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gbcopy() {
|
||||||
|
command git rev-parse --git-dir &>/dev/null || return
|
||||||
|
|
||||||
|
local branch
|
||||||
|
branch="$(git_current_branch)" || return
|
||||||
|
[[ -n "$branch" ]] || return 1
|
||||||
|
|
||||||
|
print -rn -- "$branch" | clipcopy
|
||||||
|
}
|
||||||
|
|
||||||
function grename() {
|
function grename() {
|
||||||
if [[ -z "$1" || -z "$2" ]]; then
|
if [[ -z "$1" || -z "$2" ]]; then
|
||||||
echo "Usage: $0 old_branch new_branch"
|
echo "Usage: $0 old_branch new_branch"
|
||||||
@@ -239,6 +249,7 @@ alias glod='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgre
|
|||||||
alias glola='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --all'
|
alias glola='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --all'
|
||||||
alias glols='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --stat'
|
alias glols='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --stat'
|
||||||
alias glol='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"'
|
alias glol='git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"'
|
||||||
|
alias glolm='git log $(git_main_branch) --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"'
|
||||||
alias glo='git log --oneline --decorate'
|
alias glo='git log --oneline --decorate'
|
||||||
alias glog='git log --oneline --decorate --graph'
|
alias glog='git log --oneline --decorate --graph'
|
||||||
alias gloga='git log --oneline --decorate --graph --all'
|
alias gloga='git log --oneline --decorate --graph --all'
|
||||||
|
|||||||
@@ -39,3 +39,18 @@ plugins=(... golang)
|
|||||||
| gov | `go vet` | Vet examines Go source code and reports suspicious constructs |
|
| gov | `go vet` | Vet examines Go source code and reports suspicious constructs |
|
||||||
| gove | `go version` | Prints Go version |
|
| gove | `go version` | Prints Go version |
|
||||||
| gow | `go work` | Work provides access to operations on workspaces |
|
| gow | `go work` | Work provides access to operations on workspaces |
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
This plugin provides the `go_prompt_info` function to add the installed Go
|
||||||
|
version to your prompt.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```
|
||||||
|
PROMPT="%~$ "
|
||||||
|
RPROMPT='$(go_prompt_info)'
|
||||||
|
```
|
||||||
|
changes your prompt to:
|
||||||
|
```
|
||||||
|
~/go/project$ ▋ 1.22.3
|
||||||
|
```
|
||||||
|
|||||||
+95
-11
@@ -81,6 +81,7 @@ _go() {
|
|||||||
'tool[run specified go tool]'
|
'tool[run specified go tool]'
|
||||||
'version[print Go version]'
|
'version[print Go version]'
|
||||||
'vet[run go tool vet on packages]'
|
'vet[run go tool vet on packages]'
|
||||||
|
'work[workspace maintenance]'
|
||||||
)
|
)
|
||||||
if (( CURRENT == 2 )); then
|
if (( CURRENT == 2 )); then
|
||||||
# explain go commands
|
# explain go commands
|
||||||
@@ -88,19 +89,38 @@ _go() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
build_flags=(
|
build_flags=(
|
||||||
'-a[force reinstallation of packages that are already up to date]'
|
'-C[change to dir before running the command]:directory:_path_files -/'
|
||||||
|
'-a[force rebuilding of packages that are already up-to-date]'
|
||||||
'-n[print the commands but do not run them]'
|
'-n[print the commands but do not run them]'
|
||||||
'-p[number of parallel builds]:number'
|
'-p[number of parallel builds]:number'
|
||||||
'-race[enable data race detection]'
|
'-race[enable data race detection]'
|
||||||
'-x[print the commands]'
|
'-msan[enable interoperation with memory sanitizer]'
|
||||||
|
'-asan[enable interoperation with address sanitizer]'
|
||||||
|
'-cover[enable code coverage instrumentation]'
|
||||||
|
'-covermode[set the mode for coverage analysis]:mode:(set count atomic)'
|
||||||
|
'-coverpkg[apply coverage analysis to matching packages]:pattern'
|
||||||
|
'-v[print the names of packages as they are compiled]'
|
||||||
'-work[print temporary directory name and keep it]'
|
'-work[print temporary directory name and keep it]'
|
||||||
'-ccflags[flags for 5c/6c/8c]:flags'
|
'-x[print the commands]'
|
||||||
'-gcflags[flags for 5g/6g/8g]:flags'
|
'-asmflags[arguments to pass on each go tool asm invocation]:flags'
|
||||||
'-ldflags[flags for 5l/6l/8l]:flags'
|
'-buildmode[build mode to use]:mode:(archive c-archive c-shared default shared exe pie plugin)'
|
||||||
'-gccgoflags[flags for gccgo]:flags'
|
'-buildvcs[stamp binaries with version control information]:mode:(true false auto)'
|
||||||
'-compiler[name of compiler to use]:name'
|
'-compiler[name of compiler to use]:name:(gccgo gc)'
|
||||||
'-installsuffix[suffix to add to package directory]:suffix'
|
'-gccgoflags[arguments to pass on each gccgo compiler/linker invocation]:flags'
|
||||||
|
'-gcflags[arguments to pass on each go tool compile invocation]:flags'
|
||||||
|
'-installsuffix[suffix to use in the package installation directory]:suffix'
|
||||||
|
'-json[emit build output in JSON suitable for automated processing]'
|
||||||
|
'-ldflags[arguments to pass on each go tool link invocation]:flags'
|
||||||
|
'-linkshared[build code that will be linked against shared libraries]'
|
||||||
|
'-mod[module download mode to use]:mode:(readonly vendor mod)'
|
||||||
|
'-modcacherw[leave newly-created directories in the module cache read-write]'
|
||||||
|
'-modfile[read and write an alternate go.mod file]:file:_files -g "*.mod"'
|
||||||
|
'-overlay[read a JSON config file that provides an overlay for build operations]:file:_files -g "*.json"'
|
||||||
|
'-pgo[specify the file path of a profile for profile-guided optimization]:file:_files'
|
||||||
|
'-pkgdir[install and load all packages from dir]:directory:_path_files -/'
|
||||||
'-tags[list of build tags to consider satisfied]:tags'
|
'-tags[list of build tags to consider satisfied]:tags'
|
||||||
|
'-trimpath[remove all file system paths from the resulting executable]'
|
||||||
|
'-toolexec[program to use to invoke toolchain programs]:command'
|
||||||
)
|
)
|
||||||
|
|
||||||
case ${words[2]} in
|
case ${words[2]} in
|
||||||
@@ -125,17 +145,20 @@ _go() {
|
|||||||
;;
|
;;
|
||||||
install)
|
install)
|
||||||
_arguments -s -w : ${build_flags[@]} \
|
_arguments -s -w : ${build_flags[@]} \
|
||||||
"-v[show package names]" \
|
|
||||||
'*:importpaths:__go_packages'
|
'*:importpaths:__go_packages'
|
||||||
;;
|
;;
|
||||||
get)
|
get)
|
||||||
_arguments -s -w : \
|
_arguments -s -w : \
|
||||||
${build_flags[@]}
|
${build_flags[@]} \
|
||||||
|
"-t[consider modules needed to build tests of packages]" \
|
||||||
|
"-u[update modules providing dependencies to newer minor or patch releases]" \
|
||||||
|
"-u=[update modules providing dependencies to patch releases]:mode:(patch)" \
|
||||||
|
"-tool[add a matching tool line to go.mod for each listed package]" \
|
||||||
|
"*:importpaths:__go_packages"
|
||||||
;;
|
;;
|
||||||
build)
|
build)
|
||||||
_arguments -s -w : \
|
_arguments -s -w : \
|
||||||
${build_flags[@]} \
|
${build_flags[@]} \
|
||||||
"-v[show package names]" \
|
|
||||||
"-o[output file]:file:_files" \
|
"-o[output file]:file:_files" \
|
||||||
"*:args:{ _alternative ':importpaths:__go_packages' ':files:_path_files -g \"*.go\"' }"
|
"*:args:{ _alternative ':importpaths:__go_packages' ':files:_path_files -g \"*.go\"' }"
|
||||||
;;
|
;;
|
||||||
@@ -238,6 +261,60 @@ _go() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
work)
|
||||||
|
local -a work_commands
|
||||||
|
work_commands+=(
|
||||||
|
'edit[edit go.work from tools or scripts]'
|
||||||
|
'init[initialize workspace file]'
|
||||||
|
'sync[sync workspace build list to modules]'
|
||||||
|
'use[add modules to workspace file]'
|
||||||
|
'vendor[make vendored copy of dependencies]'
|
||||||
|
)
|
||||||
|
|
||||||
|
if (( CURRENT == 3 )); then
|
||||||
|
_values 'go work commands' ${work_commands[@]} "help[display help]"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
case ${words[3]} in
|
||||||
|
help)
|
||||||
|
_values 'go work commands' ${work_commands[@]}
|
||||||
|
;;
|
||||||
|
edit)
|
||||||
|
_arguments -s -w : \
|
||||||
|
"-fmt[reformat the go.work file]" \
|
||||||
|
"-godebug[=key=value add a godebug key=value line]:key=value" \
|
||||||
|
"-dropgodebug[=key drop an existing godebug line]:key" \
|
||||||
|
"-use[=path add a use directive]:directory:_path_files -/" \
|
||||||
|
"-dropuse[=path drop a use directive]:directory:_path_files -/" \
|
||||||
|
"-replace[=old{@v}=new{@v} add a replacement of the given module path and version pair]:name" \
|
||||||
|
"-dropreplace[=old{@v} drop a replacement of the given module path and version pair]:name" \
|
||||||
|
"-go[={version} set the expected Go language version]:number" \
|
||||||
|
"-toolchain[=name set the Go toolchain to use]:name" \
|
||||||
|
"-print[print the final go.work in its text format]" \
|
||||||
|
"-json[print the final go.work file in JSON format]" \
|
||||||
|
"1:go.work file:_files -g 'go.work'"
|
||||||
|
;;
|
||||||
|
init)
|
||||||
|
_arguments -s -w : \
|
||||||
|
"*:module directories:_path_files -/"
|
||||||
|
;;
|
||||||
|
sync)
|
||||||
|
;;
|
||||||
|
use)
|
||||||
|
_arguments -s -w : \
|
||||||
|
"-r[search recursively for modules in the argument directories]" \
|
||||||
|
"*:module directories:_path_files -/"
|
||||||
|
;;
|
||||||
|
vendor)
|
||||||
|
_arguments -s -w : \
|
||||||
|
"-e[attempt to proceed despite errors encountered while loading packages]" \
|
||||||
|
"-v[print the names of vendored modules and packages]" \
|
||||||
|
"-o[create the vendor directory at the given path]:output directory:_path_files -/" \
|
||||||
|
"*:flags"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
help)
|
help)
|
||||||
_values "${commands[@]}" \
|
_values "${commands[@]}" \
|
||||||
'environment[show Go environment variables available]' \
|
'environment[show Go environment variables available]' \
|
||||||
@@ -247,6 +324,13 @@ _go() {
|
|||||||
'testflag[description of testing flags]' \
|
'testflag[description of testing flags]' \
|
||||||
'testfunc[description of testing functions]'
|
'testfunc[description of testing functions]'
|
||||||
;;
|
;;
|
||||||
|
version)
|
||||||
|
_arguments -s -w : \
|
||||||
|
"-m[print module version information]" \
|
||||||
|
"-v[report unrecognized files]" \
|
||||||
|
"-json[print module version information in JSON format]" \
|
||||||
|
"*:file:_files"
|
||||||
|
;;
|
||||||
run)
|
run)
|
||||||
_arguments -s -w : \
|
_arguments -s -w : \
|
||||||
${build_flags[@]} \
|
${build_flags[@]} \
|
||||||
|
|||||||
@@ -36,3 +36,12 @@ alias gotofx='go tool fix'
|
|||||||
alias gov='go vet'
|
alias gov='go vet'
|
||||||
alias gove='go version'
|
alias gove='go version'
|
||||||
alias gow='go work'
|
alias gow='go work'
|
||||||
|
|
||||||
|
## prompt
|
||||||
|
function go_prompt_info() {
|
||||||
|
(( $+commands[go] )) || return
|
||||||
|
local go_prompt
|
||||||
|
go_prompt=$(go version | awk '{ print substr($3, 3) }')
|
||||||
|
[[ -z "${go_prompt}" ]] && return
|
||||||
|
echo "${ZSH_THEME_GO_PROMPT_PREFIX}${go_prompt:gs/%/%%}${ZSH_THEME_GO_PROMPT_SUFFIX}"
|
||||||
|
}
|
||||||
|
|||||||
+10
-4
@@ -284,6 +284,9 @@ __gradle_subcommand() {
|
|||||||
'-Dorg.gradle.debug.suspend=[]' \
|
'-Dorg.gradle.debug.suspend=[]' \
|
||||||
'-Dorg.gradle.debug=[]:org.gradle.debug:(true false)' \
|
'-Dorg.gradle.debug=[]:org.gradle.debug:(true false)' \
|
||||||
'-Dorg.gradle.dependency.verification=[Configures the dependency verification mode. Supported values are 'strict', 'lenient', or 'off'.]:org.gradle.dependency.verification:(strict lenient off)' \
|
'-Dorg.gradle.dependency.verification=[Configures the dependency verification mode. Supported values are 'strict', 'lenient', or 'off'.]:org.gradle.dependency.verification:(strict lenient off)' \
|
||||||
|
'-Dorg.gradle.isolated-projects.dangerously-ignore-problems=[]' \
|
||||||
|
'-Dorg.gradle.isolated-projects.diagnostics=[]' \
|
||||||
|
'-Dorg.gradle.isolated-projects=[Enables Isolated Projects. Projects are configured in parallel. Implies `--configuration-cache`.]' \
|
||||||
'-Dorg.gradle.java.home=[]:org.gradle.java.home:_directories' \
|
'-Dorg.gradle.java.home=[]:org.gradle.java.home:_directories' \
|
||||||
'-Dorg.gradle.java.installations.auto-detect=[]' \
|
'-Dorg.gradle.java.installations.auto-detect=[]' \
|
||||||
'-Dorg.gradle.java.installations.auto-download=[]' \
|
'-Dorg.gradle.java.installations.auto-download=[]' \
|
||||||
@@ -299,8 +302,6 @@ __gradle_subcommand() {
|
|||||||
'-Dorg.gradle.problems.report=[Enables the HTML problems report.]' \
|
'-Dorg.gradle.problems.report=[Enables the HTML problems report.]' \
|
||||||
'-Dorg.gradle.projectcachedir=[Specifies the project-specific cache directory. Default is .gradle in the root project directory.]:org.gradle.projectcachedir:_directories' \
|
'-Dorg.gradle.projectcachedir=[Specifies the project-specific cache directory. Default is .gradle in the root project directory.]:org.gradle.projectcachedir:_directories' \
|
||||||
'-Dorg.gradle.tooling.parallel=[]' \
|
'-Dorg.gradle.tooling.parallel=[]' \
|
||||||
'-Dorg.gradle.unsafe.isolated-projects.diagnostics=[]' \
|
|
||||||
'-Dorg.gradle.unsafe.isolated-projects=[]' \
|
|
||||||
'-Dorg.gradle.vfs.verbose=[]' \
|
'-Dorg.gradle.vfs.verbose=[]' \
|
||||||
'-Dorg.gradle.vfs.watch=[Enables file system watching. Reuses file system data for subsequent builds.]:org.gradle.vfs.watch:(true false)' \
|
'-Dorg.gradle.vfs.watch=[Enables file system watching. Reuses file system data for subsequent builds.]:org.gradle.vfs.watch:(true false)' \
|
||||||
'-Dorg.gradle.warning.mode=[Specifies which mode of warnings to generate. Supported values are 'all', 'fail', 'summary' (default), or 'none'.]' \
|
'-Dorg.gradle.warning.mode=[Specifies which mode of warnings to generate. Supported values are 'all', 'fail', 'summary' (default), or 'none'.]' \
|
||||||
@@ -328,12 +329,14 @@ __gradle_subcommand() {
|
|||||||
\*'--include-build[Includes the specified build in the composite.]:include build:_directories' \
|
\*'--include-build[Includes the specified build in the composite.]:include build:_directories' \
|
||||||
(--quiet,-q,--warn,-w,--debug,-d){-i,--info}'[Sets the log level to info.]' \
|
(--quiet,-q,--warn,-w,--debug,-d){-i,--info}'[Sets the log level to info.]' \
|
||||||
\*{-I,--init-script}'[Specifies an initialization script.]:init script:_files -g \*.gradle(|.kts)' \
|
\*{-I,--init-script}'[Specifies an initialization script.]:init script:_files -g \*.gradle(|.kts)' \
|
||||||
|
(--no-isolated-projects)'--isolated-projects[Enables Isolated Projects. Projects are configured in parallel. Implies `--configuration-cache`. (incubating)]' \
|
||||||
'--max-workers[Configures the maximum number of concurrent workers Gradle is allowed to use.]' \
|
'--max-workers[Configures the maximum number of concurrent workers Gradle is allowed to use.]' \
|
||||||
(--build-cache)'--no-build-cache[Disables the Gradle build cache.]' \
|
(--build-cache)'--no-build-cache[Disables the Gradle build cache.]' \
|
||||||
(--configuration-cache)'--no-configuration-cache[Disables the configuration cache.]' \
|
(--configuration-cache)'--no-configuration-cache[Disables the configuration cache.]' \
|
||||||
(--configure-on-demand)'--no-configure-on-demand[Disables the use of configuration on demand. (incubating)]' \
|
(--configure-on-demand)'--no-configure-on-demand[Disables the use of configuration on demand. (incubating)]' \
|
||||||
(--continue)'--no-continue[Stops task execution after a task failure.]' \
|
(--continue)'--no-continue[Stops task execution after a task failure.]' \
|
||||||
(--daemon)'--no-daemon[Runs the build without the Gradle daemon. Useful occasionally if you have configured Gradle to always run with the daemon by default.]' \
|
(--daemon)'--no-daemon[Runs the build without the Gradle daemon. Useful occasionally if you have configured Gradle to always run with the daemon by default.]' \
|
||||||
|
(--isolated-projects)'--no-isolated-projects[Disables Isolated Projects. (incubating)]' \
|
||||||
(--parallel)'--no-parallel[Disables parallel project execution.]' \
|
(--parallel)'--no-parallel[Disables parallel project execution.]' \
|
||||||
(--problems-report)'--no-problems-report[Disables the HTML problems report. (incubating)]' \
|
(--problems-report)'--no-problems-report[Disables the HTML problems report. (incubating)]' \
|
||||||
{-a,--no-rebuild}'[Disables rebuilding of project dependencies.]' \
|
{-a,--no-rebuild}'[Disables rebuilding of project dependencies.]' \
|
||||||
@@ -421,6 +424,9 @@ _gradle() {
|
|||||||
'-Dorg.gradle.debug.suspend=[]:->argument-expected' \
|
'-Dorg.gradle.debug.suspend=[]:->argument-expected' \
|
||||||
'-Dorg.gradle.debug=[]:org.gradle.debug:(true false):->argument-expected' \
|
'-Dorg.gradle.debug=[]:org.gradle.debug:(true false):->argument-expected' \
|
||||||
'-Dorg.gradle.dependency.verification=[Configures the dependency verification mode. Supported values are 'strict', 'lenient', or 'off'.]:org.gradle.dependency.verification:(strict lenient off):->argument-expected' \
|
'-Dorg.gradle.dependency.verification=[Configures the dependency verification mode. Supported values are 'strict', 'lenient', or 'off'.]:org.gradle.dependency.verification:(strict lenient off):->argument-expected' \
|
||||||
|
'-Dorg.gradle.isolated-projects.dangerously-ignore-problems=[]:->argument-expected' \
|
||||||
|
'-Dorg.gradle.isolated-projects.diagnostics=[]:->argument-expected' \
|
||||||
|
'-Dorg.gradle.isolated-projects=[Enables Isolated Projects. Projects are configured in parallel. Implies `--configuration-cache`.]:->argument-expected' \
|
||||||
'-Dorg.gradle.java.home=[]:org.gradle.java.home:_directories:->argument-expected' \
|
'-Dorg.gradle.java.home=[]:org.gradle.java.home:_directories:->argument-expected' \
|
||||||
'-Dorg.gradle.java.installations.auto-detect=[]:->argument-expected' \
|
'-Dorg.gradle.java.installations.auto-detect=[]:->argument-expected' \
|
||||||
'-Dorg.gradle.java.installations.auto-download=[]:->argument-expected' \
|
'-Dorg.gradle.java.installations.auto-download=[]:->argument-expected' \
|
||||||
@@ -436,8 +442,6 @@ _gradle() {
|
|||||||
'-Dorg.gradle.problems.report=[Enables the HTML problems report.]:->argument-expected' \
|
'-Dorg.gradle.problems.report=[Enables the HTML problems report.]:->argument-expected' \
|
||||||
'-Dorg.gradle.projectcachedir=[Specifies the project-specific cache directory. Default is .gradle in the root project directory.]:org.gradle.projectcachedir:_directories:->argument-expected' \
|
'-Dorg.gradle.projectcachedir=[Specifies the project-specific cache directory. Default is .gradle in the root project directory.]:org.gradle.projectcachedir:_directories:->argument-expected' \
|
||||||
'-Dorg.gradle.tooling.parallel=[]:->argument-expected' \
|
'-Dorg.gradle.tooling.parallel=[]:->argument-expected' \
|
||||||
'-Dorg.gradle.unsafe.isolated-projects.diagnostics=[]:->argument-expected' \
|
|
||||||
'-Dorg.gradle.unsafe.isolated-projects=[]:->argument-expected' \
|
|
||||||
'-Dorg.gradle.vfs.verbose=[]:->argument-expected' \
|
'-Dorg.gradle.vfs.verbose=[]:->argument-expected' \
|
||||||
'-Dorg.gradle.vfs.watch=[Enables file system watching. Reuses file system data for subsequent builds.]:org.gradle.vfs.watch:(true false):->argument-expected' \
|
'-Dorg.gradle.vfs.watch=[Enables file system watching. Reuses file system data for subsequent builds.]:org.gradle.vfs.watch:(true false):->argument-expected' \
|
||||||
'-Dorg.gradle.warning.mode=[Specifies which mode of warnings to generate. Supported values are 'all', 'fail', 'summary' (default), or 'none'.]:->argument-expected' \
|
'-Dorg.gradle.warning.mode=[Specifies which mode of warnings to generate. Supported values are 'all', 'fail', 'summary' (default), or 'none'.]:->argument-expected' \
|
||||||
@@ -466,12 +470,14 @@ _gradle() {
|
|||||||
\*'--include-build[Includes the specified build in the composite.]:include build:_directories:->argument-expected' \
|
\*'--include-build[Includes the specified build in the composite.]:include build:_directories:->argument-expected' \
|
||||||
(--quiet,-q,--warn,-w,--debug,-d){-i,--info}'[Sets the log level to info.]' \
|
(--quiet,-q,--warn,-w,--debug,-d){-i,--info}'[Sets the log level to info.]' \
|
||||||
\*{-I,--init-script}'[Specifies an initialization script.]:init script:_files -g \*.gradle(|.kts):->argument-expected' \
|
\*{-I,--init-script}'[Specifies an initialization script.]:init script:_files -g \*.gradle(|.kts):->argument-expected' \
|
||||||
|
(--no-isolated-projects)'--isolated-projects[Enables Isolated Projects. Projects are configured in parallel. Implies `--configuration-cache`. (incubating)]' \
|
||||||
'--max-workers[Configures the maximum number of concurrent workers Gradle is allowed to use.]:->argument-expected' \
|
'--max-workers[Configures the maximum number of concurrent workers Gradle is allowed to use.]:->argument-expected' \
|
||||||
(--build-cache)'--no-build-cache[Disables the Gradle build cache.]' \
|
(--build-cache)'--no-build-cache[Disables the Gradle build cache.]' \
|
||||||
(--configuration-cache)'--no-configuration-cache[Disables the configuration cache.]' \
|
(--configuration-cache)'--no-configuration-cache[Disables the configuration cache.]' \
|
||||||
(--configure-on-demand)'--no-configure-on-demand[Disables the use of configuration on demand. (incubating)]' \
|
(--configure-on-demand)'--no-configure-on-demand[Disables the use of configuration on demand. (incubating)]' \
|
||||||
(--continue)'--no-continue[Stops task execution after a task failure.]' \
|
(--continue)'--no-continue[Stops task execution after a task failure.]' \
|
||||||
(--daemon)'--no-daemon[Runs the build without the Gradle daemon. Useful occasionally if you have configured Gradle to always run with the daemon by default.]' \
|
(--daemon)'--no-daemon[Runs the build without the Gradle daemon. Useful occasionally if you have configured Gradle to always run with the daemon by default.]' \
|
||||||
|
(--isolated-projects)'--no-isolated-projects[Disables Isolated Projects. (incubating)]' \
|
||||||
(--parallel)'--no-parallel[Disables parallel project execution.]' \
|
(--parallel)'--no-parallel[Disables parallel project execution.]' \
|
||||||
(--problems-report)'--no-problems-report[Disables the HTML problems report. (incubating)]' \
|
(--problems-report)'--no-problems-report[Disables the HTML problems report. (incubating)]' \
|
||||||
{-a,--no-rebuild}'[Disables rebuilding of project dependencies.]' \
|
{-a,--no-rebuild}'[Disables rebuilding of project dependencies.]' \
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
# herdr plugin
|
||||||
|
|
||||||
|
This plugin adds completion, aliases, an interactive session picker and a prompt
|
||||||
|
function for [herdr](https://herdr.dev), the runtime your
|
||||||
|
coding agents live on. herdr keeps agent terminals running in the background across
|
||||||
|
projects and machines, so you can close your terminal, reconnect later, and pick up
|
||||||
|
where the agents left off.
|
||||||
|
|
||||||
|
To use it, add `herdr` to the plugins array in your zshrc file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
plugins=(... herdr)
|
||||||
|
```
|
||||||
|
|
||||||
|
Install herdr first if you have not already:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://herdr.dev/install.sh | sh # or: brew install herdr
|
||||||
|
```
|
||||||
|
|
||||||
|
## Learning herdr from the terminal
|
||||||
|
|
||||||
|
The fastest way to explore herdr is tab completion. Every command group and flag shows a
|
||||||
|
short description, so you can discover what is available without leaving the shell:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ herdr <TAB>
|
||||||
|
agent -- Control and inspect agent panes
|
||||||
|
session -- Manage named persistent sessions
|
||||||
|
workspace -- Manage workspaces over the socket API
|
||||||
|
worktree -- Manage Git worktree-backed workspaces
|
||||||
|
...
|
||||||
|
$ herdr agent <TAB>
|
||||||
|
list -- List agents
|
||||||
|
prompt -- Submit a prompt to an agent
|
||||||
|
start -- Start a supported interactive agent in an existing pane
|
||||||
|
wait -- Wait until an agent reaches one of the requested states
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
A few other ways to learn as you go:
|
||||||
|
|
||||||
|
- `herdr <group>` with no subcommand prints that group's help, for example `herdr pane`.
|
||||||
|
- `herdr --skill` prints the instructions herdr gives to agents that drive it. It is a
|
||||||
|
good tour of the full command surface.
|
||||||
|
- Most control commands return JSON, so you can pipe them into `jq` in scripts.
|
||||||
|
|
||||||
|
## Common workflows
|
||||||
|
|
||||||
|
### Start and reconnect
|
||||||
|
|
||||||
|
```sh
|
||||||
|
herdr # launch, or attach to the default session
|
||||||
|
herdr --session work # use or create a named session
|
||||||
|
herdr session list # see running and stopped sessions
|
||||||
|
herdr session attach work # reconnect to a named session
|
||||||
|
herdr status # check the local client and running server
|
||||||
|
herdr update # install the latest release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Organize work into workspaces and tabs
|
||||||
|
|
||||||
|
```sh
|
||||||
|
herdr workspace list
|
||||||
|
herdr workspace create --cwd ~/projects/app
|
||||||
|
herdr tab create
|
||||||
|
herdr pane split --direction right
|
||||||
|
herdr worktree create --branch feature/login # open a Git worktree in its own workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run and watch agents
|
||||||
|
|
||||||
|
```sh
|
||||||
|
herdr agent list # what is running, and is it idle, working or blocked
|
||||||
|
herdr agent start reviewer --kind claude --pane w1:p2
|
||||||
|
herdr agent prompt reviewer "review the last commit" --wait
|
||||||
|
herdr agent read reviewer # read the agent's terminal output
|
||||||
|
herdr agent wait reviewer --until idle
|
||||||
|
herdr agent attach reviewer # jump straight into that terminal
|
||||||
|
```
|
||||||
|
|
||||||
|
### Work across machines
|
||||||
|
|
||||||
|
```sh
|
||||||
|
herdr --remote user@build-box # attach through SSH with your local keybindings
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keep the server healthy
|
||||||
|
|
||||||
|
```sh
|
||||||
|
herdr config check # validate config.toml
|
||||||
|
herdr server reload-config # apply config changes without restarting panes
|
||||||
|
herdr server stop
|
||||||
|
herdr channel set preview # switch between stable and preview releases
|
||||||
|
herdr integration status # which agent CLIs have herdr hooks installed
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [CLI reference](https://herdr.dev/docs/cli-reference/) for every command and flag.
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
| Alias | Command |
|
||||||
|
| ------- | ----------------------------- |
|
||||||
|
| `hrdr` | `herdr` |
|
||||||
|
| `hrdrst` | `herdr status` |
|
||||||
|
| `hrdrup` | `herdr update` |
|
||||||
|
| `hrdrsl` | `herdr session list` |
|
||||||
|
| `hrdrsa` | `herdr session attach` |
|
||||||
|
| `hrdrr` | `herdr --remote` |
|
||||||
|
| `hrdral` | `herdr agent list` |
|
||||||
|
| `hrdrwl` | `herdr workspace list` |
|
||||||
|
| `hrdrwc` | `herdr workspace create` |
|
||||||
|
| `hrdrwt` | `herdr worktree create` |
|
||||||
|
| `hrdrps` | `herdr pane split` |
|
||||||
|
| `hrdrrc` | `herdr server reload-config` |
|
||||||
|
|
||||||
|
Tab completion works through the aliases too, so `hrdr agent <TAB>` completes the same
|
||||||
|
way `herdr agent <TAB>` does.
|
||||||
|
|
||||||
|
## Session picker
|
||||||
|
|
||||||
|
`hrdrs` lists your herdr sessions and attaches to the one you pick. It uses
|
||||||
|
[fzf](https://github.com/junegunn/fzf) when it is installed and falls back to a numbered
|
||||||
|
menu otherwise, so it works everywhere.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ hrdrs
|
||||||
|
name status directory
|
||||||
|
1) default running /Users/me/.config/herdr
|
||||||
|
2) work stopped /Users/me/projects/app
|
||||||
|
Attach to session: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
This plugin provides the `herdr_prompt_info` function to show the current pane ID in
|
||||||
|
your prompt when the shell is running inside herdr. It reads environment variables only,
|
||||||
|
so it adds no cost to prompt rendering.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```
|
||||||
|
PROMPT="%~$ "
|
||||||
|
RPROMPT='$(herdr_prompt_info)'
|
||||||
|
```
|
||||||
|
changes your prompt inside a herdr pane to:
|
||||||
|
```
|
||||||
|
~/projects/app$ ▋ w1:p4
|
||||||
|
```
|
||||||
|
and shows nothing outside herdr.
|
||||||
|
|
||||||
|
Wrap it with `ZSH_THEME_HERDR_PROMPT_PREFIX` and `ZSH_THEME_HERDR_PROMPT_SUFFIX`, for
|
||||||
|
example:
|
||||||
|
```
|
||||||
|
ZSH_THEME_HERDR_PROMPT_PREFIX="%{$fg[cyan]%}[herdr "
|
||||||
|
ZSH_THEME_HERDR_PROMPT_SUFFIX="]%{$reset_color%}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cache
|
||||||
|
|
||||||
|
This plugin caches the completion script and automatically updates it when the plugin is
|
||||||
|
loaded, which is usually when you start a new terminal emulator.
|
||||||
|
|
||||||
|
The cache is stored at `$ZSH_CACHE_DIR/completions/_herdr`.
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Aliases, helpers and completion for herdr (https://herdr.dev), the runtime for coding agents.
|
||||||
|
|
||||||
|
# PROMPT
|
||||||
|
# Defined before the herdr check so themes can reference it on machines without herdr.
|
||||||
|
function herdr_prompt_info {
|
||||||
|
[[ "$HERDR_ENV" == 1 ]] || return
|
||||||
|
echo "${ZSH_THEME_HERDR_PROMPT_PREFIX}${HERDR_PANE_ID:gs/%/%%}${ZSH_THEME_HERDR_PROMPT_SUFFIX}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (( ! $+commands[herdr] )); then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ALIASES
|
||||||
|
alias hrdr='herdr'
|
||||||
|
alias hrdrst='herdr status'
|
||||||
|
alias hrdrup='herdr update'
|
||||||
|
alias hrdrsl='herdr session list'
|
||||||
|
alias hrdrsa='herdr session attach'
|
||||||
|
alias hrdrr='herdr --remote'
|
||||||
|
alias hrdral='herdr agent list'
|
||||||
|
alias hrdrwl='herdr workspace list'
|
||||||
|
alias hrdrwc='herdr workspace create'
|
||||||
|
alias hrdrwt='herdr worktree create'
|
||||||
|
alias hrdrps='herdr pane split'
|
||||||
|
alias hrdrrc='herdr server reload-config'
|
||||||
|
|
||||||
|
# FUNCTIONS
|
||||||
|
# Pick a session and attach to it, with fzf if available or a numbered menu otherwise.
|
||||||
|
function hrdrs {
|
||||||
|
setopt localoptions extendedglob
|
||||||
|
local -a lines
|
||||||
|
lines=("${(@f)$(herdr session list 2>/dev/null)}")
|
||||||
|
lines=("${(@)lines%%[[:space:]]#[^[:space:]]#}") # drop the socket column
|
||||||
|
if (( $#lines < 2 )); then
|
||||||
|
print "hrdrs: no herdr sessions found" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local choice
|
||||||
|
if (( $+commands[fzf] )); then
|
||||||
|
choice=$(print -l -- "${lines[@]}" | fzf --header-lines=1 --prompt='herdr session> ') || return
|
||||||
|
else
|
||||||
|
print -- "${lines[1]}"
|
||||||
|
local PS3="Attach to session: "
|
||||||
|
select choice in "${lines[@]:1}"; do
|
||||||
|
[[ -n "$choice" ]] && break
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
[[ -n "$choice" ]] || return 1
|
||||||
|
|
||||||
|
herdr session attach "${${(z)choice}[1]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# COMPLETION
|
||||||
|
# If the completion file doesn't exist yet, we need to autoload it and
|
||||||
|
# bind it to `herdr`. Otherwise, compinit will have already done that.
|
||||||
|
if [[ ! -f "$ZSH_CACHE_DIR/completions/_herdr" ]]; then
|
||||||
|
typeset -g -A _comps
|
||||||
|
autoload -Uz _herdr
|
||||||
|
_comps[herdr]=_herdr
|
||||||
|
fi
|
||||||
|
|
||||||
|
zmodload -F zsh/files b:zf_mv
|
||||||
|
() {
|
||||||
|
local TMPPREFIX="$ZSH_CACHE_DIR/completions/_herdr"
|
||||||
|
zf_mv -f -- =( herdr completion zsh < /dev/null 2> /dev/null ) "$TMPPREFIX"
|
||||||
|
} &|
|
||||||
@@ -75,7 +75,7 @@ Using [Zinit](https://github.com/zdharma-continuum/zinit):
|
|||||||
|
|
||||||
1. Use the `Oh-my-zsh` Zinit snippet in `~/.zshrc`:
|
1. Use the `Oh-my-zsh` Zinit snippet in `~/.zshrc`:
|
||||||
|
|
||||||
zinit snippet OMZ::plugins/git/git.plugin.zsh`
|
zinit snippet OMZ::plugins/git/git.plugin.zsh
|
||||||
|
|
||||||
2. Load the plugin in `~/.zshrc`:
|
2. Load the plugin in `~/.zshrc`:
|
||||||
|
|
||||||
|
|||||||
@@ -295,8 +295,8 @@ _history-substring-search-begin() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Escape and join query parts with wildcard character '*' as separator
|
# Escape and join query parts with wildcard character '*' as seperator
|
||||||
# `(j:CHAR:)` join array to string with CHAR as separator
|
# `(j:CHAR:)` join array to string with CHAR as seperator
|
||||||
#
|
#
|
||||||
local search_pattern="${(j:*:)_history_substring_search_query_parts[@]//(#m)[\][()|\\*?#<>~^]/\\$MATCH}*"
|
local search_pattern="${(j:*:)_history_substring_search_query_parts[@]//(#m)[\][()|\\*?#<>~^]/\\$MATCH}*"
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ plugins=(... jj)
|
|||||||
| jjopl | `jj op log` |
|
| jjopl | `jj op log` |
|
||||||
| jjor | `jj op restore` |
|
| jjor | `jj op restore` |
|
||||||
| jjrb | `jj rebase` |
|
| jjrb | `jj rebase` |
|
||||||
| jjrbm | `jj rebase -d "trunk()"` |
|
| jjrbm | `jj rebase -o "trunk()"` |
|
||||||
| jjrs | `jj restore` |
|
| jjrs | `jj restore` |
|
||||||
| jjrt | `cd "$(jj root \|\| echo .)"` |
|
| jjrt | `cd "$(jj root \|\| echo .)"` |
|
||||||
| jjs | `jj show` |
|
| jjs | `jj show` |
|
||||||
@@ -120,10 +120,10 @@ that.
|
|||||||
|
|
||||||
### Git async-prompt compatibility
|
### Git async-prompt compatibility
|
||||||
|
|
||||||
If you use a wrapper function that calls `git_prompt_info` (as shown above), it won't work with
|
If you use a wrapper function that calls `git_prompt_info` (as shown above), it won't work with the default
|
||||||
the default git async-prompt mode. This is because async-prompt only registers its background worker
|
git async-prompt mode. This is because async-prompt only registers its background worker when it detects
|
||||||
when it detects `$(git_prompt_info)` literally in your prompt variables. A wrapper like
|
`$(git_prompt_info)` literally in your prompt variables. A wrapper like `$(_my_theme_vcs_info)` won't match,
|
||||||
`$(_my_theme_vcs_info)` won't match, so the async output stays empty.
|
so the async output stays empty.
|
||||||
|
|
||||||
To fix this, add one of the following to your `.zshrc` **before** Oh My Zsh is sourced:
|
To fix this, add one of the following to your `.zshrc` **before** Oh My Zsh is sourced:
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ alias jjop='jj op'
|
|||||||
alias jjopl='jj op log'
|
alias jjopl='jj op log'
|
||||||
alias jjor='jj op restore'
|
alias jjor='jj op restore'
|
||||||
alias jjrb='jj rebase'
|
alias jjrb='jj rebase'
|
||||||
alias jjrbm='jj rebase -d "trunk()"'
|
alias jjrbm='jj rebase -o "trunk()"'
|
||||||
alias jjrs='jj restore'
|
alias jjrs='jj restore'
|
||||||
alias jjrt='cd "$(jj root || echo .)"'
|
alias jjrt='cd "$(jj root || echo .)"'
|
||||||
alias jjs='jj show'
|
alias jjs='jj show'
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ alias jdlr='juju debug-log --ms --replay'
|
|||||||
alias jcon='juju consume'
|
alias jcon='juju consume'
|
||||||
alias jeb='juju export-bundle'
|
alias jeb='juju export-bundle'
|
||||||
alias jex='juju expose'
|
alias jex='juju expose'
|
||||||
|
alias junex='juju unexpose'
|
||||||
alias jh='juju help'
|
alias jh='juju help'
|
||||||
alias jkc='juju kill-controller -y -t 0'
|
alias jkc='juju kill-controller -y -t 0'
|
||||||
alias jm='juju models'
|
alias jm='juju models'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Kubernetes prompt helper for bash/zsh
|
# Kubernetes prompt info for bash, fish, and zsh
|
||||||
# Displays current context and namespace
|
# Displays current context and namespace
|
||||||
|
|
||||||
# Copyright 2026 Jon Mosco
|
# Copyright 2026 Jon Mosco
|
||||||
@@ -121,7 +121,7 @@ _kube_ps1_color_fg() {
|
|||||||
if [[ "${_KUBE_PS1_TPUT_AVAILABLE}" == "true" ]]; then
|
if [[ "${_KUBE_PS1_TPUT_AVAILABLE}" == "true" ]]; then
|
||||||
_KUBE_PS1_FG_CODE="$(tput setaf "${_KUBE_PS1_FG_CODE}")"
|
_KUBE_PS1_FG_CODE="$(tput setaf "${_KUBE_PS1_FG_CODE}")"
|
||||||
elif [[ $_KUBE_PS1_FG_CODE -ge 0 ]] && [[ $_KUBE_PS1_FG_CODE -le 255 ]]; then
|
elif [[ $_KUBE_PS1_FG_CODE -ge 0 ]] && [[ $_KUBE_PS1_FG_CODE -le 255 ]]; then
|
||||||
_KUBE_PS1_FG_CODE="\033[38;5;${_KUBE_PS1_FG_CODE}m"
|
_KUBE_PS1_FG_CODE=$'\033'"[38;5;${_KUBE_PS1_FG_CODE}m"
|
||||||
else
|
else
|
||||||
_KUBE_PS1_FG_CODE="${_KUBE_PS1_DEFAULT_FG}"
|
_KUBE_PS1_FG_CODE="${_KUBE_PS1_DEFAULT_FG}"
|
||||||
fi
|
fi
|
||||||
@@ -154,7 +154,7 @@ _kube_ps1_color_bg() {
|
|||||||
if [[ "${_KUBE_PS1_TPUT_AVAILABLE}" == "true" ]]; then
|
if [[ "${_KUBE_PS1_TPUT_AVAILABLE}" == "true" ]]; then
|
||||||
_KUBE_PS1_BG_CODE="$(tput setab "${_KUBE_PS1_BG_CODE}")"
|
_KUBE_PS1_BG_CODE="$(tput setab "${_KUBE_PS1_BG_CODE}")"
|
||||||
elif [[ $_KUBE_PS1_BG_CODE -ge 0 ]] && [[ $_KUBE_PS1_BG_CODE -le 255 ]]; then
|
elif [[ $_KUBE_PS1_BG_CODE -ge 0 ]] && [[ $_KUBE_PS1_BG_CODE -le 255 ]]; then
|
||||||
_KUBE_PS1_BG_CODE="\033[48;5;${_KUBE_PS1_BG_CODE}m"
|
_KUBE_PS1_BG_CODE=$'\033'"[48;5;${_KUBE_PS1_BG_CODE}m"
|
||||||
else
|
else
|
||||||
_KUBE_PS1_BG_CODE="${_KUBE_PS1_DEFAULT_BG}"
|
_KUBE_PS1_BG_CODE="${_KUBE_PS1_DEFAULT_BG}"
|
||||||
fi
|
fi
|
||||||
@@ -412,6 +412,8 @@ kube_ps1() {
|
|||||||
|
|
||||||
local KUBE_PS1
|
local KUBE_PS1
|
||||||
local KUBE_PS1_RESET_COLOR="${_KUBE_PS1_OPEN_ESC}${_KUBE_PS1_DEFAULT_FG}${_KUBE_PS1_CLOSE_ESC}"
|
local KUBE_PS1_RESET_COLOR="${_KUBE_PS1_OPEN_ESC}${_KUBE_PS1_DEFAULT_FG}${_KUBE_PS1_CLOSE_ESC}"
|
||||||
|
local ctx_color="${KUBE_PS1_CTX_COLOR-red}"
|
||||||
|
local ns_color="${KUBE_PS1_NS_COLOR-cyan}"
|
||||||
|
|
||||||
# Background Color
|
# Background Color
|
||||||
[[ -n "${KUBE_PS1_BG_COLOR}" ]] && KUBE_PS1+="$(_kube_ps1_color_bg "${KUBE_PS1_BG_COLOR}")"
|
[[ -n "${KUBE_PS1_BG_COLOR}" ]] && KUBE_PS1+="$(_kube_ps1_color_bg "${KUBE_PS1_BG_COLOR}")"
|
||||||
@@ -432,22 +434,29 @@ kube_ps1() {
|
|||||||
|
|
||||||
# Context
|
# Context
|
||||||
if [[ "${KUBE_PS1_CONTEXT_ENABLE}" == true ]]; then
|
if [[ "${KUBE_PS1_CONTEXT_ENABLE}" == true ]]; then
|
||||||
local ctx_color="${KUBE_PS1_CTX_COLOR:-red}"
|
|
||||||
|
|
||||||
# Allow custom function to override color based on context
|
# Allow custom function to override color based on context
|
||||||
if [[ -n "${KUBE_PS1_CTX_COLOR_FUNCTION}" ]]; then
|
if [[ -n "${KUBE_PS1_CTX_COLOR_FUNCTION}" ]]; then
|
||||||
ctx_color="$("${KUBE_PS1_CTX_COLOR_FUNCTION}" "${KUBE_PS1_CONTEXT}")"
|
ctx_color="$("${KUBE_PS1_CTX_COLOR_FUNCTION}" "${KUBE_PS1_CONTEXT}")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${ctx_color}" ]]; then
|
||||||
KUBE_PS1+="$(_kube_ps1_color_fg "${ctx_color}")${KUBE_PS1_CONTEXT}${KUBE_PS1_RESET_COLOR}"
|
KUBE_PS1+="$(_kube_ps1_color_fg "${ctx_color}")${KUBE_PS1_CONTEXT}${KUBE_PS1_RESET_COLOR}"
|
||||||
|
else
|
||||||
|
KUBE_PS1+="${KUBE_PS1_CONTEXT}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Namespace
|
# Namespace
|
||||||
if [[ "${KUBE_PS1_NS_ENABLE}" == true ]]; then
|
if [[ "${KUBE_PS1_NS_ENABLE}" == true ]]; then
|
||||||
if [[ -n "${KUBE_PS1_DIVIDER}" ]] && [[ "${KUBE_PS1_CONTEXT_ENABLE}" == true ]]; then
|
if [[ -n "${KUBE_PS1_DIVIDER}" && "${KUBE_PS1_CONTEXT_ENABLE}" == true ]]; then
|
||||||
KUBE_PS1+="${KUBE_PS1_DIVIDER}"
|
KUBE_PS1+="${KUBE_PS1_DIVIDER}"
|
||||||
fi
|
fi
|
||||||
KUBE_PS1+="$(_kube_ps1_color_fg "${KUBE_PS1_NS_COLOR:-cyan}")${KUBE_PS1_NAMESPACE}${KUBE_PS1_RESET_COLOR}"
|
|
||||||
|
if [[ -n "${ns_color}" ]]; then
|
||||||
|
KUBE_PS1+="$(_kube_ps1_color_fg "${ns_color}")${KUBE_PS1_NAMESPACE}${KUBE_PS1_RESET_COLOR}"
|
||||||
|
else
|
||||||
|
KUBE_PS1+="${KUBE_PS1_NAMESPACE}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Suffix
|
# Suffix
|
||||||
@@ -460,5 +469,5 @@ kube_ps1() {
|
|||||||
# Close Background color if defined
|
# Close Background color if defined
|
||||||
[[ -n "${KUBE_PS1_BG_COLOR}" ]] && KUBE_PS1+="${_KUBE_PS1_OPEN_ESC}${_KUBE_PS1_DEFAULT_BG}${_KUBE_PS1_CLOSE_ESC}"
|
[[ -n "${KUBE_PS1_BG_COLOR}" ]] && KUBE_PS1+="${_KUBE_PS1_OPEN_ESC}${_KUBE_PS1_DEFAULT_BG}${_KUBE_PS1_CLOSE_ESC}"
|
||||||
|
|
||||||
echo "${KUBE_PS1}"
|
printf '%s' "${KUBE_PS1}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ plugins=(... kubectl)
|
|||||||
| kcsc | `kubectl config set-context` | Set a context entry in kubeconfig |
|
| kcsc | `kubectl config set-context` | Set a context entry in kubeconfig |
|
||||||
| kcdc | `kubectl config delete-context` | Delete the specified context from the kubeconfig |
|
| kcdc | `kubectl config delete-context` | Delete the specified context from the kubeconfig |
|
||||||
| kccc | `kubectl config current-context` | Display the current-context |
|
| kccc | `kubectl config current-context` | Display the current-context |
|
||||||
|
| kcrc | `kubectl config rename-context` | Rename a context from the kubeconfig file |
|
||||||
| kcgc | `kubectl config get-contexts` | List of contexts available |
|
| kcgc | `kubectl config get-contexts` | List of contexts available |
|
||||||
| | | **General aliases** |
|
| | | **General aliases** |
|
||||||
| kdel | `kubectl delete` | Delete resources by filenames, stdin, resources and names, or by resources and label selector |
|
| kdel | `kubectl delete` | Delete resources by filenames, stdin, resources and names, or by resources and label selector |
|
||||||
@@ -130,7 +131,7 @@ plugins=(... kubectl)
|
|||||||
| kdss | `kubectl describe statefulset` | Describe statefulset resource in detail |
|
| kdss | `kubectl describe statefulset` | Describe statefulset resource in detail |
|
||||||
| kdelss | `kubectl delete statefulset` | Delete the statefulset |
|
| kdelss | `kubectl delete statefulset` | Delete the statefulset |
|
||||||
| ksss | `kubectl scale statefulset` | Scale a statefulset |
|
| ksss | `kubectl scale statefulset` | Scale a statefulset |
|
||||||
| krsss | `kubectl rollout status statefulset` | Check the rollout status of a deployment |
|
| krsss | `kubectl rollout status statefulset` | Check the rollout status of a statefulset |
|
||||||
| krrss | `kubectl rollout restart statefulset` | Rollout restart a statefulset |
|
| krrss | `kubectl rollout restart statefulset` | Rollout restart a statefulset |
|
||||||
| | | **Service Accounts management** |
|
| | | **Service Accounts management** |
|
||||||
| kdsa | `kubectl describe sa` | Describe a service account in details |
|
| kdsa | `kubectl describe sa` | Describe a service account in details |
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ alias kcuc='kubectl config use-context'
|
|||||||
alias kcsc='kubectl config set-context'
|
alias kcsc='kubectl config set-context'
|
||||||
alias kcdc='kubectl config delete-context'
|
alias kcdc='kubectl config delete-context'
|
||||||
alias kccc='kubectl config current-context'
|
alias kccc='kubectl config current-context'
|
||||||
|
alias kcrc='kubectl config rename-context'
|
||||||
|
|
||||||
# List all contexts
|
# List all contexts
|
||||||
alias kcgc='kubectl config get-contexts'
|
alias kcgc='kubectl config get-contexts'
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ plugins=(... laravel)
|
|||||||
| `pami` | `php artisan make:interface` |
|
| `pami` | `php artisan make:interface` |
|
||||||
| `pamtr` | `php artisan make:trait` |
|
| `pamtr` | `php artisan make:trait` |
|
||||||
| `pamv` | `php artisan make:view` |
|
| `pamv` | `php artisan make:view` |
|
||||||
|
| `pammig` | `php artisan make:migration` |
|
||||||
|
|
||||||
## Clears
|
## Clears
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ alias pamen='php artisan make:enum'
|
|||||||
alias pami='php artisan make:interface'
|
alias pami='php artisan make:interface'
|
||||||
alias pamtr='php artisan make:trait'
|
alias pamtr='php artisan make:trait'
|
||||||
alias pamv='php artisan make:view'
|
alias pamv='php artisan make:view'
|
||||||
|
alias pammig='php artisan make:migration'
|
||||||
|
|
||||||
|
|
||||||
# Clears
|
# Clears
|
||||||
|
|||||||
+2
-2
@@ -157,13 +157,13 @@ case $state in
|
|||||||
'*::file:_files'
|
'*::file:_files'
|
||||||
;;
|
;;
|
||||||
(test)
|
(test)
|
||||||
_files
|
_path_files -X "All tests" -g "test/**/*_test.exs" -g "apps/*/test/**/*_test.exs"
|
||||||
;;
|
;;
|
||||||
(test.watch)
|
(test.watch)
|
||||||
_files
|
_files
|
||||||
;;
|
;;
|
||||||
(run)
|
(run)
|
||||||
_files
|
_files -g "*.(exs|ex)"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -23,6 +23,16 @@ plugins=(... podman)
|
|||||||
| pirm | `podman image rm` | Remove one or more images |
|
| pirm | `podman image rm` | Remove one or more images |
|
||||||
| pit | `podman image tag` | Add a name and tag to a particular image |
|
| pit | `podman image tag` | Add a name and tag to a particular image |
|
||||||
| plo | `podman container logs` | Fetch the logs of a podman container |
|
| plo | `podman container logs` | Fetch the logs of a podman container |
|
||||||
|
| pmif | `podman machine info` | Display machine host info |
|
||||||
|
| pmit | `podman machine init` | Initialize a virtual machine |
|
||||||
|
| pmis | `podman machine inspect` | Inspect an existing machine |
|
||||||
|
| pml | `podman machine list` | List machines |
|
||||||
|
| pmo | `podman machine os` | Manage a Podman virtual machine's OS |
|
||||||
|
| pmrm | `podman machine rm` | Remove an existing machine |
|
||||||
|
| pms | `podman machine set` | Set a virtual machine setting |
|
||||||
|
| pmss | `podman machine ssh` | SSH into an existing machine |
|
||||||
|
| pmst | `podman machine start` | Start an existing machine |
|
||||||
|
| pmsp | `podman machine stop` | Stop an existing machine |
|
||||||
| pnc | `podman network create` | Create a new network |
|
| pnc | `podman network create` | Create a new network |
|
||||||
| pncn | `podman network connect` | Connect a container to a network |
|
| pncn | `podman network connect` | Connect a container to a network |
|
||||||
| pndcn | `podman network disconnect` | Disconnect a container from a network |
|
| pndcn | `podman network disconnect` | Disconnect a container from a network |
|
||||||
|
|||||||
@@ -26,6 +26,16 @@ alias pils='podman image ls'
|
|||||||
alias pipu='podman image push'
|
alias pipu='podman image push'
|
||||||
alias pirm='podman image rm'
|
alias pirm='podman image rm'
|
||||||
alias pit='podman image tag'
|
alias pit='podman image tag'
|
||||||
|
alias pmif='podman machine info'
|
||||||
|
alias pmit='podman machine init'
|
||||||
|
alias pmis='podman machine inspect'
|
||||||
|
alias pml='podman machine list'
|
||||||
|
alias pmo='podman machine os'
|
||||||
|
alias pmrm='podman machine rm'
|
||||||
|
alias pms='podman machine set'
|
||||||
|
alias pmss='podman machine ssh'
|
||||||
|
alias pmst='podman machine start'
|
||||||
|
alias pmsp='podman machine stop'
|
||||||
alias plo='podman container logs'
|
alias plo='podman container logs'
|
||||||
alias pnc='podman network create'
|
alias pnc='podman network create'
|
||||||
alias pncn='podman network connect'
|
alias pncn='podman network connect'
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ _togglePoetryShell() {
|
|||||||
|
|
||||||
# Activate the environment if in a Poetry directory and no environment is currently active
|
# Activate the environment if in a Poetry directory and no environment is currently active
|
||||||
if [[ $in_poetry_dir -eq 1 ]] && [[ $poetry_active -ne 1 ]]; then
|
if [[ $in_poetry_dir -eq 1 ]] && [[ $poetry_active -ne 1 ]]; then
|
||||||
venv_dir=$(poetry env info --path 2>/dev/null)
|
local venv_dir=$(poetry env info --path 2>/dev/null)
|
||||||
# Handle case where poetry returns "." for in-project virtual environments
|
# Handle case where poetry returns "." for in-project virtual environments
|
||||||
if [[ "$venv_dir" == "." ]]; then
|
if [[ "$venv_dir" == "." ]]; then
|
||||||
venv_dir="$PWD/.venv"
|
venv_dir="$PWD/.venv"
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ function rdsl() { _rails_db_command db:schema:load "$@" }
|
|||||||
|
|
||||||
# legacy stuff
|
# legacy stuff
|
||||||
alias sc='ruby script/console'
|
alias sc='ruby script/console'
|
||||||
alias sd='ruby script/destroy'
|
|
||||||
alias sd='ruby script/server --debugger'
|
alias sd='ruby script/server --debugger'
|
||||||
alias sg='ruby script/generate'
|
alias sg='ruby script/generate'
|
||||||
alias sp='ruby script/plugin'
|
alias sp='ruby script/plugin'
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
# Load bracketed-paste-magic if zsh version is >= 5.1
|
# Load bracketed-paste-magic if zsh version is >= 5.1
|
||||||
autoload -Uz is-at-least
|
autoload -Uz is-at-least
|
||||||
if is-at-least 5.1; then
|
if is-at-least 5.1; then
|
||||||
set zle_bracketed_paste # Explicitly restore this zsh default
|
|
||||||
autoload -Uz bracketed-paste-magic
|
autoload -Uz bracketed-paste-magic
|
||||||
zle -N bracketed-paste bracketed-paste-magic
|
zle -N bracketed-paste bracketed-paste-magic
|
||||||
return ### The rest of this file is NOT executed on zsh version >= 5.1 ###
|
return ### The rest of this file is NOT executed on zsh version >= 5.1 ###
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ if [[ "$TERM" == screen* ]]; then
|
|||||||
# tell GNU screen what the tab window title ($1) and the hardstatus($2) should be
|
# tell GNU screen what the tab window title ($1) and the hardstatus($2) should be
|
||||||
function screen_set()
|
function screen_set()
|
||||||
{
|
{
|
||||||
|
[[ "${DISABLE_AUTO_TITLE:-}" != true ]] || return 0
|
||||||
|
|
||||||
# set the tab window title (%t) for screen
|
# set the tab window title (%t) for screen
|
||||||
print -nR $'\033k'$1$'\033'\\\
|
print -nR $'\033k'$1$'\033'\\\
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
# Shopify CLI plugin
|
||||||
|
|
||||||
|
This plugin adds aliases, helper functions and completion for the
|
||||||
|
[Shopify CLI](https://shopify.dev/docs/api/shopify-cli).
|
||||||
|
|
||||||
|
To use it, add `shopify` to the plugins array in your zshrc file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
plugins=(... shopify)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
[Shopify CLI](https://shopify.dev/docs/api/shopify-cli) 4.0 or newer, installed
|
||||||
|
and on your `PATH`. The plugin does nothing if it is not:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
npm install -g @shopify/cli
|
||||||
|
# or
|
||||||
|
brew tap shopify/shopify && brew install shopify-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
| Alias | Command | Description |
|
||||||
|
| :----- | :-------- | :--------------------- |
|
||||||
|
| `shop` | `shopify` | The Shopify CLI itself |
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
| :------------- | :--------------------------------------------------------------------------------- |
|
||||||
|
| `shopd` | Runs `theme dev`, `app dev` or `hydrogen dev`, whichever fits the current project |
|
||||||
|
| `shopi` | Shows what the current project is connected to |
|
||||||
|
| `shopify_here` | Prints the kind of Shopify project you are in and the commands worth running in it |
|
||||||
|
| `shopify` | Wraps the CLI to confirm before irreversible commands. See Settings |
|
||||||
|
|
||||||
|
`shopd` and `shopi` work out which topic applies by looking at the project you
|
||||||
|
are standing in, so you do not have to remember whether this directory is a
|
||||||
|
theme, an app or a Hydrogen storefront. They complete like the command they
|
||||||
|
stand in for, so in a theme `shopd --<TAB>` offers the flags of
|
||||||
|
`shopify theme dev`.
|
||||||
|
|
||||||
|
## Completion
|
||||||
|
|
||||||
|
Every command completes with a description of what it does, at every level, and
|
||||||
|
so do their flags, short forms and allowed values. `--environment` completes
|
||||||
|
from the `[environments.*]` sections of your local `shopify.theme.toml` or
|
||||||
|
`shopify.app.toml`.
|
||||||
|
|
||||||
|
The Shopify CLI ships no completion generator of its own, so `_shopify` is
|
||||||
|
generated from `shopify commands --json` and kept in this repository. It targets
|
||||||
|
Shopify CLI 4.x.
|
||||||
|
|
||||||
|
## Settings
|
||||||
|
|
||||||
|
Set these with `zstyle` in your zshrc, before Oh My Zsh is sourced.
|
||||||
|
|
||||||
|
### Confirming destructive commands
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:shopify' confirm-destructive no
|
||||||
|
```
|
||||||
|
|
||||||
|
By default the plugin asks for confirmation before three irreversible
|
||||||
|
operations:
|
||||||
|
|
||||||
|
- `shopify theme push` with `--live`/`-l` or `--publish`/`-p`, which overwrites
|
||||||
|
or publishes the live storefront
|
||||||
|
- `shopify theme delete`, which the CLI's own help describes as impossible to
|
||||||
|
undo
|
||||||
|
- `shopify app deploy --allow-deletes`, which can permanently remove extensions
|
||||||
|
|
||||||
|
Nothing else is intercepted, and the prompt is skipped when the command already
|
||||||
|
carries `--force`/`-f` or when stdin is not a terminal, so scripts, pipelines
|
||||||
|
and CI are unaffected. Set the style to `no` to turn the prompt off entirely.
|
||||||
|
|
||||||
|
### Completing theme IDs
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:shopify' dynamic-theme-completion yes
|
||||||
|
```
|
||||||
|
|
||||||
|
Off by default. When enabled, `--theme` is completed from
|
||||||
|
`shopify theme list --json`, showing each theme's name and role next to its ID
|
||||||
|
instead of making you copy IDs by hand. It is opt-in because it runs the CLI and
|
||||||
|
makes a network call when you press <kbd>Tab</kbd>, and because it needs you to
|
||||||
|
be authenticated. Results are cached for five minutes.
|
||||||
|
|
||||||
|
### Disabling the aliases
|
||||||
|
|
||||||
|
This works for every Oh My Zsh plugin:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:shopify' aliases no
|
||||||
|
```
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
- `shopify` is a shell function here. Run `command shopify` to reach the binary
|
||||||
|
directly.
|
||||||
|
- When a project has its own copy of the CLI in `node_modules/.bin/shopify`,
|
||||||
|
that one is used in preference to the global install. App and Hydrogen
|
||||||
|
projects normally pin the CLI in `package.json`, and running a different
|
||||||
|
global version against them is a common source of confusing errors.
|
||||||
|
- `--password` and `--store-password` are unrelated, and you often need both.
|
||||||
|
`--password` is the CLI's own authentication token, from the Theme Access app
|
||||||
|
or the Admin API. `--store-password` is the password for a
|
||||||
|
password-protected storefront.
|
||||||
|
- `shopify theme push` deletes remote files that are missing locally, and
|
||||||
|
`shopify theme pull` deletes local files that are missing remotely, unless you
|
||||||
|
pass `--nodelete`/`-n`. The plugin does not prompt for these.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,203 @@
|
|||||||
|
# Shopify CLI: completion, aliases and guard rails.
|
||||||
|
# https://shopify.dev/docs/api/shopify-cli
|
||||||
|
|
||||||
|
if (( ! $+commands[shopify] )); then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prefer a project-local CLI: app and Hydrogen projects pin their own version.
|
||||||
|
# The walk stops at $HOME so a stray ~/node_modules cannot hijack every project.
|
||||||
|
# $commands avoids resolving back to the wrapper function below.
|
||||||
|
function _shopify_bin() {
|
||||||
|
local dir="$PWD"
|
||||||
|
while [[ -n "$dir" && "$dir" != "/" && "$dir" != "$HOME" ]]; do
|
||||||
|
if [[ -x "$dir/node_modules/.bin/shopify" ]]; then
|
||||||
|
print -r -- "$dir/node_modules/.bin/shopify"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
dir="${dir:h}"
|
||||||
|
done
|
||||||
|
print -r -- "$commands[shopify]"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print the project type in $PWD: hydrogen, app or theme.
|
||||||
|
# Hydrogen is tested first because those projects usually carry a
|
||||||
|
# shopify.app.toml too. shopify.theme.toml is not a theme marker: it only
|
||||||
|
# exists once environments are configured.
|
||||||
|
function _shopify_project_type() {
|
||||||
|
local dir="$PWD"
|
||||||
|
local -a app_config
|
||||||
|
|
||||||
|
while [[ -n "$dir" && "$dir" != "/" && "$dir" != "$HOME" ]]; do
|
||||||
|
if [[ -x "$dir/node_modules/.bin/h2" ]] ||
|
||||||
|
[[ -r "$dir/package.json" && "$(<"$dir/package.json")" == *'"@shopify/hydrogen"'* ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
app_config=("$dir"/shopify.app*.toml(N))
|
||||||
|
if (( $#app_config )); then
|
||||||
|
print -r -- app
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$dir/config/settings_schema.json" && -f "$dir/layout/theme.liquid" ]]; then
|
||||||
|
print -r -- theme
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
dir="${dir:h}"
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Does this invocation need confirming? Sets REPLY to the reason.
|
||||||
|
function _shopify_is_destructive() {
|
||||||
|
zstyle -T ':omz:plugins:shopify' confirm-destructive || return 1
|
||||||
|
|
||||||
|
# Nobody to answer: CI and pipelines are unaffected.
|
||||||
|
[[ -t 0 ]] || return 1
|
||||||
|
|
||||||
|
local topic="$1" subcommand="$2" arg
|
||||||
|
local -a long
|
||||||
|
local short=""
|
||||||
|
|
||||||
|
# Short flags can be bundled, so collect them as characters: -al counts as l.
|
||||||
|
for arg in "${@[3,-1]}"; do
|
||||||
|
[[ "$arg" == "--" ]] && break
|
||||||
|
case "$arg" in
|
||||||
|
--*) long+=("${arg%%=*}") ;;
|
||||||
|
-?*) short+="${${arg%%=*}#-}" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# An explicit force flag states the intent already.
|
||||||
|
if (( long[(I)--force] )) || [[ "$short" == *f* ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$topic $subcommand" in
|
||||||
|
"theme push")
|
||||||
|
if (( long[(I)--live] || long[(I)--publish] )) || [[ "$short" == *[lp]* ]]; then
|
||||||
|
REPLY="this overwrites or publishes the live theme on the storefront."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"theme delete")
|
||||||
|
REPLY="deleting a theme cannot be undone."
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
"app deploy")
|
||||||
|
if (( long[(I)--allow-deletes] )); then
|
||||||
|
REPLY="this can permanently remove app extensions."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Adds a confirmation prompt before irreversible operations. Everything else
|
||||||
|
# passes straight through, so `theme dev` stays interactive and pipes stay clean.
|
||||||
|
function shopify() {
|
||||||
|
local REPLY
|
||||||
|
if _shopify_is_destructive "$@"; then
|
||||||
|
print -u2 -- "shopify: $REPLY"
|
||||||
|
if ! read -q "?Continue? [y/N] "; then
|
||||||
|
print -u2 -- ""
|
||||||
|
return 130
|
||||||
|
fi
|
||||||
|
print -u2 -- ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$(_shopify_bin)" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print the commands worth running in the current directory.
|
||||||
|
function shopify_here() {
|
||||||
|
local project_type
|
||||||
|
project_type="$(_shopify_project_type)"
|
||||||
|
|
||||||
|
case "$project_type" in
|
||||||
|
theme)
|
||||||
|
print -- "Shopify theme project."
|
||||||
|
print -- " shopify theme dev Preview locally with live reload"
|
||||||
|
print -- " shopify theme check Lint the theme"
|
||||||
|
print -- " shopify theme list List the themes on the store"
|
||||||
|
print -- " shopify theme pull Download a remote theme into this folder"
|
||||||
|
print -- " shopify theme push Upload this folder to a remote theme"
|
||||||
|
;;
|
||||||
|
app)
|
||||||
|
print -- "Shopify app project."
|
||||||
|
print -- " shopify app dev Run the app against a development store"
|
||||||
|
print -- " shopify app info Show how the app is configured"
|
||||||
|
print -- " shopify app deploy Deploy the app and its extensions"
|
||||||
|
print -- " shopify app logs Stream app logs"
|
||||||
|
;;
|
||||||
|
hydrogen)
|
||||||
|
print -- "Hydrogen storefront."
|
||||||
|
print -- " shopify hydrogen dev Run the storefront locally"
|
||||||
|
print -- " shopify hydrogen build Build for production"
|
||||||
|
print -- " shopify hydrogen deploy Deploy to Oxygen"
|
||||||
|
print -- " shopify hydrogen link Link this project to a storefront"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print -- "No Shopify project found here."
|
||||||
|
print -- " shopify theme init Start a new theme"
|
||||||
|
print -- " shopify app init Start a new app"
|
||||||
|
print -- " shopify hydrogen init Start a new Hydrogen storefront"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run the dev server for whichever kind of project this is.
|
||||||
|
function shopd() {
|
||||||
|
local project_type
|
||||||
|
if ! project_type="$(_shopify_project_type)"; then
|
||||||
|
print -u2 -- "shopd: not inside a Shopify theme, app or Hydrogen project."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
shopify "$project_type" dev "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show what the current project is connected to.
|
||||||
|
function shopi() {
|
||||||
|
local project_type
|
||||||
|
if ! project_type="$(_shopify_project_type)"; then
|
||||||
|
print -u2 -- "shopi: not inside a Shopify theme, app or Hydrogen project."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
case "$project_type" in
|
||||||
|
hydrogen) shopify hydrogen list "$@" ;;
|
||||||
|
*) shopify "$project_type" info "$@" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Complete the helpers like the commands they stand in for.
|
||||||
|
if (( $+functions[compdef] )); then
|
||||||
|
_shopd() {
|
||||||
|
local project_type
|
||||||
|
project_type="$(_shopify_project_type)" || return 1
|
||||||
|
words=(shopify "$project_type" dev ${words[2,-1]})
|
||||||
|
(( CURRENT += 2 ))
|
||||||
|
_shopify
|
||||||
|
}
|
||||||
|
|
||||||
|
_shopi() {
|
||||||
|
local project_type
|
||||||
|
project_type="$(_shopify_project_type)" || return 1
|
||||||
|
if [[ "$project_type" == hydrogen ]]; then
|
||||||
|
words=(shopify hydrogen list ${words[2,-1]})
|
||||||
|
else
|
||||||
|
words=(shopify "$project_type" info ${words[2,-1]})
|
||||||
|
fi
|
||||||
|
(( CURRENT += 2 ))
|
||||||
|
_shopify
|
||||||
|
}
|
||||||
|
|
||||||
|
compdef _shopd shopd
|
||||||
|
compdef _shopi shopi
|
||||||
|
fi
|
||||||
|
|
||||||
|
alias shop='shopify'
|
||||||
@@ -21,6 +21,18 @@ To enable **agent forwarding support** add the following to your zshrc file:
|
|||||||
zstyle :omz:plugins:ssh-agent agent-forwarding yes
|
zstyle :omz:plugins:ssh-agent agent-forwarding yes
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `honor-existing`
|
||||||
|
|
||||||
|
If your session already provides an ssh-agent — a desktop keyring, `gpg-agent`,
|
||||||
|
KeePassXC, or an agent forwarded over SSH — the plugin normally ignores it and
|
||||||
|
starts one of its own, which leaves you with two agents. Set this to reuse the
|
||||||
|
running agent instead, and only start a new one when `$SSH_AUTH_SOCK` is empty
|
||||||
|
or does not answer:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle :omz:plugins:ssh-agent honor-existing yes
|
||||||
|
```
|
||||||
|
|
||||||
### `helper`
|
### `helper`
|
||||||
|
|
||||||
To set an **external helper** to ask for the passwords and possibly store
|
To set an **external helper** to ask for the passwords and possibly store
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
# Get the filename to store/lookup the environment from
|
# Get the filename to store/lookup the environment from
|
||||||
ssh_env_cache="$HOME/.ssh/environment-$SHORT_HOST"
|
ssh_env_cache="$HOME/.ssh/environment-$SHORT_HOST"
|
||||||
|
|
||||||
|
# Test if $SSH_AUTH_SOCK points at a listening agent
|
||||||
|
function _is_agent_running() {
|
||||||
|
local REPLY
|
||||||
|
[[ -n "$SSH_AUTH_SOCK" && -S "$SSH_AUTH_SOCK" ]] || return 1
|
||||||
|
zmodload zsh/net/socket 2>/dev/null || return 1
|
||||||
|
zsocket "$SSH_AUTH_SOCK" 2>/dev/null || return 1
|
||||||
|
exec {REPLY}>&- # close the probe connection
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
function _start_agent() {
|
function _start_agent() {
|
||||||
|
# Reuse an agent the session already provides, if enabled
|
||||||
|
if zstyle -t :omz:plugins:ssh-agent honor-existing && _is_agent_running; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Check if ssh-agent is already running
|
# Check if ssh-agent is already running
|
||||||
if [[ -f "$ssh_env_cache" ]]; then
|
if [[ -f "$ssh_env_cache" ]]; then
|
||||||
. "$ssh_env_cache" > /dev/null
|
. "$ssh_env_cache" > /dev/null
|
||||||
|
|
||||||
# Test if $SSH_AUTH_SOCK is visible
|
# Test if $SSH_AUTH_SOCK is visible
|
||||||
zmodload zsh/net/socket
|
_is_agent_running && return 0
|
||||||
if [[ -S "$SSH_AUTH_SOCK" ]] && zsocket "$SSH_AUTH_SOCK" 2>/dev/null; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -d "$HOME/.ssh" ]]; then
|
if [[ ! -d "$HOME/.ssh" ]]; then
|
||||||
@@ -124,4 +136,4 @@ if ! zstyle -t :omz:plugins:ssh-agent lazy; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
unset agent_forwarding ssh_env_cache
|
unset agent_forwarding ssh_env_cache
|
||||||
unfunction _start_agent _add_identities
|
unfunction _start_agent _add_identities _is_agent_running
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ Related: [#9798](https://github.com/ohmyzsh/ohmyzsh/pull/9798).
|
|||||||
| Alias | Commands | Description |
|
| Alias | Commands | Description |
|
||||||
| ----- | ------------------- | ---------------------------------------- |
|
| ----- | ------------------- | ---------------------------------------- |
|
||||||
| zar | `sudo zypper ar` | add a repository |
|
| zar | `sudo zypper ar` | add a repository |
|
||||||
| zcl | `sudo zypper clean` | clean cache |
|
|
||||||
| zlr | `zypper lr` | list repositories |
|
| zlr | `zypper lr` | list repositories |
|
||||||
| zmr | `sudo zypper mr` | modify repositories |
|
| zmr | `sudo zypper mr` | modify repositories |
|
||||||
| znr | `sudo zypper nr` | rename repositories (for the alias only) |
|
| znr | `sudo zypper nr` | rename repositories (for the alias only) |
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ alias zwp='zypper --no-refresh wp'
|
|||||||
|
|
||||||
#Repositories commands
|
#Repositories commands
|
||||||
alias zar='sudo zypper ar'
|
alias zar='sudo zypper ar'
|
||||||
alias zcl='sudo zypper clean'
|
|
||||||
alias zlr='zypper lr'
|
alias zlr='zypper lr'
|
||||||
alias zmr='sudo zypper mr'
|
alias zmr='sudo zypper mr'
|
||||||
alias znr='sudo zypper nr'
|
alias znr='sudo zypper nr'
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ plugins=(... systemadmin)
|
|||||||
| mkdir | `mkdir -pv` | Automatically create parent directories and display verbose output |
|
| mkdir | `mkdir -pv` | Automatically create parent directories and display verbose output |
|
||||||
| psmem | `ps -e -orss=,args= \| sort -b -k1 -nr` | Display the processes using the most memory |
|
| psmem | `ps -e -orss=,args= \| sort -b -k1 -nr` | Display the processes using the most memory |
|
||||||
| psmem10 | `ps -e -orss=,args= \| sort -b -k1 -nr \| head -n 10` | Display the top 10 processes using the most memory |
|
| psmem10 | `ps -e -orss=,args= \| sort -b -k1 -nr \| head -n 10` | Display the top 10 processes using the most memory |
|
||||||
|
| pszombie| `ps -eo user,pid,ppid,state,comm \| awk '$4=="Z"'` | List zombie processes with ownership and parent process details |
|
||||||
| pscpu | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr` | Display the top processes using the most CPU |
|
| pscpu | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr` | Display the top processes using the most CPU |
|
||||||
| pscpu10 | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr \| head -n 10` | Display the top 10 processes using the most CPU |
|
| pscpu10 | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr \| head -n 10` | Display the top 10 processes using the most CPU |
|
||||||
| hist10 | `print -l ${(o)history%% *} \| uniq -c \| sort -nr \| head -n 10` | Display the top 10 most used commands in the history |
|
| hist10 | `print -l ${(o)history%% *} \| uniq -c \| sort -nr \| head -n 10` | Display the top 10 most used commands in the history |
|
||||||
@@ -48,5 +49,4 @@ plugins=(... systemadmin)
|
|||||||
| d0 | Delete 0 byte files recursively in the current directory or another if specified |
|
| d0 | Delete 0 byte files recursively in the current directory or another if specified |
|
||||||
| geteip | Gather information regarding an external IP address using [icanhazip.com](https://icanhazip.com) |
|
| geteip | Gather information regarding an external IP address using [icanhazip.com](https://icanhazip.com) |
|
||||||
| getip | Determine the local IP Address with `ip addr` or `ifconfig` |
|
| getip | Determine the local IP Address with `ip addr` or `ifconfig` |
|
||||||
| clrz | Clear zombie processes |
|
|
||||||
| conssec | Show number of concurrent connections per second based on nginx/access.log file or another log file if specified |
|
| conssec | Show number of concurrent connections per second based on nginx/access.log file or another log file if specified |
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ alias mkdir='mkdir -pv'
|
|||||||
# get top process eating memory
|
# get top process eating memory
|
||||||
alias psmem='ps -e -orss=,args= | sort -b -k1 -nr'
|
alias psmem='ps -e -orss=,args= | sort -b -k1 -nr'
|
||||||
alias psmem10='ps -e -orss=,args= | sort -b -k1 -nr | head -n 10'
|
alias psmem10='ps -e -orss=,args= | sort -b -k1 -nr | head -n 10'
|
||||||
|
# list all zombie processes with ownership and parent process details
|
||||||
|
alias pszombie="ps -eo user,pid,ppid,state,comm | awk '\$4==\"Z\"'"
|
||||||
# get top process eating cpu if not work try execute : export LC_ALL='C'
|
# get top process eating cpu if not work try execute : export LC_ALL='C'
|
||||||
alias pscpu='ps -e -o pcpu,cpu,nice,state,cputime,args | sort -k1,1n -nr'
|
alias pscpu='ps -e -o pcpu,cpu,nice,state,cputime,args | sort -k1,1n -nr'
|
||||||
alias pscpu10='ps -e -o pcpu,cpu,nice,state,cputime,args | sort -k1,1n -nr | head -n 10'
|
alias pscpu10='ps -e -o pcpu,cpu,nice,state,cputime,args | sort -k1,1n -nr | head -n 10'
|
||||||
@@ -177,11 +179,6 @@ function getip() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Clear zombie processes
|
|
||||||
function clrz() {
|
|
||||||
ps -eal | awk '{ if ($2 == "Z") {print $4}}' | kill -9
|
|
||||||
}
|
|
||||||
|
|
||||||
# Second concurrent
|
# Second concurrent
|
||||||
function conssec() {
|
function conssec() {
|
||||||
awk '{if($9~/200|30|404/)COUNT[$4]++}END{for( a in COUNT) print a,COUNT[a]}' "$(retlog)" | sort -k 2 -nr | head -n10
|
awk '{if($9~/200|30|404/)COUNT[$4]++}END{for( a in COUNT) print a,COUNT[a]}' "$(retlog)" | sort -k 2 -nr | head -n10
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ plugins=(... systemd)
|
|||||||
| `sc-set-environment` | `sudo systemctl set-environment` | Set one or more systemd manager environment variables |
|
| `sc-set-environment` | `sudo systemctl set-environment` | Set one or more systemd manager environment variables |
|
||||||
| `sc-unset-environment` | `sudo systemctl unset-environment` | Unset one or more systemd manager environment variables |
|
| `sc-unset-environment` | `sudo systemctl unset-environment` | Unset one or more systemd manager environment variables |
|
||||||
| `sc-edit` | `sudo systemctl edit` | Edit a drop-in snippet or a whole replacement file with `--full` |
|
| `sc-edit` | `sudo systemctl edit` | Edit a drop-in snippet or a whole replacement file with `--full` |
|
||||||
|
| `sc-edit-full` | `sudo systemctl edit --full` | Edit the whole unit file instead of a drop-in snippet |
|
||||||
| `sc-enable-now` | `sudo systemctl enable --now` | Enable and start unit(s) |
|
| `sc-enable-now` | `sudo systemctl enable --now` | Enable and start unit(s) |
|
||||||
| `sc-disable-now` | `sudo systemctl disable --now` | Disable and stop unit(s) |
|
| `sc-disable-now` | `sudo systemctl disable --now` | Disable and stop unit(s) |
|
||||||
| `sc-mask-now` | `sudo systemctl mask --now` | Mask and stop unit(s) |
|
| `sc-mask-now` | `sudo systemctl mask --now` | Mask and stop unit(s) |
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ alias scu-mask-now="scu-mask --now"
|
|||||||
alias scu-failed='systemctl --user --failed'
|
alias scu-failed='systemctl --user --failed'
|
||||||
alias sc-failed='systemctl --failed'
|
alias sc-failed='systemctl --failed'
|
||||||
|
|
||||||
|
# --full commands
|
||||||
|
alias sc-edit-full="sc-edit --full"
|
||||||
|
alias scu-edit-full="scu-edit --full"
|
||||||
|
|
||||||
function systemd_prompt_info {
|
function systemd_prompt_info {
|
||||||
local unit
|
local unit
|
||||||
for unit in "$@"; do
|
for unit in "$@"; do
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# term_tab plugin
|
# term_tab plugin
|
||||||
|
|
||||||
This plugin only works for Solaris and linux.
|
This plugin works on Linux, macOS and Solaris.
|
||||||
|
|
||||||
term_tab - `cwd` for all open zsh sessions
|
term_tab - `cwd` for all open zsh sessions
|
||||||
|
|
||||||
|
|||||||
@@ -178,6 +178,11 @@ alias tmux=_zsh_tmux_plugin_run
|
|||||||
function _tmux_directory_session() {
|
function _tmux_directory_session() {
|
||||||
# current directory without leading path
|
# current directory without leading path
|
||||||
local dir=${PWD##*/}
|
local dir=${PWD##*/}
|
||||||
|
# tmux target syntax treats '.' and ':' as separators, a leading '$', '@' or '%'
|
||||||
|
# as an id and a leading '=' as an exact-match prefix, so a session named after
|
||||||
|
# such a directory can't be found on reattach
|
||||||
|
dir=${dir//[.:]/_}
|
||||||
|
dir=${dir/#[\$@%=]/_}
|
||||||
# md5 hash for the full working directory path
|
# md5 hash for the full working directory path
|
||||||
local md5=$(printf '%s' "$PWD" | md5sum | cut -d ' ' -f 1)
|
local md5=$(printf '%s' "$PWD" | md5sum | cut -d ' ' -f 1)
|
||||||
# human friendly unique session name for this directory
|
# human friendly unique session name for this directory
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ case $state in
|
|||||||
(box)
|
(box)
|
||||||
__vagrant-box
|
__vagrant-box
|
||||||
;;
|
;;
|
||||||
(up|provision|port|package|destroy|reload|ssh|ssh-config|halt|resume|status)
|
(up|provision|port|package|destroy|reload|ssh|ssh-config|halt|resume|status|suspend|rdp)
|
||||||
_arguments ':feature:__vm_list'
|
_arguments ':feature:__vm_list'
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ if [[ ! $DISABLE_VENV_CD -eq 1 ]]; then
|
|||||||
# Get absolute path, resolving symlinks
|
# Get absolute path, resolving symlinks
|
||||||
local PROJECT_ROOT="${PWD:A}"
|
local PROJECT_ROOT="${PWD:A}"
|
||||||
while [[ "$PROJECT_ROOT" != "/" && ! -e "$PROJECT_ROOT/.venv" \
|
while [[ "$PROJECT_ROOT" != "/" && ! -e "$PROJECT_ROOT/.venv" \
|
||||||
&& ! -d "$PROJECT_ROOT/.git" ]]; do
|
&& ! -e "$PROJECT_ROOT/.git" ]]; do
|
||||||
PROJECT_ROOT="${PROJECT_ROOT:h}"
|
PROJECT_ROOT="${PROJECT_ROOT:h}"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ Available search contexts are:
|
|||||||
| `npmpkg` | `https://www.npmjs.com/search?q=` |
|
| `npmpkg` | `https://www.npmjs.com/search?q=` |
|
||||||
| `packagist` | `https://packagist.org/?query=` |
|
| `packagist` | `https://packagist.org/?query=` |
|
||||||
| `gopkg` | `https://pkg.go.dev/search?m=package&q=` |
|
| `gopkg` | `https://pkg.go.dev/search?m=package&q=` |
|
||||||
|
| `maven` | `https://central.sonatype.com/search?q=` |
|
||||||
|
| `pypi` | `https://pypi.org/search/?q=` |
|
||||||
|
| `aur` | `https://aur.archlinux.org/packages?O=0&K=` |
|
||||||
|
| `archwiki` | `https://wiki.archlinux.org/index.php?search=` |
|
||||||
|
| `wikipedia` | `https://en.wikipedia.org/w/index.php?search=` |
|
||||||
| `chatgpt` | `https://chatgpt.com/?q=` |
|
| `chatgpt` | `https://chatgpt.com/?q=` |
|
||||||
| `claudeai` | `https://claude.ai/new?q=` |
|
| `claudeai` | `https://claude.ai/new?q=` |
|
||||||
| `grokcom` | `https://grok.com/?q=` |
|
| `grokcom` | `https://grok.com/?q=` |
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ function web_search() {
|
|||||||
npmpkg "https://www.npmjs.com/search?q="
|
npmpkg "https://www.npmjs.com/search?q="
|
||||||
packagist "https://packagist.org/?query="
|
packagist "https://packagist.org/?query="
|
||||||
gopkg "https://pkg.go.dev/search?m=package&q="
|
gopkg "https://pkg.go.dev/search?m=package&q="
|
||||||
|
maven "https://central.sonatype.com/search?q="
|
||||||
|
pypi "https://pypi.org/search/?q="
|
||||||
|
aur "https://aur.archlinux.org/packages?O=0&K="
|
||||||
|
archwiki "https://wiki.archlinux.org/index.php?search="
|
||||||
|
wikipedia "https://en.wikipedia.org/w/index.php?search="
|
||||||
chatgpt "https://chatgpt.com/?q="
|
chatgpt "https://chatgpt.com/?q="
|
||||||
grok "https://grok.com/?q="
|
grok "https://grok.com/?q="
|
||||||
claudeai "https://claude.ai/new?q="
|
claudeai "https://claude.ai/new?q="
|
||||||
@@ -92,6 +97,11 @@ alias gems='web_search gems'
|
|||||||
alias npmpkg='web_search npmpkg'
|
alias npmpkg='web_search npmpkg'
|
||||||
alias packagist='web_search packagist'
|
alias packagist='web_search packagist'
|
||||||
alias gopkg='web_search gopkg'
|
alias gopkg='web_search gopkg'
|
||||||
|
alias maven='web_search maven'
|
||||||
|
alias pypi='web_search pypi'
|
||||||
|
alias aur='web_search aur'
|
||||||
|
alias archwiki='web_search archwiki'
|
||||||
|
alias wikipedia='web_search wikipedia'
|
||||||
alias chatgpt='web_search chatgpt'
|
alias chatgpt='web_search chatgpt'
|
||||||
alias grokcom='web_search grok'
|
alias grokcom='web_search grok'
|
||||||
alias claudeai='web_search claudeai'
|
alias claudeai='web_search claudeai'
|
||||||
@@ -116,4 +126,3 @@ if [[ ${#ZSH_WEB_SEARCH_ENGINES} -gt 0 ]]; then
|
|||||||
done
|
done
|
||||||
unset engines key
|
unset engines key
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
Copyright (c) 2013 Thiago de Arruda
|
||||||
|
Copyright (c) 2016-2021 Eric Freese
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
# zsh-autosuggestions
|
||||||
|
|
||||||
|
_[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
|
||||||
|
|
||||||
|
It suggests commands as you type based on history and completions.
|
||||||
|
|
||||||
|
Requirements: Zsh v4.3.11 or later
|
||||||
|
|
||||||
|
[](https://gitter.im/zsh-users/zsh-autosuggestions)
|
||||||
|
|
||||||
|
<a href="https://asciinema.org/a/37390" target="_blank"><img src="https://asciinema.org/a/37390.png" width="400" /></a>
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
See [the Oh My Zsh plugin README](README.md).
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
As you type commands, you will see a completion offered after the cursor in a muted gray color. This color can be changed by setting the `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` variable. See [configuration](#configuration).
|
||||||
|
|
||||||
|
If you press the <kbd>→</kbd> key (`forward-char` widget) or <kbd>End</kbd> (`end-of-line` widget) with the cursor at the end of the buffer, it will accept the suggestion, replacing the contents of the command line buffer with the suggestion.
|
||||||
|
|
||||||
|
If you invoke the `forward-word` widget, it will partially accept the suggestion up to the point that the cursor moves to.
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
You may want to override the default global config variables. Default values of these variables can be found [here](src/config.zsh).
|
||||||
|
|
||||||
|
**Note:** If you are using Oh My Zsh, you can put this configuration in a file in the `$ZSH_CUSTOM` directory. See their comments on [overriding internals](https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals).
|
||||||
|
|
||||||
|
|
||||||
|
### Suggestion Highlight Style
|
||||||
|
|
||||||
|
Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion is shown with. The default is `fg=8`, which will set the foreground color to color 8 from the [256-color palette](https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg). If your terminal only supports 8 colors, you will need to use a number between 0 and 7.
|
||||||
|
|
||||||
|
Background color can also be set, and the suggestion can be styled bold, underlined, or standout. For example, this would show suggestions with bold, underlined, pink text on a cyan background:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#ff00ff,bg=cyan,bold,underline"
|
||||||
|
```
|
||||||
|
|
||||||
|
For more info, read the Character Highlighting section of the zsh manual: `man zshzle` or [online](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting).
|
||||||
|
|
||||||
|
**Note:** Some iTerm2 users have reported [not being able to see the suggestions](https://github.com/zsh-users/zsh-autosuggestions/issues/416#issuecomment-486516333). If this affects you, the problem is likely caused by incorrect color settings. In order to correct this, go into iTerm2's setting, navigate to profile > colors and make sure that the colors for Basic Colors > Background and ANSI Colors > Bright Black are **different**.
|
||||||
|
|
||||||
|
|
||||||
|
### Suggestion Strategy
|
||||||
|
|
||||||
|
`ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated. The strategies in the array are tried successively until a suggestion is found. There are currently three built-in strategies to choose from:
|
||||||
|
|
||||||
|
- `history`: Chooses the most recent match from history.
|
||||||
|
- `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module, which is included with zsh since 4.0.1)
|
||||||
|
- `match_prev_cmd`: Like `history`, but chooses the most recent match whose preceding history item matches the most recently executed command ([more info](src/strategies/match_prev_cmd.zsh)). Note that this strategy won't work as expected with ZSH options that don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`.
|
||||||
|
|
||||||
|
For example, setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` will first try to find a suggestion from your history, but, if it can't find a match, will find a suggestion from the completion engine.
|
||||||
|
|
||||||
|
|
||||||
|
### Widget Mapping
|
||||||
|
|
||||||
|
This plugin works by triggering custom behavior when certain [zle widgets](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets) are invoked. You can add and remove widgets from these arrays to change the behavior of this plugin:
|
||||||
|
|
||||||
|
- `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`: Widgets in this array will clear the suggestion when invoked.
|
||||||
|
- `ZSH_AUTOSUGGEST_ACCEPT_WIDGETS`: Widgets in this array will accept the suggestion when invoked.
|
||||||
|
- `ZSH_AUTOSUGGEST_EXECUTE_WIDGETS`: Widgets in this array will execute the suggestion when invoked.
|
||||||
|
- `ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS`: Widgets in this array will partially accept the suggestion when invoked.
|
||||||
|
- `ZSH_AUTOSUGGEST_IGNORE_WIDGETS`: Widgets in this array will not trigger any custom behavior.
|
||||||
|
|
||||||
|
Widgets that modify the buffer and are not found in any of these arrays will fetch a new suggestion after they are invoked.
|
||||||
|
|
||||||
|
**Note:** A widget shouldn't belong to more than one of the above arrays.
|
||||||
|
|
||||||
|
|
||||||
|
### Disabling suggestion for large buffers
|
||||||
|
|
||||||
|
Set `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an integer value to disable autosuggestion for large buffers. The default is unset, which means that autosuggestion will be tried for any buffer size. Recommended value is 20.
|
||||||
|
This can be useful when pasting large amount of text in the terminal, to avoid triggering autosuggestion for strings that are too long.
|
||||||
|
|
||||||
|
### Asynchronous Mode
|
||||||
|
|
||||||
|
Suggestions are fetched asynchronously by default in zsh versions 5.0.8 and greater. To disable asynchronous suggestions and fetch them synchronously instead, `unset ZSH_AUTOSUGGEST_USE_ASYNC` after sourcing the plugin.
|
||||||
|
|
||||||
|
Alternatively, if you are using a version of zsh older than 5.0.8 and want to enable asynchronous mode, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable after sourcing the plugin (it can be set to anything). Note that there is [a bug](https://github.com/zsh-users/zsh-autosuggestions/issues/364#issuecomment-481423232) in versions of zsh older than 5.0.8 where <kbd>ctrl</kbd> + <kbd>c</kbd> will fail to reset the prompt immediately after fetching a suggestion asynchronously.
|
||||||
|
|
||||||
|
### Disabling automatic widget re-binding
|
||||||
|
|
||||||
|
Set `ZSH_AUTOSUGGEST_MANUAL_REBIND` (it can be set to anything) to disable automatic widget re-binding on each precmd. This can be a big boost to performance, but you'll need to handle re-binding yourself if any of the widget lists change or if you or another plugin wrap any of the autosuggest widgets. To re-bind widgets, run `_zsh_autosuggest_bind_widgets`.
|
||||||
|
|
||||||
|
### Ignoring history suggestions that match a pattern
|
||||||
|
|
||||||
|
Set `ZSH_AUTOSUGGEST_HISTORY_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering suggestions for history entries that match the pattern. For example, set it to `"cd *"` to never suggest any `cd` commands from history. Or set to `"?(#c50,)"` to never suggest anything 50 characters or longer.
|
||||||
|
|
||||||
|
**Note:** This only affects the `history` and `match_prev_cmd` suggestion strategies.
|
||||||
|
|
||||||
|
### Skipping completion suggestions for certain cases
|
||||||
|
|
||||||
|
Set `ZSH_AUTOSUGGEST_COMPLETION_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering completion suggestions when the buffer matches that pattern. For example, set it to `"git *"` to disable completion suggestions for git subcommands.
|
||||||
|
|
||||||
|
**Note:** This only affects the `completion` suggestion strategy.
|
||||||
|
|
||||||
|
|
||||||
|
### Key Bindings
|
||||||
|
|
||||||
|
This plugin provides a few widgets that you can use with `bindkey`:
|
||||||
|
|
||||||
|
1. `autosuggest-accept`: Accepts the current suggestion.
|
||||||
|
2. `autosuggest-execute`: Accepts and executes the current suggestion.
|
||||||
|
3. `autosuggest-clear`: Clears the current suggestion.
|
||||||
|
4. `autosuggest-fetch`: Fetches a suggestion (works even when suggestions are disabled).
|
||||||
|
5. `autosuggest-disable`: Disables suggestions.
|
||||||
|
6. `autosuggest-enable`: Re-enables suggestions.
|
||||||
|
7. `autosuggest-toggle`: Toggles between enabled/disabled suggestions.
|
||||||
|
|
||||||
|
For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bindkey '^ ' autosuggest-accept
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If you have a problem, please search through [the list of issues on GitHub](https://github.com/zsh-users/zsh-autosuggestions/issues?q=) to see if someone else has already reported it.
|
||||||
|
|
||||||
|
### Reporting an Issue
|
||||||
|
|
||||||
|
Before reporting an issue, please try temporarily disabling sections of your configuration and other plugins that may be conflicting with this plugin to isolate the problem.
|
||||||
|
|
||||||
|
When reporting an issue, please include:
|
||||||
|
|
||||||
|
- The smallest, simplest `.zshrc` configuration that will reproduce the problem. See [this comment](https://github.com/zsh-users/zsh-autosuggestions/issues/102#issuecomment-180944764) for a good example of what this means.
|
||||||
|
- The version of zsh you're using (`zsh --version`)
|
||||||
|
- Which operating system you're running
|
||||||
|
|
||||||
|
|
||||||
|
## Uninstallation
|
||||||
|
|
||||||
|
1. Remove the code referencing this plugin from `~/.zshrc`.
|
||||||
|
|
||||||
|
2. Remove the git repository from your hard drive
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rm -rf ~/.zsh/zsh-autosuggestions # Or wherever you installed
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Build Process
|
||||||
|
|
||||||
|
Edit the source files in `src/`. Run `make` to build `zsh-autosuggestions.zsh` from those source files.
|
||||||
|
|
||||||
|
|
||||||
|
### Pull Requests
|
||||||
|
|
||||||
|
Pull requests are welcome! If you send a pull request, please:
|
||||||
|
|
||||||
|
- Request to merge into the `develop` branch (*NOT* `master`)
|
||||||
|
- Match the existing coding conventions.
|
||||||
|
- Include helpful comments to keep the barrier-to-entry low for people new to the project.
|
||||||
|
- Write tests that cover your code as much as possible.
|
||||||
|
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
Tests are written in ruby using the [`rspec`](http://rspec.info/) framework. They use [`tmux`](https://tmux.github.io/) to drive a pseudoterminal, sending simulated keystrokes and making assertions on the terminal content.
|
||||||
|
|
||||||
|
Test files live in `spec/`. To run the tests, run `make test`. To run a specific test, run `TESTS=spec/some_spec.rb make test`. You can also specify a `zsh` binary to use by setting the `TEST_ZSH_BIN` environment variable (ex: `TEST_ZSH_BIN=/bin/zsh make test`).
|
||||||
|
|
||||||
|
It's possible to run the tests for any supported version of zsh in a Docker image by building an image from the provided Dockerfile. To build the docker image for a specific version of zsh (where `<version>` below is substituted with the contents of a line from the [`ZSH_VERSIONS`](ZSH_VERSIONS) file), run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker build --build-arg TEST_ZSH_VERSION=<version> -t zsh-autosuggestions-test .
|
||||||
|
```
|
||||||
|
|
||||||
|
After building the image, run the tests via:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker run -it -v $PWD:/zsh-autosuggestions zsh-autosuggestions-test make test
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under [MIT license](http://opensource.org/licenses/MIT).
|
||||||
|
For the full text of the license, see the [LICENSE](LICENSE) file.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# zsh-autosuggestions
|
||||||
|
|
||||||
|
This plugin suggests commands as you type, based on command history and completions.
|
||||||
|
|
||||||
|
To use it, add `zsh-autosuggestions` to the plugins array in your zshrc file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
plugins=(... zsh-autosuggestions)
|
||||||
|
```
|
||||||
|
|
||||||
|
Start a new terminal session after updating your zshrc file.
|
||||||
|
|
||||||
|
Suggestions appear in muted gray text by default. Press <kbd>→</kbd> or <kbd>End</kbd> at the end of the
|
||||||
|
command line to accept the displayed suggestion.
|
||||||
|
|
||||||
|
For configuration options and additional key bindings, see the [upstream documentation](MANUAL.md).
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Async #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_request() {
|
||||||
|
zmodload zsh/system 2>/dev/null # For `$sysparams`
|
||||||
|
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
|
||||||
|
|
||||||
|
# If we've got a pending request, cancel it
|
||||||
|
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
|
||||||
|
# Close the file descriptor and remove the handler
|
||||||
|
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
|
||||||
|
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
|
||||||
|
|
||||||
|
# We won't know the pid unless the user has zsh/system module installed
|
||||||
|
if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then
|
||||||
|
# Zsh will make a new process group for the child process only if job
|
||||||
|
# control is enabled (MONITOR option)
|
||||||
|
if [[ -o MONITOR ]]; then
|
||||||
|
# Send the signal to the process group to kill any processes that may
|
||||||
|
# have been forked by the suggestion strategy
|
||||||
|
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
||||||
|
else
|
||||||
|
# Kill just the child process since it wasn't placed in a new process
|
||||||
|
# group. If the suggestion strategy forked any child processes they may
|
||||||
|
# be orphaned and left behind.
|
||||||
|
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fork a process to fetch a suggestion and open a pipe to read from it
|
||||||
|
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
|
||||||
|
# Tell parent process our pid
|
||||||
|
echo $sysparams[pid]
|
||||||
|
|
||||||
|
# Fetch and print the suggestion
|
||||||
|
local suggestion
|
||||||
|
_zsh_autosuggest_fetch_suggestion "$1"
|
||||||
|
echo -nE "$suggestion"
|
||||||
|
)
|
||||||
|
|
||||||
|
# There's a weird bug here where ^C stops working unless we force a fork
|
||||||
|
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
|
||||||
|
autoload -Uz is-at-least
|
||||||
|
is-at-least 5.8 || command true
|
||||||
|
|
||||||
|
# Read the pid from the child process
|
||||||
|
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
|
||||||
|
|
||||||
|
# When the fd is readable, call the response handler
|
||||||
|
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
|
||||||
|
}
|
||||||
|
|
||||||
|
# Called when new data is ready to be read from the pipe
|
||||||
|
# First arg will be fd ready for reading
|
||||||
|
# Second arg will be passed in case of error
|
||||||
|
_zsh_autosuggest_async_response() {
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
local suggestion
|
||||||
|
|
||||||
|
if [[ -z "$2" || "$2" == "hup" ]]; then
|
||||||
|
# Read everything from the fd and give it as a suggestion
|
||||||
|
IFS='' read -rd '' -u $1 suggestion
|
||||||
|
zle autosuggest-suggest -- "$suggestion"
|
||||||
|
|
||||||
|
# Close the fd
|
||||||
|
builtin exec {1}<&-
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Always remove the handler
|
||||||
|
zle -F "$1"
|
||||||
|
_ZSH_AUTOSUGGEST_ASYNC_FD=
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Widget Helpers #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_incr_bind_count() {
|
||||||
|
typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1))
|
||||||
|
_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
|
||||||
|
}
|
||||||
|
|
||||||
|
# Bind a single widget to an autosuggest widget, saving a reference to the original widget
|
||||||
|
_zsh_autosuggest_bind_widget() {
|
||||||
|
typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS
|
||||||
|
|
||||||
|
local widget=$1
|
||||||
|
local autosuggest_action=$2
|
||||||
|
local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
|
||||||
|
|
||||||
|
local -i bind_count
|
||||||
|
|
||||||
|
# Save a reference to the original widget
|
||||||
|
case $widgets[$widget] in
|
||||||
|
# Already bound
|
||||||
|
user:_zsh_autosuggest_(bound|orig)_*)
|
||||||
|
bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget]))
|
||||||
|
;;
|
||||||
|
|
||||||
|
# User-defined widget
|
||||||
|
user:*)
|
||||||
|
_zsh_autosuggest_incr_bind_count $widget
|
||||||
|
zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:}
|
||||||
|
;;
|
||||||
|
|
||||||
|
# Built-in widget
|
||||||
|
builtin)
|
||||||
|
_zsh_autosuggest_incr_bind_count $widget
|
||||||
|
eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
|
||||||
|
zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget
|
||||||
|
;;
|
||||||
|
|
||||||
|
# Completion widget
|
||||||
|
completion:*)
|
||||||
|
_zsh_autosuggest_incr_bind_count $widget
|
||||||
|
eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Pass the original widget's name explicitly into the autosuggest
|
||||||
|
# function. Use this passed in widget name to call the original
|
||||||
|
# widget instead of relying on the $WIDGET variable being set
|
||||||
|
# correctly. $WIDGET cannot be trusted because other plugins call
|
||||||
|
# zle without the `-w` flag (e.g. `zle self-insert` instead of
|
||||||
|
# `zle self-insert -w`).
|
||||||
|
eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() {
|
||||||
|
_zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Create the bound widget
|
||||||
|
zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget
|
||||||
|
}
|
||||||
|
|
||||||
|
# Map all configured widgets to the right autosuggest widgets
|
||||||
|
_zsh_autosuggest_bind_widgets() {
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
local widget
|
||||||
|
local ignore_widgets
|
||||||
|
|
||||||
|
ignore_widgets=(
|
||||||
|
.\*
|
||||||
|
_\*
|
||||||
|
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
|
||||||
|
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
|
||||||
|
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find every widget we might want to bind and bind it appropriately
|
||||||
|
for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
|
||||||
|
if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget clear
|
||||||
|
elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget accept
|
||||||
|
elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget execute
|
||||||
|
elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget partial_accept
|
||||||
|
else
|
||||||
|
# Assume any unspecified widget might modify the buffer
|
||||||
|
_zsh_autosuggest_bind_widget $widget modify
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Given the name of an original widget and args, invoke it, if it exists
|
||||||
|
_zsh_autosuggest_invoke_original_widget() {
|
||||||
|
# Do nothing unless called with at least one arg
|
||||||
|
(( $# )) || return 0
|
||||||
|
|
||||||
|
local original_widget_name="$1"
|
||||||
|
|
||||||
|
shift
|
||||||
|
|
||||||
|
if (( ${+widgets[$original_widget_name]} )); then
|
||||||
|
zle $original_widget_name -- $@
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Global Configuration Variables #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Color to use when highlighting suggestion
|
||||||
|
# Uses format of `region_highlight`
|
||||||
|
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
|
||||||
|
|
||||||
|
# Prefix to use when saving original versions of bound widgets
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
|
||||||
|
|
||||||
|
# Strategies to use to fetch a suggestion
|
||||||
|
# Will try each strategy in order until a suggestion is returned
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_STRATEGY
|
||||||
|
ZSH_AUTOSUGGEST_STRATEGY=(history)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that clear the suggestion
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
|
||||||
|
history-search-forward
|
||||||
|
history-search-backward
|
||||||
|
history-beginning-search-forward
|
||||||
|
history-beginning-search-backward
|
||||||
|
history-beginning-search-forward-end
|
||||||
|
history-beginning-search-backward-end
|
||||||
|
history-substring-search-up
|
||||||
|
history-substring-search-down
|
||||||
|
up-line-or-beginning-search
|
||||||
|
down-line-or-beginning-search
|
||||||
|
up-line-or-history
|
||||||
|
down-line-or-history
|
||||||
|
accept-line
|
||||||
|
copy-earlier-word
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that accept the entire suggestion
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
|
||||||
|
forward-char
|
||||||
|
end-of-line
|
||||||
|
vi-forward-char
|
||||||
|
vi-end-of-line
|
||||||
|
vi-add-eol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that accept the entire suggestion and execute it
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that accept the suggestion as far as the cursor moves
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
|
||||||
|
forward-word
|
||||||
|
emacs-forward-word
|
||||||
|
vi-forward-word
|
||||||
|
vi-forward-word-end
|
||||||
|
vi-forward-blank-word
|
||||||
|
vi-forward-blank-word-end
|
||||||
|
vi-find-next-char
|
||||||
|
vi-find-next-char-skip
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that should be ignored (globbing supported but must be escaped)
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
|
||||||
|
orig-\*
|
||||||
|
beep
|
||||||
|
run-help
|
||||||
|
set-local-history
|
||||||
|
which-command
|
||||||
|
yank
|
||||||
|
yank-pop
|
||||||
|
zle-\*
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pty name for capturing completions for completion suggestion strategy
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Fetch Suggestion #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Loops through all specified strategies and returns a suggestion
|
||||||
|
# from the first strategy to provide one.
|
||||||
|
#
|
||||||
|
|
||||||
|
_zsh_autosuggest_fetch_suggestion() {
|
||||||
|
typeset -g suggestion
|
||||||
|
local -a strategies
|
||||||
|
local strategy
|
||||||
|
|
||||||
|
# Ensure we are working with an array
|
||||||
|
strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
|
||||||
|
|
||||||
|
for strategy in $strategies; do
|
||||||
|
# Try to get a suggestion from this strategy
|
||||||
|
_zsh_autosuggest_strategy_$strategy "$1"
|
||||||
|
|
||||||
|
# Ensure the suggestion matches the prefix
|
||||||
|
[[ "$suggestion" != "$1"* ]] && unset suggestion
|
||||||
|
|
||||||
|
# Break once we've found a valid suggestion
|
||||||
|
[[ -n "$suggestion" ]] && break
|
||||||
|
done
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Highlighting #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# If there was a highlight, remove it
|
||||||
|
_zsh_autosuggest_highlight_reset() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
|
||||||
|
if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
|
||||||
|
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
|
||||||
|
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# If there's a suggestion, highlight it
|
||||||
|
_zsh_autosuggest_highlight_apply() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
|
||||||
|
if (( $#POSTDISPLAY )); then
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
|
||||||
|
region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
|
||||||
|
else
|
||||||
|
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Start #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Start the autosuggestion widgets
|
||||||
|
_zsh_autosuggest_start() {
|
||||||
|
# By default we re-bind widgets on every precmd to ensure we wrap other
|
||||||
|
# wrappers. Specifically, highlighting breaks if our widgets are wrapped by
|
||||||
|
# zsh-syntax-highlighting widgets. This also allows modifications to the
|
||||||
|
# widget list variables to take effect on the next precmd. However this has
|
||||||
|
# a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND
|
||||||
|
# to disable the automatic re-binding.
|
||||||
|
if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then
|
||||||
|
add-zsh-hook -d precmd _zsh_autosuggest_start
|
||||||
|
fi
|
||||||
|
|
||||||
|
_zsh_autosuggest_bind_widgets
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mark for auto-loading the functions that we use
|
||||||
|
autoload -Uz add-zsh-hook is-at-least
|
||||||
|
|
||||||
|
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
|
||||||
|
# older versions because there is a bug when using async mode where ^C does not
|
||||||
|
# work immediately after fetching a suggestion.
|
||||||
|
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
|
||||||
|
if is-at-least 5.0.8; then
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start the autosuggestion widgets on the next precmd
|
||||||
|
add-zsh-hook precmd _zsh_autosuggest_start
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Completion Suggestion Strategy #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Fetches a suggestion from the completion engine
|
||||||
|
#
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_postcompletion() {
|
||||||
|
# Always insert the first completion into the buffer
|
||||||
|
compstate[insert]=1
|
||||||
|
|
||||||
|
# Don't list completions
|
||||||
|
unset 'compstate[list]'
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_completion_widget() {
|
||||||
|
# Add a post-completion hook to be called after all completions have been
|
||||||
|
# gathered. The hook can modify compstate to affect what is done with the
|
||||||
|
# gathered completions.
|
||||||
|
local -a +h comppostfuncs
|
||||||
|
comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
|
||||||
|
|
||||||
|
# Only capture completions at the end of the buffer
|
||||||
|
CURSOR=$#BUFFER
|
||||||
|
|
||||||
|
# Run the original widget wrapping `.complete-word` so we don't
|
||||||
|
# recursively try to fetch suggestions, since our pty is forked
|
||||||
|
# after autosuggestions is initialized.
|
||||||
|
zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
|
||||||
|
|
||||||
|
if is-at-least 5.0.3; then
|
||||||
|
# Don't do any cr/lf transformations. We need to do this immediately before
|
||||||
|
# output because if we do it in setup, onlcr will be re-enabled when we enter
|
||||||
|
# vared in the async code path. There is a bug in zpty module in older versions
|
||||||
|
# where the tty is not properly attached to the pty slave, resulting in stty
|
||||||
|
# getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream
|
||||||
|
# commit f75904a38
|
||||||
|
stty -onlcr -ocrnl -F /dev/tty
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The completion has been added, print the buffer as the suggestion
|
||||||
|
echo -nE - $'\0'$BUFFER$'\0'
|
||||||
|
}
|
||||||
|
|
||||||
|
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_setup() {
|
||||||
|
# There is a bug in zpty module in older zsh versions by which a
|
||||||
|
# zpty that exits will kill all zpty processes that were forked
|
||||||
|
# before it. Here we set up a zsh exit hook to SIGKILL the zpty
|
||||||
|
# process immediately, before it has a chance to kill any other
|
||||||
|
# zpty processes.
|
||||||
|
if ! is-at-least 5.4; then
|
||||||
|
zshexit() {
|
||||||
|
# The zsh builtin `kill` fails sometimes in older versions
|
||||||
|
# https://unix.stackexchange.com/a/477647/156673
|
||||||
|
kill -KILL $$ 2>&- || command kill -KILL $$
|
||||||
|
|
||||||
|
# Block for long enough for the signal to come through
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to avoid any suggestions that wouldn't match the prefix
|
||||||
|
zstyle ':completion:*' matcher-list ''
|
||||||
|
zstyle ':completion:*' path-completion false
|
||||||
|
zstyle ':completion:*' max-errors 0 not-numeric
|
||||||
|
|
||||||
|
bindkey '^I' autosuggest-capture-completion
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_completion_sync() {
|
||||||
|
_zsh_autosuggest_capture_setup
|
||||||
|
|
||||||
|
zle autosuggest-capture-completion
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_completion_async() {
|
||||||
|
_zsh_autosuggest_capture_setup
|
||||||
|
|
||||||
|
zmodload zsh/parameter 2>/dev/null || return # For `$functions`
|
||||||
|
|
||||||
|
# Make vared completion work as if for a normal command line
|
||||||
|
# https://stackoverflow.com/a/7057118/154703
|
||||||
|
autoload +X _complete
|
||||||
|
functions[_original_complete]=$functions[_complete]
|
||||||
|
function _complete() {
|
||||||
|
unset 'compstate[vared]'
|
||||||
|
_original_complete "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Open zle with buffer set so we can capture completions for it
|
||||||
|
vared 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_strategy_completion() {
|
||||||
|
# Reset options to defaults and enable LOCAL_OPTIONS
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Enable extended glob for completion ignore pattern
|
||||||
|
setopt EXTENDED_GLOB
|
||||||
|
|
||||||
|
typeset -g suggestion
|
||||||
|
local line REPLY
|
||||||
|
|
||||||
|
# Exit if we don't have completions
|
||||||
|
whence compdef >/dev/null || return
|
||||||
|
|
||||||
|
# Exit if we don't have zpty
|
||||||
|
zmodload zsh/zpty 2>/dev/null || return
|
||||||
|
|
||||||
|
# Exit if our search string matches the ignore pattern
|
||||||
|
[[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return
|
||||||
|
|
||||||
|
# Zle will be inactive if we are in async mode
|
||||||
|
if zle; then
|
||||||
|
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
|
||||||
|
else
|
||||||
|
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
|
||||||
|
zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
# The completion result is surrounded by null bytes, so read the
|
||||||
|
# content between the first two null bytes.
|
||||||
|
zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
|
||||||
|
|
||||||
|
# Extract the suggestion from between the null bytes. On older
|
||||||
|
# versions of zsh (older than 5.3), we sometimes get extra bytes after
|
||||||
|
# the second null byte, so trim those off the end.
|
||||||
|
# See http://www.zsh.org/mla/workers/2015/msg03290.html
|
||||||
|
suggestion="${${(@0)line}[2]}"
|
||||||
|
} always {
|
||||||
|
# Destroy the pty
|
||||||
|
zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# History Suggestion Strategy #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Suggests the most recent history item that matches the given
|
||||||
|
# prefix.
|
||||||
|
#
|
||||||
|
|
||||||
|
_zsh_autosuggest_strategy_history() {
|
||||||
|
# Reset options to defaults and enable LOCAL_OPTIONS
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
|
||||||
|
setopt EXTENDED_GLOB
|
||||||
|
|
||||||
|
# Escape backslashes and all of the glob operators so we can use
|
||||||
|
# this string as a pattern to search the $history associative array.
|
||||||
|
# - (#m) globbing flag enables setting references for match data
|
||||||
|
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
|
||||||
|
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
|
||||||
|
|
||||||
|
# Get the history items that match the prefix, excluding those that match
|
||||||
|
# the ignore pattern
|
||||||
|
local pattern="$prefix*"
|
||||||
|
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
|
||||||
|
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Give the first history item matching the pattern as the suggestion
|
||||||
|
# - (r) subscript flag makes the pattern match on values
|
||||||
|
typeset -g suggestion="${history[(r)$pattern]}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Match Previous Command Suggestion Strategy #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Suggests the most recent history item that matches the given
|
||||||
|
# prefix and whose preceding history item also matches the most
|
||||||
|
# recently executed command.
|
||||||
|
#
|
||||||
|
# For example, suppose your history has the following entries:
|
||||||
|
# - pwd
|
||||||
|
# - ls foo
|
||||||
|
# - ls bar
|
||||||
|
# - pwd
|
||||||
|
#
|
||||||
|
# Given the history list above, when you type 'ls', the suggestion
|
||||||
|
# will be 'ls foo' rather than 'ls bar' because your most recently
|
||||||
|
# executed command (pwd) was previously followed by 'ls foo'.
|
||||||
|
#
|
||||||
|
# Note that this strategy won't work as expected with ZSH options that don't
|
||||||
|
# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
|
||||||
|
# `HIST_EXPIRE_DUPS_FIRST`.
|
||||||
|
|
||||||
|
_zsh_autosuggest_strategy_match_prev_cmd() {
|
||||||
|
# Reset options to defaults and enable LOCAL_OPTIONS
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
|
||||||
|
setopt EXTENDED_GLOB
|
||||||
|
|
||||||
|
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
|
||||||
|
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
|
||||||
|
|
||||||
|
# Get the history items that match the prefix, excluding those that match
|
||||||
|
# the ignore pattern
|
||||||
|
local pattern="$prefix*"
|
||||||
|
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
|
||||||
|
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get all history event numbers that correspond to history
|
||||||
|
# entries that match the pattern
|
||||||
|
local history_match_keys
|
||||||
|
history_match_keys=(${(k)history[(R)$~pattern]})
|
||||||
|
|
||||||
|
# By default we use the first history number (most recent history entry)
|
||||||
|
local histkey="${history_match_keys[1]}"
|
||||||
|
|
||||||
|
# Get the previously executed command
|
||||||
|
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
|
||||||
|
|
||||||
|
# Iterate up to the first 200 history event numbers that match $prefix
|
||||||
|
for key in "${(@)history_match_keys[1,200]}"; do
|
||||||
|
# Stop if we ran out of history
|
||||||
|
[[ $key -gt 1 ]] || break
|
||||||
|
|
||||||
|
# See if the history entry preceding the suggestion matches the
|
||||||
|
# previous command, and use it if it does
|
||||||
|
if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
|
||||||
|
histkey="$key"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Give back the matched history entry
|
||||||
|
typeset -g suggestion="$history[$histkey]"
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Utility Functions #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_escape_command() {
|
||||||
|
setopt localoptions EXTENDED_GLOB
|
||||||
|
|
||||||
|
# Escape special chars in the string (requires EXTENDED_GLOB)
|
||||||
|
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Autosuggest Widget Implementations #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Disable suggestions
|
||||||
|
_zsh_autosuggest_disable() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_DISABLED
|
||||||
|
_zsh_autosuggest_clear
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enable suggestions
|
||||||
|
_zsh_autosuggest_enable() {
|
||||||
|
unset _ZSH_AUTOSUGGEST_DISABLED
|
||||||
|
|
||||||
|
if (( $#BUFFER )); then
|
||||||
|
_zsh_autosuggest_fetch
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Toggle suggestions (enable/disable)
|
||||||
|
_zsh_autosuggest_toggle() {
|
||||||
|
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
|
||||||
|
_zsh_autosuggest_enable
|
||||||
|
else
|
||||||
|
_zsh_autosuggest_disable
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clear the suggestion
|
||||||
|
_zsh_autosuggest_clear() {
|
||||||
|
# Remove the suggestion
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
}
|
||||||
|
|
||||||
|
# Modify the buffer and get a new suggestion
|
||||||
|
_zsh_autosuggest_modify() {
|
||||||
|
local -i retval
|
||||||
|
|
||||||
|
# Only available in zsh >= 5.4
|
||||||
|
local -i KEYS_QUEUED_COUNT
|
||||||
|
|
||||||
|
# Save the contents of the buffer/postdisplay
|
||||||
|
local orig_buffer="$BUFFER"
|
||||||
|
local orig_postdisplay="$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Clear suggestion while waiting for next one
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
# Original widget may modify the buffer
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
retval=$?
|
||||||
|
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Don't fetch a new suggestion if there's more input to be read immediately
|
||||||
|
if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then
|
||||||
|
POSTDISPLAY="$orig_postdisplay"
|
||||||
|
return $retval
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Optimize if manually typing in the suggestion or if buffer hasn't changed
|
||||||
|
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
|
||||||
|
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
|
||||||
|
return $retval
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Bail out if suggestions are disabled
|
||||||
|
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get a new suggestion if the buffer is not empty after modification
|
||||||
|
if (( $#BUFFER > 0 )); then
|
||||||
|
if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then
|
||||||
|
_zsh_autosuggest_fetch
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $retval
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch a new suggestion based on what's currently in the buffer
|
||||||
|
_zsh_autosuggest_fetch() {
|
||||||
|
if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then
|
||||||
|
_zsh_autosuggest_async_request "$BUFFER"
|
||||||
|
else
|
||||||
|
local suggestion
|
||||||
|
_zsh_autosuggest_fetch_suggestion "$BUFFER"
|
||||||
|
_zsh_autosuggest_suggest "$suggestion"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Offer a suggestion
|
||||||
|
_zsh_autosuggest_suggest() {
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
local suggestion="$1"
|
||||||
|
|
||||||
|
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
|
||||||
|
POSTDISPLAY="${suggestion#$BUFFER}"
|
||||||
|
else
|
||||||
|
POSTDISPLAY=
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accept the entire suggestion
|
||||||
|
_zsh_autosuggest_accept() {
|
||||||
|
local -i retval max_cursor_pos=$#BUFFER
|
||||||
|
|
||||||
|
# When vicmd keymap is active, the cursor can't move all the way
|
||||||
|
# to the end of the buffer
|
||||||
|
if [[ "$KEYMAP" = "vicmd" ]]; then
|
||||||
|
max_cursor_pos=$((max_cursor_pos - 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we're not in a valid state to accept a suggestion, just run the
|
||||||
|
# original widget and bail out
|
||||||
|
if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only accept if the cursor is at the end of the buffer
|
||||||
|
# Add the suggestion to the buffer
|
||||||
|
BUFFER="$BUFFER$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Remove the suggestion
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
# Run the original widget before manually moving the cursor so that the
|
||||||
|
# cursor movement doesn't make the widget do something unexpected
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
retval=$?
|
||||||
|
|
||||||
|
# Move the cursor to the end of the buffer
|
||||||
|
if [[ "$KEYMAP" = "vicmd" ]]; then
|
||||||
|
CURSOR=$(($#BUFFER - 1))
|
||||||
|
else
|
||||||
|
CURSOR=$#BUFFER
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $retval
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accept the entire suggestion and execute it
|
||||||
|
_zsh_autosuggest_execute() {
|
||||||
|
# Add the suggestion to the buffer
|
||||||
|
BUFFER="$BUFFER$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Remove the suggestion
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
# Call the original `accept-line` to handle syntax highlighting or
|
||||||
|
# other potential custom behavior
|
||||||
|
_zsh_autosuggest_invoke_original_widget "accept-line"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Partially accept the suggestion
|
||||||
|
_zsh_autosuggest_partial_accept() {
|
||||||
|
local -i retval cursor_loc
|
||||||
|
|
||||||
|
# Save the contents of the buffer so we can restore later if needed
|
||||||
|
local original_buffer="$BUFFER"
|
||||||
|
|
||||||
|
# Temporarily accept the suggestion.
|
||||||
|
BUFFER="$BUFFER$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Original widget moves the cursor
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
retval=$?
|
||||||
|
|
||||||
|
# Normalize cursor location across vi/emacs modes
|
||||||
|
cursor_loc=$CURSOR
|
||||||
|
if [[ "$KEYMAP" = "vicmd" ]]; then
|
||||||
|
cursor_loc=$((cursor_loc + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we've moved past the end of the original buffer
|
||||||
|
if (( $cursor_loc > $#original_buffer )); then
|
||||||
|
# Set POSTDISPLAY to text right of the cursor
|
||||||
|
POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
|
||||||
|
|
||||||
|
# Clip the buffer at the cursor
|
||||||
|
BUFFER="${BUFFER[1,$cursor_loc]}"
|
||||||
|
else
|
||||||
|
# Restore the original buffer
|
||||||
|
BUFFER="$original_buffer"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $retval
|
||||||
|
}
|
||||||
|
|
||||||
|
() {
|
||||||
|
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
|
||||||
|
|
||||||
|
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
|
||||||
|
clear
|
||||||
|
fetch
|
||||||
|
suggest
|
||||||
|
accept
|
||||||
|
execute
|
||||||
|
enable
|
||||||
|
disable
|
||||||
|
toggle
|
||||||
|
)
|
||||||
|
|
||||||
|
local action
|
||||||
|
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
|
||||||
|
eval "_zsh_autosuggest_widget_$action() {
|
||||||
|
local -i retval
|
||||||
|
|
||||||
|
_zsh_autosuggest_highlight_reset
|
||||||
|
|
||||||
|
_zsh_autosuggest_$action \$@
|
||||||
|
retval=\$?
|
||||||
|
|
||||||
|
_zsh_autosuggest_highlight_apply
|
||||||
|
|
||||||
|
zle -R
|
||||||
|
|
||||||
|
return \$retval
|
||||||
|
}"
|
||||||
|
done
|
||||||
|
|
||||||
|
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
|
||||||
|
zle -N autosuggest-$action _zsh_autosuggest_widget_$action
|
||||||
|
done
|
||||||
|
}
|
||||||
@@ -0,0 +1,867 @@
|
|||||||
|
# Fish-like fast/unobtrusive autosuggestions for zsh.
|
||||||
|
# https://github.com/zsh-users/zsh-autosuggestions
|
||||||
|
# v0.7.1
|
||||||
|
# Copyright (c) 2013 Thiago de Arruda
|
||||||
|
# Copyright (c) 2016-2021 Eric Freese
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person
|
||||||
|
# obtaining a copy of this software and associated documentation
|
||||||
|
# files (the "Software"), to deal in the Software without
|
||||||
|
# restriction, including without limitation the rights to use,
|
||||||
|
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the
|
||||||
|
# Software is furnished to do so, subject to the following
|
||||||
|
# conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
# OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Global Configuration Variables #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Color to use when highlighting suggestion
|
||||||
|
# Uses format of `region_highlight`
|
||||||
|
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
|
||||||
|
|
||||||
|
# Prefix to use when saving original versions of bound widgets
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
|
||||||
|
|
||||||
|
# Strategies to use to fetch a suggestion
|
||||||
|
# Will try each strategy in order until a suggestion is returned
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_STRATEGY} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_STRATEGY
|
||||||
|
ZSH_AUTOSUGGEST_STRATEGY=(history)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that clear the suggestion
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_CLEAR_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
|
||||||
|
history-search-forward
|
||||||
|
history-search-backward
|
||||||
|
history-beginning-search-forward
|
||||||
|
history-beginning-search-backward
|
||||||
|
history-beginning-search-forward-end
|
||||||
|
history-beginning-search-backward-end
|
||||||
|
history-substring-search-up
|
||||||
|
history-substring-search-down
|
||||||
|
up-line-or-beginning-search
|
||||||
|
down-line-or-beginning-search
|
||||||
|
up-line-or-history
|
||||||
|
down-line-or-history
|
||||||
|
accept-line
|
||||||
|
copy-earlier-word
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that accept the entire suggestion
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_ACCEPT_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
|
||||||
|
forward-char
|
||||||
|
end-of-line
|
||||||
|
vi-forward-char
|
||||||
|
vi-end-of-line
|
||||||
|
vi-add-eol
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that accept the entire suggestion and execute it
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_EXECUTE_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that accept the suggestion as far as the cursor moves
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
|
||||||
|
forward-word
|
||||||
|
emacs-forward-word
|
||||||
|
vi-forward-word
|
||||||
|
vi-forward-word-end
|
||||||
|
vi-forward-blank-word
|
||||||
|
vi-forward-blank-word-end
|
||||||
|
vi-find-next-char
|
||||||
|
vi-find-next-char-skip
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Widgets that should be ignored (globbing supported but must be escaped)
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
|
||||||
|
typeset -ga ZSH_AUTOSUGGEST_IGNORE_WIDGETS
|
||||||
|
ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
|
||||||
|
orig-\*
|
||||||
|
beep
|
||||||
|
run-help
|
||||||
|
set-local-history
|
||||||
|
which-command
|
||||||
|
yank
|
||||||
|
yank-pop
|
||||||
|
zle-\*
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pty name for capturing completions for completion suggestion strategy
|
||||||
|
(( ! ${+ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Utility Functions #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_escape_command() {
|
||||||
|
setopt localoptions EXTENDED_GLOB
|
||||||
|
|
||||||
|
# Escape special chars in the string (requires EXTENDED_GLOB)
|
||||||
|
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Widget Helpers #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_incr_bind_count() {
|
||||||
|
typeset -gi bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]+1))
|
||||||
|
_ZSH_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
|
||||||
|
}
|
||||||
|
|
||||||
|
# Bind a single widget to an autosuggest widget, saving a reference to the original widget
|
||||||
|
_zsh_autosuggest_bind_widget() {
|
||||||
|
typeset -gA _ZSH_AUTOSUGGEST_BIND_COUNTS
|
||||||
|
|
||||||
|
local widget=$1
|
||||||
|
local autosuggest_action=$2
|
||||||
|
local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
|
||||||
|
|
||||||
|
local -i bind_count
|
||||||
|
|
||||||
|
# Save a reference to the original widget
|
||||||
|
case $widgets[$widget] in
|
||||||
|
# Already bound
|
||||||
|
user:_zsh_autosuggest_(bound|orig)_*)
|
||||||
|
bind_count=$((_ZSH_AUTOSUGGEST_BIND_COUNTS[$widget]))
|
||||||
|
;;
|
||||||
|
|
||||||
|
# User-defined widget
|
||||||
|
user:*)
|
||||||
|
_zsh_autosuggest_incr_bind_count $widget
|
||||||
|
zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:}
|
||||||
|
;;
|
||||||
|
|
||||||
|
# Built-in widget
|
||||||
|
builtin)
|
||||||
|
_zsh_autosuggest_incr_bind_count $widget
|
||||||
|
eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
|
||||||
|
zle -N $prefix$bind_count-$widget _zsh_autosuggest_orig_$widget
|
||||||
|
;;
|
||||||
|
|
||||||
|
# Completion widget
|
||||||
|
completion:*)
|
||||||
|
_zsh_autosuggest_incr_bind_count $widget
|
||||||
|
eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Pass the original widget's name explicitly into the autosuggest
|
||||||
|
# function. Use this passed in widget name to call the original
|
||||||
|
# widget instead of relying on the $WIDGET variable being set
|
||||||
|
# correctly. $WIDGET cannot be trusted because other plugins call
|
||||||
|
# zle without the `-w` flag (e.g. `zle self-insert` instead of
|
||||||
|
# `zle self-insert -w`).
|
||||||
|
eval "_zsh_autosuggest_bound_${bind_count}_${(q)widget}() {
|
||||||
|
_zsh_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Create the bound widget
|
||||||
|
zle -N -- $widget _zsh_autosuggest_bound_${bind_count}_$widget
|
||||||
|
}
|
||||||
|
|
||||||
|
# Map all configured widgets to the right autosuggest widgets
|
||||||
|
_zsh_autosuggest_bind_widgets() {
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
local widget
|
||||||
|
local ignore_widgets
|
||||||
|
|
||||||
|
ignore_widgets=(
|
||||||
|
.\*
|
||||||
|
_\*
|
||||||
|
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
|
||||||
|
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
|
||||||
|
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find every widget we might want to bind and bind it appropriately
|
||||||
|
for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
|
||||||
|
if [[ -n ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget clear
|
||||||
|
elif [[ -n ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget accept
|
||||||
|
elif [[ -n ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget execute
|
||||||
|
elif [[ -n ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
|
||||||
|
_zsh_autosuggest_bind_widget $widget partial_accept
|
||||||
|
else
|
||||||
|
# Assume any unspecified widget might modify the buffer
|
||||||
|
_zsh_autosuggest_bind_widget $widget modify
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Given the name of an original widget and args, invoke it, if it exists
|
||||||
|
_zsh_autosuggest_invoke_original_widget() {
|
||||||
|
# Do nothing unless called with at least one arg
|
||||||
|
(( $# )) || return 0
|
||||||
|
|
||||||
|
local original_widget_name="$1"
|
||||||
|
|
||||||
|
shift
|
||||||
|
|
||||||
|
if (( ${+widgets[$original_widget_name]} )); then
|
||||||
|
zle $original_widget_name -- $@
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Highlighting #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# If there was a highlight, remove it
|
||||||
|
_zsh_autosuggest_highlight_reset() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
|
||||||
|
if [[ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
|
||||||
|
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
|
||||||
|
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# If there's a suggestion, highlight it
|
||||||
|
_zsh_autosuggest_highlight_apply() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
|
||||||
|
if (( $#POSTDISPLAY )); then
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
|
||||||
|
region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
|
||||||
|
else
|
||||||
|
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Autosuggest Widget Implementations #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Disable suggestions
|
||||||
|
_zsh_autosuggest_disable() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_DISABLED
|
||||||
|
_zsh_autosuggest_clear
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enable suggestions
|
||||||
|
_zsh_autosuggest_enable() {
|
||||||
|
unset _ZSH_AUTOSUGGEST_DISABLED
|
||||||
|
|
||||||
|
if (( $#BUFFER )); then
|
||||||
|
_zsh_autosuggest_fetch
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Toggle suggestions (enable/disable)
|
||||||
|
_zsh_autosuggest_toggle() {
|
||||||
|
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
|
||||||
|
_zsh_autosuggest_enable
|
||||||
|
else
|
||||||
|
_zsh_autosuggest_disable
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clear the suggestion
|
||||||
|
_zsh_autosuggest_clear() {
|
||||||
|
# Remove the suggestion
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
}
|
||||||
|
|
||||||
|
# Modify the buffer and get a new suggestion
|
||||||
|
_zsh_autosuggest_modify() {
|
||||||
|
local -i retval
|
||||||
|
|
||||||
|
# Only available in zsh >= 5.4
|
||||||
|
local -i KEYS_QUEUED_COUNT
|
||||||
|
|
||||||
|
# Save the contents of the buffer/postdisplay
|
||||||
|
local orig_buffer="$BUFFER"
|
||||||
|
local orig_postdisplay="$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Clear suggestion while waiting for next one
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
# Original widget may modify the buffer
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
retval=$?
|
||||||
|
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Don't fetch a new suggestion if there's more input to be read immediately
|
||||||
|
if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then
|
||||||
|
POSTDISPLAY="$orig_postdisplay"
|
||||||
|
return $retval
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Optimize if manually typing in the suggestion or if buffer hasn't changed
|
||||||
|
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
|
||||||
|
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
|
||||||
|
return $retval
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Bail out if suggestions are disabled
|
||||||
|
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get a new suggestion if the buffer is not empty after modification
|
||||||
|
if (( $#BUFFER > 0 )); then
|
||||||
|
if [[ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]] || (( $#BUFFER <= $ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE )); then
|
||||||
|
_zsh_autosuggest_fetch
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $retval
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch a new suggestion based on what's currently in the buffer
|
||||||
|
_zsh_autosuggest_fetch() {
|
||||||
|
if (( ${+ZSH_AUTOSUGGEST_USE_ASYNC} )); then
|
||||||
|
_zsh_autosuggest_async_request "$BUFFER"
|
||||||
|
else
|
||||||
|
local suggestion
|
||||||
|
_zsh_autosuggest_fetch_suggestion "$BUFFER"
|
||||||
|
_zsh_autosuggest_suggest "$suggestion"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Offer a suggestion
|
||||||
|
_zsh_autosuggest_suggest() {
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
local suggestion="$1"
|
||||||
|
|
||||||
|
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
|
||||||
|
POSTDISPLAY="${suggestion#$BUFFER}"
|
||||||
|
else
|
||||||
|
POSTDISPLAY=
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accept the entire suggestion
|
||||||
|
_zsh_autosuggest_accept() {
|
||||||
|
local -i retval max_cursor_pos=$#BUFFER
|
||||||
|
|
||||||
|
# When vicmd keymap is active, the cursor can't move all the way
|
||||||
|
# to the end of the buffer
|
||||||
|
if [[ "$KEYMAP" = "vicmd" ]]; then
|
||||||
|
max_cursor_pos=$((max_cursor_pos - 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we're not in a valid state to accept a suggestion, just run the
|
||||||
|
# original widget and bail out
|
||||||
|
if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only accept if the cursor is at the end of the buffer
|
||||||
|
# Add the suggestion to the buffer
|
||||||
|
BUFFER="$BUFFER$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Remove the suggestion
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
# Run the original widget before manually moving the cursor so that the
|
||||||
|
# cursor movement doesn't make the widget do something unexpected
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
retval=$?
|
||||||
|
|
||||||
|
# Move the cursor to the end of the buffer
|
||||||
|
if [[ "$KEYMAP" = "vicmd" ]]; then
|
||||||
|
CURSOR=$(($#BUFFER - 1))
|
||||||
|
else
|
||||||
|
CURSOR=$#BUFFER
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $retval
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accept the entire suggestion and execute it
|
||||||
|
_zsh_autosuggest_execute() {
|
||||||
|
# Add the suggestion to the buffer
|
||||||
|
BUFFER="$BUFFER$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Remove the suggestion
|
||||||
|
POSTDISPLAY=
|
||||||
|
|
||||||
|
# Call the original `accept-line` to handle syntax highlighting or
|
||||||
|
# other potential custom behavior
|
||||||
|
_zsh_autosuggest_invoke_original_widget "accept-line"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Partially accept the suggestion
|
||||||
|
_zsh_autosuggest_partial_accept() {
|
||||||
|
local -i retval cursor_loc
|
||||||
|
|
||||||
|
# Save the contents of the buffer so we can restore later if needed
|
||||||
|
local original_buffer="$BUFFER"
|
||||||
|
|
||||||
|
# Temporarily accept the suggestion.
|
||||||
|
BUFFER="$BUFFER$POSTDISPLAY"
|
||||||
|
|
||||||
|
# Original widget moves the cursor
|
||||||
|
_zsh_autosuggest_invoke_original_widget $@
|
||||||
|
retval=$?
|
||||||
|
|
||||||
|
# Normalize cursor location across vi/emacs modes
|
||||||
|
cursor_loc=$CURSOR
|
||||||
|
if [[ "$KEYMAP" = "vicmd" ]]; then
|
||||||
|
cursor_loc=$((cursor_loc + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we've moved past the end of the original buffer
|
||||||
|
if (( $cursor_loc > $#original_buffer )); then
|
||||||
|
# Set POSTDISPLAY to text right of the cursor
|
||||||
|
POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
|
||||||
|
|
||||||
|
# Clip the buffer at the cursor
|
||||||
|
BUFFER="${BUFFER[1,$cursor_loc]}"
|
||||||
|
else
|
||||||
|
# Restore the original buffer
|
||||||
|
BUFFER="$original_buffer"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $retval
|
||||||
|
}
|
||||||
|
|
||||||
|
() {
|
||||||
|
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
|
||||||
|
|
||||||
|
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
|
||||||
|
clear
|
||||||
|
fetch
|
||||||
|
suggest
|
||||||
|
accept
|
||||||
|
execute
|
||||||
|
enable
|
||||||
|
disable
|
||||||
|
toggle
|
||||||
|
)
|
||||||
|
|
||||||
|
local action
|
||||||
|
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
|
||||||
|
eval "_zsh_autosuggest_widget_$action() {
|
||||||
|
local -i retval
|
||||||
|
|
||||||
|
_zsh_autosuggest_highlight_reset
|
||||||
|
|
||||||
|
_zsh_autosuggest_$action \$@
|
||||||
|
retval=\$?
|
||||||
|
|
||||||
|
_zsh_autosuggest_highlight_apply
|
||||||
|
|
||||||
|
zle -R
|
||||||
|
|
||||||
|
return \$retval
|
||||||
|
}"
|
||||||
|
done
|
||||||
|
|
||||||
|
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
|
||||||
|
zle -N autosuggest-$action _zsh_autosuggest_widget_$action
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Completion Suggestion Strategy #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Fetches a suggestion from the completion engine
|
||||||
|
#
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_postcompletion() {
|
||||||
|
# Always insert the first completion into the buffer
|
||||||
|
compstate[insert]=1
|
||||||
|
|
||||||
|
# Don't list completions
|
||||||
|
unset 'compstate[list]'
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_completion_widget() {
|
||||||
|
# Add a post-completion hook to be called after all completions have been
|
||||||
|
# gathered. The hook can modify compstate to affect what is done with the
|
||||||
|
# gathered completions.
|
||||||
|
local -a +h comppostfuncs
|
||||||
|
comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
|
||||||
|
|
||||||
|
# Only capture completions at the end of the buffer
|
||||||
|
CURSOR=$#BUFFER
|
||||||
|
|
||||||
|
# Run the original widget wrapping `.complete-word` so we don't
|
||||||
|
# recursively try to fetch suggestions, since our pty is forked
|
||||||
|
# after autosuggestions is initialized.
|
||||||
|
zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
|
||||||
|
|
||||||
|
if is-at-least 5.0.3; then
|
||||||
|
# Don't do any cr/lf transformations. We need to do this immediately before
|
||||||
|
# output because if we do it in setup, onlcr will be re-enabled when we enter
|
||||||
|
# vared in the async code path. There is a bug in zpty module in older versions
|
||||||
|
# where the tty is not properly attached to the pty slave, resulting in stty
|
||||||
|
# getting stopped with a SIGTTOU. See zsh-workers thread 31660 and upstream
|
||||||
|
# commit f75904a38
|
||||||
|
stty -onlcr -ocrnl -F /dev/tty
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The completion has been added, print the buffer as the suggestion
|
||||||
|
echo -nE - $'\0'$BUFFER$'\0'
|
||||||
|
}
|
||||||
|
|
||||||
|
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_setup() {
|
||||||
|
# There is a bug in zpty module in older zsh versions by which a
|
||||||
|
# zpty that exits will kill all zpty processes that were forked
|
||||||
|
# before it. Here we set up a zsh exit hook to SIGKILL the zpty
|
||||||
|
# process immediately, before it has a chance to kill any other
|
||||||
|
# zpty processes.
|
||||||
|
if ! is-at-least 5.4; then
|
||||||
|
zshexit() {
|
||||||
|
# The zsh builtin `kill` fails sometimes in older versions
|
||||||
|
# https://unix.stackexchange.com/a/477647/156673
|
||||||
|
kill -KILL $$ 2>&- || command kill -KILL $$
|
||||||
|
|
||||||
|
# Block for long enough for the signal to come through
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to avoid any suggestions that wouldn't match the prefix
|
||||||
|
zstyle ':completion:*' matcher-list ''
|
||||||
|
zstyle ':completion:*' path-completion false
|
||||||
|
zstyle ':completion:*' max-errors 0 not-numeric
|
||||||
|
|
||||||
|
bindkey '^I' autosuggest-capture-completion
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_completion_sync() {
|
||||||
|
_zsh_autosuggest_capture_setup
|
||||||
|
|
||||||
|
zle autosuggest-capture-completion
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_capture_completion_async() {
|
||||||
|
_zsh_autosuggest_capture_setup
|
||||||
|
|
||||||
|
zmodload zsh/parameter 2>/dev/null || return # For `$functions`
|
||||||
|
|
||||||
|
# Make vared completion work as if for a normal command line
|
||||||
|
# https://stackoverflow.com/a/7057118/154703
|
||||||
|
autoload +X _complete
|
||||||
|
functions[_original_complete]=$functions[_complete]
|
||||||
|
function _complete() {
|
||||||
|
unset 'compstate[vared]'
|
||||||
|
_original_complete "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Open zle with buffer set so we can capture completions for it
|
||||||
|
vared 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_strategy_completion() {
|
||||||
|
# Reset options to defaults and enable LOCAL_OPTIONS
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Enable extended glob for completion ignore pattern
|
||||||
|
setopt EXTENDED_GLOB
|
||||||
|
|
||||||
|
typeset -g suggestion
|
||||||
|
local line REPLY
|
||||||
|
|
||||||
|
# Exit if we don't have completions
|
||||||
|
whence compdef >/dev/null || return
|
||||||
|
|
||||||
|
# Exit if we don't have zpty
|
||||||
|
zmodload zsh/zpty 2>/dev/null || return
|
||||||
|
|
||||||
|
# Exit if our search string matches the ignore pattern
|
||||||
|
[[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return
|
||||||
|
|
||||||
|
# Zle will be inactive if we are in async mode
|
||||||
|
if zle; then
|
||||||
|
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
|
||||||
|
else
|
||||||
|
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
|
||||||
|
zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
# The completion result is surrounded by null bytes, so read the
|
||||||
|
# content between the first two null bytes.
|
||||||
|
zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
|
||||||
|
|
||||||
|
# Extract the suggestion from between the null bytes. On older
|
||||||
|
# versions of zsh (older than 5.3), we sometimes get extra bytes after
|
||||||
|
# the second null byte, so trim those off the end.
|
||||||
|
# See http://www.zsh.org/mla/workers/2015/msg03290.html
|
||||||
|
suggestion="${${(@0)line}[2]}"
|
||||||
|
} always {
|
||||||
|
# Destroy the pty
|
||||||
|
zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# History Suggestion Strategy #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Suggests the most recent history item that matches the given
|
||||||
|
# prefix.
|
||||||
|
#
|
||||||
|
|
||||||
|
_zsh_autosuggest_strategy_history() {
|
||||||
|
# Reset options to defaults and enable LOCAL_OPTIONS
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
|
||||||
|
setopt EXTENDED_GLOB
|
||||||
|
|
||||||
|
# Escape backslashes and all of the glob operators so we can use
|
||||||
|
# this string as a pattern to search the $history associative array.
|
||||||
|
# - (#m) globbing flag enables setting references for match data
|
||||||
|
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
|
||||||
|
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
|
||||||
|
|
||||||
|
# Get the history items that match the prefix, excluding those that match
|
||||||
|
# the ignore pattern
|
||||||
|
local pattern="$prefix*"
|
||||||
|
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
|
||||||
|
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Give the first history item matching the pattern as the suggestion
|
||||||
|
# - (r) subscript flag makes the pattern match on values
|
||||||
|
typeset -g suggestion="${history[(r)$pattern]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Match Previous Command Suggestion Strategy #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Suggests the most recent history item that matches the given
|
||||||
|
# prefix and whose preceding history item also matches the most
|
||||||
|
# recently executed command.
|
||||||
|
#
|
||||||
|
# For example, suppose your history has the following entries:
|
||||||
|
# - pwd
|
||||||
|
# - ls foo
|
||||||
|
# - ls bar
|
||||||
|
# - pwd
|
||||||
|
#
|
||||||
|
# Given the history list above, when you type 'ls', the suggestion
|
||||||
|
# will be 'ls foo' rather than 'ls bar' because your most recently
|
||||||
|
# executed command (pwd) was previously followed by 'ls foo'.
|
||||||
|
#
|
||||||
|
# Note that this strategy won't work as expected with ZSH options that don't
|
||||||
|
# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
|
||||||
|
# `HIST_EXPIRE_DUPS_FIRST`.
|
||||||
|
|
||||||
|
_zsh_autosuggest_strategy_match_prev_cmd() {
|
||||||
|
# Reset options to defaults and enable LOCAL_OPTIONS
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
# Enable globbing flags so that we can use (#m) and (x~y) glob operator
|
||||||
|
setopt EXTENDED_GLOB
|
||||||
|
|
||||||
|
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
|
||||||
|
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
|
||||||
|
|
||||||
|
# Get the history items that match the prefix, excluding those that match
|
||||||
|
# the ignore pattern
|
||||||
|
local pattern="$prefix*"
|
||||||
|
if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then
|
||||||
|
pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get all history event numbers that correspond to history
|
||||||
|
# entries that match the pattern
|
||||||
|
local history_match_keys
|
||||||
|
history_match_keys=(${(k)history[(R)$~pattern]})
|
||||||
|
|
||||||
|
# By default we use the first history number (most recent history entry)
|
||||||
|
local histkey="${history_match_keys[1]}"
|
||||||
|
|
||||||
|
# Get the previously executed command
|
||||||
|
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
|
||||||
|
|
||||||
|
# Iterate up to the first 200 history event numbers that match $prefix
|
||||||
|
for key in "${(@)history_match_keys[1,200]}"; do
|
||||||
|
# Stop if we ran out of history
|
||||||
|
[[ $key -gt 1 ]] || break
|
||||||
|
|
||||||
|
# See if the history entry preceding the suggestion matches the
|
||||||
|
# previous command, and use it if it does
|
||||||
|
if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
|
||||||
|
histkey="$key"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Give back the matched history entry
|
||||||
|
typeset -g suggestion="$history[$histkey]"
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Fetch Suggestion #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Loops through all specified strategies and returns a suggestion
|
||||||
|
# from the first strategy to provide one.
|
||||||
|
#
|
||||||
|
|
||||||
|
_zsh_autosuggest_fetch_suggestion() {
|
||||||
|
typeset -g suggestion
|
||||||
|
local -a strategies
|
||||||
|
local strategy
|
||||||
|
|
||||||
|
# Ensure we are working with an array
|
||||||
|
strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
|
||||||
|
|
||||||
|
for strategy in $strategies; do
|
||||||
|
# Try to get a suggestion from this strategy
|
||||||
|
_zsh_autosuggest_strategy_$strategy "$1"
|
||||||
|
|
||||||
|
# Ensure the suggestion matches the prefix
|
||||||
|
[[ "$suggestion" != "$1"* ]] && unset suggestion
|
||||||
|
|
||||||
|
# Break once we've found a valid suggestion
|
||||||
|
[[ -n "$suggestion" ]] && break
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Async #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_request() {
|
||||||
|
zmodload zsh/system 2>/dev/null # For `$sysparams`
|
||||||
|
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
|
||||||
|
|
||||||
|
# If we've got a pending request, cancel it
|
||||||
|
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
|
||||||
|
# Close the file descriptor and remove the handler
|
||||||
|
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
|
||||||
|
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
|
||||||
|
|
||||||
|
# We won't know the pid unless the user has zsh/system module installed
|
||||||
|
if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then
|
||||||
|
# Zsh will make a new process group for the child process only if job
|
||||||
|
# control is enabled (MONITOR option)
|
||||||
|
if [[ -o MONITOR ]]; then
|
||||||
|
# Send the signal to the process group to kill any processes that may
|
||||||
|
# have been forked by the suggestion strategy
|
||||||
|
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
||||||
|
else
|
||||||
|
# Kill just the child process since it wasn't placed in a new process
|
||||||
|
# group. If the suggestion strategy forked any child processes they may
|
||||||
|
# be orphaned and left behind.
|
||||||
|
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fork a process to fetch a suggestion and open a pipe to read from it
|
||||||
|
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
|
||||||
|
# Tell parent process our pid
|
||||||
|
echo $sysparams[pid]
|
||||||
|
|
||||||
|
# Fetch and print the suggestion
|
||||||
|
local suggestion
|
||||||
|
_zsh_autosuggest_fetch_suggestion "$1"
|
||||||
|
echo -nE "$suggestion"
|
||||||
|
)
|
||||||
|
|
||||||
|
# There's a weird bug here where ^C stops working unless we force a fork
|
||||||
|
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
|
||||||
|
autoload -Uz is-at-least
|
||||||
|
is-at-least 5.8 || command true
|
||||||
|
|
||||||
|
# Read the pid from the child process
|
||||||
|
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
|
||||||
|
|
||||||
|
# When the fd is readable, call the response handler
|
||||||
|
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
|
||||||
|
}
|
||||||
|
|
||||||
|
# Called when new data is ready to be read from the pipe
|
||||||
|
# First arg will be fd ready for reading
|
||||||
|
# Second arg will be passed in case of error
|
||||||
|
_zsh_autosuggest_async_response() {
|
||||||
|
emulate -L zsh
|
||||||
|
|
||||||
|
local suggestion
|
||||||
|
|
||||||
|
if [[ -z "$2" || "$2" == "hup" ]]; then
|
||||||
|
# Read everything from the fd and give it as a suggestion
|
||||||
|
IFS='' read -rd '' -u $1 suggestion
|
||||||
|
zle autosuggest-suggest -- "$suggestion"
|
||||||
|
|
||||||
|
# Close the fd
|
||||||
|
builtin exec {1}<&-
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Always remove the handler
|
||||||
|
zle -F "$1"
|
||||||
|
_ZSH_AUTOSUGGEST_ASYNC_FD=
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Start #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Start the autosuggestion widgets
|
||||||
|
_zsh_autosuggest_start() {
|
||||||
|
# By default we re-bind widgets on every precmd to ensure we wrap other
|
||||||
|
# wrappers. Specifically, highlighting breaks if our widgets are wrapped by
|
||||||
|
# zsh-syntax-highlighting widgets. This also allows modifications to the
|
||||||
|
# widget list variables to take effect on the next precmd. However this has
|
||||||
|
# a decent performance hit, so users can set ZSH_AUTOSUGGEST_MANUAL_REBIND
|
||||||
|
# to disable the automatic re-binding.
|
||||||
|
if (( ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )); then
|
||||||
|
add-zsh-hook -d precmd _zsh_autosuggest_start
|
||||||
|
fi
|
||||||
|
|
||||||
|
_zsh_autosuggest_bind_widgets
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mark for auto-loading the functions that we use
|
||||||
|
autoload -Uz add-zsh-hook is-at-least
|
||||||
|
|
||||||
|
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
|
||||||
|
# older versions because there is a bug when using async mode where ^C does not
|
||||||
|
# work immediately after fetching a suggestion.
|
||||||
|
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
|
||||||
|
if is-at-least 5.0.8; then
|
||||||
|
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start the autosuggestion widgets on the next precmd
|
||||||
|
add-zsh-hook precmd _zsh_autosuggest_start
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
Copyright (c) 2010-2020 zsh-syntax-highlighting contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||||
|
and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||||
|
conditions and the following disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
|
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
zsh-syntax-highlighting [![Build Status][build-status-image]][build-status]
|
||||||
|
=======================
|
||||||
|
|
||||||
|
**[Fish shell][fish]-like syntax highlighting for [Zsh][zsh].**
|
||||||
|
|
||||||
|
*Requirements: zsh 4.3.11+.*
|
||||||
|
|
||||||
|
[fish]: https://fishshell.com/
|
||||||
|
[zsh]: https://www.zsh.org/
|
||||||
|
|
||||||
|
This package provides syntax highlighting for the shell zsh. It enables
|
||||||
|
highlighting of commands whilst they are typed at a zsh prompt into an
|
||||||
|
interactive terminal. This helps in reviewing commands before running
|
||||||
|
them, particularly in catching syntax errors.
|
||||||
|
|
||||||
|
Some examples:
|
||||||
|
|
||||||
|
Before: [](images/before1.png)
|
||||||
|
<br/>
|
||||||
|
After: [](images/after1.png)
|
||||||
|
|
||||||
|
Before: [](images/before2.png)
|
||||||
|
<br/>
|
||||||
|
After: [](images/after2.png)
|
||||||
|
|
||||||
|
Before: [](images/before3.png)
|
||||||
|
<br/>
|
||||||
|
After: [](images/after3.png)
|
||||||
|
|
||||||
|
Before: [](images/before4-smaller.png)
|
||||||
|
<br/>
|
||||||
|
After: [](images/after4-smaller.png)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
How to install
|
||||||
|
--------------
|
||||||
|
|
||||||
|
See [the Oh My Zsh plugin README](README.md).
|
||||||
|
|
||||||
|
|
||||||
|
FAQ
|
||||||
|
---
|
||||||
|
|
||||||
|
### Why must `zsh-syntax-highlighting.zsh` be sourced at the end of the `.zshrc` file?
|
||||||
|
|
||||||
|
zsh-syntax-highlighting works by hooking into the Zsh Line Editor (ZLE) and
|
||||||
|
computing syntax highlighting for the command-line buffer as it stands at the
|
||||||
|
time z-sy-h's hook is invoked.
|
||||||
|
|
||||||
|
In zsh 5.2 and older,
|
||||||
|
`zsh-syntax-highlighting.zsh` hooks into ZLE by wrapping ZLE widgets. It must
|
||||||
|
be sourced after all custom widgets have been created (i.e., after all `zle -N`
|
||||||
|
calls and after running `compinit`) in order to be able to wrap all of them.
|
||||||
|
Widgets created after z-sy-h is sourced will work, but will not update the
|
||||||
|
syntax highlighting.
|
||||||
|
|
||||||
|
In zsh newer than 5.8 (not including 5.8 itself),
|
||||||
|
zsh-syntax-highlighting uses the `add-zle-hook-widget` facility to install
|
||||||
|
a `zle-line-pre-redraw` hook. Hooks are run in order of registration,
|
||||||
|
therefore, z-sy-h must be sourced (and register its hook) after anything else
|
||||||
|
that adds hooks that modify the command-line buffer.
|
||||||
|
|
||||||
|
### Does syntax highlighting work during incremental history search?
|
||||||
|
|
||||||
|
Highlighting the command line during an incremental history search (by default bound to
|
||||||
|
to <kbd>Ctrl+R</kbd> in zsh's emacs keymap) requires zsh 5.4 or newer.
|
||||||
|
|
||||||
|
Under zsh versions older than 5.4, the zsh-default [underlining][zshzle-Character-Highlighting]
|
||||||
|
of the matched portion of the buffer remains available, but zsh-syntax-highlighting's
|
||||||
|
additional highlighting is unavailable. (Those versions of zsh do not provide
|
||||||
|
enough information to allow computing the highlighting correctly.)
|
||||||
|
|
||||||
|
See issues [#288][i288] and [#415][i415] for details.
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
|
[i288]: https://github.com/zsh-users/zsh-syntax-highlighting/pull/288
|
||||||
|
[i415]: https://github.com/zsh-users/zsh-syntax-highlighting/pull/415
|
||||||
|
|
||||||
|
### How are new releases announced?
|
||||||
|
|
||||||
|
There is currently no "push" announcements channel. However, the following
|
||||||
|
alternatives exist:
|
||||||
|
|
||||||
|
- GitHub's RSS feed of releases: https://github.com/zsh-users/zsh-syntax-highlighting/releases.atom
|
||||||
|
- An anitya entry: https://release-monitoring.org/project/7552/
|
||||||
|
|
||||||
|
|
||||||
|
How to tweak
|
||||||
|
------------
|
||||||
|
|
||||||
|
Syntax highlighting is done by pluggable highlighter scripts. See the
|
||||||
|
[documentation on highlighters](docs/highlighters.md) for details and
|
||||||
|
configuration settings.
|
||||||
|
|
||||||
|
[build-status]: https://github.com/zsh-users/zsh-syntax-highlighting/actions
|
||||||
|
[build-status-image]: https://github.com/zsh-users/zsh-syntax-highlighting/workflows/Tests/badge.svg
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# zsh-syntax-highlighting
|
||||||
|
|
||||||
|
This plugin enables Fish-like syntax highlighting for commands as they are typed at a zsh prompt.
|
||||||
|
|
||||||
|
To use it, add `zsh-syntax-highlighting` to the end of the plugins array in your zshrc file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
plugins=(... zsh-autosuggestions zsh-syntax-highlighting)
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin must be loaded after plugins that create or wrap ZLE widgets, so it should remain the last plugin
|
||||||
|
in the array. Start a new terminal session after updating your zshrc file.
|
||||||
|
|
||||||
|
For available highlighters and configuration options, see the [upstream documentation](MANUAL.md) and the
|
||||||
|
[highlighter documentation](docs/highlighters.md).
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Syntax highlighting is done by pluggable highlighters:
|
||||||
|
|
||||||
|
* `main` - the base highlighter, and the only one [active by default][main].
|
||||||
|
* `brackets` - [matches brackets][brackets] and parenthesis.
|
||||||
|
* `pattern` - matches [user-defined patterns][pattern].
|
||||||
|
* `regexp` - matches [user-defined regular expressions][regexp].
|
||||||
|
* `cursor` - matches [the cursor position][cursor].
|
||||||
|
* `root` - highlights the whole command line [if the current user is root][root].
|
||||||
|
* `line` - applied to [the whole command line][line].
|
||||||
|
|
||||||
|
[main]: highlighters/main.md
|
||||||
|
[brackets]: highlighters/brackets.md
|
||||||
|
[pattern]: highlighters/pattern.md
|
||||||
|
[regexp]: highlighters/regexp.md
|
||||||
|
[cursor]: highlighters/cursor.md
|
||||||
|
[root]: highlighters/root.md
|
||||||
|
[line]: highlighters/line.md
|
||||||
|
|
||||||
|
|
||||||
|
Highlighter-independent settings
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
By default, all command lines are highlighted. However, it is possible to
|
||||||
|
prevent command lines longer than a fixed number of characters from being
|
||||||
|
highlighted by setting the variable `${ZSH_HIGHLIGHT_MAXLENGTH}` to the maximum
|
||||||
|
length (in characters) of command lines to be highlighter. This is useful when
|
||||||
|
editing very long command lines (for example, with the [`fned`][fned] utility
|
||||||
|
function). Example:
|
||||||
|
|
||||||
|
[fned]: https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#index-zed
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZSH_HIGHLIGHT_MAXLENGTH=512
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
How to activate highlighters
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
To activate an highlighter, add it to the `ZSH_HIGHLIGHT_HIGHLIGHTERS` array.
|
||||||
|
By default `ZSH_HIGHLIGHT_HIGHLIGHTERS` is `(main)`. For example to activate
|
||||||
|
`brackets`, `pattern`, and `cursor` highlighters, in `~/.zshrc` do:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZSH_HIGHLIGHT_HIGHLIGHTERS+=(brackets pattern cursor)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
How to tweak highlighters
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Highlighters look up styles from the `ZSH_HIGHLIGHT_STYLES` associative array.
|
||||||
|
Navigate into the [individual highlighters' documentation](highlighters/) to
|
||||||
|
see what styles (keys) each highlighter defines; the syntax for values is the
|
||||||
|
same as the syntax of "types of highlighting" of the zsh builtin
|
||||||
|
`$zle_highlight` array, which is documented in [the `zshzle(1)` manual
|
||||||
|
page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
|
|
||||||
|
Some highlighters support additional configuration parameters; see each
|
||||||
|
highlighter's documentation for details and examples.
|
||||||
|
|
||||||
|
|
||||||
|
How to implement a new highlighter
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
To create your own `acme` highlighter:
|
||||||
|
|
||||||
|
* Create your script at
|
||||||
|
`highlighters/acme/acme-highlighter.zsh`.
|
||||||
|
|
||||||
|
* Implement the `_zsh_highlight_highlighter_acme_predicate` function.
|
||||||
|
This function must return 0 when the highlighter needs to be called and
|
||||||
|
non-zero otherwise, for example:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
_zsh_highlight_highlighter_acme_predicate() {
|
||||||
|
# Call this highlighter in SVN working copies
|
||||||
|
[[ -d .svn ]]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* Implement the `_zsh_highlight_highlighter_acme_paint` function.
|
||||||
|
This function does the actual syntax highlighting, by calling
|
||||||
|
`_zsh_highlight_add_highlight` with the start and end of the region to
|
||||||
|
be highlighted and the `ZSH_HIGHLIGHT_STYLES` key to use. Define the default
|
||||||
|
style for that key in the highlighter script outside of any function with
|
||||||
|
`: ${ZSH_HIGHLIGHT_STYLES[key]:=value}`, being sure to prefix
|
||||||
|
the key with your highlighter name and a colon. For example:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[acme:aurora]:=fg=green}
|
||||||
|
|
||||||
|
_zsh_highlight_highlighter_acme_paint() {
|
||||||
|
# Colorize the whole buffer with the 'aurora' style
|
||||||
|
_zsh_highlight_add_highlight 0 $#BUFFER acme:aurora
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to test which options the user has set, test `zsyh_user_options`
|
||||||
|
with a sensible default if the option is not present in supported zsh
|
||||||
|
versions. For example:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
[[ ${zsyh_user_options[ignoreclosebraces]:-off} == on ]]
|
||||||
|
```
|
||||||
|
|
||||||
|
The option name must be all lowercase with no underscores and not an alias.
|
||||||
|
|
||||||
|
* Name your own functions and global variables `_zsh_highlight_acme_*`.
|
||||||
|
|
||||||
|
- In zsh-syntax-highlighting 0.4.0 and earlier, the entrypoints
|
||||||
|
`_zsh_highlight_highlighter_acme_predicate` and
|
||||||
|
`_zsh_highlight_highlighter_acme_paint`
|
||||||
|
were named
|
||||||
|
`_zsh_highlight_acme_highlighter_predicate` and
|
||||||
|
`_zsh_highlight_highlighter_acme_paint` respectively.
|
||||||
|
|
||||||
|
These names are still supported for backwards compatibility;
|
||||||
|
however, support for them will be removed in a future major or minor release (v0.x.0 or v1.0.0).
|
||||||
|
|
||||||
|
* Activate your highlighter in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZSH_HIGHLIGHT_HIGHLIGHTERS+=(acme)
|
||||||
|
```
|
||||||
|
|
||||||
|
* [Write tests](../tests/README.md).
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters / brackets
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
This is the `brackets` highlighter, that highlights brackets and parentheses, and
|
||||||
|
matches them.
|
||||||
|
|
||||||
|
|
||||||
|
### How to tweak it
|
||||||
|
|
||||||
|
This highlighter defines the following styles:
|
||||||
|
|
||||||
|
* `bracket-error` - unmatched brackets
|
||||||
|
* `bracket-level-N` - brackets with nest level N
|
||||||
|
* `cursor-matchingbracket` - the matching bracket, if cursor is on a bracket
|
||||||
|
|
||||||
|
To override one of those styles, change its entry in `ZSH_HIGHLIGHT_STYLES`,
|
||||||
|
for example in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
# To define styles for nested brackets up to level 4
|
||||||
|
ZSH_HIGHLIGHT_STYLES[bracket-level-1]='fg=blue,bold'
|
||||||
|
ZSH_HIGHLIGHT_STYLES[bracket-level-2]='fg=red,bold'
|
||||||
|
ZSH_HIGHLIGHT_STYLES[bracket-level-3]='fg=yellow,bold'
|
||||||
|
ZSH_HIGHLIGHT_STYLES[bracket-level-4]='fg=magenta,bold'
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax for values is the same as the syntax of "types of highlighting" of
|
||||||
|
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
|
||||||
|
manual page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters / cursor
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
This is the `cursor` highlighter, that highlights the cursor.
|
||||||
|
|
||||||
|
|
||||||
|
### How to tweak it
|
||||||
|
|
||||||
|
This highlighter defines the following styles:
|
||||||
|
|
||||||
|
* `cursor` - the style for the current cursor position
|
||||||
|
|
||||||
|
To override one of those styles, change its entry in `ZSH_HIGHLIGHT_STYLES`,
|
||||||
|
for example in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZSH_HIGHLIGHT_STYLES[cursor]='bg=blue'
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax for values is the same as the syntax of "types of highlighting" of
|
||||||
|
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
|
||||||
|
manual page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters / line
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
This is the `line` highlighter, that highlights the whole line.
|
||||||
|
|
||||||
|
|
||||||
|
### How to tweak it
|
||||||
|
|
||||||
|
This highlighter defines the following styles:
|
||||||
|
|
||||||
|
* `line` - the style for the whole line
|
||||||
|
|
||||||
|
To override one of those styles, change its entry in `ZSH_HIGHLIGHT_STYLES`,
|
||||||
|
for example in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZSH_HIGHLIGHT_STYLES[line]='bold'
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax for values is the same as the syntax of "types of highlighting" of
|
||||||
|
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
|
||||||
|
manual page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters / main
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
This is the `main` highlighter, that highlights:
|
||||||
|
|
||||||
|
* Commands
|
||||||
|
* Options
|
||||||
|
* Arguments
|
||||||
|
* Paths
|
||||||
|
* Strings
|
||||||
|
|
||||||
|
This highlighter is active by default.
|
||||||
|
|
||||||
|
|
||||||
|
### How to tweak it
|
||||||
|
|
||||||
|
This highlighter defines the following styles:
|
||||||
|
|
||||||
|
* `unknown-token` - unknown tokens / errors
|
||||||
|
* `reserved-word` - shell reserved words (`if`, `for`)
|
||||||
|
* `alias` - aliases
|
||||||
|
* `suffix-alias` - suffix aliases (requires zsh 5.1.1 or newer)
|
||||||
|
* `global-alias` - global aliases
|
||||||
|
* `builtin` - shell builtin commands (`shift`, `pwd`, `zstyle`)
|
||||||
|
* `function` - function names
|
||||||
|
* `command` - command names
|
||||||
|
* `precommand` - precommand modifiers (e.g., `noglob`, `builtin`)
|
||||||
|
* `commandseparator` - command separation tokens (`;`, `&&`)
|
||||||
|
* `hashed-command` - hashed commands
|
||||||
|
* `autodirectory` - a directory name in command position when the `AUTO_CD` option is set
|
||||||
|
* `path` - existing filenames
|
||||||
|
* `path_pathseparator` - path separators in filenames (`/`); if unset, `path` is used (default)
|
||||||
|
* `path_prefix` - prefixes of existing filenames
|
||||||
|
* `path_prefix_pathseparator` - path separators in prefixes of existing filenames (`/`); if unset, `path_prefix` is used (default)
|
||||||
|
* `globbing` - globbing expressions (`*.txt`)
|
||||||
|
* `history-expansion` - history expansion expressions (`!foo` and `^foo^bar`)
|
||||||
|
* `command-substitution` - command substitutions (`$(echo foo)`)
|
||||||
|
* `command-substitution-unquoted` - an unquoted command substitution (`$(echo foo)`)
|
||||||
|
* `command-substitution-quoted` - a quoted command substitution (`"$(echo foo)"`)
|
||||||
|
* `command-substitution-delimiter` - command substitution delimiters (`$(` and `)`)
|
||||||
|
* `command-substitution-delimiter-unquoted` - an unquoted command substitution delimiters (`$(` and `)`)
|
||||||
|
* `command-substitution-delimiter-quoted` - a quoted command substitution delimiters (`"$(` and `)"`)
|
||||||
|
* `process-substitution` - process substitutions (`<(echo foo)`)
|
||||||
|
* `process-substitution-delimiter` - process substitution delimiters (`<(` and `)`)
|
||||||
|
* `arithmetic-expansion` - arithmetic expansion `$(( 42 ))`)
|
||||||
|
* `single-hyphen-option` - single-hyphen options (`-o`)
|
||||||
|
* `double-hyphen-option` - double-hyphen options (`--option`)
|
||||||
|
* `back-quoted-argument` - backtick command substitution (`` `foo` ``)
|
||||||
|
* `back-quoted-argument-unclosed` - unclosed backtick command substitution (`` `foo ``)
|
||||||
|
* `back-quoted-argument-delimiter` - backtick command substitution delimiters (`` ` ``)
|
||||||
|
* `single-quoted-argument` - single-quoted arguments (`` 'foo' ``)
|
||||||
|
* `single-quoted-argument-unclosed` - unclosed single-quoted arguments (`` 'foo ``)
|
||||||
|
* `double-quoted-argument` - double-quoted arguments (`` "foo" ``)
|
||||||
|
* `double-quoted-argument-unclosed` - unclosed double-quoted arguments (`` "foo ``)
|
||||||
|
* `dollar-quoted-argument` - dollar-quoted arguments (`` $'foo' ``)
|
||||||
|
* `dollar-quoted-argument-unclosed` - unclosed dollar-quoted arguments (`` $'foo ``)
|
||||||
|
* `rc-quote` - two single quotes inside single quotes when the `RC_QUOTES` option is set (`` 'foo''bar' ``)
|
||||||
|
* `dollar-double-quoted-argument` - parameter expansion inside double quotes (`$foo` inside `""`)
|
||||||
|
* `back-double-quoted-argument` - backslash escape sequences inside double-quoted arguments (`\"` in `"foo\"bar"`)
|
||||||
|
* `back-dollar-quoted-argument` - backslash escape sequences inside dollar-quoted arguments (`\x` in `$'\x48'`)
|
||||||
|
* `assign` - parameter assignments (`x=foo` and `x=( )`)
|
||||||
|
* `redirection` - redirection operators (`<`, `>`, etc)
|
||||||
|
* `comment` - comments, when `setopt INTERACTIVE_COMMENTS` is in effect (`echo # foo`)
|
||||||
|
* `comment` - elided parameters in command position (`$x ls` when `$x` is unset or empty)
|
||||||
|
* `named-fd` - named file descriptor (the `fd` in `echo foo {fd}>&2`)
|
||||||
|
* `numeric-fd` - numeric file descriptor (the `2` in `echo foo {fd}>&2`)
|
||||||
|
* `arg0` - a command word other than one of those enumerated above (other than a command, precommand, alias, function, or shell builtin command).
|
||||||
|
* `default` - everything else
|
||||||
|
|
||||||
|
To override one of those styles, change its entry in `ZSH_HIGHLIGHT_STYLES`,
|
||||||
|
for example in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
# Declare the variable
|
||||||
|
typeset -A ZSH_HIGHLIGHT_STYLES
|
||||||
|
|
||||||
|
# To differentiate aliases from other command types
|
||||||
|
ZSH_HIGHLIGHT_STYLES[alias]='fg=magenta,bold'
|
||||||
|
|
||||||
|
# To have paths colored instead of underlined
|
||||||
|
ZSH_HIGHLIGHT_STYLES[path]='fg=cyan'
|
||||||
|
|
||||||
|
# To disable highlighting of globbing expressions
|
||||||
|
ZSH_HIGHLIGHT_STYLES[globbing]='none'
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax for values is the same as the syntax of "types of highlighting" of
|
||||||
|
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
|
||||||
|
manual page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
To avoid partial path lookups on a path, add the path to the `ZSH_HIGHLIGHT_DIRS_BLACKLIST` array.
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZSH_HIGHLIGHT_DIRS_BLACKLIST+=(/mnt/slow_share)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Useless trivia
|
||||||
|
|
||||||
|
#### Forward compatibility.
|
||||||
|
|
||||||
|
zsh-syntax-highlighting attempts to be forward-compatible with zsh.
|
||||||
|
Specifically, we attempt to facilitate highlighting _command word_ types that
|
||||||
|
had not yet been invented when this version of zsh-syntax-highlighting was
|
||||||
|
released.
|
||||||
|
|
||||||
|
A _command word_ is something like a function name, external command name, et
|
||||||
|
cetera. (See
|
||||||
|
[Simple Commands & Pipelines in `zshmisc(1)`][zshmisc-Simple-Commands-And-Pipelines]
|
||||||
|
for a formal definition.)
|
||||||
|
|
||||||
|
If a new _kind_ of command word is ever added to zsh — something conceptually
|
||||||
|
different than "function" and "alias" and "external command" — then command words
|
||||||
|
of that (new) kind will be highlighted by the style `arg0_$kind`,
|
||||||
|
where `$kind` is the output of `type -w` on the new kind of command word. If that
|
||||||
|
style is not defined, then the style `arg0` will be used instead.
|
||||||
|
|
||||||
|
[zshmisc-Simple-Commands-And-Pipelines]: https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#Simple-Commands-_0026-Pipelines
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters / pattern
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
This is the `pattern` highlighter, that highlights user-defined patterns.
|
||||||
|
|
||||||
|
|
||||||
|
### How to tweak it
|
||||||
|
|
||||||
|
To use this highlighter, associate patterns with styles in the
|
||||||
|
`ZSH_HIGHLIGHT_PATTERNS` associative array, for example in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
# Declare the variable
|
||||||
|
typeset -A ZSH_HIGHLIGHT_PATTERNS
|
||||||
|
|
||||||
|
# To have commands starting with `rm -rf` in red:
|
||||||
|
ZSH_HIGHLIGHT_PATTERNS+=('rm -rf *' 'fg=white,bold,bg=red')
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax for values is the same as the syntax of "types of highlighting" of
|
||||||
|
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
|
||||||
|
manual page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters / regexp
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
This is the `regexp` highlighter, that highlights user-defined regular
|
||||||
|
expressions. It's similar to the `pattern` highlighter, but allows more complex
|
||||||
|
patterns.
|
||||||
|
|
||||||
|
### How to tweak it
|
||||||
|
|
||||||
|
To use this highlighter, associate regular expressions with styles in the
|
||||||
|
`ZSH_HIGHLIGHT_REGEXP` associative array, for example in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
typeset -A ZSH_HIGHLIGHT_REGEXP
|
||||||
|
ZSH_HIGHLIGHT_REGEXP+=('^rm .*' fg=red,bold)
|
||||||
|
```
|
||||||
|
|
||||||
|
This will highlight lines that start with a call to the `rm` command.
|
||||||
|
|
||||||
|
The regular expressions flavour used is [PCRE][pcresyntax] when the
|
||||||
|
`RE_MATCH_PCRE` option is set and POSIX Extended Regular Expressions (ERE),
|
||||||
|
as implemented by the platform's C library, otherwise. For details on the
|
||||||
|
latter, see [the `zsh/regex` module's documentation][MAN_ZSH_REGEX] and the
|
||||||
|
`regcomp(3)` and `re_format(7)` manual pages on your system.
|
||||||
|
|
||||||
|
For instance, to highlight `sudo` only as a complete word, i.e., `sudo cmd`,
|
||||||
|
but not `sudoedit`, one might use:
|
||||||
|
|
||||||
|
* When the `RE_MATCH_PCRE` is set:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
typeset -A ZSH_HIGHLIGHT_REGEXP
|
||||||
|
ZSH_HIGHLIGHT_REGEXP+=('\bsudo\b' fg=123,bold)
|
||||||
|
```
|
||||||
|
|
||||||
|
* When the `RE_MATCH_PCRE` is unset, on platforms with GNU `libc` (e.g., many GNU/Linux distributions):
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
typeset -A ZSH_HIGHLIGHT_REGEXP
|
||||||
|
ZSH_HIGHLIGHT_REGEXP+=('\<sudo\>' fg=123,bold)
|
||||||
|
```
|
||||||
|
|
||||||
|
* When the `RE_MATCH_PCRE` is unset, on BSD-based platforms (e.g., macOS):
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
typeset -A ZSH_HIGHLIGHT_REGEXP
|
||||||
|
ZSH_HIGHLIGHT_REGEXP+=('[[:<:]]sudo[[:>:]]' fg=123,bold)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note, however, that PCRE and POSIX ERE have a large common subset:
|
||||||
|
for instance, the regular expressions `[abc]`, `a*`, and `(a|b)` have the same
|
||||||
|
meaning in both flavours.
|
||||||
|
|
||||||
|
The syntax for values is the same as the syntax of "types of highlighting" of
|
||||||
|
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
|
||||||
|
manual page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
See also: [regular expressions tutorial][perlretut], zsh regexp operator `=~`
|
||||||
|
in [the `zshmisc(1)` manual page][zshmisc-Conditional-Expressions]
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
|
[perlretut]: https://perldoc.perl.org/perlretut
|
||||||
|
[zshmisc-Conditional-Expressions]: https://zsh.sourceforge.io/Doc/Release/Conditional-Expressions.html#Conditional-Expressions
|
||||||
|
[MAN_ZSH_REGEX]: https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-zsh_002fregex-Module
|
||||||
|
[pcresyntax]: https://www.pcre.org/original/doc/html/pcresyntax.html
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters / root
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
This is the `root` highlighter, that highlights the whole line if the current
|
||||||
|
user is root.
|
||||||
|
|
||||||
|
|
||||||
|
### How to tweak it
|
||||||
|
|
||||||
|
This highlighter defines the following styles:
|
||||||
|
|
||||||
|
* `root` - the style for the whole line if the current user is root.
|
||||||
|
|
||||||
|
To override one of those styles, change its entry in `ZSH_HIGHLIGHT_STYLES`,
|
||||||
|
for example in `~/.zshrc`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ZSH_HIGHLIGHT_STYLES[root]='bg=red'
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax for values is the same as the syntax of "types of highlighting" of
|
||||||
|
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
|
||||||
|
manual page][zshzle-Character-Highlighting].
|
||||||
|
|
||||||
|
[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
zsh-syntax-highlighting / highlighters
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Navigate into the individual highlighters' documentation to see
|
||||||
|
what styles (`$ZSH_HIGHLIGHT_STYLES` keys) each highlighter defines.
|
||||||
|
|
||||||
|
Refer to the [documentation on highlighters](../docs/highlighters.md) for further
|
||||||
|
information.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../docs/highlighters/brackets.md
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2010-2017 zsh-syntax-highlighting contributors
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||||
|
# and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||||
|
# conditions and the following disclaimer in the documentation and/or other materials provided
|
||||||
|
# with the distribution.
|
||||||
|
# * Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software without specific prior
|
||||||
|
# written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||||
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
|
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
|
||||||
|
# vim: ft=zsh sw=2 ts=2 et
|
||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
# Define default styles.
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[bracket-error]:=fg=red,bold}
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[bracket-level-1]:=fg=blue,bold}
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[bracket-level-2]:=fg=green,bold}
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[bracket-level-3]:=fg=magenta,bold}
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[bracket-level-4]:=fg=yellow,bold}
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[bracket-level-5]:=fg=cyan,bold}
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[cursor-matchingbracket]:=standout}
|
||||||
|
|
||||||
|
# Whether the brackets highlighter should be called or not.
|
||||||
|
_zsh_highlight_highlighter_brackets_predicate()
|
||||||
|
{
|
||||||
|
[[ $WIDGET == zle-line-finish ]] || _zsh_highlight_cursor_moved || _zsh_highlight_buffer_modified
|
||||||
|
}
|
||||||
|
|
||||||
|
# Brackets highlighting function.
|
||||||
|
_zsh_highlight_highlighter_brackets_paint()
|
||||||
|
{
|
||||||
|
local char style
|
||||||
|
local -i bracket_color_size=${#ZSH_HIGHLIGHT_STYLES[(I)bracket-level-*]} buflen=${#BUFFER} level=0 matchingpos pos
|
||||||
|
local -A levelpos lastoflevel matching
|
||||||
|
|
||||||
|
# Find all brackets and remember which one is matching
|
||||||
|
pos=0
|
||||||
|
for char in ${(s..)BUFFER} ; do
|
||||||
|
(( ++pos ))
|
||||||
|
case $char in
|
||||||
|
["([{"])
|
||||||
|
levelpos[$pos]=$((++level))
|
||||||
|
lastoflevel[$level]=$pos
|
||||||
|
;;
|
||||||
|
[")]}"])
|
||||||
|
if (( level > 0 )); then
|
||||||
|
matchingpos=$lastoflevel[$level]
|
||||||
|
levelpos[$pos]=$((level--))
|
||||||
|
if _zsh_highlight_brackets_match $matchingpos $pos; then
|
||||||
|
matching[$matchingpos]=$pos
|
||||||
|
matching[$pos]=$matchingpos
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
levelpos[$pos]=-1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Now highlight all found brackets
|
||||||
|
for pos in ${(k)levelpos}; do
|
||||||
|
if (( $+matching[$pos] )); then
|
||||||
|
if (( bracket_color_size )); then
|
||||||
|
_zsh_highlight_add_highlight $((pos - 1)) $pos bracket-level-$(( (levelpos[$pos] - 1) % bracket_color_size + 1 ))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
_zsh_highlight_add_highlight $((pos - 1)) $pos bracket-error
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# If cursor is on a bracket, then highlight corresponding bracket, if any.
|
||||||
|
if [[ $WIDGET != zle-line-finish ]]; then
|
||||||
|
pos=$((CURSOR + 1))
|
||||||
|
if (( $+levelpos[$pos] )) && (( $+matching[$pos] )); then
|
||||||
|
local -i otherpos=$matching[$pos]
|
||||||
|
_zsh_highlight_add_highlight $((otherpos - 1)) $otherpos cursor-matchingbracket
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper function to differentiate type
|
||||||
|
_zsh_highlight_brackets_match()
|
||||||
|
{
|
||||||
|
case $BUFFER[$1] in
|
||||||
|
\() [[ $BUFFER[$2] == \) ]];;
|
||||||
|
\[) [[ $BUFFER[$2] == \] ]];;
|
||||||
|
\{) [[ $BUFFER[$2] == \} ]];;
|
||||||
|
*) false;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../docs/highlighters/cursor.md
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2010-2011 zsh-syntax-highlighting contributors
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||||
|
# and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||||
|
# conditions and the following disclaimer in the documentation and/or other materials provided
|
||||||
|
# with the distribution.
|
||||||
|
# * Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software without specific prior
|
||||||
|
# written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||||
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
|
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
|
||||||
|
# vim: ft=zsh sw=2 ts=2 et
|
||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
# Define default styles.
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[cursor]:=standout}
|
||||||
|
|
||||||
|
# Whether the cursor highlighter should be called or not.
|
||||||
|
_zsh_highlight_highlighter_cursor_predicate()
|
||||||
|
{
|
||||||
|
# remove cursor highlighting when the line is finished
|
||||||
|
[[ $WIDGET == zle-line-finish ]] || _zsh_highlight_cursor_moved
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cursor highlighting function.
|
||||||
|
_zsh_highlight_highlighter_cursor_paint()
|
||||||
|
{
|
||||||
|
[[ $WIDGET == zle-line-finish ]] && return
|
||||||
|
|
||||||
|
_zsh_highlight_add_highlight $CURSOR $(( $CURSOR + 1 )) cursor
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../docs/highlighters/line.md
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2010-2011 zsh-syntax-highlighting contributors
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||||
|
# and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||||
|
# conditions and the following disclaimer in the documentation and/or other materials provided
|
||||||
|
# with the distribution.
|
||||||
|
# * Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software without specific prior
|
||||||
|
# written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||||
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
|
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
|
||||||
|
# vim: ft=zsh sw=2 ts=2 et
|
||||||
|
# -------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
# Define default styles.
|
||||||
|
: ${ZSH_HIGHLIGHT_STYLES[line]:=}
|
||||||
|
|
||||||
|
# Whether the root highlighter should be called or not.
|
||||||
|
_zsh_highlight_highlighter_line_predicate()
|
||||||
|
{
|
||||||
|
_zsh_highlight_buffer_modified
|
||||||
|
}
|
||||||
|
|
||||||
|
# root highlighting function.
|
||||||
|
_zsh_highlight_highlighter_line_paint()
|
||||||
|
{
|
||||||
|
_zsh_highlight_add_highlight 0 $#BUFFER line
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../docs/highlighters/main.md
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
../../docs/highlighters/pattern.md
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user