mirror of
https://github.com/ohmyzsh/ohmyzsh.git
synced 2026-10-20 12:32:10 +08:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c184381d0 |
@@ -75,7 +75,7 @@ dependencies:
|
||||
plugins/zsh-syntax-highlighting:
|
||||
repo: zsh-users/zsh-syntax-highlighting
|
||||
branch: master
|
||||
version: e6683f20e5c38d3e5447f45845d04ddda75d0f23
|
||||
version: 2fc57d63067c18b1100ecdbf684fa5baf49459d1
|
||||
precopy: |
|
||||
set -e
|
||||
version=$(<.version)
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
contents: write # this is needed to push commits and branches
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
- test
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
if: github.repository == 'ohmyzsh/ohmyzsh'
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
if: github.repository == 'ohmyzsh/ohmyzsh'
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
- name: Authenticate as @ohmyzsh
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -53,13 +53,13 @@ jobs:
|
||||
publish_results: true
|
||||
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -45,7 +45,6 @@ Twitter), and join us on [Discord](https://discord.gg/ohmyzsh).
|
||||
- [Using Plugins](#using-plugins)
|
||||
- [Themes](#themes)
|
||||
- [Selecting A Theme](#selecting-a-theme)
|
||||
- [Shellsavers](#shellsavers)
|
||||
- [FAQ](#faq)
|
||||
- [Advanced Topics](#advanced-topics)
|
||||
- [Advanced Installation](#advanced-installation)
|
||||
@@ -242,33 +241,6 @@ If you only know which themes you don't like, you can add them similarly to an i
|
||||
ZSH_THEME_RANDOM_IGNORED=(pygmalion tjkirch_mod)
|
||||
```
|
||||
|
||||
### Shellsavers
|
||||
|
||||
Give your terminal a little downtime with `omz shellsaver`—our playful name for
|
||||
terminal screensavers. The aquarium is the default; choose another scene to change the mood:
|
||||
|
||||
```zsh
|
||||
omz shellsaver # A quiet aquarium full of sea shells
|
||||
omz shellsaver logo # The updater's rainbow logo, bouncing around
|
||||
omz shellsaver hermit # A slightly lost hermit crab
|
||||
omz shellsaver party # A rainbow stage and a dancing crowd
|
||||
```
|
||||
|
||||
Press any key or Ctrl-C to return to your shell. Screensavers run only when invoked
|
||||
and restore the terminal when they exit. No plugin or configuration change is needed.
|
||||
Use `omz help` to discover the command, and Tab to complete scene names and options.
|
||||
|
||||
```zsh
|
||||
omz shellsaver aquarium --seconds 30 # Stop automatically after 30 seconds
|
||||
omz shellsaver logo --mono # Use the terminal's foreground color
|
||||
omz shellsaver --list # List scenes (aquarium is the default)
|
||||
omz shellsaver --help # Show all scenes and options
|
||||
```
|
||||
|
||||
Requires Zsh 5.8 or newer, `stty`, and an xterm-compatible terminal with alternate-screen
|
||||
support. No additional animation package is required. `NO_COLOR` is respected.
|
||||
A window of at least 49 columns by 18 rows is recommended.
|
||||
|
||||
### FAQ
|
||||
|
||||
If you have some more questions or issues, you might find a solution in our
|
||||
|
||||
-23
@@ -28,25 +28,12 @@ function _omz {
|
||||
'plugin:Manage plugins'
|
||||
'pr:Manage Oh My Zsh Pull Requests'
|
||||
'reload:Reload the current zsh session'
|
||||
'shellsaver:Launch a whimsical terminal screensaver'
|
||||
'shop:Open the Oh My Zsh shop'
|
||||
'theme:Manage themes'
|
||||
'update:Update Oh My Zsh'
|
||||
'version:Show the version'
|
||||
)
|
||||
|
||||
if [[ "$words[2]" == (screensaver|shellsaver) ]] && (( CURRENT > 2 )); then
|
||||
_arguments \
|
||||
'1:command:' \
|
||||
'2::scene:(aquarium logo hermit party)' \
|
||||
'--list[List available scenes]' \
|
||||
'--mono[Use the default foreground color]' \
|
||||
'--seconds[Exit after a number of seconds]:seconds:' \
|
||||
'--snapshot[Print a plain-text still]::frame:' \
|
||||
'--help[Show Shellsaver help]'
|
||||
return
|
||||
fi
|
||||
|
||||
if (( CURRENT == 2 )); then
|
||||
_describe 'command' cmds
|
||||
elif (( CURRENT == 3 )); then
|
||||
@@ -187,7 +174,6 @@ Available commands:
|
||||
plugin <command> Manage plugins
|
||||
pr <command> Manage Oh My Zsh Pull Requests
|
||||
reload Reload the current zsh session
|
||||
shellsaver [scene] Launch a Shellsaver (aquarium by default)
|
||||
shop Open the Oh My Zsh shop
|
||||
theme <command> Manage themes
|
||||
update Update Oh My Zsh
|
||||
@@ -196,15 +182,6 @@ Available commands:
|
||||
EOF
|
||||
}
|
||||
|
||||
function _omz::shellsaver {
|
||||
command zsh -f "$ZSH/tools/shellsaver.zsh" "$@"
|
||||
}
|
||||
|
||||
# Hidden alias; only shellsaver is advertised in help and command completion.
|
||||
function _omz::screensaver {
|
||||
_omz::shellsaver "$@"
|
||||
}
|
||||
|
||||
function _omz::changelog {
|
||||
local version=${1:-HEAD} format=${3:-"--text"}
|
||||
|
||||
|
||||
@@ -110,6 +110,23 @@ bindkey -M emacs '^[[1;5D' backward-word
|
||||
bindkey -M viins '^[[1;5D' backward-word
|
||||
bindkey -M vicmd '^[[1;5D' backward-word
|
||||
|
||||
# [Keypad] - application mode (enabled above) makes the keypad send escape
|
||||
# sequences instead of characters, so map them back to the plain keys
|
||||
() {
|
||||
local seq key
|
||||
local -A keypad=(
|
||||
'^[Op' '0' '^[Oq' '1' '^[Or' '2' '^[Os' '3' '^[Ot' '4'
|
||||
'^[Ou' '5' '^[Ov' '6' '^[Ow' '7' '^[Ox' '8' '^[Oy' '9'
|
||||
'^[On' '.' '^[Ol' ',' '^[Ok' '+' '^[Om' '-' '^[Oj' '*'
|
||||
'^[Oo' '/' '^[OX' '=' '^[OM' '^M'
|
||||
)
|
||||
for seq key in "${(@kv)keypad}"; do
|
||||
bindkey -M emacs -s "$seq" "$key"
|
||||
bindkey -M viins -s "$seq" "$key"
|
||||
bindkey -M vicmd -s "$seq" "$key"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
bindkey '\ew' kill-region # [Esc-w] - Kill from the cursor to the mark
|
||||
bindkey -s '\el' '^q ls\n' # [Esc-l] - run command: ls
|
||||
|
||||
+5
-7
@@ -5,6 +5,7 @@
|
||||
# See: http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#ss3.1
|
||||
# Fully supports screen, iterm, and probably most modern xterm and rxvt
|
||||
# (In screen, only short_tab_title is used)
|
||||
# Limited support for Apple Terminal (Terminal can't set window and tab separately)
|
||||
function title {
|
||||
setopt localoptions nopromptsubst
|
||||
|
||||
@@ -16,7 +17,7 @@ function title {
|
||||
: ${2=$1}
|
||||
|
||||
case "$TERM" in
|
||||
cygwin|xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty*|st*|foot*|contour*|wezterm*|nsterm*)
|
||||
cygwin|xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty*|st*|foot*|contour*|wezterm*)
|
||||
print -Pn "\e]2;${2:q}\a" # set window name
|
||||
print -Pn "\e]1;${1:q}\a" # set tab name
|
||||
;;
|
||||
@@ -25,12 +26,10 @@ function title {
|
||||
print -Pn "\ek${1:q}\e\\" # set screen hardstatus/tmux window name if `allow-rename` is on
|
||||
;;
|
||||
*)
|
||||
case "$TERM_PROGRAM" in
|
||||
"iTerm.app"|"Apple_Terminal")
|
||||
if [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then
|
||||
print -Pn "\e]2;${2:q}\a" # set window name
|
||||
print -Pn "\e]1;${1:q}\a" # set tab name
|
||||
;;
|
||||
*)
|
||||
else
|
||||
# Try to use terminfo to set the title if the feature is available
|
||||
if (( ${+terminfo[fsl]} && ${+terminfo[tsl]} )); then
|
||||
# Emit the capabilities with echoti so terminfo does its own parameter
|
||||
@@ -40,8 +39,7 @@ function title {
|
||||
print -Pn "$1"
|
||||
echoti fsl
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ function copyfile {
|
||||
return 1
|
||||
fi
|
||||
|
||||
clipcopy $1 || return 1
|
||||
clipcopy $1
|
||||
echo ${(%):-"%B$1%b copied to clipboard."}
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
emulate -LR zsh
|
||||
|
||||
source "${1:-${0:A:h:h}/copyfile.plugin.zsh}"
|
||||
|
||||
test_dir=$(mktemp -d) || exit 1
|
||||
trap 'command rm -rf -- "$test_dir"' EXIT
|
||||
|
||||
typeset -i clipboard_status=0 failures=0 tests=0
|
||||
typeset output expected_output
|
||||
|
||||
clipcopy() {
|
||||
print -r -- "$#" "$1" >| "$test_dir/call"
|
||||
if (( clipboard_status )); then
|
||||
print -u2 -r -- "clipboard backend failed"
|
||||
return $clipboard_status
|
||||
fi
|
||||
command cat -- "$1" >| "$test_dir/clipboard"
|
||||
}
|
||||
|
||||
check_copyfile() {
|
||||
local description="$1" expected_status="$2" expected_stdout="$3" expected_stderr="$4"
|
||||
shift 4
|
||||
|
||||
output=$(copyfile "$@" 2> "$test_dir/stderr")
|
||||
local actual_status=$?
|
||||
(( tests++ ))
|
||||
|
||||
if [[ $actual_status == $expected_status && $output == "$expected_stdout" && $(<"$test_dir/stderr") == "$expected_stderr" ]]; then
|
||||
print -r -- "PASS: $description"
|
||||
else
|
||||
print -u2 -r -- "FAIL: $description"
|
||||
print -u2 -r -- " status: $actual_status (expected $expected_status)"
|
||||
print -u2 -r -- " stdout: ${(qqq)output} (expected ${(qqq)expected_stdout})"
|
||||
print -u2 -r -- " stderr: $(<"$test_dir/stderr") (expected $expected_stderr)"
|
||||
(( failures++ ))
|
||||
fi
|
||||
}
|
||||
|
||||
for filename in plain.txt 'file with spaces.txt' 'unicode-ą.txt' empty.txt; do
|
||||
if [[ $filename == empty.txt ]]; then
|
||||
: >| "$test_dir/$filename"
|
||||
else
|
||||
print -r -- "contents of $filename" >| "$test_dir/$filename"
|
||||
fi
|
||||
|
||||
expected_output=${(%):-"%B$test_dir/$filename%b copied to clipboard."}
|
||||
clipboard_status=0
|
||||
check_copyfile "successful copy of $filename" 0 "$expected_output" '' "$test_dir/$filename"
|
||||
|
||||
if [[ $(<"$test_dir/call") != "1 $test_dir/$filename" ]] || ! command cmp -s -- "$test_dir/$filename" "$test_dir/clipboard"; then
|
||||
print -u2 -r -- "FAIL: clipboard received a different argument or contents for $filename"
|
||||
(( failures++ ))
|
||||
fi
|
||||
|
||||
for clipboard_status in 1 42 127; do
|
||||
check_copyfile "clipboard exit $clipboard_status for $filename" 1 '' 'clipboard backend failed' "$test_dir/$filename"
|
||||
done
|
||||
done
|
||||
|
||||
command rm -f -- "$test_dir/call"
|
||||
check_copyfile 'missing argument' 1 'Usage: copyfile <file>' ''
|
||||
check_copyfile 'empty argument' 1 'Usage: copyfile <file>' '' ''
|
||||
check_copyfile 'nonexistent file' 1 "Error: '$test_dir/missing.txt' is not a valid file." '' "$test_dir/missing.txt"
|
||||
check_copyfile 'directory argument' 1 "Error: '$test_dir' is not a valid file." '' "$test_dir"
|
||||
|
||||
if [[ -e "$test_dir/call" ]]; then
|
||||
print -u2 -r -- 'FAIL: invalid input invoked the clipboard backend'
|
||||
(( failures++ ))
|
||||
fi
|
||||
|
||||
print -r -- "$tests tests, $failures failures"
|
||||
(( failures == 0 ))
|
||||
@@ -13,32 +13,28 @@ plugins=(... docker-compose)
|
||||
|
||||
## Aliases
|
||||
|
||||
| Alias | Command | Description |
|
||||
|-----------|-------------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| dco | `docker-compose` | Docker-compose main command |
|
||||
| dcb | `docker-compose build` | Build containers |
|
||||
| dcc | `docker-compose config` | Parse, resolve and render compose file in canonical format |
|
||||
| dce | `docker-compose exec` | Execute command inside a container |
|
||||
| dcps | `docker-compose ps` | List containers |
|
||||
| dcrestart | `docker-compose restart` | Restart container |
|
||||
| dcrm | `docker-compose rm` | Remove container |
|
||||
| dcr | `docker-compose run` | Run a command in container |
|
||||
| dcstop | `docker-compose stop` | Stop a container |
|
||||
| dcup | `docker-compose up` | Build, (re)create, start, and attach to containers for a service |
|
||||
| dcupb | `docker-compose up --build` | Same as `dcup`, but build images before starting containers |
|
||||
| dcupd | `docker-compose up -d` | Same as `dcup`, but starts as daemon |
|
||||
| dcupdb | `docker-compose up -d --build` | Same as `dcup`, but build images before starting containers and starts as daemon |
|
||||
| dcupw | `docker-compose up --watch` | Watch changes in service and rebuild/restart accordingly (see [Use Compose Watch] for usage) |
|
||||
| dcupwb | `docker-compose up --watch --build` | Same as `dcupw`, but build images before starting containers |
|
||||
| dcdn | `docker-compose down` | Stop and remove containers |
|
||||
| dcl | `docker-compose logs` | Show logs of container |
|
||||
| dclf | `docker-compose logs -f` | Show logs and follow output |
|
||||
| dclF | `docker-compose logs -f --tail0` | Just follow recent logs |
|
||||
| dcpull | `docker-compose pull` | Pull image of a service |
|
||||
| dcstart | `docker-compose start` | Start a container |
|
||||
| dck | `docker-compose kill` | Kills containers |
|
||||
| dcv | `docker-compose version` | Show version information |
|
||||
| dcsts | `docker-compose stats` | Show stats of containers |
|
||||
| dci | `docker-compose images` | List images |
|
||||
|
||||
[Use Compose Watch]: https://docs.docker.com/compose/how-tos/file-watch/
|
||||
| Alias | Command | Description |
|
||||
|-----------|----------------------------------|----------------------------------------------------------------------------------|
|
||||
| dco | `docker-compose` | Docker-compose main command |
|
||||
| dcb | `docker-compose build` | Build containers |
|
||||
| dcc | `docker-compose config` | Parse, resolve and render compose file in canonical format |
|
||||
| dce | `docker-compose exec` | Execute command inside a container |
|
||||
| dcps | `docker-compose ps` | List containers |
|
||||
| dcrestart | `docker-compose restart` | Restart container |
|
||||
| dcrm | `docker-compose rm` | Remove container |
|
||||
| dcr | `docker-compose run` | Run a command in container |
|
||||
| dcstop | `docker-compose stop` | Stop a container |
|
||||
| dcup | `docker-compose up` | Build, (re)create, start, and attach to containers for a service |
|
||||
| dcupb | `docker-compose up --build` | Same as `dcup`, but build images before starting containers |
|
||||
| dcupd | `docker-compose up -d` | Same as `dcup`, but starts as daemon |
|
||||
| dcupdb | `docker-compose up -d --build` | Same as `dcup`, but build images before starting containers and starts as daemon |
|
||||
| dcdn | `docker-compose down` | Stop and remove containers |
|
||||
| dcl | `docker-compose logs` | Show logs of container |
|
||||
| dclf | `docker-compose logs -f` | Show logs and follow output |
|
||||
| dclF | `docker-compose logs -f --tail0` | Just follow recent logs |
|
||||
| dcpull | `docker-compose pull` | Pull image of a service |
|
||||
| dcstart | `docker-compose start` | Start a container |
|
||||
| dck | `docker-compose kill` | Kills containers |
|
||||
| dcv | `docker-compose version` | Show version information |
|
||||
| dcsts | `docker-compose stats` | Show stats of containers |
|
||||
| dci | `docker-compose images` | List images |
|
||||
|
||||
@@ -17,8 +17,6 @@ alias dcup="$dccmd up"
|
||||
alias dcupb="$dccmd up --build"
|
||||
alias dcupd="$dccmd up -d"
|
||||
alias dcupdb="$dccmd up -d --build"
|
||||
alias dcupw="$dccmd up --watch"
|
||||
alias dcupwb="$dccmd up --watch --build"
|
||||
alias dcdn="$dccmd down"
|
||||
alias dcl="$dccmd logs"
|
||||
alias dclf="$dccmd logs -f"
|
||||
|
||||
@@ -48,11 +48,6 @@ fi
|
||||
0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
|
||||
0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
|
||||
# Make sure the cache directory exists; when the plugin is loaded by a
|
||||
# standalone plugin manager (e.g. antigen) the core is not sourced, so
|
||||
# $ZSH_CACHE_DIR/completions may not have been created yet (#13679).
|
||||
[[ -d "$ZSH_CACHE_DIR/completions" ]] || mkdir -p "$ZSH_CACHE_DIR/completions"
|
||||
|
||||
# If the completion file doesn't exist yet, we need to autoload it and
|
||||
# bind it to `docker`. Otherwise, compinit will have already done that.
|
||||
if [[ ! -f "$ZSH_CACHE_DIR/completions/_docker" ]]; then
|
||||
|
||||
@@ -101,14 +101,12 @@ EOF
|
||||
(*.tar.lz4) lz4 -c -d "$full_path" | tar xvf - ;;
|
||||
(*.tar.lrz) (( $+commands[lrzuntar] )) && lrzuntar "$full_path" ;;
|
||||
(*.gz) (( $+commands[pigz] )) && pigz -cdk "$full_path" > "${file:t:r}" || gunzip -ck "$full_path" > "${file:t:r}" ;;
|
||||
(*.bz2)
|
||||
(( $+commands[pbzip2] )) && pbzip2 -cd "$full_path" > "${file:t:r}" \
|
||||
|| bunzip2 -c "$full_path" > "${file:t:r}" ;;
|
||||
(*.bz2) (( $+commands[pbzip2] )) && pbzip2 -d "$full_path" || bunzip2 "$full_path" ;;
|
||||
(*.xz) xzcat "$full_path" > "${file:t:r}" ;;
|
||||
(*.lrz) (( $+commands[lrunzip] )) && lrunzip "$full_path" ;;
|
||||
(*.lz4) lz4 -d "$full_path" ;;
|
||||
(*.lzma) unlzma -c "$full_path" > "${file:t:r}" ;;
|
||||
(*.z) uncompress -c "$full_path" > "${file:t:r}" ;;
|
||||
(*.lzma) unlzma "$full_path" ;;
|
||||
(*.z) uncompress "$full_path" ;;
|
||||
(*.zip|*.war|*.jar|*.ear|*.sublime-package|*.ipa|*.ipsw|*.xpi|*.apk|*.aar|*.whl|*.vsix|*.crx|*.pk3|*.pk4) unzip "$full_path" ;;
|
||||
(*.rar)
|
||||
if (( $+commands[unrar] )); then
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
# Run with: zsh -df plugins/extract/tests/extract.test.zsh
|
||||
emulate -L zsh
|
||||
setopt err_return
|
||||
|
||||
for tool in lzma unlzma uncompress; do
|
||||
(( $+commands[$tool] )) || {
|
||||
print -u2 -r -- "These tests require $tool."
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
source "${0:A:h:h}/extract.plugin.zsh"
|
||||
local test_dir=$(mktemp -d) original_dir=$PWD
|
||||
|
||||
check_extract() {
|
||||
local extension=$1 mode=$2
|
||||
local case_dir="$test_dir/$extension-$mode"
|
||||
mkdir -p "$case_dir/source files" "$case_dir/work/target dir"
|
||||
local archive="$case_dir/source files/sample.txt.$extension"
|
||||
cp "$test_dir/fixture.$extension" "$archive"
|
||||
builtin cd "$case_dir/work"
|
||||
|
||||
local output="$PWD/sample.txt"
|
||||
local -a args
|
||||
case "$mode" in
|
||||
target)
|
||||
args=(-t 'target dir')
|
||||
output="$PWD/target dir/sample.txt"
|
||||
;;
|
||||
remove) args=(-r) ;;
|
||||
esac
|
||||
|
||||
# Run the plugin without the test's ERR_RETURN option.
|
||||
() {
|
||||
emulate -L zsh
|
||||
extract "${args[@]}" "$archive"
|
||||
} || return 1
|
||||
cmp "$test_dir/plain" "$output"
|
||||
if [[ $mode == remove ]]; then
|
||||
[[ ! -e $archive ]]
|
||||
else
|
||||
[[ -f $archive ]]
|
||||
fi
|
||||
print -r -- "PASS: $extension ($mode)"
|
||||
}
|
||||
|
||||
{
|
||||
print -r -- hello > "$test_dir/plain"
|
||||
lzma -c "$test_dir/plain" > "$test_dir/fixture.lzma"
|
||||
# "hello\n" as a .Z stream, since many systems only ship uncompress.
|
||||
printf '\037\235\220\150\312\260\141\363\106\001' \
|
||||
> "$test_dir/fixture.Z"
|
||||
|
||||
for extension in lzma Z; do
|
||||
for mode in default target remove; do
|
||||
check_extract "$extension" "$mode"
|
||||
done
|
||||
done
|
||||
print 'All extract compressed-file tests passed.'
|
||||
} always {
|
||||
builtin cd "$original_dir"
|
||||
rm -rf -- "$test_dir"
|
||||
}
|
||||
@@ -191,7 +191,6 @@ plugins=(... git)
|
||||
| `grmc` | `git rm --cached` |
|
||||
| `gcount` | `git shortlog --summary -n` |
|
||||
| `gsh` | `git show` |
|
||||
| `gshs` | `git show --stat` |
|
||||
| `gsps` | `git show --pretty=short --show-signature` |
|
||||
| `gstall` | `git stash --all` |
|
||||
| `gstu` | `git stash --include-untracked` |
|
||||
|
||||
@@ -392,7 +392,6 @@ alias grm='git rm'
|
||||
alias grmc='git rm --cached'
|
||||
alias gcount='git shortlog --summary --numbered'
|
||||
alias gsh='git show'
|
||||
alias gshs='git show --stat'
|
||||
alias gsps='git show --pretty=short --show-signature'
|
||||
alias gstall='git stash --all'
|
||||
alias gstaa='git stash apply'
|
||||
|
||||
@@ -4,11 +4,7 @@ globalias() {
|
||||
# (A) makes it an array even if there's only one element
|
||||
local word=${${(Az)LBUFFER}[-1]}
|
||||
if [[ $GLOBALIAS_FILTER_VALUES[(Ie)$word] -eq 0 ]]; then
|
||||
# Completion also considers quoted strings and assignment values as aliases.
|
||||
# Only expand when the complete shell word is an alias name.
|
||||
if (( ${+aliases[$word]} || ${+galiases[$word]} )); then
|
||||
zle _expand_alias
|
||||
fi
|
||||
zle _expand_alias
|
||||
zle expand-word
|
||||
fi
|
||||
zle self-insert
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
# Exercise the actual ZLE widgets in an isolated interactive shell.
|
||||
emulate -L zsh
|
||||
setopt err_return
|
||||
zmodload zsh/zpty
|
||||
zmodload zsh/zselect
|
||||
|
||||
local test_dir=$(mktemp -d)
|
||||
export GLOBALIAS_TEST_PLUGIN=${0:A:h:h}/globalias.plugin.zsh
|
||||
export GLOBALIAS_TEST_RESULT=$test_dir/result
|
||||
|
||||
wait_for_marker() {
|
||||
local marker=$1 output received
|
||||
local -i deadline=$(( SECONDS + 5 ))
|
||||
while (( SECONDS < deadline )); do
|
||||
if zpty -r globalias-test output; then
|
||||
received+=$output
|
||||
[[ $received == *$marker* ]] && return 0
|
||||
else
|
||||
zselect -t 1 || true
|
||||
fi
|
||||
done
|
||||
print -u2 -r -- "Timed out waiting for ZLE: $received"
|
||||
return 1
|
||||
}
|
||||
|
||||
check_expansion() {
|
||||
local input=$1 expected=$2 actual
|
||||
zpty -w -n globalias-test "$input"$' \x18'
|
||||
wait_for_marker GLOBALIAS_TEST_CAPTURED
|
||||
actual=$(< "$GLOBALIAS_TEST_RESULT")
|
||||
if [[ $actual != "$expected" ]]; then
|
||||
print -u2 -r -- "Input: ${(qqq)input}"
|
||||
print -u2 -r -- "Expected: ${(qqq)expected}; got: ${(qqq)actual}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
{
|
||||
cat > "$test_dir/setup.zsh" <<'SETUP'
|
||||
autoload -Uz compinit
|
||||
compinit -D
|
||||
source "$GLOBALIAS_TEST_PLUGIN"
|
||||
alias 1='cd -1'
|
||||
alias ll='ls -l'
|
||||
alias -g G='| grep'
|
||||
GLOBALIAS_FILTER_VALUES=(ll)
|
||||
_globalias_test_capture() {
|
||||
print -rn -- "$BUFFER" > "$GLOBALIAS_TEST_RESULT"
|
||||
print -r -- $'\nGLOBALIAS_TEST_CAPTURED'
|
||||
BUFFER=
|
||||
zle .accept-line
|
||||
}
|
||||
zle -N _globalias_test_capture
|
||||
bindkey '^X' _globalias_test_capture
|
||||
PS1='GLOBALIAS_TEST_READY> '
|
||||
RPROMPT=
|
||||
SETUP
|
||||
zpty -b globalias-test zsh -dfi
|
||||
zpty -w globalias-test "source ${(q)test_dir}/setup.zsh"
|
||||
wait_for_marker GLOBALIAS_TEST_READY
|
||||
|
||||
check_expansion 'DEBUG=1' 'DEBUG=1 '
|
||||
check_expansion 'DEBUG="1"' 'DEBUG="1" '
|
||||
check_expansion "DEBUG='1'" "DEBUG='1' "
|
||||
check_expansion '1' 'cd -1 '
|
||||
check_expansion '"1"' '"1" '
|
||||
check_expansion "'1'" "'1' "
|
||||
check_expansion '\1' '\1 '
|
||||
check_expansion 'echo G' 'echo | grep '
|
||||
check_expansion 'DEBUG=1 1' 'DEBUG=1 cd -1 '
|
||||
check_expansion 'll' 'll '
|
||||
check_expansion 'echo $((1+2))' 'echo 3 '
|
||||
check_expansion 'echo {a,b}' 'echo a b '
|
||||
check_expansion '' ' '
|
||||
print 'All globalias expansion tests passed.'
|
||||
} always {
|
||||
zpty -d globalias-test 2>/dev/null || true
|
||||
rm -rf -- "$test_dir"
|
||||
}
|
||||
@@ -5,40 +5,10 @@ Applies some fixes for some common issues encountered with [GPG's gpg-agent](htt
|
||||
More specifically, this plugin:
|
||||
|
||||
- Updates the `GPG_TTY` environment variable before each shell execution.
|
||||
- Updates the `SSH_AUTH_SOCK` environment variable if `gpg-agent` is your SSH
|
||||
agent. By default the plugin checks whether `enable-ssh-support` is turned
|
||||
on. The [`ssh-support` setting](#settings) lets you say so yourself.
|
||||
- Updates the `SSH_AUTH_SOCK` environment variable if `enable-ssh-support` is turned on.
|
||||
|
||||
To use it, add `gpg-agent` to the plugins array of your zshrc file:
|
||||
|
||||
```zsh
|
||||
plugins=(... gpg-agent)
|
||||
```
|
||||
|
||||
## Settings
|
||||
|
||||
Every time a shell starts, the plugin runs `gpgconf --list-options gpg-agent` to
|
||||
find out whether `enable-ssh-support` is turned on. That check can be slow. If
|
||||
you already know the answer, state it with the `ssh-support` style and the
|
||||
plugin skips the check. Set it in your zshrc, before Oh My Zsh is sourced.
|
||||
|
||||
If you don't use `gpg-agent` as your SSH agent:
|
||||
|
||||
```zsh
|
||||
zstyle ':omz:plugins:gpg-agent' ssh-support no
|
||||
```
|
||||
|
||||
The plugin then only sets `GPG_TTY`. It leaves `SSH_AUTH_SOCK` alone, and it
|
||||
doesn't update the agent's tty before each command, which only SSH support
|
||||
needs.
|
||||
|
||||
If you do use `gpg-agent` as your SSH agent:
|
||||
|
||||
```zsh
|
||||
zstyle ':omz:plugins:gpg-agent' ssh-support yes
|
||||
```
|
||||
|
||||
The plugin then sets `SSH_AUTH_SOCK` without checking. `enable-ssh-support`
|
||||
still has to be set in your `gpg-agent.conf` for SSH to work.
|
||||
|
||||
Leave the style unset to keep the automatic check.
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
export GPG_TTY=$TTY
|
||||
|
||||
# The ssh-support style says whether gpg-agent is used as the ssh agent.
|
||||
# Setting it saves asking gpgconf, which can be slow.
|
||||
zstyle -t ':omz:plugins:gpg-agent' ssh-support
|
||||
_gpg_agent_ssh_support=$? # 0 if yes, 1 if no, 2 if not set
|
||||
|
||||
# Everything below is only needed for ssh support
|
||||
if (( _gpg_agent_ssh_support == 1 )); then
|
||||
unset _gpg_agent_ssh_support
|
||||
return
|
||||
fi
|
||||
|
||||
# Fix for passphrase prompt on the correct tty
|
||||
# See https://www.gnupg.org/documentation/manuals/gnupg/Agent-Options.html#option-_002d_002denable_002dssh_002dsupport
|
||||
function _gpg-agent_update-tty_preexec {
|
||||
@@ -20,13 +9,9 @@ autoload -U add-zsh-hook
|
||||
add-zsh-hook preexec _gpg-agent_update-tty_preexec
|
||||
|
||||
# If enable-ssh-support is set, fix ssh agent integration
|
||||
if (( _gpg_agent_ssh_support == 0 )) \
|
||||
|| [[ $(gpgconf --list-options gpg-agent 2>/dev/null \
|
||||
| awk -F: '$1=="enable-ssh-support" {print $10}') = 1 ]]; then
|
||||
if [[ $(gpgconf --list-options gpg-agent 2>/dev/null | awk -F: '$1=="enable-ssh-support" {print $10}') = 1 ]]; then
|
||||
unset SSH_AGENT_PID
|
||||
if [[ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]]; then
|
||||
export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
|
||||
fi
|
||||
fi
|
||||
|
||||
unset _gpg_agent_ssh_support
|
||||
|
||||
@@ -22,17 +22,14 @@ fi
|
||||
# Define json tools for each method
|
||||
case "$JSONTOOLS_METHOD" in
|
||||
node)
|
||||
# Read stdin directly so input is not limited by command-line argument size.
|
||||
# node doesn't make it easy to deal with stdin, so we pass it as an argument with xargs -0
|
||||
function pp_json() {
|
||||
node -e '
|
||||
const input = require("fs").readFileSync(0, "utf8");
|
||||
console.log(JSON.stringify(JSON.parse(input), null, 4));
|
||||
'
|
||||
xargs -0 node -e 'console.log(JSON.stringify(JSON.parse(process.argv[1]), null, 4));'
|
||||
}
|
||||
function is_json() {
|
||||
node -e '
|
||||
xargs -0 node -e '
|
||||
try {
|
||||
JSON.parse(require("fs").readFileSync(0, "utf8"));
|
||||
json = JSON.parse(process.argv[1]);
|
||||
console.log("true");
|
||||
process.exit(0);
|
||||
} catch (e) {
|
||||
@@ -42,14 +39,10 @@ case "$JSONTOOLS_METHOD" in
|
||||
'
|
||||
}
|
||||
function urlencode_json() {
|
||||
node -e '
|
||||
console.log(encodeURIComponent(require("fs").readFileSync(0, "utf8")));
|
||||
'
|
||||
xargs -0 node -e "console.log(encodeURIComponent(process.argv[1]))"
|
||||
}
|
||||
function urldecode_json() {
|
||||
node -e '
|
||||
console.log(decodeURIComponent(require("fs").readFileSync(0, "utf8")));
|
||||
'
|
||||
xargs -0 node -e "console.log(decodeURIComponent(process.argv[1]))"
|
||||
}
|
||||
;;
|
||||
python3)
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
# Run with: zsh -df plugins/jsontools/tests/jsontools.test.zsh
|
||||
emulate -L zsh
|
||||
setopt err_return
|
||||
|
||||
(( $+commands[node] )) || {
|
||||
print -u2 'These tests require Node.js.'
|
||||
exit 1
|
||||
}
|
||||
|
||||
JSONTOOLS_METHOD=node
|
||||
source "${0:A:h:h}/jsontools.plugin.zsh"
|
||||
local test_dir=$(mktemp -d)
|
||||
|
||||
check_output() {
|
||||
local tool=$1 description=$2 expected_status=${3:-0}
|
||||
local -i result=0
|
||||
$tool < "$test_dir/input" > "$test_dir/actual" || result=$?
|
||||
if (( result != expected_status )) \
|
||||
|| ! cmp -s "$test_dir/expected" "$test_dir/actual"; then
|
||||
print -u2 -r -- "FAIL: $description ($tool exited $result)"
|
||||
return 1
|
||||
fi
|
||||
print -r -- "PASS: $description"
|
||||
}
|
||||
|
||||
{
|
||||
print -rn -- '{"value":42}' > "$test_dir/input"
|
||||
printf '{\n "value": 42\n}\n' > "$test_dir/expected"
|
||||
check_output pp_json 'pretty-print a small document'
|
||||
|
||||
# Larger than the 128 KiB limit for a single command-line argument.
|
||||
local large_value=${(l:262144::x:):-}
|
||||
print -rn -- '{"value":"'"$large_value"'"}' > "$test_dir/input"
|
||||
printf '{\n "value": "%s"\n}\n' "$large_value" > "$test_dir/expected"
|
||||
check_output pp_json 'pretty-print a large document'
|
||||
print -r -- true > "$test_dir/expected"
|
||||
check_output is_json 'validate a large document'
|
||||
|
||||
print -r -- '%7B%22value%22%3A%22'"$large_value"'%22%7D' \
|
||||
> "$test_dir/expected"
|
||||
check_output urlencode_json 'encode a large document'
|
||||
local encoded=$(< "$test_dir/expected")
|
||||
print -rn -- "$encoded" > "$test_dir/input"
|
||||
print -r -- '{"value":"'"$large_value"'"}' > "$test_dir/expected"
|
||||
check_output urldecode_json 'decode a large document'
|
||||
|
||||
# Passed as an argument, node used to parse this as its own option.
|
||||
print -rn -- '--version' > "$test_dir/input"
|
||||
print -r -- '--version' > "$test_dir/expected"
|
||||
check_output urlencode_json 'encode input that starts with --'
|
||||
|
||||
print -rn -- '{invalid}' > "$test_dir/input"
|
||||
print -r -- false > "$test_dir/expected"
|
||||
check_output is_json 'reject invalid JSON' 1
|
||||
|
||||
printf '1\0002' > "$test_dir/input"
|
||||
check_output is_json 'reject input with NUL bytes' 1
|
||||
|
||||
print 'All jsontools Node.js tests passed.'
|
||||
} always {
|
||||
rm -rf -- "$test_dir"
|
||||
}
|
||||
@@ -6,21 +6,6 @@ This plugin adds aliases and autocompletion for Laravel [Artisan](https://larave
|
||||
plugins=(... laravel)
|
||||
```
|
||||
|
||||
## Settings
|
||||
|
||||
By default the aliases run `php artisan`. To use a different PHP command, such as
|
||||
`herd php` (which runs the PHP version the [Laravel Herd](https://herd.laravel.com) site
|
||||
is isolated to, instead of Herd's global version) or a specific version like `php8.4`,
|
||||
set this before Oh My Zsh is sourced:
|
||||
|
||||
```zsh
|
||||
zstyle ':omz:plugins:laravel' php 'herd php'
|
||||
```
|
||||
|
||||
`php` in the aliases below is then replaced with that command.
|
||||
|
||||
## Aliases
|
||||
|
||||
| Alias | Description |
|
||||
|:-:|:-:|
|
||||
| `artisan` | `php artisan` |
|
||||
|
||||
@@ -1,56 +1,51 @@
|
||||
#!zsh
|
||||
# Command used to run artisan, e.g. `herd php` or `php8.4` (default: `php`)
|
||||
zstyle -s ':omz:plugins:laravel' php _omz_laravel_php || _omz_laravel_php=php
|
||||
|
||||
alias artisan="$_omz_laravel_php artisan"
|
||||
alias bob="$_omz_laravel_php artisan bob::build"
|
||||
alias artisan='php artisan'
|
||||
alias bob='php artisan bob::build'
|
||||
|
||||
# Development
|
||||
alias pas="$_omz_laravel_php artisan serve"
|
||||
alias pad="$_omz_laravel_php artisan dev"
|
||||
alias pats="$_omz_laravel_php artisan test"
|
||||
alias pas='php artisan serve'
|
||||
alias pad='php artisan dev'
|
||||
alias pats='php artisan test'
|
||||
|
||||
# Database
|
||||
alias pam="$_omz_laravel_php artisan migrate"
|
||||
alias pamf="$_omz_laravel_php artisan migrate:fresh"
|
||||
alias pamfs="$_omz_laravel_php artisan migrate:fresh --seed"
|
||||
alias pamr="$_omz_laravel_php artisan migrate:rollback"
|
||||
alias pads="$_omz_laravel_php artisan db:seed"
|
||||
alias padw="$_omz_laravel_php artisan db:wipe"
|
||||
alias pam='php artisan migrate'
|
||||
alias pamf='php artisan migrate:fresh'
|
||||
alias pamfs='php artisan migrate:fresh --seed'
|
||||
alias pamr='php artisan migrate:rollback'
|
||||
alias pads='php artisan db:seed'
|
||||
alias padw='php artisan db:wipe'
|
||||
|
||||
# Makers
|
||||
alias pamm="$_omz_laravel_php artisan make:model"
|
||||
alias pamc="$_omz_laravel_php artisan make:controller"
|
||||
alias pams="$_omz_laravel_php artisan make:seeder"
|
||||
alias pamt="$_omz_laravel_php artisan make:test"
|
||||
alias pamfa="$_omz_laravel_php artisan make:factory"
|
||||
alias pamp="$_omz_laravel_php artisan make:policy"
|
||||
alias pame="$_omz_laravel_php artisan make:event"
|
||||
alias pamj="$_omz_laravel_php artisan make:job"
|
||||
alias paml="$_omz_laravel_php artisan make:listener"
|
||||
alias pamn="$_omz_laravel_php artisan make:notification"
|
||||
alias pampp="$_omz_laravel_php artisan make:provider"
|
||||
alias pamcl="$_omz_laravel_php artisan make:class"
|
||||
alias pamen="$_omz_laravel_php artisan make:enum"
|
||||
alias pami="$_omz_laravel_php artisan make:interface"
|
||||
alias pamtr="$_omz_laravel_php artisan make:trait"
|
||||
alias pamv="$_omz_laravel_php artisan make:view"
|
||||
alias pammig="$_omz_laravel_php artisan make:migration"
|
||||
alias pamm='php artisan make:model'
|
||||
alias pamc='php artisan make:controller'
|
||||
alias pams='php artisan make:seeder'
|
||||
alias pamt='php artisan make:test'
|
||||
alias pamfa='php artisan make:factory'
|
||||
alias pamp='php artisan make:policy'
|
||||
alias pame='php artisan make:event'
|
||||
alias pamj='php artisan make:job'
|
||||
alias paml='php artisan make:listener'
|
||||
alias pamn='php artisan make:notification'
|
||||
alias pampp='php artisan make:provider'
|
||||
alias pamcl='php artisan make:class'
|
||||
alias pamen='php artisan make:enum'
|
||||
alias pami='php artisan make:interface'
|
||||
alias pamtr='php artisan make:trait'
|
||||
alias pamv='php artisan make:view'
|
||||
alias pammig='php artisan make:migration'
|
||||
|
||||
|
||||
# Clears
|
||||
alias pacac="$_omz_laravel_php artisan cache:clear"
|
||||
alias pacoc="$_omz_laravel_php artisan config:clear"
|
||||
alias pavic="$_omz_laravel_php artisan view:clear"
|
||||
alias paroc="$_omz_laravel_php artisan route:clear"
|
||||
alias paopc="$_omz_laravel_php artisan optimize:clear"
|
||||
alias pacac='php artisan cache:clear'
|
||||
alias pacoc='php artisan config:clear'
|
||||
alias pavic='php artisan view:clear'
|
||||
alias paroc='php artisan route:clear'
|
||||
alias paopc='php artisan optimize:clear'
|
||||
|
||||
# queues
|
||||
alias paqf="$_omz_laravel_php artisan queue:failed"
|
||||
alias paqft="$_omz_laravel_php artisan queue:failed-table"
|
||||
alias paql="$_omz_laravel_php artisan queue:listen"
|
||||
alias paqr="$_omz_laravel_php artisan queue:retry"
|
||||
alias paqt="$_omz_laravel_php artisan queue:table"
|
||||
alias paqw="$_omz_laravel_php artisan queue:work"
|
||||
|
||||
unset _omz_laravel_php
|
||||
alias paqf='php artisan queue:failed'
|
||||
alias paqft='php artisan queue:failed-table'
|
||||
alias paql='php artisan queue:listen'
|
||||
alias paqr='php artisan queue:retry'
|
||||
alias paqt='php artisan queue:table'
|
||||
alias paqw='php artisan queue:work'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
if (( $+commands[mise] )); then
|
||||
_mise_bin=$commands[mise]
|
||||
_mise_bin=mise
|
||||
elif [[ -x ~/.local/bin/mise ]]; then
|
||||
_mise_bin=~/.local/bin/mise
|
||||
else
|
||||
@@ -8,6 +8,7 @@ fi
|
||||
|
||||
# Load mise hooks
|
||||
eval "$($_mise_bin activate zsh)"
|
||||
unset _mise_bin
|
||||
|
||||
# If the completion file doesn't exist yet, we need to autoload it and
|
||||
# bind it to `mise`. Otherwise, compinit will have already done that.
|
||||
@@ -17,13 +18,9 @@ if [[ ! -f "$ZSH_CACHE_DIR/completions/_mise" ]]; then
|
||||
_comps[mise]=_mise
|
||||
fi
|
||||
|
||||
# Generate completion only when missing/empty or stale relative to the mise binary.
|
||||
if [[ ! -s "$ZSH_CACHE_DIR/completions/_mise" || "$_mise_bin" -nt "$ZSH_CACHE_DIR/completions/_mise" ]]; then
|
||||
zmodload -F zsh/files b:zf_mv
|
||||
() {
|
||||
local TMPPREFIX="$ZSH_CACHE_DIR/completions/._mise"
|
||||
zf_mv -f -- =( "$_mise_bin" completion zsh ) "$ZSH_CACHE_DIR/completions/_mise"
|
||||
} &|
|
||||
fi
|
||||
|
||||
unset _mise_bin
|
||||
# Generate and load mise completion
|
||||
zmodload -F zsh/files b:zf_mv
|
||||
() {
|
||||
local TMPPREFIX="$ZSH_CACHE_DIR/completions/._mise"
|
||||
zf_mv -f -- =( mise completion zsh ) "$ZSH_CACHE_DIR/completions/_mise"
|
||||
} &|
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# opencode plugin
|
||||
|
||||
This plugin adds completion and aliases for the [OpenCode](https://opencode.ai) CLI.
|
||||
Install OpenCode using its [installation instructions](https://opencode.ai/docs/#install),
|
||||
and make sure `opencode` is available on your `$PATH`.
|
||||
|
||||
To enable it, add `opencode` to the plugins array in your `.zshrc`:
|
||||
|
||||
```zsh
|
||||
plugins=(... opencode)
|
||||
```
|
||||
|
||||
## Learning OpenCode from the terminal
|
||||
|
||||
Use tab completion to explore commands and their descriptions without leaving the
|
||||
shell. For example, these are some of the candidates shown by the CLI:
|
||||
|
||||
```text
|
||||
$ opencode <TAB>
|
||||
agent -- manage agents
|
||||
models -- list all available models
|
||||
run -- run opencode with a message
|
||||
session -- manage sessions
|
||||
stats -- show token usage and cost statistics
|
||||
...
|
||||
|
||||
$ opencode session <TAB>
|
||||
delete -- delete a session
|
||||
list -- list sessions
|
||||
|
||||
$ opencode run --<TAB>
|
||||
--agent -- agent to use
|
||||
--continue -- continue the last session
|
||||
--file -- file(s) to attach to message
|
||||
--model -- model to use in the format of provider/model
|
||||
...
|
||||
```
|
||||
|
||||
Completion works through the aliases too. Type a partial command or option and
|
||||
press Tab to finish it:
|
||||
|
||||
```text
|
||||
$ opc session li<TAB>
|
||||
$ opc session list
|
||||
|
||||
$ opcr --att<TAB>
|
||||
$ opcr --attach
|
||||
|
||||
$ opcc --log-l<TAB>
|
||||
$ opcc --log-level
|
||||
```
|
||||
|
||||
Candidates depend on your installed OpenCode version. In OpenCode 1.18.29, the
|
||||
CLI's completion output omits top-level TUI flags such as `--model` and `--fork`,
|
||||
even though those flags work when typed. Use `opencode --help` or
|
||||
`opencode run --help` for the full options, and see the
|
||||
[CLI reference](https://opencode.ai/docs/cli/) for more workflows.
|
||||
|
||||
## Aliases
|
||||
|
||||
| Alias | Command | Description |
|
||||
| ------ | --------------------- | ----------------------------------- |
|
||||
| `opc` | `opencode` | Launch the terminal UI |
|
||||
| `opcc` | `opencode --continue` | Continue the last session |
|
||||
| `opcr` | `opencode run` | Run a prompt without opening the UI |
|
||||
|
||||
To keep completion but skip the aliases, set this in your `.zshrc`, above the line
|
||||
that sources Oh My Zsh:
|
||||
|
||||
```zsh
|
||||
# ~/.zshrc
|
||||
zstyle ':omz:plugins:opencode' aliases no
|
||||
|
||||
plugins=(... opencode)
|
||||
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
```
|
||||
|
||||
## Common workflows
|
||||
|
||||
All aliases accept additional arguments:
|
||||
|
||||
```zsh
|
||||
# Open a project
|
||||
opc ~/projects/my-app
|
||||
|
||||
# Explore a different approach by forking the last session
|
||||
opcc --fork
|
||||
|
||||
# Ask a question without entering the terminal UI
|
||||
opcr "Explain the test setup in this project"
|
||||
|
||||
# Reuse an already running backend to avoid MCP server cold starts
|
||||
opcr --attach http://localhost:4096 "Explain this project's architecture"
|
||||
```
|
||||
|
||||
## Completion
|
||||
|
||||
Completion queries the installed OpenCode CLI on demand for commands and options,
|
||||
including through the aliases above. It falls back to Zsh's default completion when
|
||||
the CLI returns no candidates. No OpenCode process is started at shell startup,
|
||||
and no generated completion cache is needed.
|
||||
|
||||
## Credits
|
||||
|
||||
Based on the OpenCode plugin proposals by
|
||||
[pranavavva](https://github.com/pranavavva) in
|
||||
[#13545](https://github.com/ohmyzsh/ohmyzsh/pull/13545) and
|
||||
[mskadu](https://github.com/mskadu) in
|
||||
[#13794](https://github.com/ohmyzsh/ohmyzsh/pull/13794).
|
||||
The completion adapter is derived from OpenCode's `opencode completion` output.
|
||||
@@ -1,12 +0,0 @@
|
||||
#compdef opencode
|
||||
|
||||
# Adapted from `opencode completion`, using the CLI's live Yargs completions.
|
||||
local -a reply
|
||||
reply=("${(@f)$(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" \
|
||||
command opencode --get-yargs-completions "${words[@]}" < /dev/null 2> /dev/null)}")
|
||||
|
||||
if [[ -n "${reply[1]}" ]]; then
|
||||
_describe 'values' reply
|
||||
else
|
||||
_default
|
||||
fi
|
||||
@@ -1,7 +0,0 @@
|
||||
if (( ! $+commands[opencode] )); then
|
||||
return
|
||||
fi
|
||||
|
||||
alias opc='opencode'
|
||||
alias opcc='opencode --continue'
|
||||
alias opcr='opencode run'
|
||||
@@ -3,8 +3,6 @@
|
||||
The primary job of this plugin is to provide `rbenv_prompt_info` which can be added to your theme to include Ruby
|
||||
version and gemset information into your prompt.
|
||||
|
||||
Additionally, this plugin provides completion for the `rbenv` command. See also <https://github.com/rbenv/rbenv/#shell-completions>.
|
||||
|
||||
Some functionality of this plugin will not work unless you also have the rbenv plugin *gemset* installed.
|
||||
https://github.com/jf/rbenv-gemset
|
||||
|
||||
|
||||
@@ -24,13 +24,6 @@ if [[ $FOUND_RBENV -ne 1 ]]; then
|
||||
fi
|
||||
|
||||
if [[ $FOUND_RBENV -eq 1 ]]; then
|
||||
rbenv_completions="${commands[rbenv]:A:h:h}/completions"
|
||||
if [[ -f "$rbenv_completions/_rbenv" ]]; then
|
||||
fpath+=("$rbenv_completions")
|
||||
autoload -Uz _rbenv
|
||||
compdef _rbenv rbenv
|
||||
fi
|
||||
|
||||
eval "$(rbenv init --no-rehash - zsh)"
|
||||
|
||||
alias rubies="rbenv versions"
|
||||
@@ -72,4 +65,4 @@ else
|
||||
}
|
||||
fi
|
||||
|
||||
unset FOUND_RBENV rbenvdirs dir rbenv_completions
|
||||
unset FOUND_RBENV rbenvdirs dir
|
||||
|
||||
@@ -14,9 +14,9 @@ plugins=(... ruby)
|
||||
| ------- | -------------------------------------- | ---------------------------------------------------- |
|
||||
| rb | `ruby` | The Ruby command |
|
||||
| sgem | `sudo gem` | Run sudo gem on the system ruby, not the active ruby |
|
||||
| rfind | `find . -name "*.rb" -print0 \| xargs -0 grep -n` | Find ruby file |
|
||||
| rfind | `find . -name "*.rb" \| xargs grep -n` | Find ruby file |
|
||||
| rrun | `ruby -e` | Execute some code: E.g: `rrun "puts 'Hello world!'"` |
|
||||
| rserver | `ruby -run -e httpd . -p 8080` | Start HTTP Webrick serving local directory/files |
|
||||
| rserver | `ruby -e httpd . -p 8080` | Start HTTP Webrick serving local directory/files |
|
||||
| gein | `gem install` | Install a gem into the local repository |
|
||||
| geun | `gem uninstall` | Uninstall gems from the local repository |
|
||||
| geli | `gem list` | Display gems installed locally |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
alias sgem='sudo gem'
|
||||
|
||||
# Find ruby file
|
||||
alias rfind='find . -name "*.rb" -print0 | xargs -0 grep -n'
|
||||
alias rfind='find . -name "*.rb" | xargs grep -n'
|
||||
|
||||
# Shorthand Ruby
|
||||
alias rb="ruby"
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
emulate -LR zsh
|
||||
|
||||
source "${1:-${0:A:h:h}/ruby.plugin.zsh}"
|
||||
|
||||
test_dir=$(mktemp -d) || exit 1
|
||||
trap 'command rm -rf -- "$test_dir"' EXIT
|
||||
|
||||
typeset -i failures=0 tests=0
|
||||
typeset filename output
|
||||
|
||||
for filename in plain.rb 'file with spaces.rb' "single'quote.rb" 'double"quote.rb' $'line\nbreak.rb' 'unicode-ą.rb'; do
|
||||
print -r -- 'needle' >| "$test_dir/$filename"
|
||||
output=$(cd "$test_dir" && rfind needle 2> "$test_dir/stderr")
|
||||
actual_status=$?
|
||||
(( tests++ ))
|
||||
|
||||
if [[ $actual_status == 0 && $output == '1:needle' && ! -s "$test_dir/stderr" ]]; then
|
||||
print -r -- "PASS: ${(qqq)filename}"
|
||||
else
|
||||
print -u2 -r -- "FAIL: ${(qqq)filename} (status $actual_status)"
|
||||
print -u2 -r -- " stdout: ${(qqq)output}"
|
||||
print -u2 -r -- " stderr: $(<"$test_dir/stderr")"
|
||||
(( failures++ ))
|
||||
fi
|
||||
|
||||
command rm -- "$test_dir/$filename"
|
||||
done
|
||||
|
||||
print -r -- "$tests tests, $failures failures"
|
||||
(( failures == 0 ))
|
||||
+1
-1
@@ -237,7 +237,7 @@ case "$words[1]" in
|
||||
'(-c|--noancestors)'{-c,--noancestors}'[do not include second-generation package ancestors in the scratch org]' \
|
||||
'(-i|--clientid)'{-i,--clientid}'[connected app consumer key]' \
|
||||
'(-s|--setdefaultusername)'{-s,--setdefaultusername}'[set the created org as the default username]' \
|
||||
'(-a|--setalias)'{-a,--setalias}'[set an alias for the created scratch org]' \
|
||||
'(-a|--setalias)'{-a,--setalias}'[set an alias for for the created scratch org]' \
|
||||
'(-e|--env)'{-e,--env}'[environment where the scratch org is created: \[sandbox*,virtual,prototype\] (sandbox*,virtual,prototype)]' \
|
||||
'(-w|--wait)'{-w,--wait}'[the streaming client socket timeout (in minutes) (default:6, min:2)]' \
|
||||
'(-d|--durationdays)'{-d,--durationdays}'[duration of the scratch org (in days) (default:7, min:1, max:30)]' \
|
||||
|
||||
@@ -15,8 +15,8 @@ plugins=(... uv)
|
||||
| :---- | ---------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- |
|
||||
| uva | `uv add` | Add packages to the project |
|
||||
| uvexp | `uv export --format requirements-txt --no-hashes --output-file requirements.txt --quiet` | Export the lock file to `requirements.txt` |
|
||||
| uvi | `uv init` | Initialize a new project |
|
||||
| uvinw | `uv init --no-workspace` | Initialize a standalone project without joining a parent workspace |
|
||||
| uvi | `uv init` | Initialize a new project in current workspace and environment. |
|
||||
| uvinw | `uv init --no-workspace` | Initialize a new project in a new workspace and environment |
|
||||
| uvl | `uv lock` | Lock the dependencies |
|
||||
| uvlr | `uv lock --refresh` | Rebuild the lock file without upgrading dependencies |
|
||||
| uvlu | `uv lock --upgrade` | Lock the dependencies to the newest compatible versions |
|
||||
|
||||
@@ -1240,14 +1240,9 @@ _zsh_highlight_main_highlighter_check_path()
|
||||
fi
|
||||
tmp_path=$tmp_path:a
|
||||
|
||||
local candidate_new_tmp_path
|
||||
while [[ $tmp_path != / ]]; do
|
||||
[[ -n ${(M)ZSH_HIGHLIGHT_DIRS_BLACKLIST:#$tmp_path} ]] && return 1
|
||||
candidate_new_tmp_path=${tmp_path:h}
|
||||
if [[ $candidate_new_tmp_path == $tmp_path ]]; then
|
||||
break
|
||||
fi
|
||||
tmp_path=${candidate_new_tmp_path}
|
||||
tmp_path=$tmp_path:h
|
||||
done
|
||||
|
||||
if (( in_command_position )); then
|
||||
|
||||
@@ -274,14 +274,11 @@ function handle_update() {
|
||||
|
||||
# Ask for confirmation and only update on 'y', 'Y' or Enter
|
||||
# Otherwise just show a reminder for how to update
|
||||
# ㅛ (U+315B) is the character produced at the Y key position on the Korean
|
||||
# Dubeolsik layout, so it is accepted too to avoid cancelling the update
|
||||
# when a Korean IME is active.
|
||||
printf "[oh-my-zsh] Would you like to update? [Y/n] "
|
||||
read -r -k 1 option
|
||||
[[ "$option" = $'\n' ]] || echo
|
||||
case "$option" in
|
||||
[yY$'\n']|$'ㅛ') update_ohmyzsh ;;
|
||||
[yY$'\n']) update_ohmyzsh ;;
|
||||
[nN]) update_last_updated_file ;&
|
||||
*) echo "[oh-my-zsh] You can update manually by running \`omz update\`" ;;
|
||||
esac
|
||||
|
||||
@@ -1,657 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
# Shared on-demand renderer for `omz shellsaver <scene>`.
|
||||
# The CLI launches a separate Zsh process, keeping all state out of the caller.
|
||||
{
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
unsetopt multibyte
|
||||
|
||||
integer tick=0 width=96 height=28 resized=1 active=0 seconds_limit=0
|
||||
integer mono=0 snapshot=0 scene_selected=0
|
||||
local saved_tty='' key='' blank='' result='' scene=''
|
||||
local -a canvas inks palette
|
||||
|
||||
_zshell_list() {
|
||||
print -r -- 'aquarium Sea shells, a ~ hermit crab, and a quiet current (default).
|
||||
logo The Oh My Zsh wordmark takes a bouncing coffee break.
|
||||
hermit A bewildered hermit crab tries to find its working directory.
|
||||
party A rainbow terminal stage and a crowd of dancing shell fans.'
|
||||
}
|
||||
|
||||
_zshell_usage() {
|
||||
print -r -- 'Oh My Zsh / experimental Shellsavers
|
||||
|
||||
Usage: omz shellsaver [aquarium|logo|hermit|party] [--mono] [--seconds N]
|
||||
omz shellsaver [aquarium|logo|hermit|party] --snapshot [FRAME]
|
||||
omz shellsaver --list
|
||||
'
|
||||
_zshell_list
|
||||
print -r -- '
|
||||
Any key returns to the shell. Ctrl-C also exits safely.
|
||||
--list List available scenes and the default.
|
||||
--mono Use the terminal default foreground color.
|
||||
--seconds N Exit automatically after 1-3600 seconds.
|
||||
--snapshot Print a still at 96 columns x 28 rows (no terminal needed).
|
||||
|
||||
Requires Zsh 5.8+, stty, and an xterm-compatible terminal with an alternate screen.
|
||||
Nothing is installed or enabled automatically.'
|
||||
}
|
||||
case "${1-}" in
|
||||
--help|-h) _zshell_usage; exit 0 ;;
|
||||
''|--*) scene=aquarium ;;
|
||||
aquarium|logo|hermit|party) scene=$1; scene_selected=1; shift ;;
|
||||
*) print -u2 -r -- "omz shellsaver: unknown scene: $1 (choose aquarium, logo, hermit, or party)"; exit 2 ;;
|
||||
esac
|
||||
|
||||
while (( $# )); do
|
||||
case "$1" in
|
||||
aquarium|logo|hermit|party)
|
||||
if (( scene_selected )); then
|
||||
print -u2 -r -- 'omz shellsaver: choose only one scene (try --help)'
|
||||
exit 2
|
||||
fi
|
||||
scene=$1; scene_selected=1 ;;
|
||||
--help|-h) _zshell_usage; exit 0 ;;
|
||||
--list) _zshell_list; exit 0 ;;
|
||||
--mono) mono=1 ;;
|
||||
--seconds)
|
||||
shift
|
||||
if [[ $1 != <1-3600> ]]; then
|
||||
print -u2 -r -- 'omz shellsaver: --seconds requires an integer from 1 to 3600'
|
||||
exit 2
|
||||
fi
|
||||
seconds_limit=$1 ;;
|
||||
--snapshot)
|
||||
snapshot=1
|
||||
if [[ ${2-} == <0-100000> ]]; then tick=$2; shift; fi ;;
|
||||
*) print -u2 -r -- "omz shellsaver: unknown argument: $1 (try --help)"; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Paint into separate ASCII text and color planes. Clip before slicing so a
|
||||
# creature partly outside the viewport never wraps onto another terminal row.
|
||||
_zshell_put() {
|
||||
integer x=$1 y=$2 ink=$3 count skip
|
||||
local text=$4 prefix='' suffix='' iprefix='' isuffix=''
|
||||
(( y >= 1 && y <= height && x <= width )) || return 0
|
||||
if (( x < 1 )); then
|
||||
skip=$(( 2 - x ))
|
||||
(( skip <= ${#text} )) || return 0
|
||||
text=${text[$skip,-1]}
|
||||
x=1
|
||||
fi
|
||||
count=$(( width - x + 1 ))
|
||||
text=${text[1,$count]}
|
||||
count=${#text}
|
||||
(( count )) || return 0
|
||||
if (( x > 1 )); then
|
||||
prefix=${canvas[$y][1,$((x-1))]}
|
||||
iprefix=${inks[$y][1,$((x-1))]}
|
||||
fi
|
||||
if (( x + count <= width )); then
|
||||
suffix=${canvas[$y][$((x+count)),-1]}
|
||||
isuffix=${inks[$y][$((x+count)),-1]}
|
||||
fi
|
||||
canvas[$y]="$prefix$text$suffix"
|
||||
inks[$y]="$iprefix${(pl:$count::$ink:)}$isuffix"
|
||||
}
|
||||
|
||||
_zshell_sprite() {
|
||||
integer sx=$1 sy=$2 color=$3
|
||||
shift 3
|
||||
local line
|
||||
for line in "$@"; do
|
||||
_zshell_put $sx $sy $color "$line"
|
||||
(( sy++ ))
|
||||
done
|
||||
}
|
||||
|
||||
_zshell_logo() {
|
||||
# The full-size artwork and per-letter color bands match tools/upgrade.sh.
|
||||
# A compact badge preserves the bounce in narrower terminal windows.
|
||||
local -a logo logo_inks quips
|
||||
local line glyph bands run
|
||||
integer logo_width=0 logo_height span_x span_y px py x y color i j n offset
|
||||
logo=(
|
||||
' __ __ '
|
||||
' ____ / /_ ____ ___ __ __ ____ _____/ /_ '
|
||||
' / __ \/ __ \ / __ `__ \/ / / / /_ / / ___/ __ \ '
|
||||
'/ /_/ / / / / / / / / / / /_/ / / /_(__ ) / / / '
|
||||
'\____/_/ /_/ /_/ /_/ /_/\__, / /___/____/_/ /_/ '
|
||||
' /____/ '
|
||||
)
|
||||
logo_inks=(
|
||||
11111111122222222333333333334444444455555556666677777
|
||||
11111111222222223333333333344444444555555566666777777
|
||||
11111112222222233333333333444444445555555666666777777
|
||||
11111112222222333333333333444444455555556666667777777
|
||||
11111122222223333333333334444444555555556666677777777
|
||||
11112222222233333333333444444445555555666667777777777
|
||||
)
|
||||
if (( width < 64 )); then
|
||||
logo=( '.------------------.' '| Oh My Zsh |' '| ~ >_ |' "'------------------'" )
|
||||
logo_inks=()
|
||||
for line in "${logo[@]}"; do
|
||||
bands=''
|
||||
for (( j=1; j<=${#line}; j++ )); do
|
||||
bands+=$((1+(j-1)*7/${#line}))
|
||||
done
|
||||
logo_inks+=( "$bands" )
|
||||
done
|
||||
fi
|
||||
for line in "${logo[@]}"; do
|
||||
(( ${#line} > logo_width )) && logo_width=${#line}
|
||||
done
|
||||
logo_height=${#logo}
|
||||
span_x=$(( width-logo_width-4 ))
|
||||
span_y=$(( height-logo_height-8 ))
|
||||
px=$(( (tick/2+span_x/2) % (2*span_x) ))
|
||||
py=$(( (tick/6+span_y/2) % (2*span_y) ))
|
||||
x=$(( 3 + (px <= span_x ? px : 2*span_x-px) ))
|
||||
y=$(( 5 + (py <= span_y ? py : 2*span_y-py) ))
|
||||
|
||||
_zshell_put 3 2 1 'O H M Y Z S H'
|
||||
_zshell_put $((width-17)) 2 0 'prompt on a break'
|
||||
for (( i=0; i<width/14; i++ )); do
|
||||
glyph='~'; (( i % 2 )) && glyph='>'
|
||||
_zshell_put $((3+(i*23+tick/20)%(width-5))) $((4+(i*7)%(height-7))) 0 "$glyph"
|
||||
done
|
||||
# Keep the updater's red-to-pink bands attached to their letters on bounce.
|
||||
for (( i=1; i<=logo_height; i++ )); do
|
||||
line=${logo[$i]} bands=${logo_inks[$i]} offset=0
|
||||
while [[ -n $bands ]]; do
|
||||
glyph=${bands[1]}
|
||||
run=${bands%%[^$glyph]*}
|
||||
n=${#run}
|
||||
_zshell_put $((x+offset)) $((y+i-1)) $glyph "${line[1,$n]}"
|
||||
(( offset += n ))
|
||||
line=${line[$((n+1)),-1]}
|
||||
bands=${bands[$((n+1)),-1]}
|
||||
done
|
||||
done
|
||||
_zshell_put $((x+logo_width-2)) $((y+logo_height)) 1 '>_'
|
||||
if (( (px == 0 || px == span_x) && (py == 0 || py == span_y) )); then
|
||||
_zshell_put $((x-2)) $((y-1)) 3 '*'
|
||||
_zshell_put $((x+logo_width+1)) $((y-1)) 3 '*'
|
||||
_zshell_put $(( (width-17)/2 )) $((height-2)) 3 'corner committed!'
|
||||
else
|
||||
quips=( 'home is where the ~ is' 'plugins on a coffee break' 'a delightful little detour' 'your prompt will be right back' )
|
||||
line=${quips[$((1+tick/80%${#quips}))]}
|
||||
_zshell_put $(( (width-${#line})/2 )) $((height-2)) 0 "$line"
|
||||
fi
|
||||
_zshell_put 3 $height 0 'SCREENSAVER / LOGO'
|
||||
_zshell_put $((width-21)) $height 0 'any key: back to work'
|
||||
}
|
||||
|
||||
_zshell_hermit() {
|
||||
integer beat=$((tick/40%8)) within=$((tick%40)) shuffle=0 x y i
|
||||
local left_eye='(o )' right_eye='(o )' mouth='._.' thought='...' legs
|
||||
# Long, still looks make the tiny blinks and indecisive steps more visible.
|
||||
case $beat in
|
||||
0) thought='...where was I going?' ;;
|
||||
1) left_eye='( o)'; right_eye='( o)'; thought='...over there?' ;;
|
||||
2) left_eye='(O )'; right_eye='( O)'; mouth=' o '; thought='pwd...?' ;;
|
||||
3) left_eye='( o)'; right_eye='(o )'; mouth='-_-'; thought='I brought home. Now what?' ;;
|
||||
4) left_eye='( o)'; right_eye='( o)'; shuffle=$((within/10)); thought='maybe this way.' ;;
|
||||
5) left_eye='( o)'; right_eye='(o )'; shuffle=3; thought='wrong directory.' ;;
|
||||
6) shuffle=$((3-within/10)); thought='cd .. ?' ;;
|
||||
7) left_eye='( ^)'; right_eye='(^ )'; mouth=' u '; thought='~ sweet ~ ...wait.' ;;
|
||||
esac
|
||||
# Short blinks run independently of the longer expression cycle.
|
||||
if (( tick%73 >= 71 )); then left_eye='( -)'; right_eye='(- )'; fi
|
||||
x=$(( (width-42)/2 + shuffle ))
|
||||
y=$(( (height-12)/2 + 1 ))
|
||||
_zshell_put 3 2 1 'O H M Y Z S H'
|
||||
_zshell_put $((width-21)) 2 0 'a little shell-shocked'
|
||||
# Photo-inspired three-quarter silhouette: tapered shell whorls behind
|
||||
# the exposed head, unequal eyestalks, antennae and a hanging front claw.
|
||||
_zshell_sprite $x $y 3 \
|
||||
' __...---.' \
|
||||
" _.-' .--. '." \
|
||||
" .-' .' '. \\" \
|
||||
" .' _.-./ ~ \ |" \
|
||||
" / .' \ / |" \
|
||||
"/ / .-. |'-----' /" \
|
||||
'| ( ( @ ) / /' \
|
||||
"\ \ '-' .' .'" \
|
||||
" '-._'--'______.-'"
|
||||
# Staggered eyes on stalks; the small head emerges from the shell opening.
|
||||
_zshell_put $((x+25)) $((y+2)) 5 "$left_eye"
|
||||
_zshell_put $((x+32)) $((y+1)) 5 "$right_eye"
|
||||
_zshell_put $((x+27)) $((y+3)) 4 '|'
|
||||
_zshell_put $((x+27)) $((y+4)) 4 '|'
|
||||
_zshell_put $((x+33)) $((y+2)) 4 '/'
|
||||
_zshell_put $((x+32)) $((y+3)) 4 '/'
|
||||
_zshell_put $((x+31)) $((y+4)) 4 '/'
|
||||
_zshell_put $((x+36)) $((y+3)) 5 "_.-'"
|
||||
_zshell_put $((x+33)) $((y+4)) 5 ".-'"
|
||||
_zshell_put $((x+32)) $((y+5)) 5 '/'
|
||||
_zshell_put $((x+22)) $((y+5)) 4 '/___'
|
||||
_zshell_put $((x+21)) $((y+6)) 4 '\___'
|
||||
_zshell_put $((x+20)) $((y+7)) 4 '\__'
|
||||
_zshell_put $((x+26)) $((y+5)) 4 '.----.'
|
||||
_zshell_put $((x+25)) $((y+6)) 4 '/ \'
|
||||
_zshell_put $((x+23)) $((y+7)) 4 '__\______/'
|
||||
_zshell_put $((x+21)) $((y+8)) 4 '\___/ /\ \__'
|
||||
_zshell_put $((x+27)) $((y+6)) 5 "$mouth"
|
||||
# Legs bend down and forward instead of spreading symmetrically sideways.
|
||||
_zshell_put $((x+18)) $((y+9)) 4 '\___/ / \___'
|
||||
_zshell_put $((x+16)) $((y+10)) 4 '___/ / \'
|
||||
legs=' _/____/ \_'
|
||||
if (( (beat == 4 || beat == 6) && within/3%2 )); then
|
||||
legs=' /___/ _/'
|
||||
fi
|
||||
_zshell_put $x $((y+11)) 4 "$legs"
|
||||
# The big claw hangs in front. The much smaller claw tucks under the face.
|
||||
if (( beat == 3 )); then
|
||||
_zshell_sprite $((x+35)) $((y+7)) 4 ' __ ' '/ \' '| / |' ' V V '
|
||||
_zshell_put $((x+32)) $((y+6)) 4 '()'
|
||||
else
|
||||
_zshell_sprite $((x+35)) $((y+8)) 4 ' __ ' '/ \' '| / |' ' V V '
|
||||
_zshell_put $((x+30)) $((y+8)) 4 '()'
|
||||
fi
|
||||
if (( beat == 2 || beat == 5 )); then
|
||||
_zshell_put $((x+39)) $y 1 '?'
|
||||
fi
|
||||
if (( height >= 24 )); then
|
||||
for (( i=3; i<width-2; i+=5 )); do
|
||||
_zshell_put $i $((height-4)) 8 '.'
|
||||
done
|
||||
fi
|
||||
_zshell_put $(( (width-${#thought})/2 )) $((height-2)) 0 "$thought"
|
||||
_zshell_put 3 $height 0 'SCREENSAVER / HERMIT'
|
||||
_zshell_put $((width-21)) $height 0 'any key: back to home'
|
||||
}
|
||||
|
||||
_zshell_party() {
|
||||
integer x y i j row col sx sy glyph_width=5 scale=1 logo_width logo_x logo_y
|
||||
integer crowd count step pose bob sway base bars profile build stature outfit hair body_rows person_height leg_y
|
||||
local line bits letter pixel border
|
||||
local -a letters letter_colors rows heads builds statures hairstyles outfits
|
||||
local -A font
|
||||
# A tiny bitmap font gives the stage the chunky, rainbow look of the image.
|
||||
# Use ASCII pixels to keep the same width in every supported terminal font.
|
||||
font=(
|
||||
O '01110 10001 10001 10001 01110'
|
||||
H '10001 10001 11111 10001 10001'
|
||||
M '10001 11011 10101 10001 10001'
|
||||
Y '10001 01010 00100 00100 00100'
|
||||
Z '11111 00010 00100 01000 11111'
|
||||
S '01111 10000 01110 00001 11110'
|
||||
)
|
||||
if (( width < 64 )); then
|
||||
glyph_width=3
|
||||
font=( O '111 101 101 101 111' H '101 101 111 101 101'
|
||||
M '101 111 111 101 101' Y '101 101 010 010 010'
|
||||
Z '111 001 010 100 111' S '111 100 111 001 111' )
|
||||
elif (( width >= 120 )); then
|
||||
scale=2
|
||||
fi
|
||||
letters=( O H M Y Z S H )
|
||||
letter_colors=( 4 3 6 1 7 2 4 )
|
||||
logo_width=$(( (7*glyph_width+6+4)*scale ))
|
||||
logo_x=$(( (width-logo_width)/2+1 ))
|
||||
logo_y=$(( height/4 )); (( logo_y < 4 )) && logo_y=4
|
||||
|
||||
# A terminal window behind the crowd, including tiny window controls.
|
||||
border="+${(pl:$((width-8))::-:)}+"
|
||||
_zshell_put 4 2 5 "$border"
|
||||
_zshell_put 4 $((height-5)) 5 "$border"
|
||||
for (( y=3; y<height-5; y++ )); do
|
||||
_zshell_put 4 $y 5 '|'
|
||||
_zshell_put $((width-3)) $y 5 '|'
|
||||
done
|
||||
_zshell_put 7 2 0 ' O H M Y Z S H '
|
||||
_zshell_put $((width-10)) 2 4 'o'
|
||||
_zshell_put $((width-8)) 2 3 'o'
|
||||
_zshell_put $((width-6)) 2 6 'o'
|
||||
x=$logo_x
|
||||
for (( i=1; i<=7; i++ )); do
|
||||
letter=${letters[$i]}
|
||||
rows=( ${=font[$letter]} )
|
||||
for (( row=1; row<=5; row++ )); do
|
||||
bits=${rows[$row]}
|
||||
line=''
|
||||
for (( col=1; col<=glyph_width; col++ )); do
|
||||
pixel=' '; [[ ${bits[$col]} == 1 ]] && pixel='#'
|
||||
line+="${(pl:$scale::$pixel:)}"
|
||||
done
|
||||
_zshell_put $x $((logo_y+row-1)) ${letter_colors[$i]} "$line"
|
||||
done
|
||||
(( x += (glyph_width+1)*scale ))
|
||||
(( i == 2 || i == 4 )) && (( x += 2*scale ))
|
||||
done
|
||||
|
||||
# Small moving meters suggest music without sound or full-screen flashes.
|
||||
for (( i=0; i<10; i++ )); do
|
||||
bars=$((1+(tick/4+i*7)%3))
|
||||
x=$((logo_x+i*logo_width/10))
|
||||
for (( j=0; j<bars; j++ )); do
|
||||
_zshell_put $x $((logo_y+7-j)) 6 ':'
|
||||
done
|
||||
done
|
||||
|
||||
# Stable appearance profiles are independent of the dance cycle. Hair,
|
||||
# clothing, build and height vary separately rather than forming one type.
|
||||
builds=( 0 2 1 2 0 1 2 0 )
|
||||
statures=( 1 0 2 1 0 2 0 1 )
|
||||
hairstyles=( 0 1 2 3 4 1 0 2 )
|
||||
outfits=( 0 1 0 2 1 2 0 1 )
|
||||
count=$(( (width-2)/9 ))
|
||||
base=$(( (width-count*9)/2+1 ))
|
||||
for (( crowd=0; crowd<count; crowd++ )); do
|
||||
profile=$((crowd%8+1))
|
||||
build=${builds[$profile]} stature=${statures[$profile]}
|
||||
hair=${hairstyles[$profile]} outfit=${outfits[$profile]}
|
||||
body_rows=$((1+stature))
|
||||
person_height=$((5+body_rows))
|
||||
# Different tempos and offsets prevent synchronized, marching motion.
|
||||
step=$((tick/(3+crowd%3)+crowd*3))
|
||||
pose=$((step%4))
|
||||
bob=$((step%3 == 0))
|
||||
sway=$((pose == 1 ? 1 : 0))
|
||||
sx=$((base+crowd*9+sway))
|
||||
sy=$((height-3-person_height+bob))
|
||||
for (( row=0; row<person_height; row++ )); do
|
||||
_zshell_put $sx $((sy+row)) 0 ' '
|
||||
done
|
||||
case $hair in
|
||||
0) heads=( ' __ ' ' / \ ' ' \__/ ' ) ;;
|
||||
1) heads=( ' /~~\ ' '(| |)' '(|__|)' ) ;;
|
||||
2) heads=( ' .~~. ' '(: :)' ' \__/ ' ) ;;
|
||||
3) heads=( ' _()_ ' ' / \ ' ' \__/ ' ) ;;
|
||||
4) heads=( ' .--._' ' | |)' ' \__/ ' ) ;;
|
||||
esac
|
||||
_zshell_sprite $((sx+1)) $sy 5 "${heads[@]}"
|
||||
for (( row=0; row<body_rows; row++ )); do
|
||||
case $build in
|
||||
0) line=' | | ' ;;
|
||||
1) line=' | | ' ;;
|
||||
2) line=' | | ' ;;
|
||||
esac
|
||||
if (( row == body_rows-1 )); then
|
||||
case $build in
|
||||
0) line=' |_| ' ;;
|
||||
1) line=' |__| ' ;;
|
||||
2) line=' |____| ' ;;
|
||||
esac
|
||||
(( outfit == 1 )) && line=' /____\ '
|
||||
fi
|
||||
_zshell_put $sx $((sy+3+row)) 5 "$line"
|
||||
done
|
||||
# Longer hair continues beside the shoulders; outfits aren't tied to it.
|
||||
if (( hair == 1 && body_rows > 1 )); then
|
||||
_zshell_put $((sx+1)) $((sy+3)) 5 '|'
|
||||
_zshell_put $((sx+6)) $((sy+3)) 5 '|'
|
||||
fi
|
||||
leg_y=$((sy+3+body_rows))
|
||||
if (( outfit == 2 )); then
|
||||
if (( pose%2 )); then
|
||||
_zshell_sprite $sx $leg_y 5 ' | |\ \ ' ' |_/_\_\'
|
||||
else
|
||||
_zshell_sprite $sx $leg_y 5 ' | || | ' ' |_||_| '
|
||||
fi
|
||||
else
|
||||
case $pose in
|
||||
0) _zshell_sprite $sx $leg_y 5 ' / \ ' ' _/ \_ ' ;;
|
||||
1) _zshell_sprite $sx $leg_y 5 ' > / ' ' / /_ ' ;;
|
||||
2) _zshell_sprite $sx $leg_y 5 ' / < ' ' /_ \_ ' ;;
|
||||
3) _zshell_sprite $sx $leg_y 5 ' \ \ ' ' _\ _\ ' ;;
|
||||
esac
|
||||
fi
|
||||
# Arms animate around each silhouette, leaving hair and clothes stable.
|
||||
if (( pose == 1 || pose == 3 )); then
|
||||
_zshell_put $sx $sy 5 '\'
|
||||
_zshell_put $((sx+1)) $((sy+1)) 5 '\'
|
||||
_zshell_put $((sx+1)) $((sy+2)) 5 '|'
|
||||
else
|
||||
_zshell_put $((sx+1)) $((sy+3)) 5 '/'
|
||||
_zshell_put $sx $((sy+4)) 5 '/'
|
||||
fi
|
||||
if (( pose == 1 || pose == 2 )); then
|
||||
_zshell_put $((sx+7)) $sy 5 '/'
|
||||
_zshell_put $((sx+6)) $((sy+1)) 5 '/'
|
||||
_zshell_put $((sx+6)) $((sy+2)) 5 '|'
|
||||
else
|
||||
_zshell_put $((sx+6)) $((sy+3)) 5 '\'
|
||||
_zshell_put $((sx+7)) $((sy+4)) 5 '\'
|
||||
fi
|
||||
done
|
||||
_zshell_put 3 $height 0 'SCREENSAVER / PARTY'
|
||||
_zshell_put $((width-21)) $height 0 'any key: after-party'
|
||||
}
|
||||
|
||||
_zshell_scene() {
|
||||
integer y x i j base phase sway drift bob floor=$(( height - 5 ))
|
||||
local leaf bubble
|
||||
blank=${(pl:$width:: :)}
|
||||
canvas=() inks=()
|
||||
for (( y=1; y<=height; y++ )); do
|
||||
canvas+=( "$blank" )
|
||||
inks+=( "${(pl:$width::0:)}" )
|
||||
done
|
||||
if (( width < 48 || height < 18 )); then
|
||||
if [[ $scene == aquarium ]]; then
|
||||
_zshell_put 2 2 1 'A little more ocean, please.'
|
||||
else
|
||||
_zshell_put 2 2 1 'A little more room, please.'
|
||||
fi
|
||||
_zshell_put 2 4 0 'Resize to at least 49 x 18.'
|
||||
_zshell_put 2 6 0 'Any key returns to your shell.'
|
||||
return
|
||||
fi
|
||||
if [[ $scene == logo ]]; then
|
||||
_zshell_logo
|
||||
return
|
||||
elif [[ $scene == hermit ]]; then
|
||||
_zshell_hermit
|
||||
return
|
||||
elif [[ $scene == party ]]; then
|
||||
_zshell_party
|
||||
return
|
||||
fi
|
||||
|
||||
_zshell_put 3 2 1 'O H M Y Z S H'
|
||||
_zshell_put $((width-17)) 2 0 'a shell aquarium'
|
||||
_zshell_put 3 $height 0 'SCREENSAVER / AQUARIUM'
|
||||
_zshell_put $((width-22)) $height 0 'any key: back to shore'
|
||||
|
||||
# Tiny particles occupy the background; bubbles rise at different speeds.
|
||||
for (( i=0; i<width/7; i++ )); do
|
||||
x=$(( 2 + (i * 31 + tick / 24) % (width - 3) ))
|
||||
y=$(( 4 + (i * 11 + 3) % (floor - 5) ))
|
||||
_zshell_put $x $y 0 '.'
|
||||
done
|
||||
for (( i=0; i<5; i++ )); do
|
||||
y=$(( floor - 1 - (tick / (3 + i % 2) + i * 5) % (floor - 4) ))
|
||||
x=$(( 5 + (i * 23 + tick / 18 + (y % 3)) % (width - 9) ))
|
||||
bubble='o'
|
||||
(( (y+i) % 3 )) && bubble='.'
|
||||
_zshell_put $x $y 7 "$bubble"
|
||||
done
|
||||
|
||||
# Sand and tide marks.
|
||||
for (( x=2; x<width; x+=3 )); do
|
||||
_zshell_put $x $((floor+3)) 8 '.'
|
||||
(( x % 2 )) && _zshell_put $((x+1)) $((floor+2)) 8 '_'
|
||||
done
|
||||
for (( i=0; i<4; i++ )); do
|
||||
base=$(( i < 2 ? 3 + i * 4 : width - 4 - (i-2)*4 ))
|
||||
for (( j=0; j<4+i%2; j++ )); do
|
||||
sway=$(( (tick/7 + j + i) % 4 ))
|
||||
leaf=')'; (( sway > 1 )) && leaf='('
|
||||
_zshell_put $((base + (sway>1))) $((floor+1-j)) 6 "$leaf"
|
||||
done
|
||||
done
|
||||
|
||||
# Spirals ride a slow current. A triangle wave provides gentle vertical bob.
|
||||
drift=$(( (tick / 9) % (width + 18) ))
|
||||
x=$(( (width/4 + drift) % (width+18) - 9 ))
|
||||
phase=$(( tick/12 % 6 )); bob=$(( phase < 3 ? phase : 5-phase ))
|
||||
_zshell_sprite $x $((5+bob)) 2 ' __ ' ' /@/)' ' \_/'
|
||||
|
||||
# Nautilus moves in the opposite direction, tentacles trailing behind it.
|
||||
x=$(( (width*3/4 + width+20 - tick/6 % (width+20)) % (width+20) - 10 ))
|
||||
_zshell_sprite $x $((5+(tick/18%2))) 2 ' .---. ' ' / (@) \ ' ' \ __/~~' ' `" ~~'
|
||||
|
||||
# A fan shell closes briefly, then scoots during the same part of its cycle.
|
||||
phase=$(( tick % 100 ))
|
||||
drift=$(( (tick/100*4 + (phase>80 ? (phase-80)/5 : 0)) % (width+14) ))
|
||||
x=$(( (width/2 + drift) % (width+14) - 7 ))
|
||||
y=$(( floor-4 - (phase>80 && phase<95 ? 1 : 0) ))
|
||||
if (( phase > 80 )); then
|
||||
_zshell_sprite $x $y 4 ' _______ ' '(_______)' ' \/'
|
||||
else
|
||||
_zshell_sprite $x $y 4 ' .-----.' ' /|/|\|\' ' \|||||/' ' \___/'
|
||||
fi
|
||||
|
||||
# Conch and hermit crab live on different stretches of the seabed.
|
||||
x=$(( 7 + (width/5 + tick/24) % (width-22) ))
|
||||
_zshell_sprite $x $((floor-1)) 3 ' /\__' ' _/ / /\>' '(__/_/_)'
|
||||
x=$(( 8 + (width*2/3 + tick/10) % (width-22) ))
|
||||
if (( tick/5 % 2 )); then
|
||||
_zshell_sprite $x $((floor-1)) 5 ' .-~-. ' ' ( ~ )oo' ' _/___/\\_'
|
||||
else
|
||||
_zshell_sprite $x $((floor-1)) 5 ' .-~-. ' ' ( ~ )oo' ' /_/_/ /\'
|
||||
fi
|
||||
}
|
||||
|
||||
# Render color runs rather than individual cells. One write per frame and no
|
||||
# per-frame subprocesses; the final column stays unused to prevent autowrap.
|
||||
_zshell_render() {
|
||||
integer row n
|
||||
local text colors ink run
|
||||
result=${terminfo[home]}
|
||||
for (( row=1; row<=height; row++ )); do
|
||||
text=${canvas[$row]} colors=${inks[$row]}
|
||||
while [[ -n $colors ]]; do
|
||||
ink=${colors[1]}
|
||||
run=${colors%%[^$ink]*}
|
||||
n=${#run}
|
||||
result+="${palette[$((ink+1))]}${text[1,$n]}"
|
||||
text=${text[$((n+1)),-1]}
|
||||
colors=${colors[$((n+1)),-1]}
|
||||
done
|
||||
result+=${terminfo[el]}
|
||||
(( row < height )) && result+=$'\r\n'
|
||||
done
|
||||
result+=${terminfo[sgr0]}
|
||||
}
|
||||
|
||||
if (( snapshot )); then
|
||||
_zshell_scene
|
||||
print -r -- "${(F)canvas}"
|
||||
exit 0
|
||||
fi
|
||||
if [[ ! -t 0 || ! -t 1 || -z $TERM || $TERM == dumb ]]; then
|
||||
print -u2 -r -- 'omz shellsaver: run in an interactive terminal (or use --snapshot)'
|
||||
exit 1
|
||||
fi
|
||||
zmodload zsh/terminfo || exit 1
|
||||
zmodload zsh/datetime || exit 1
|
||||
local capability
|
||||
for capability in smcup rmcup home clear civis cnorm sgr0 el; do
|
||||
if [[ -z ${terminfo[$capability]} ]]; then
|
||||
print -u2 -r -- "omz shellsaver: terminal lacks $capability; try --snapshot"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if (( mono || ${+NO_COLOR} || ${terminfo[colors]:-0} < 8 )); then
|
||||
palette=( '' '' '' '' '' '' '' '' '' )
|
||||
elif (( ${terminfo[colors]} >= 256 )); then
|
||||
palette=( $'\e[38;5;60m' $'\e[38;5;159m' $'\e[38;5;183m'
|
||||
$'\e[38;5;222m' $'\e[38;5;210m' $'\e[38;5;230m'
|
||||
$'\e[38;5;72m' $'\e[38;5;110m' $'\e[38;5;137m' )
|
||||
else
|
||||
palette=( $'\e[34m' $'\e[36m' $'\e[35m' $'\e[33m' $'\e[31m'
|
||||
$'\e[37m' $'\e[32m' $'\e[36m' $'\e[33m' )
|
||||
fi
|
||||
|
||||
# Match the updater's exact truecolor and 256-color rainbow. The other
|
||||
# scenes retain their own palettes, and monochrome always takes precedence.
|
||||
if [[ $scene == logo ]] && (( !mono && !${+NO_COLOR} && ${terminfo[colors]:-0} >= 8 )); then
|
||||
local -a rainbow
|
||||
if [[ $COLORTERM == (truecolor|24bit) || $TERM == (iterm|tmux-truecolor|linux-truecolor|xterm-truecolor|screen-truecolor) ]]; then
|
||||
rainbow=( $'\e[38;2;255;0;0m' $'\e[38;2;255;97;0m' $'\e[38;2;247;255;0m'
|
||||
$'\e[38;2;0;255;30m' $'\e[38;2;77;0;255m' $'\e[38;2;168;0;255m'
|
||||
$'\e[38;2;245;0;172m' )
|
||||
elif (( ${terminfo[colors]} >= 256 )); then
|
||||
rainbow=( $'\e[38;5;196m' $'\e[38;5;202m' $'\e[38;5;226m'
|
||||
$'\e[38;5;082m' $'\e[38;5;021m' $'\e[38;5;093m' $'\e[38;5;163m' )
|
||||
else
|
||||
rainbow=( $'\e[31m' $'\e[33m' $'\e[33m' $'\e[32m' $'\e[34m' $'\e[35m' $'\e[35m' )
|
||||
fi
|
||||
integer color_index
|
||||
for (( color_index=1; color_index<=7; color_index++ )); do
|
||||
palette[$((color_index+1))]=${rainbow[$color_index]}
|
||||
done
|
||||
fi
|
||||
|
||||
_zshell_cleanup() {
|
||||
# Ignore handled signals throughout restoration, including in child stty.
|
||||
# Keep active set until both the screen and terminal modes are restored.
|
||||
trap '' INT TERM HUP QUIT TSTP WINCH
|
||||
(( active )) || return 0
|
||||
print -rn -- "${terminfo[sgr0]}${terminfo[cnorm]}${terminfo[rmcup]}"
|
||||
command stty "$saved_tty" 2>/dev/null
|
||||
active=0
|
||||
}
|
||||
_zshell_size() {
|
||||
local dimensions
|
||||
integer old_width=$width old_height=$height first=$resized
|
||||
dimensions=$(command stty size 2>/dev/null) || return 1
|
||||
local -a size=( ${=dimensions} )
|
||||
(( ${#size} == 2 && size[1] > 0 && size[2] > 1 )) || return 1
|
||||
height=$size[1] width=$((size[2]-1))
|
||||
# Very large terminals retain a calm, bounded scene in the top-left corner.
|
||||
(( width > 180 )) && width=180
|
||||
(( height > 55 )) && height=55
|
||||
resized=0
|
||||
if (( first || old_width != width || old_height != height )); then
|
||||
print -rn -- "${terminfo[clear]}"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
saved_tty=$(command stty -g) || exit 1
|
||||
trap '_zshell_cleanup' EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
trap 'exit 129' HUP
|
||||
trap 'exit 131' QUIT
|
||||
# Suspending a raw terminal would strand the parent prompt. Exit on Ctrl-Z.
|
||||
trap 'exit 148' TSTP
|
||||
trap 'resized=1' WINCH
|
||||
{
|
||||
active=1
|
||||
command stty -echo -icanon -ixon min 1 time 0 || exit 1
|
||||
print -rn -- "${terminfo[smcup]}${terminfo[civis]}"
|
||||
float started=$EPOCHREALTIME deadline wait_for next_size_check=0
|
||||
while true; do
|
||||
# Zsh can defer WINCH while a timed read is active. Poll at 2 Hz as well.
|
||||
if (( resized || EPOCHREALTIME >= next_size_check )); then
|
||||
_zshell_size || exit 1
|
||||
next_size_check=$(( EPOCHREALTIME + 0.5 ))
|
||||
fi
|
||||
tick=$(( (EPOCHREALTIME-started)*10 ))
|
||||
if (( seconds_limit && EPOCHREALTIME-started >= seconds_limit )); then break; fi
|
||||
deadline=$(( EPOCHREALTIME + 0.1 ))
|
||||
_zshell_scene
|
||||
_zshell_render
|
||||
print -rn -- "$result"
|
||||
wait_for=$(( deadline-EPOCHREALTIME ))
|
||||
(( wait_for < 0.005 )) && wait_for=0.005
|
||||
if read -r -k 1 -u 0 -t $wait_for key; then
|
||||
# Drain the entire key sequence or paste until input goes quiet, so no
|
||||
# queued suffix (including pasted commands) reaches the parent prompt.
|
||||
while read -r -k 1 -u 0 -t 0.01 key; do :; done
|
||||
break
|
||||
fi
|
||||
done
|
||||
} always {
|
||||
_zshell_cleanup
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
Reference in New Issue
Block a user