mirror of
https://github.com/robbyrussell/oh-my-zsh.git
synced 2026-09-28 05:56:07 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
419fc5e9b5 | ||
|
|
338a1131c8 |
@@ -12,7 +12,7 @@ dependencies:
|
|||||||
plugins/gradle:
|
plugins/gradle:
|
||||||
repo: gradle/gradle-completion
|
repo: gradle/gradle-completion
|
||||||
branch: master
|
branch: master
|
||||||
version: e7c881dbef7462bc35ad05328397e1582fe25cb8
|
version: 63578c9bc56134b80766e88957ba0239e6be2343
|
||||||
precopy: |
|
precopy: |
|
||||||
set -e
|
set -e
|
||||||
find . ! -name _gradle ! -name LICENSE -delete
|
find . ! -name _gradle ! -name LICENSE -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@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|||||||
@@ -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@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||||
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@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||||
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@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||||
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@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||||
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@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,6 @@ 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>
|
||||||
|
|
||||||
@@ -171,19 +163,6 @@ adds any) and extra goodies that are included in that particular plugin.
|
|||||||
|
|
||||||
### Themes
|
### Themes
|
||||||
|
|
||||||
Preview installed themes in your current directory without changing your prompt or `.zshrc`:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
omz theme browse # Interactive browser
|
|
||||||
omz theme browse agn # Start with a theme-name filter
|
|
||||||
omz theme preview agnoster # Print one isolated static preview
|
|
||||||
```
|
|
||||||
|
|
||||||
In the browser, type to filter, use Up/Down or Ctrl-P/Ctrl-N to navigate, and press Enter
|
|
||||||
for explicit use/save actions. Esc or Ctrl-C cancels without applying a theme.
|
|
||||||
See the [theme browser guide](tools/theme-browser/README.md) for shortcuts, preview limitations,
|
|
||||||
and local testing instructions.
|
|
||||||
|
|
||||||
We'll admit it. Early in the Oh My Zsh world, we may have gotten a bit too theme-happy. We have over one
|
We'll admit it. Early in the Oh My Zsh world, we may have gotten a bit too theme-happy. We have over one
|
||||||
hundred and fifty themes now bundled. Most of them have
|
hundred and fifty themes now bundled. Most of them have
|
||||||
[screenshots](https://github.com/ohmyzsh/ohmyzsh/wiki/Themes) on the wiki (We are working on updating this!).
|
[screenshots](https://github.com/ohmyzsh/ohmyzsh/wiki/Themes) on the wiki (We are working on updating this!).
|
||||||
|
|||||||
+1
-46
@@ -51,7 +51,7 @@ function _omz {
|
|||||||
_describe 'command' subcmds ;;
|
_describe 'command' subcmds ;;
|
||||||
pr) subcmds=('clean:Delete all Pull Request branches' 'test:Test a Pull Request')
|
pr) subcmds=('clean:Delete all Pull Request branches' 'test:Test a Pull Request')
|
||||||
_describe 'command' subcmds ;;
|
_describe 'command' subcmds ;;
|
||||||
theme) subcmds=('browse:Browse theme previews' 'preview:Preview a theme without applying it' 'list:List themes' 'set:Set a theme in your .zshrc file' 'use:Load a theme')
|
theme) subcmds=('list:List themes' 'set:Set a theme in your .zshrc file' 'use:Load a theme')
|
||||||
_describe 'command' subcmds ;;
|
_describe 'command' subcmds ;;
|
||||||
esac
|
esac
|
||||||
elif (( CURRENT == 4 )); then
|
elif (( CURRENT == 4 )); then
|
||||||
@@ -77,10 +77,6 @@ function _omz {
|
|||||||
local -a opts
|
local -a opts
|
||||||
opts=('--enabled:List enabled plugins only')
|
opts=('--enabled:List enabled plugins only')
|
||||||
_describe -o 'options' opts ;;
|
_describe -o 'options' opts ;;
|
||||||
theme::(browse|preview))
|
|
||||||
local -a themes
|
|
||||||
themes=("${(@f)$(source "$ZSH/tools/theme-browser/preview.zsh"; _omz_theme_names)}")
|
|
||||||
_describe 'theme' themes ;;
|
|
||||||
theme::(set|use))
|
theme::(set|use))
|
||||||
local -aU themes
|
local -aU themes
|
||||||
themes=("$ZSH"/themes/*.zsh-theme(-.N:t:r) "$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::))
|
themes=("$ZSH"/themes/*.zsh-theme(-.N:t:r) "$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::))
|
||||||
@@ -753,8 +749,6 @@ Usage: ${(j: :)${(s.::.)0#_}} <command> [options]
|
|||||||
|
|
||||||
Available commands:
|
Available commands:
|
||||||
|
|
||||||
browse [filter] Browse installed themes without applying them
|
|
||||||
preview <theme> Preview a theme in the current directory
|
|
||||||
list List all available Oh My Zsh themes
|
list List all available Oh My Zsh themes
|
||||||
set <theme> Set a theme in your .zshrc file
|
set <theme> Set a theme in your .zshrc file
|
||||||
use <theme> Load a theme
|
use <theme> Load a theme
|
||||||
@@ -769,45 +763,6 @@ EOF
|
|||||||
$0::$command "$@"
|
$0::$command "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function _omz::theme::preview {
|
|
||||||
if (( $# != 1 )); then
|
|
||||||
print -u2 -r -- 'Usage: omz theme preview <theme>'
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
source "$ZSH/tools/theme-browser/preview.zsh"
|
|
||||||
_omz_theme_preview "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
function _omz::theme::browse {
|
|
||||||
if (( $# > 1 )); then
|
|
||||||
print -u2 -r -- 'Usage: omz theme browse [filter]'
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if [[ ! -o interactive || ! -t 0 || ! -t 1 ]]; then
|
|
||||||
print -u2 -r -- 'omz theme browse requires an interactive terminal; use omz theme preview <theme> instead.'
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
source "$ZSH/tools/theme-browser/preview.zsh"
|
|
||||||
source "$ZSH/tools/theme-browser/browser.zsh"
|
|
||||||
local selection action name
|
|
||||||
selection=$(_omz_theme_browser "$1") || return $?
|
|
||||||
[[ -n $selection ]] || return 0
|
|
||||||
action=${selection%%$'\n'*}
|
|
||||||
name=${selection#*$'\n'}
|
|
||||||
_omz_theme_resolve "$name" >/dev/null || return 1
|
|
||||||
case $action in
|
|
||||||
use) _omz::theme::use "$name" ;;
|
|
||||||
set)
|
|
||||||
# The existing set command interpolates the name into shell and awk text.
|
|
||||||
[[ $name != *[^a-zA-Z0-9_./-]* ]] || {
|
|
||||||
print -u2 -r -- 'Cannot save this theme name safely; set ZSH_THEME manually.'
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
_omz::theme::set "$name" ;;
|
|
||||||
*) return 1 ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function _omz::theme::list {
|
function _omz::theme::list {
|
||||||
local -a custom_themes builtin_themes
|
local -a custom_themes builtin_themes
|
||||||
custom_themes=("$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::))
|
custom_themes=("$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::))
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-17
@@ -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
|
||||||
[[ -d "$ZSH_CACHE_DIR/completions" ]] || mkdir -p "$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...
|
||||||
@@ -114,17 +114,9 @@ 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
|
||||||
zcompdump_refresh=0
|
if ! command grep -q -Fx "$zcompdump_revision" "$ZSH_COMPDUMP" 2>/dev/null \
|
||||||
if ! _omz_compdump_has_metadata; then
|
|| ! command grep -q -Fx "$zcompdump_fpath" "$ZSH_COMPDUMP" 2>/dev/null; then
|
||||||
command rm -f "$ZSH_COMPDUMP"
|
command rm -f "$ZSH_COMPDUMP"
|
||||||
zcompdump_refresh=1
|
zcompdump_refresh=1
|
||||||
fi
|
fi
|
||||||
@@ -142,8 +134,9 @@ else
|
|||||||
compinit -u -d "$ZSH_COMPDUMP"
|
compinit -u -d "$ZSH_COMPDUMP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Append zcompdump metadata if missing (compinit may have regenerated the file)
|
# Append zcompdump metadata if missing
|
||||||
if (( zcompdump_refresh )) || ! _omz_compdump_has_metadata; then
|
if (( $zcompdump_refresh )) \
|
||||||
|
|| ! 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
|
||||||
@@ -153,12 +146,9 @@ $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.
|
||||||
# Test that first so the lock directory and zrecompile are skipped when it's fresh.
|
if command mkdir "${ZSH_COMPDUMP}.lock" 2>/dev/null; then
|
||||||
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
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ function asr() {
|
|||||||
local -a available_regions
|
local -a available_regions
|
||||||
available_regions=($(aws_regions))
|
available_regions=($(aws_regions))
|
||||||
if [[ -z "${available_regions[(r)$1]}" ]]; then
|
if [[ -z "${available_regions[(r)$1]}" ]]; then
|
||||||
echo "${fg[red]}Available regions: \n$(aws_regions)${reset_color}" >&2
|
echo "${fg[red]}Available regions: \n$(aws_regions)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
# Grafana CLI plugin
|
|
||||||
|
|
||||||
This plugin adds completion for the [Grafana CLI (gcx)](https://github.com/grafana/gcx).
|
|
||||||
|
|
||||||
To use it, add `gcx` to the plugins array in your zshrc file:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
plugins=(... gcx)
|
|
||||||
```
|
|
||||||
|
|
||||||
This plugin does not add any aliases.
|
|
||||||
|
|
||||||
## 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/_gcx`.
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Autocompletion for the Grafana CLI (gcx).
|
|
||||||
if (( ! $+commands[gcx] )); then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If the completion file doesn't exist yet, we need to autoload it and
|
|
||||||
# bind it to `gcx`. Otherwise, compinit will have already done that.
|
|
||||||
if [[ ! -f "$ZSH_CACHE_DIR/completions/_gcx" ]]; then
|
|
||||||
typeset -g -A _comps
|
|
||||||
autoload -Uz _gcx
|
|
||||||
_comps[gcx]=_gcx
|
|
||||||
fi
|
|
||||||
|
|
||||||
zmodload -F zsh/files b:zf_mv
|
|
||||||
() {
|
|
||||||
local TMPPREFIX="$ZSH_CACHE_DIR/completions/_gcx"
|
|
||||||
zf_mv -f -- =( gcx completion zsh ) "$TMPPREFIX"
|
|
||||||
} &|
|
|
||||||
@@ -39,18 +39,3 @@ 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
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -36,12 +36,3 @@ 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}"
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-10
@@ -284,9 +284,6 @@ __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=[]' \
|
||||||
@@ -302,6 +299,8 @@ __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'.]' \
|
||||||
@@ -329,14 +328,12 @@ __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.]' \
|
||||||
@@ -424,9 +421,6 @@ _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' \
|
||||||
@@ -442,6 +436,8 @@ _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' \
|
||||||
@@ -470,14 +466,12 @@ _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.]' \
|
||||||
|
|||||||
@@ -19,54 +19,35 @@ plugins=(... jj)
|
|||||||
| jjbd | `jj bookmark delete` |
|
| jjbd | `jj bookmark delete` |
|
||||||
| jjbf | `jj bookmark forget` |
|
| jjbf | `jj bookmark forget` |
|
||||||
| jjbl | `jj bookmark list` |
|
| jjbl | `jj bookmark list` |
|
||||||
| jjblt | `jj bookmark list --tracked` |
|
|
||||||
| jjbm | `jj bookmark move` |
|
| jjbm | `jj bookmark move` |
|
||||||
| jjbr | `jj bookmark rename` |
|
| jjbr | `jj bookmark rename` |
|
||||||
| jjbs | `jj bookmark set` |
|
| jjbs | `jj bookmark set` |
|
||||||
| jjbt | `jj bookmark track` |
|
| jjbt | `jj bookmark track` |
|
||||||
| jjbu | `jj bookmark untrack` |
|
| jjbu | `jj bookmark untrack` |
|
||||||
| jjc | `jj commit` |
|
| jjc | `jj commit` |
|
||||||
| jjcfg | `jj config` |
|
|
||||||
| jjcfgl | `jj config list` |
|
|
||||||
| jjcmsg | `jj commit --message` |
|
| jjcmsg | `jj commit --message` |
|
||||||
| jjd | `jj diff` |
|
| jjd | `jj diff` |
|
||||||
| jjdmsg | `jj desc --message` |
|
| jjdmsg | `jj desc --message` |
|
||||||
| jjds | `jj desc` |
|
| jjds | `jj desc` |
|
||||||
| jjdst | `jj diff --stat` |
|
|
||||||
| jje | `jj edit` |
|
| jje | `jj edit` |
|
||||||
| jjev | `jj evolog` |
|
|
||||||
| jjf | `jj file` |
|
|
||||||
| jjfl | `jj file list` |
|
|
||||||
| jjg | `jj git` |
|
|
||||||
| jjgcl | `jj git clone` |
|
| jjgcl | `jj git clone` |
|
||||||
| jjgf | `jj git fetch` |
|
| jjgf | `jj git fetch` |
|
||||||
| jjgfa | `jj git fetch --all-remotes` |
|
| jjgfa | `jj git fetch --all-remotes` |
|
||||||
| jjgi | `jj git init` |
|
|
||||||
| jjgp | `jj git push` |
|
| jjgp | `jj git push` |
|
||||||
| jjgpa | `jj git push --all` |
|
| jjgpa | `jj git push --all` |
|
||||||
| jjgpd | `jj git push --deleted` |
|
| jjgpd | `jj git push --deleted` |
|
||||||
| jjgpt | `jj git push --tracked` |
|
| jjgpt | `jj git push --tracked` |
|
||||||
| jjgrl | `jj git remote list` |
|
|
||||||
| jjl | `jj log` |
|
| jjl | `jj log` |
|
||||||
| jjla | `jj log -r "all()"` |
|
| jjla | `jj log -r "all()"` |
|
||||||
| jjn | `jj new` |
|
| jjn | `jj new` |
|
||||||
| jjnt | `jj new "trunk()"` |
|
| jjnt | `jj new "trunk()"` |
|
||||||
| jjop | `jj op` |
|
|
||||||
| jjopl | `jj op log` |
|
|
||||||
| jjor | `jj op restore` |
|
|
||||||
| jjrb | `jj rebase` |
|
| jjrb | `jj rebase` |
|
||||||
| jjrbm | `jj rebase -d "trunk()"` |
|
| jjrbm | `jj rebase -d "trunk()"` |
|
||||||
| jjrs | `jj restore` |
|
| jjrs | `jj restore` |
|
||||||
| jjrt | `cd "$(jj root \|\| echo .)"` |
|
| jjrt | `cd "$(jj root \|\| echo .)"` |
|
||||||
| jjs | `jj show` |
|
|
||||||
| jjsp | `jj split` |
|
| jjsp | `jj split` |
|
||||||
| jjsq | `jj squash` |
|
| jjsq | `jj squash` |
|
||||||
| jjst | `jj status` |
|
| jjst | `jj status` |
|
||||||
| jju | `jj undo` |
|
|
||||||
| jjw | `jj workspace` |
|
|
||||||
| jjwa | `jj workspace add` |
|
|
||||||
| jjwf | `jj workspace forget` |
|
|
||||||
| jjwl | `jj workspace list` |
|
|
||||||
|
|
||||||
## Prompt usage
|
## Prompt usage
|
||||||
|
|
||||||
|
|||||||
@@ -45,51 +45,34 @@ alias jjbc='jj bookmark create'
|
|||||||
alias jjbd='jj bookmark delete'
|
alias jjbd='jj bookmark delete'
|
||||||
alias jjbf='jj bookmark forget'
|
alias jjbf='jj bookmark forget'
|
||||||
alias jjbl='jj bookmark list'
|
alias jjbl='jj bookmark list'
|
||||||
alias jjblt='jj bookmark list --tracked'
|
|
||||||
alias jjbm='jj bookmark move'
|
alias jjbm='jj bookmark move'
|
||||||
alias jjbr='jj bookmark rename'
|
alias jjbr='jj bookmark rename'
|
||||||
alias jjbs='jj bookmark set'
|
alias jjbs='jj bookmark set'
|
||||||
alias jjbt='jj bookmark track'
|
alias jjbt='jj bookmark track'
|
||||||
alias jjbu='jj bookmark untrack'
|
alias jjbu='jj bookmark untrack'
|
||||||
alias jjc='jj commit'
|
alias jjc='jj commit'
|
||||||
alias jjcfg='jj config'
|
|
||||||
alias jjcfgl='jj config list'
|
|
||||||
alias jjcmsg='jj commit --message'
|
alias jjcmsg='jj commit --message'
|
||||||
alias jjd='jj diff'
|
alias jjd='jj diff'
|
||||||
alias jjdmsg='jj desc --message'
|
alias jjdmsg='jj desc --message'
|
||||||
alias jjds='jj desc'
|
alias jjds='jj desc'
|
||||||
alias jjdst='jj diff --stat'
|
|
||||||
alias jje='jj edit'
|
alias jje='jj edit'
|
||||||
alias jjev='jj evolog'
|
|
||||||
alias jjf='jj file'
|
|
||||||
alias jjfl='jj file list'
|
|
||||||
alias jjg='jj git'
|
|
||||||
alias jjgcl='jj git clone'
|
alias jjgcl='jj git clone'
|
||||||
alias jjgf='jj git fetch'
|
alias jjgf='jj git fetch'
|
||||||
alias jjgfa='jj git fetch --all-remotes'
|
alias jjgfa='jj git fetch --all-remotes'
|
||||||
alias jjgi='jj git init'
|
|
||||||
alias jjgp='jj git push'
|
alias jjgp='jj git push'
|
||||||
alias jjgpa='jj git push --all'
|
alias jjgpa='jj git push --all'
|
||||||
alias jjgpd='jj git push --deleted'
|
alias jjgpd='jj git push --deleted'
|
||||||
alias jjgpt='jj git push --tracked'
|
alias jjgpt='jj git push --tracked'
|
||||||
alias jjgrl='jj git remote list'
|
|
||||||
alias jjl='jj log'
|
alias jjl='jj log'
|
||||||
alias jjla='jj log -r "all()"'
|
alias jjla='jj log -r "all()"'
|
||||||
alias jjn='jj new'
|
alias jjn='jj new'
|
||||||
alias jjnt='jj new "trunk()"'
|
alias jjnt='jj new "trunk()"'
|
||||||
alias jjop='jj op'
|
|
||||||
alias jjopl='jj op log'
|
|
||||||
alias jjor='jj op restore'
|
|
||||||
alias jjrb='jj rebase'
|
alias jjrb='jj rebase'
|
||||||
alias jjrbm='jj rebase -d "trunk()"'
|
alias jjrbm='jj rebase -d "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 jjsp='jj split'
|
alias jjsp='jj split'
|
||||||
alias jjsq='jj squash'
|
alias jjsq='jj squash'
|
||||||
alias jjst='jj status'
|
alias jjst='jj status'
|
||||||
alias jju='jj undo'
|
|
||||||
alias jjw='jj workspace'
|
|
||||||
alias jjwa='jj workspace add'
|
alias jjwa='jj workspace add'
|
||||||
alias jjwf='jj workspace forget'
|
alias jjwf='jj workspace forget'
|
||||||
alias jjwl='jj workspace list'
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ 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'
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ plugins=(... kubectl)
|
|||||||
| | | **Secret management** |
|
| | | **Secret management** |
|
||||||
| kgsec | `kubectl get secret` | Get secret for decoding |
|
| kgsec | `kubectl get secret` | Get secret for decoding |
|
||||||
| kgseca | `kubectl get secret --all-namespaces` | List secrets across all namespaces |
|
| kgseca | `kubectl get secret --all-namespaces` | List secrets across all namespaces |
|
||||||
| kesec | `kubectl edit secret` | Edit secret resource |
|
|
||||||
| kdsec | `kubectl describe secret` | Describe secret resource in detail |
|
| kdsec | `kubectl describe secret` | Describe secret resource in detail |
|
||||||
| kdelsec | `kubectl delete secret` | Delete the secret |
|
| kdelsec | `kubectl delete secret` | Delete the secret |
|
||||||
| | | **Deployment management** |
|
| | | **Deployment management** |
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ alias kdelcm='kubectl delete configmap'
|
|||||||
# Secret management
|
# Secret management
|
||||||
alias kgsec='kubectl get secret'
|
alias kgsec='kubectl get secret'
|
||||||
alias kgseca='kubectl get secret --all-namespaces'
|
alias kgseca='kubectl get secret --all-namespaces'
|
||||||
alias kesec='kubectl edit secret'
|
|
||||||
alias kdsec='kubectl describe secret'
|
alias kdsec='kubectl describe secret'
|
||||||
alias kdelsec='kubectl delete secret'
|
alias kdelsec='kubectl delete secret'
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ plugins=(... laravel)
|
|||||||
| `pamen` | `php artisan make:enum` |
|
| `pamen` | `php artisan make:enum` |
|
||||||
| `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` |
|
|
||||||
| `pammig` | `php artisan make:migration` |
|
|
||||||
|
|
||||||
## Clears
|
## Clears
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ alias pamcl='php artisan make:class'
|
|||||||
alias pamen='php artisan make:enum'
|
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 pammig='php artisan make:migration'
|
|
||||||
|
|
||||||
|
|
||||||
# Clears
|
# Clears
|
||||||
|
|||||||
@@ -56,26 +56,19 @@ if zstyle -T ':omz:plugins:pipenv' auto-shell; then
|
|||||||
# deactivate shell if Pipfile doesn't exist and not in a subdir
|
# deactivate shell if Pipfile doesn't exist and not in a subdir
|
||||||
if [[ ! -f "$PWD/Pipfile" ]]; then
|
if [[ ! -f "$PWD/Pipfile" ]]; then
|
||||||
if [[ "$PIPENV_ACTIVE" == 1 ]]; then
|
if [[ "$PIPENV_ACTIVE" == 1 ]]; then
|
||||||
# Compare whole path components: `$pipfile_dir"*` also matches unrelated
|
if [[ "$PWD" != "$pipfile_dir"* ]]; then
|
||||||
# siblings that merely start with the same text (…/proj -> …/proj-docs),
|
|
||||||
# which would keep the virtualenv active outside the project.
|
|
||||||
local project_dir="${pipfile_dir%/}"
|
|
||||||
if [[ "$PWD" != "$project_dir" && "$PWD" != "$project_dir"/* ]]; then
|
|
||||||
unset PIPENV_ACTIVE pipfile_dir
|
unset PIPENV_ACTIVE pipfile_dir
|
||||||
deactivate
|
deactivate
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# activate the shell if Pipfile exists and its virtualenv is usable
|
# activate the shell if Pipfile exists
|
||||||
if [[ "$PIPENV_ACTIVE" != 1 ]]; then
|
if [[ "$PIPENV_ACTIVE" != 1 ]]; then
|
||||||
if [[ -f "$PWD/Pipfile" ]]; then
|
if [[ -f "$PWD/Pipfile" ]]; then
|
||||||
local venv_path
|
export pipfile_dir="$PWD"
|
||||||
if venv_path="$(pipenv --venv 2>/dev/null)" && [[ -n "$venv_path" && -f "$venv_path/bin/activate" ]]; then
|
source "$(pipenv --venv)/bin/activate"
|
||||||
export pipfile_dir="$PWD"
|
export PIPENV_ACTIVE=1
|
||||||
source "$venv_path/bin/activate"
|
|
||||||
export PIPENV_ACTIVE=1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
# Poetry Environment Plugin
|
# Poetry Environment Plugin
|
||||||
|
|
||||||
This plugin automatically activates a Poetry environment when you enter a
|
This plugin automatically changes poetry environment when you cd into or out of the project directory.
|
||||||
directory containing both `pyproject.toml` and `poetry.lock`. It keeps the
|
Note: Script looks for pyproject.toml file to determine poetry if its a poetry environment
|
||||||
environment active in project subdirectories, switches to nested Poetry
|
|
||||||
projects, and deactivates it when you leave the project tree.
|
|
||||||
|
|
||||||
To use it, add `poetry-env` to the plugins array in your zshrc file:
|
To use it, add `poetry-env` to the plugins array in your zshrc file:
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,20 @@
|
|||||||
_togglePoetryShell() {
|
_togglePoetryShell() {
|
||||||
# Determine if currently in a Poetry-managed directory
|
# Determine if currently in a Poetry-managed directory
|
||||||
local in_poetry_dir=0
|
local in_poetry_dir=0
|
||||||
local in_active_poetry_dir=0
|
|
||||||
if [[ -f "$PWD/pyproject.toml" && -f "$PWD/poetry.lock" ]]; then
|
if [[ -f "$PWD/pyproject.toml" && -f "$PWD/poetry.lock" ]]; then
|
||||||
in_poetry_dir=1
|
in_poetry_dir=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Deactivate when leaving the active project or entering a nested project
|
# Deactivate the current environment if moving out of a Poetry directory or into a different Poetry directory
|
||||||
if [[ $poetry_active -eq 1 ]]; then
|
if [[ $poetry_active -eq 1 ]] && { [[ $in_poetry_dir -eq 0 ]] || [[ "$PWD" != "$poetry_dir"* ]]; }; then
|
||||||
local project_dir="${poetry_dir%/}"
|
export poetry_active=0
|
||||||
if [[ "$PWD" == "$project_dir" || "$PWD" == "$project_dir"/* ]]; then
|
unset poetry_dir
|
||||||
in_active_poetry_dir=1
|
(( $+functions[deactivate] )) && deactivate
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $in_active_poetry_dir -eq 0 ]] ||
|
|
||||||
{ [[ $in_poetry_dir -eq 1 ]] && [[ "$PWD" != "$poetry_dir" ]]; }; then
|
|
||||||
export poetry_active=0
|
|
||||||
unset poetry_dir
|
|
||||||
(( $+functions[deactivate] )) && deactivate
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 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
|
||||||
local venv_dir=$(poetry env info --path 2>/dev/null)
|
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"
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
# ruff plugin
|
|
||||||
|
|
||||||
This plugin automatically installs [ruff](https://github.com/astral-sh/ruff)'s completions for you,
|
|
||||||
and keeps them up to date. It also adds convenient aliases for common usage.
|
|
||||||
|
|
||||||
To use it, add `ruff` to the plugins array in your zshrc file:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
plugins=(... ruff)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Aliases
|
|
||||||
|
|
||||||
| Alias | Command | Description |
|
|
||||||
| :---- | -------------------- | :----------------------------------------------------------- |
|
|
||||||
| ruc | `ruff check` | Run Ruff linter on the given files or directories |
|
|
||||||
| rucf | `ruff check --fix` | Run Ruff linter and fix auto-fixable issues |
|
|
||||||
| ruf | `ruff format` | Run the Ruff formatter on the given files or directories |
|
|
||||||
| rufc | `ruff format --check`| Check if files are already formatted without making changes |
|
|
||||||
| rur | `ruff rule` | Explain a rule (or all rules) |
|
|
||||||
| rul | `ruff linter` | List all supported upstream linters |
|
|
||||||
| rucl | `ruff clean` | Clear any caches in the current directory and subdirectories |
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Return immediately if ruff is not found
|
|
||||||
if (( ! ${+commands[ruff]} )); then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
alias ruc='ruff check'
|
|
||||||
alias rucf='ruff check --fix'
|
|
||||||
alias ruf='ruff format'
|
|
||||||
alias rufc='ruff format --check'
|
|
||||||
alias rur='ruff rule'
|
|
||||||
alias rul='ruff linter'
|
|
||||||
alias rucl='ruff clean'
|
|
||||||
|
|
||||||
# If the completion file doesn't exist yet, we need to autoload it and
|
|
||||||
# bind it. Otherwise, compinit will have already done that.
|
|
||||||
if [[ ! -f "$ZSH_CACHE_DIR/completions/_ruff" ]]; then
|
|
||||||
typeset -g -A _comps
|
|
||||||
autoload -Uz _ruff
|
|
||||||
_comps[ruff]=_ruff
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Overwrites the file each time as completions might change with ruff versions.
|
|
||||||
zmodload -F zsh/files b:zf_mv
|
|
||||||
() {
|
|
||||||
local TMPPREFIX="$ZSH_CACHE_DIR/completions/_ruff"
|
|
||||||
zf_mv -f -- =( ruff generate-shell-completion zsh ) "$TMPPREFIX"
|
|
||||||
} &|
|
|
||||||
@@ -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,204 @@
|
|||||||
|
# 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" ]] ||
|
||||||
|
[[ -f "$dir/package.json" && "$(<"$dir/package.json")" == *'"@shopify/hydrogen"'* ]]; then
|
||||||
|
print -r -- hydrogen
|
||||||
|
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'
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
ssm_run_sudo() {sudo $_sublime_merge_path "$@" >/dev/null 2>&1}
|
ssm_run_sudo() {sudo $_sublime_merge_path "$@" >/dev/null 2>&1}
|
||||||
alias ssm=ssm_run_sudo
|
alias ssm=ssm_run_sudo
|
||||||
alias sm=sm_run
|
alias sm=sm_run
|
||||||
alias smerge="'$_sublime_merge_path'"
|
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -34,7 +33,6 @@
|
|||||||
if [[ -a $_sublime_merge_path ]]; then
|
if [[ -a $_sublime_merge_path ]]; then
|
||||||
subm () { "$_sublime_merge_path" "$@" }
|
subm () { "$_sublime_merge_path" "$@" }
|
||||||
alias sm=subm
|
alias sm=subm
|
||||||
alias smerge="'$_sublime_merge_path'"
|
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -47,7 +45,6 @@
|
|||||||
if [[ -a $_sublime_merge_path ]]; then
|
if [[ -a $_sublime_merge_path ]]; then
|
||||||
subm () { "$_sublime_merge_path" "$@" }
|
subm () { "$_sublime_merge_path" "$@" }
|
||||||
alias sm=subm
|
alias sm=subm
|
||||||
alias smerge="'$_sublime_merge_path'"
|
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
# - https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Console/Resources/completion.bash
|
# - https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Console/Resources/completion.bash
|
||||||
#
|
#
|
||||||
_sf_console() {
|
_sf_console() {
|
||||||
local lastParam out comp sf_cmd
|
local lastParam flagPrefix requestComp out comp
|
||||||
local -a completions flagPrefix requestComp inputs
|
local -a completions
|
||||||
|
|
||||||
# The user could have moved the cursor backwards on the command-line.
|
# The user could have moved the cursor backwards on the command-line.
|
||||||
# We need to trigger completion from the $CURRENT location, so we need
|
# We need to trigger completion from the $CURRENT location, so we need
|
||||||
@@ -29,20 +29,11 @@ _sf_console() {
|
|||||||
setopt local_options BASH_REMATCH
|
setopt local_options BASH_REMATCH
|
||||||
if [[ "${lastParam}" =~ '-.*=' ]]; then
|
if [[ "${lastParam}" =~ '-.*=' ]]; then
|
||||||
# We are dealing with a flag with an =
|
# We are dealing with a flag with an =
|
||||||
flagPrefix=(-P "${BASH_REMATCH}")
|
flagPrefix="-P ${BASH_REMATCH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Prepare the command to obtain completions. An alias is resolved here,
|
# Prepare the command to obtain completions
|
||||||
# because the request is no longer read again by the shell.
|
requestComp="${words[0]} ${words[1]} _complete --no-interaction -szsh -a1 -c$((CURRENT-1))" i=""
|
||||||
sf_cmd="${words[1]}"
|
|
||||||
if [[ -n "${aliases[$sf_cmd]}" ]]; then
|
|
||||||
requestComp=(${(z)aliases[$sf_cmd]})
|
|
||||||
else
|
|
||||||
requestComp=(${~sf_cmd})
|
|
||||||
fi
|
|
||||||
|
|
||||||
requestComp+=(_complete --no-interaction -szsh -a1 "-c$((CURRENT-1))")
|
|
||||||
|
|
||||||
for w in ${words[@]}; do
|
for w in ${words[@]}; do
|
||||||
w=$(printf -- '%b' "$w")
|
w=$(printf -- '%b' "$w")
|
||||||
# remove quotes from typed values
|
# remove quotes from typed values
|
||||||
@@ -56,18 +47,19 @@ _sf_console() {
|
|||||||
fi
|
fi
|
||||||
# empty values are ignored
|
# empty values are ignored
|
||||||
if [ ! -z "$w" ]; then
|
if [ ! -z "$w" ]; then
|
||||||
inputs+=("-i$w")
|
i="${i}-i${w} "
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Ensure at least 1 input
|
# Ensure at least 1 input
|
||||||
if (( ! $#inputs )); then
|
if [ "${i}" = "" ]; then
|
||||||
inputs=(-i' ')
|
requestComp="${requestComp} -i\" \""
|
||||||
|
else
|
||||||
|
requestComp="${requestComp} ${i}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The request is run without being read again by the shell, so that a
|
# Use eval to handle any environment variables and such
|
||||||
# "$(...)" or a backtick typed on the command line is not executed
|
out=$(eval ${requestComp} 2>/dev/null)
|
||||||
out=$(SHELL_VERBOSITY=0 "${requestComp[@]}" "${inputs[@]}" 2>/dev/null)
|
|
||||||
|
|
||||||
while IFS='\n' read -r comp; do
|
while IFS='\n' read -r comp; do
|
||||||
if [ -n "$comp" ]; then
|
if [ -n "$comp" ]; then
|
||||||
@@ -83,7 +75,7 @@ _sf_console() {
|
|||||||
done < <(printf "%s\n" "${out[@]}")
|
done < <(printf "%s\n" "${out[@]}")
|
||||||
|
|
||||||
# Let inbuilt _describe handle completions
|
# Let inbuilt _describe handle completions
|
||||||
_describe "completions" completions "${flagPrefix[@]}"
|
eval _describe "completions" completions $flagPrefix
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
# uv Environment Plugin
|
|
||||||
|
|
||||||
This plugin automatically activates the uv virtual environment when you cd into a project directory, and deactivates it when you cd out.
|
|
||||||
Note: Script looks for pyproject.toml and uv.lock files to determine if it's a uv project
|
|
||||||
|
|
||||||
To use it, add `uv-env` to the plugins array in your zshrc file:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
plugins=(... uv-env)
|
|
||||||
```
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
_toggleUvShell() {
|
|
||||||
local in_uv_dir=0
|
|
||||||
if [[ -f "$PWD/pyproject.toml" && -f "$PWD/uv.lock" ]]; then
|
|
||||||
in_uv_dir=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $uv_active -eq 1 ]] && { [[ $in_uv_dir -eq 0 ]] || [[ "$PWD" != "$uv_dir" && "$PWD" != "$uv_dir"/* ]]; }; then
|
|
||||||
typeset -g uv_active=0
|
|
||||||
unset uv_dir
|
|
||||||
(( $+functions[deactivate] )) && deactivate
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $in_uv_dir -eq 1 ]] && [[ $uv_active -ne 1 ]]; then
|
|
||||||
local venv_dir="${UV_PROJECT_ENVIRONMENT:-$PWD/.venv}"
|
|
||||||
[[ "$venv_dir" != /* ]] && venv_dir="$PWD/$venv_dir"
|
|
||||||
|
|
||||||
if [[ -f "${venv_dir}/bin/activate" ]]; then
|
|
||||||
typeset -g uv_active=1
|
|
||||||
typeset -g uv_dir="$PWD"
|
|
||||||
source "${venv_dir}/bin/activate"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
autoload -Uz add-zsh-hook
|
|
||||||
add-zsh-hook chpwd _toggleUvShell
|
|
||||||
_toggleUvShell
|
|
||||||
@@ -47,7 +47,6 @@ _box_arguments=(
|
|||||||
'help:COMMAND List subcommands'
|
'help:COMMAND List subcommands'
|
||||||
'list:Lists all installed boxes'
|
'list:Lists all installed boxes'
|
||||||
'outdated:Checks if a box has newer version'
|
'outdated:Checks if a box has newer version'
|
||||||
'prune:Removes old versions of installed boxes'
|
|
||||||
'remove:NAME Removes a box from the system'
|
'remove:NAME Removes a box from the system'
|
||||||
'repackage:NAME PROVIDER VERSION Repackages an installed box into a `.box` file'
|
'repackage:NAME PROVIDER VERSION Repackages an installed box into a `.box` file'
|
||||||
'update:Updates box to a newer version, if available'
|
'update:Updates box to a newer version, if available'
|
||||||
@@ -127,7 +126,7 @@ case $state in
|
|||||||
(box)
|
(box)
|
||||||
__vagrant-box
|
__vagrant-box
|
||||||
;;
|
;;
|
||||||
(up|provision|port|package|destroy|reload|ssh|ssh-config|halt|resume|status|suspend|rdp)
|
(up|provision|port|package|destroy|reload|ssh|ssh-config|halt|resume|status)
|
||||||
_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" \
|
||||||
&& ! -e "$PROJECT_ROOT/.git" ]]; do
|
&& ! -d "$PROJECT_ROOT/.git" ]]; do
|
||||||
PROJECT_ROOT="${PROJECT_ROOT:h}"
|
PROJECT_ROOT="${PROJECT_ROOT:h}"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -51,11 +51,6 @@ 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,11 +32,6 @@ 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="
|
||||||
@@ -97,11 +92,6 @@ 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'
|
||||||
@@ -126,3 +116,4 @@ if [[ ${#ZSH_WEB_SEARCH_ENGINES} -gt 0 ]]; then
|
|||||||
done
|
done
|
||||||
unset engines key
|
unset engines key
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ export LSCOLORS=dxFxCxDxBxegedabagacad
|
|||||||
|
|
||||||
local git_branch='$(git_prompt_info)%{$reset_color%}$(git_remote_status)'
|
local git_branch='$(git_prompt_info)%{$reset_color%}$(git_remote_status)'
|
||||||
|
|
||||||
PROMPT="%{%(#~$fg[red]~$fg[green])%}╭─%n@%m %{$reset_color%}%{$fg[yellow]%}in %~ %{$reset_color%}${git_branch}
|
PROMPT="%{$fg[green]%}╭─%n@%m %{$reset_color%}%{$fg[yellow]%}in %~ %{$reset_color%}${git_branch}
|
||||||
%{%(#~$fg[red]~$fg[green])%}╰%(#~#~\$) %{$reset_color%}"
|
%{$fg[green]%}╰\$ %{$reset_color%}"
|
||||||
|
|
||||||
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[yellow]%}on "
|
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[yellow]%}on "
|
||||||
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}"
|
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}"
|
||||||
|
|||||||
@@ -23,32 +23,12 @@ zstyle -s ':omz:update' mode update_mode || {
|
|||||||
# - the automatic update is disabled
|
# - the automatic update is disabled
|
||||||
# - the current user doesn't have write permissions nor owns the $ZSH directory
|
# - the current user doesn't have write permissions nor owns the $ZSH directory
|
||||||
# - is not run from a tty
|
# - is not run from a tty
|
||||||
if [[ "$update_mode" = disabled ]] \
|
|
||||||
|| [[ ! -w "$ZSH" || ! -O "$ZSH" ]] \
|
|
||||||
|| [[ ! -t 1 && ${POWERLEVEL9K_INSTANT_PROMPT:-off} == off ]]; then
|
|
||||||
unset update_mode
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Cancel update if it's not time to check yet. This runs before the git checks
|
|
||||||
# below because those fork on every startup. Skipped when a background update
|
|
||||||
# left a result that still needs to be reported (EXIT_STATUS is set).
|
|
||||||
() {
|
|
||||||
local LAST_EPOCH EXIT_STATUS ERROR epoch_target
|
|
||||||
zmodload zsh/datetime
|
|
||||||
source "${ZSH_CACHE_DIR}/.zsh-update" 2>/dev/null || return 1
|
|
||||||
[[ -n "$LAST_EPOCH" && -z "$EXIT_STATUS" ]] || return 1
|
|
||||||
zstyle -s ':omz:update' frequency epoch_target || epoch_target=${UPDATE_ZSH_DAYS:-13}
|
|
||||||
(( ( EPOCHSECONDS / 60 / 60 / 24 - LAST_EPOCH ) < epoch_target ))
|
|
||||||
} && {
|
|
||||||
unset update_mode
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
# Cancel update if:
|
|
||||||
# - git is unavailable on the system
|
# - git is unavailable on the system
|
||||||
# - $ZSH is not a git repository
|
# - $ZSH is not a git repository
|
||||||
if ! command git --version >/dev/null 2>&1 \
|
if [[ "$update_mode" = disabled ]] \
|
||||||
|
|| [[ ! -w "$ZSH" || ! -O "$ZSH" ]] \
|
||||||
|
|| [[ ! -t 1 && ${POWERLEVEL9K_INSTANT_PROMPT:-off} == off ]] \
|
||||||
|
|| ! command git --version >/dev/null 2>&1 \
|
||||||
|| (builtin cd -q "$ZSH"; ! command git rev-parse --is-inside-work-tree &>/dev/null); then
|
|| (builtin cd -q "$ZSH"; ! command git rev-parse --is-inside-work-tree &>/dev/null); then
|
||||||
unset update_mode
|
unset update_mode
|
||||||
return
|
return
|
||||||
|
|||||||
+3
-4
@@ -528,10 +528,9 @@ print_success() {
|
|||||||
"$(fmt_code "$(fmt_link ".zshrc" "file://$zdot/.zshrc" --text)")" \
|
"$(fmt_code "$(fmt_link ".zshrc" "file://$zdot/.zshrc" --text)")" \
|
||||||
"file to select plugins, themes, and options."
|
"file to select plugins, themes, and options."
|
||||||
printf '\n'
|
printf '\n'
|
||||||
printf '%s\n' "• Follow along on X ($(fmt_link @ohmyzsh https://x.com/ohmyzsh)) or Bluesky ($(fmt_link @ohmyz.sh https://bsky.app/profile/ohmyz.sh))"
|
printf '%s\n' "• Follow us on X: $(fmt_link @ohmyzsh https://x.com/ohmyzsh)"
|
||||||
printf '%s\n' "• Questions or ideas? Join the community on $(fmt_link Discord https://discord.gg/ohmyzsh)"
|
printf '%s\n' "• Join our Discord community: $(fmt_link "Discord server" https://discord.gg/ohmyzsh)"
|
||||||
printf '%s\n' "• Help support the project: sponsor us on $(fmt_link "Open Collective" https://opencollective.com/ohmyzsh),"
|
printf '%s\n' "• Get stickers, t-shirts, coffee mugs and more: $(fmt_link "CommitGoods Shop" https://commitgoods.com/collections/oh-my-zsh)"
|
||||||
printf '%s\n' " or grab stickers, shirts, and swag from $(fmt_link CommitGoods https://commitgoods.com/ohmyzsh)"
|
|
||||||
printf '%s\n' $FMT_RESET
|
printf '%s\n' $FMT_RESET
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
# Theme Browser
|
|
||||||
|
|
||||||
Preview installed themes without changing your current prompt:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
omz theme browse
|
|
||||||
omz theme browse agn
|
|
||||||
omz theme preview agnoster
|
|
||||||
```
|
|
||||||
|
|
||||||
The browser filters theme names as you type and renders the highlighted theme using
|
|
||||||
the current directory, including synchronous Git information.
|
|
||||||
|
|
||||||
## Controls
|
|
||||||
|
|
||||||
| Key | Action |
|
|
||||||
| --- | --- |
|
|
||||||
| Up / Down, Ctrl-P / Ctrl-N | Previous / next theme |
|
|
||||||
| Page Up / Page Down | Move one page |
|
|
||||||
| Printable text | Filter names |
|
|
||||||
| Backspace | Delete the last filter character |
|
|
||||||
| Ctrl-U | Clear the filter |
|
|
||||||
| Enter | Open selection actions |
|
|
||||||
| Esc / Ctrl-C | Cancel without applying or saving |
|
|
||||||
| `u` in selection actions | Use the theme for this session |
|
|
||||||
| `s` in selection actions | Save as default and reload the shell |
|
|
||||||
| `b` or Enter in selection actions | Return to browsing |
|
|
||||||
|
|
||||||
Using a theme changes the current session. It does not remove hooks or widgets installed
|
|
||||||
by the previous theme. Saving updates `ZSH_THEME` in `.zshrc` and reloads the shell.
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
- Previews run in a fresh shell, so plugin-dependent and interactive themes may be incomplete.
|
|
||||||
- Right prompts are labeled and shown separately rather than positioned by ZLE.
|
|
||||||
- The browser requires an interactive terminal with alternate-screen support.
|
|
||||||
- Theme code is isolated from your active shell, but it is not sandboxed. Preview only trusted themes.
|
|
||||||
|
|
||||||
## Local Testing
|
|
||||||
|
|
||||||
From this checkout, launch a disposable interactive shell:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
env ZSH="$PWD" zsh -dfi
|
|
||||||
source "$ZSH/lib/cli.zsh"
|
|
||||||
omz theme preview robbyrussell
|
|
||||||
omz theme browse
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the regression suites with:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
zsh -df tools/theme-browser/tests/preview_test.zsh
|
|
||||||
zsh -df tools/theme-browser/tests/browser_test.zsh
|
|
||||||
```
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
# Loaded only by `omz theme browse`. The UI runs in a subshell; stdout is a
|
|
||||||
# two-line data handoff, while all terminal I/O goes through a private tty fd.
|
|
||||||
function _omz_theme_browser() (
|
|
||||||
emulate -L zsh
|
|
||||||
setopt extendedglob promptpercent
|
|
||||||
# Displayed names, filter text, and worker output are data, not prompt code.
|
|
||||||
unsetopt promptsubst
|
|
||||||
zmodload zsh/terminfo && zmodload zsh/zpty && zmodload zsh/system && zmodload zsh/datetime || return 1
|
|
||||||
local tty saved filter=$1 key suffix name previous='' preview='' chunk
|
|
||||||
local mode=browse action='' pty=omz-browser-$sysparams[pid] record pgid
|
|
||||||
local -a names matches lines size
|
|
||||||
local -i selected=1 page=1 height=0 width=0 rows=0 cols=0 active=0 dirty=1 i row cancelled=0
|
|
||||||
local -F render_after=0
|
|
||||||
[[ -n $terminfo[smcup] && -n $terminfo[rmcup] && -n $terminfo[cup] ]] || {
|
|
||||||
print -u2 -r -- 'Theme browser requires a terminal with alternate-screen support.'
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
exec {tty}<>/dev/tty || return 1
|
|
||||||
saved=$(command stty -g <&$tty) || return 1
|
|
||||||
names=("${(@f)$(_omz_theme_names)}")
|
|
||||||
names=("${(@)names:#}")
|
|
||||||
trap 'cancelled=1' INT TERM HUP
|
|
||||||
trap 'dirty=1' WINCH
|
|
||||||
|
|
||||||
function _omz_browser_stop {
|
|
||||||
if (( active )); then
|
|
||||||
[[ $pgid == <2-> ]] && kill -HUP -- -$pgid 2>/dev/null
|
|
||||||
# Let the preview supervisor clean up its nested worker group first.
|
|
||||||
local -i wait_count=0
|
|
||||||
while zpty -t "$pty" && (( wait_count++ < 100 )); do
|
|
||||||
zselect -t 1
|
|
||||||
done
|
|
||||||
zpty -d "$pty" 2>/dev/null
|
|
||||||
active=0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function _omz_browser_line {
|
|
||||||
local text=${1//$'\t'/ } formatted='' MATCH MBEGIN MEND
|
|
||||||
text=${text//\%/%%}
|
|
||||||
# Tell prompt truncation that SGR has zero display width. All other terminal
|
|
||||||
# controls have already been removed by the preview backend.
|
|
||||||
while [[ $text =~ $'\e\\[[0-9;:]*m' ]]; do
|
|
||||||
formatted+=${text[1,$(( MBEGIN - 1 ))]}"%{"$MATCH"%}"
|
|
||||||
text=${text[$(( MEND + 1 )),-1]}
|
|
||||||
done
|
|
||||||
formatted+=$text
|
|
||||||
echoti cup $row 0 >&$tty
|
|
||||||
print -Prn -u $tty -- "%${width}<..<${formatted}%<<%f%k%b"
|
|
||||||
(( row++ ))
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
zmodload zsh/zselect || return 1
|
|
||||||
command stty -echo -icanon min 0 time 0 <&$tty || return 1
|
|
||||||
print -rn -u $tty -- "$terminfo[smcup]$terminfo[civis]"
|
|
||||||
while (( ! cancelled )); do
|
|
||||||
size=(${=$(command stty size <&$tty)})
|
|
||||||
rows=${size[1]:-24} cols=${size[2]:-80}
|
|
||||||
if (( height != rows || width != cols - 1 )); then
|
|
||||||
height=$rows width=$(( cols - 1 )) dirty=1
|
|
||||||
fi
|
|
||||||
matches=()
|
|
||||||
for name in "${names[@]}"; do
|
|
||||||
[[ ${(L)name} == *${(L)filter}* ]] && matches+=("$name")
|
|
||||||
done
|
|
||||||
(( selected > $#matches )) && selected=$#matches
|
|
||||||
(( selected < 1 )) && selected=1
|
|
||||||
name=${matches[$selected]}
|
|
||||||
if [[ $name != "$previous" ]]; then
|
|
||||||
_omz_browser_stop
|
|
||||||
previous=$name preview='' dirty=1
|
|
||||||
render_after=$(( EPOCHREALTIME + 0.12 ))
|
|
||||||
fi
|
|
||||||
# Coalesce typing and key repeats rather than starting a worker per key.
|
|
||||||
if (( ! active && EPOCHREALTIME >= render_after )); then
|
|
||||||
if [[ -n $name ]]; then
|
|
||||||
# zpty joins arguments as shell text; quote the literal theme name.
|
|
||||||
zpty -b "$pty" _omz_theme_preview "${(q)name}" || return 1
|
|
||||||
active=1
|
|
||||||
pgid=''
|
|
||||||
for record in "${(@f)$(zpty)}"; do
|
|
||||||
[[ $record == \(<->\)\ "$pty":* ]] && pgid=${${record#\(}%%\)*}
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if (( active )); then
|
|
||||||
while zpty -r -t "$pty" chunk; do
|
|
||||||
preview+=${chunk//$'\r'/}
|
|
||||||
dirty=1
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
page=$(( height > 24 ? 8 : 4 ))
|
|
||||||
if (( dirty )); then
|
|
||||||
print -rn -u $tty -- "$terminfo[clear]"
|
|
||||||
row=0
|
|
||||||
if (( width < 39 || height < 16 )); then
|
|
||||||
_omz_browser_line 'Resize to at least 40 columns x 16 rows.'
|
|
||||||
_omz_browser_line 'Esc / Ctrl-C: cancel'
|
|
||||||
else
|
|
||||||
_omz_browser_line 'Oh My Zsh theme browser | Esc / Ctrl-C: cancel'
|
|
||||||
_omz_browser_line "Filter: ${(V)filter} ($#matches themes)"
|
|
||||||
if [[ $mode == actions ]]; then
|
|
||||||
_omz_browser_line '[u] Use in session [s] Save + reload [b] Back'
|
|
||||||
_omz_browser_line 'Use keeps old theme hooks. Save edits .zshrc + reloads.'
|
|
||||||
else
|
|
||||||
_omz_browser_line 'Arrows / Ctrl-P,N: move | PgUp,Dn | Enter: actions'
|
|
||||||
_omz_browser_line 'Type to filter | Backspace: delete | Ctrl-U: clear'
|
|
||||||
fi
|
|
||||||
for (( i = ((selected - 1) / page) * page + 1; i <= $#matches && row < page + 4; i++ )); do
|
|
||||||
if (( i == selected )); then
|
|
||||||
_omz_browser_line "> ${(V)matches[$i]}"
|
|
||||||
else
|
|
||||||
_omz_browser_line " ${(V)matches[$i]}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
_omz_browser_line '--- Static preview (right prompt shown separately) ---'
|
|
||||||
lines=("${(@f)preview}")
|
|
||||||
if [[ -z $preview ]]; then
|
|
||||||
[[ -n $name ]] && lines=('Rendering...') || lines=('No matching themes.')
|
|
||||||
fi
|
|
||||||
for chunk in "${lines[@]}"; do
|
|
||||||
(( row < height - 1 )) || break
|
|
||||||
_omz_browser_line "$chunk"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
dirty=0
|
|
||||||
fi
|
|
||||||
key=''
|
|
||||||
read -r -k 1 -t 0.1 -u $tty key || continue
|
|
||||||
if [[ $key == $'\e' ]]; then
|
|
||||||
suffix=''
|
|
||||||
while read -r -k 1 -t 0.03 -u $tty chunk; do
|
|
||||||
suffix+=$chunk
|
|
||||||
[[ $chunk == [A-Za-z~] || ${#suffix} -ge 8 ]] && break
|
|
||||||
done
|
|
||||||
[[ -n $suffix ]] || break
|
|
||||||
key=$'\e'$suffix
|
|
||||||
fi
|
|
||||||
[[ $key == $'\x03' ]] && break
|
|
||||||
if [[ $mode == actions ]]; then
|
|
||||||
case $key in
|
|
||||||
u) action=use; break ;;
|
|
||||||
s) action=set; break ;;
|
|
||||||
b|$'\r'|$'\n') mode=browse ;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
case $key in
|
|
||||||
$'\e[A'|$'\eOA'|$'\x10') (( selected-- )) ;;
|
|
||||||
$'\e[B'|$'\eOB'|$'\x0e') (( selected++ )) ;;
|
|
||||||
$'\e[5~') (( selected -= page )) ;;
|
|
||||||
$'\e[6~') (( selected += page )) ;;
|
|
||||||
$'\x7f'|$'\b') filter=${filter[1,-2]}; selected=1 ;;
|
|
||||||
$'\x15') filter=''; selected=1 ;;
|
|
||||||
$'\r'|$'\n') [[ -n $name ]] && mode=actions ;;
|
|
||||||
[[:print:]]) filter+=$key; selected=1 ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
dirty=1
|
|
||||||
done
|
|
||||||
} always {
|
|
||||||
_omz_browser_stop
|
|
||||||
print -rn -u $tty -- $'\e[0m'"$terminfo[cnorm]$terminfo[rmcup]"
|
|
||||||
command stty "$saved" <&$tty
|
|
||||||
exec {tty}>&-
|
|
||||||
}
|
|
||||||
(( cancelled )) && return 130
|
|
||||||
[[ -n $action ]] && print -rl -- "$action" "$name"
|
|
||||||
return 0
|
|
||||||
)
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
# Invoked only by preview.zsh in a fresh zsh -df process. Themes and hooks
|
|
||||||
# are intentionally sourced/run at top level (not inside a setup function).
|
|
||||||
emulate -R zsh
|
|
||||||
if [[ $1 == --supervise ]]; then
|
|
||||||
# This process is the private PTY's session leader. Keep the actual worker's
|
|
||||||
# standard descriptors non-TTY, and report its status outside theme state.
|
|
||||||
typeset -r _omz_preview_tmp=$2
|
|
||||||
shift 2
|
|
||||||
unsetopt monitor
|
|
||||||
command "$commands[zsh]" -df "${0:A}" "$@" \
|
|
||||||
< /dev/null > "$_omz_preview_tmp/output" 2>&1
|
|
||||||
print -r -- $? > "$_omz_preview_tmp/result"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
typeset -r _omz_preview_root=$1 _omz_preview_theme=$2 _omz_preview_status=$3
|
|
||||||
export ZSH=${ZSH:-$_omz_preview_root}
|
|
||||||
ZSH_THEME=$4
|
|
||||||
ZSH_CUSTOM=$5
|
|
||||||
fpath=("$_omz_preview_root/functions" $fpath)
|
|
||||||
autoload -Uz colors add-zsh-hook vcs_info
|
|
||||||
colors
|
|
||||||
setopt prompt_subst prompt_percent
|
|
||||||
zstyle ':omz:alpha:lib:git' async-prompt no
|
|
||||||
ZSH_THEME_GIT_PROMPT_PREFIX='git:('
|
|
||||||
ZSH_THEME_GIT_PROMPT_SUFFIX=')'
|
|
||||||
ZSH_THEME_GIT_PROMPT_DIRTY='*'
|
|
||||||
ZSH_THEME_GIT_PROMPT_CLEAN=''
|
|
||||||
ZSH_THEME_RUBY_PROMPT_PREFIX='('
|
|
||||||
ZSH_THEME_RUBY_PROMPT_SUFFIX=')'
|
|
||||||
source "$_omz_preview_root/lib/git.zsh"
|
|
||||||
source "$_omz_preview_root/lib/vcs_info.zsh"
|
|
||||||
source "$_omz_preview_root/lib/bzr.zsh"
|
|
||||||
source "$_omz_preview_root/lib/nvm.zsh"
|
|
||||||
source "$_omz_preview_root/lib/prompt_info_functions.zsh"
|
|
||||||
source "$_omz_preview_root/lib/spectrum.zsh"
|
|
||||||
# Check syntax before accepting a final false conditional as a successful load.
|
|
||||||
# This subprocess shares the worker's execution deadline and process group.
|
|
||||||
command "$commands[zsh]" -dfn "$_omz_preview_theme" || {
|
|
||||||
print -u2 -r -- 'theme preview: theme syntax check failed'
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
# Keep zsh's PROMPT/PS1 and RPROMPT/RPS1 aliases intact (dieter sets RPS1).
|
|
||||||
PROMPT=''
|
|
||||||
RPROMPT=''
|
|
||||||
source "$_omz_preview_theme"
|
|
||||||
typeset -i _omz_preview_load_status=$?
|
|
||||||
# Status 1 may just be a final conditional; require an initialized prompt below.
|
|
||||||
# Higher statuses include syntax/runtime errors and missing commands.
|
|
||||||
if (( _omz_preview_load_status > 1 )); then
|
|
||||||
print -u2 -r -- "theme preview: theme could not be loaded (exit $_omz_preview_load_status)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
function _omz_preview_set_status { return "$_omz_preview_status" }
|
|
||||||
typeset -i _omz_preview_hook_status=0
|
|
||||||
if (( $+functions[precmd] )); then
|
|
||||||
_omz_preview_set_status
|
|
||||||
precmd
|
|
||||||
_omz_preview_hook_status=$?
|
|
||||||
if (( _omz_preview_hook_status )); then
|
|
||||||
print -u2 -r -- "theme preview: precmd failed (exit $_omz_preview_hook_status); remaining hooks skipped"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
for _omz_preview_hook in "${precmd_functions[@]}"; do
|
|
||||||
(( _omz_preview_hook_status )) && break
|
|
||||||
if (( $+functions[$_omz_preview_hook] )); then
|
|
||||||
_omz_preview_set_status
|
|
||||||
"$_omz_preview_hook"
|
|
||||||
_omz_preview_hook_status=$?
|
|
||||||
if (( _omz_preview_hook_status )); then
|
|
||||||
print -u2 -r -- "theme preview: precmd hook $_omz_preview_hook failed (exit $_omz_preview_hook_status); remaining hooks skipped"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if (( _omz_preview_load_status )) && [[ -z $PROMPT && -z $RPROMPT ]]; then
|
|
||||||
print -u2 -r -- "theme preview: theme did not initialize a prompt (load exit $_omz_preview_load_status)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# Native prompt expansion handles PROMPT_SUBST once, followed by percent escapes.
|
|
||||||
# An explicit (e) pass here would re-execute literal substitutions from helpers.
|
|
||||||
print -r -- "Left prompt (status $_omz_preview_status):"
|
|
||||||
_omz_preview_set_status
|
|
||||||
print -Pr -- "${PROMPT-}"
|
|
||||||
print -r -- 'Right prompt (shown separately):'
|
|
||||||
_omz_preview_set_status
|
|
||||||
print -Pr -- "${RPROMPT-}"
|
|
||||||
(( _omz_preview_hook_status )) && exit 1
|
|
||||||
exit 42
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
# Static previews execute theme code as the current user, not in a sandbox.
|
|
||||||
# A private PTY supplies a process group without requiring shell job control.
|
|
||||||
typeset -g _OMZ_THEME_PREVIEW_DIR=${${(%):-%x}:A:h}
|
|
||||||
|
|
||||||
function _omz_theme_names() (
|
|
||||||
emulate -L zsh
|
|
||||||
setopt extendedglob
|
|
||||||
local root=${ZSH:-${_OMZ_THEME_PREVIEW_DIR:h:h}}
|
|
||||||
local custom=${ZSH_CUSTOM:-$root/custom} dir file name
|
|
||||||
local -a names files
|
|
||||||
for dir in "$custom" "$root/themes"; do
|
|
||||||
if [[ $dir == "$custom" ]]; then
|
|
||||||
files=("$dir"/**/*.zsh-theme(N-.))
|
|
||||||
else
|
|
||||||
files=("$dir"/*.zsh-theme(N-.))
|
|
||||||
fi
|
|
||||||
for file in "${files[@]}"; do
|
|
||||||
name=${${file#"$dir/"}%.zsh-theme}
|
|
||||||
[[ $dir == "$custom" ]] && name=${name#themes/}
|
|
||||||
[[ -n $name && $name != random && /$name/ != */(.|..)/* && $name != /* && $name != *[[:cntrl:]\\]* ]] || continue
|
|
||||||
names+=("$name")
|
|
||||||
done
|
|
||||||
done
|
|
||||||
(( $#names )) && print -rl -- ${(ou)names}
|
|
||||||
return 0
|
|
||||||
)
|
|
||||||
|
|
||||||
function _omz_theme_resolve() (
|
|
||||||
emulate -L zsh
|
|
||||||
setopt extendedglob
|
|
||||||
local name=$1 root=${ZSH:-${_OMZ_THEME_PREVIEW_DIR:h:h}}
|
|
||||||
local custom=${ZSH_CUSTOM:-$root/custom} dir
|
|
||||||
if (( $# != 1 )) || [[ -z $name || $name == random || /$name/ == */(.|..)/* || $name == /* || $name == *//* || $name == *[[:cntrl:]\\]* ]]; then
|
|
||||||
print -u2 -r -- 'theme preview: invalid or non-selectable theme name'
|
|
||||||
return 2
|
|
||||||
fi
|
|
||||||
for dir in "$custom" "$custom/themes" "$root/themes"; do
|
|
||||||
if [[ -f "$dir/$name.zsh-theme" ]]; then
|
|
||||||
print -r -- "${dir:A}/$name.zsh-theme"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
print -u2 -r -- 'theme preview: theme not found'
|
|
||||||
return 1
|
|
||||||
)
|
|
||||||
|
|
||||||
# One sample, with the requested exit status (0 by default). All execution and
|
|
||||||
# state changes are confined to this subshell and the fresh -df worker.
|
|
||||||
# For asynchronous callers, cancel the job group, not just zsh's waiting wrapper.
|
|
||||||
function _omz_theme_preview() (
|
|
||||||
emulate -L zsh
|
|
||||||
local theme sample=${2:-0} backend=$_OMZ_THEME_PREVIEW_DIR
|
|
||||||
if (( $# < 1 || $# > 2 )) || [[ $sample != <0-255> ]]; then
|
|
||||||
print -u2 -r -- 'theme preview: usage: _omz_theme_preview name [status 0..255]'
|
|
||||||
return 2
|
|
||||||
fi
|
|
||||||
theme=$(_omz_theme_resolve "$1") || return $?
|
|
||||||
if ! zmodload zsh/zpty || ! zmodload zsh/system || ! zmodload zsh/datetime || ! zmodload zsh/zselect; then
|
|
||||||
print -u2 -r -- 'theme preview: required zsh modules unavailable (zpty, system, datetime, zselect)'
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
local tmp fifo_fd pty=omz-preview-$sysparams[pid] record pgid raw='' chunk error=''
|
|
||||||
local selected=$1 custom=${ZSH_CUSTOM:-${ZSH:-${backend:h:h}}/custom}
|
|
||||||
local -i active=0 cancelled=0 bytes=0 count remaining result=1
|
|
||||||
local -F deadline
|
|
||||||
trap 'cancelled=130' INT
|
|
||||||
trap 'cancelled=143' TERM
|
|
||||||
trap 'cancelled=129' HUP
|
|
||||||
{
|
|
||||||
tmp=$(command mktemp -d "${TMPDIR:-/tmp}/omz-preview.XXXXXXXX") || return 1
|
|
||||||
command mkfifo "$tmp/output" || return 1
|
|
||||||
sysopen -r -o nonblock,cloexec -u fifo_fd "$tmp/output" || return 1
|
|
||||||
|
|
||||||
# Exec immediately: a forked shell function could run inherited EXIT traps
|
|
||||||
# after returning. Both the launcher and theme worker must start fresh.
|
|
||||||
local -a launch=("$commands[zsh]" -df "$backend/preview-worker.zsh" --supervise
|
|
||||||
"$tmp" "${backend:h:h}" "$theme" "$sample" "$selected" "$custom")
|
|
||||||
deadline=$(( EPOCHREALTIME + 3 ))
|
|
||||||
if ! zpty -b "$pty" exec "${(@q)launch}"; then
|
|
||||||
print -u2 -r -- 'theme preview: could not allocate a private PTY'
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
active=1
|
|
||||||
# The builtin listing supplies the session leader even before the child
|
|
||||||
# starts; this avoids a PID-handshake race during immediate cancellation.
|
|
||||||
for record in "${(@f)$(zpty)}"; do
|
|
||||||
if [[ $record == \(<->\)\ "$pty":* ]]; then
|
|
||||||
pgid=${${record#\(}%%\)*}
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ $pgid != <2-> ]]; then
|
|
||||||
print -u2 -r -- 'theme preview: could not identify worker process group'
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
while true; do
|
|
||||||
if (( cancelled )); then
|
|
||||||
error='cancelled'
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
if (( EPOCHREALTIME >= deadline )); then
|
|
||||||
error='timed out after 3 seconds'
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
remaining=$(( 32001 - bytes ))
|
|
||||||
if sysread -i "$fifo_fd" -s $(( remaining < 4096 ? remaining : 4096 )) -t 0.02 -c count chunk; then
|
|
||||||
raw+=$chunk
|
|
||||||
(( bytes += count ))
|
|
||||||
if (( bytes > 32000 )); then
|
|
||||||
error='output exceeded 32 KiB'
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
elif [[ -s "$tmp/result" ]]; then
|
|
||||||
result=$(<"$tmp/result")
|
|
||||||
# The worker's dedicated completion status distinguishes a theme's
|
|
||||||
# early exit (including exit 0) from rendering both prompts.
|
|
||||||
[[ $result == 42 ]] || error="worker did not complete preview (exit $result)"
|
|
||||||
break
|
|
||||||
elif ! zpty -t "$pty"; then
|
|
||||||
error='worker supervisor exited before completing preview'
|
|
||||||
break
|
|
||||||
else
|
|
||||||
zselect -t 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
} always {
|
|
||||||
# Clean up the whole group even on success. Deliberately detached processes
|
|
||||||
# are outside this boundary. Delete only our PTY, not any inherited ones.
|
|
||||||
if [[ $pgid == <2-> ]]; then
|
|
||||||
kill -TERM -- -$pgid 2>/dev/null
|
|
||||||
zselect -t 5
|
|
||||||
kill -KILL -- -$pgid 2>/dev/null
|
|
||||||
fi
|
|
||||||
(( active )) && zpty -d "$pty" 2>/dev/null
|
|
||||||
[[ -n $fifo_fd ]] && exec {fifo_fd}<&-
|
|
||||||
[[ -n $tmp ]] && command rm -rf -- "$tmp"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Bound by bytes before splitting into locale-aware characters. No escape is
|
|
||||||
# emitted until it is a complete numeric SGR; all string controls are dropped,
|
|
||||||
# including their payloads and incomplete sequences at the output boundary.
|
|
||||||
unsetopt multibyte
|
|
||||||
raw=${raw[1,32000]}
|
|
||||||
setopt multibyte
|
|
||||||
local char safe='' state=text sgr=''
|
|
||||||
local -i code valid=1
|
|
||||||
for char in "${(@s::)raw}"; do
|
|
||||||
if (( cancelled )); then
|
|
||||||
error='cancelled'
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
printf -v code '%d' "'$char" 2>/dev/null
|
|
||||||
case $state in
|
|
||||||
string|string-escape)
|
|
||||||
if [[ $char == $'\a' || $char == $'\xc2\x9c' || $char == $'\x9c' || ( $state == string-escape && $char == \\ ) ]]; then
|
|
||||||
state=text
|
|
||||||
elif [[ $char == $'\e' ]]; then
|
|
||||||
state=string-escape
|
|
||||||
else
|
|
||||||
state=string
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
escape)
|
|
||||||
case $char in
|
|
||||||
'[') state=csi; sgr=''; valid=1 ;;
|
|
||||||
']'|P|X|'^'|_) state=string ;;
|
|
||||||
$'\e') ;;
|
|
||||||
*)
|
|
||||||
if (( code >= 32 && code <= 47 )); then
|
|
||||||
state=intermediate
|
|
||||||
else
|
|
||||||
state=text
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
intermediate)
|
|
||||||
(( code >= 32 && code <= 47 )) || state=text
|
|
||||||
;;
|
|
||||||
csi)
|
|
||||||
if [[ $char == [0-9\;:] ]]; then
|
|
||||||
sgr+=$char
|
|
||||||
elif (( code >= 64 && code <= 126 )); then
|
|
||||||
[[ $char == m && $valid == 1 ]] && safe+=$'\e['${sgr}m
|
|
||||||
state=text
|
|
||||||
elif [[ $char == $'\e' ]]; then
|
|
||||||
state=escape
|
|
||||||
else
|
|
||||||
valid=0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
text)
|
|
||||||
case $char in
|
|
||||||
$'\e') state=escape ;;
|
|
||||||
$'\xc2\x9b') state=csi; sgr=''; valid=1 ;;
|
|
||||||
# Drop raw 8-bit CSI instead of expanding it to two bytes. Filtering
|
|
||||||
# can then never enlarge the byte-bounded input buffer.
|
|
||||||
$'\x9b') state=csi; sgr=''; valid=0 ;;
|
|
||||||
$'\xc2\x90'|$'\xc2\x98'|$'\xc2\x9d'|$'\xc2\x9e'|$'\xc2\x9f'|$'\x90'|$'\x98'|$'\x9d'|$'\x9e'|$'\x9f') state=string ;;
|
|
||||||
$'\n'|$'\t') safe+=$char ;;
|
|
||||||
*)
|
|
||||||
# Reject format/directional controls even on libc implementations
|
|
||||||
# that classify them as printable. Keep private-use font glyphs.
|
|
||||||
if [[ $char == [[:print:]] ]] && ! (( code >= 0x200b && code <= 0x200f || code >= 0x2028 && code <= 0x202e || code >= 0x2060 && code <= 0x206f || code == 0xfeff )); then
|
|
||||||
safe+=$char
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
(( cancelled )) && error='cancelled'
|
|
||||||
print -rn -- "$safe"$'\e[0m\n'
|
|
||||||
[[ -n $error ]] && print -u2 -r -- "theme preview: $error"
|
|
||||||
(( cancelled )) && return $cancelled
|
|
||||||
[[ -z $error ]]
|
|
||||||
)
|
|
||||||
@@ -1,406 +0,0 @@
|
|||||||
#!/usr/bin/env zsh
|
|
||||||
# Run with: zsh -df tools/theme-browser/tests/browser_test.zsh
|
|
||||||
# Optionally pass one group, e.g. `slow-interrupt`, to run it alone.
|
|
||||||
# Each browser runs under a real controlling PTY, with no user startup files.
|
|
||||||
emulate -R zsh
|
|
||||||
|
|
||||||
if [[ $1 == --child ]]; then
|
|
||||||
if [[ $2 == completion ]]; then
|
|
||||||
function compdef { print -r -- "REGISTERED:${(j.:.)@}"; }
|
|
||||||
fi
|
|
||||||
source "$ZSH/lib/cli.zsh"
|
|
||||||
# Match normal OMZ sessions without sourcing any user startup/configuration.
|
|
||||||
setopt promptsubst
|
|
||||||
[[ -z $BROWSER_TEST_NO_PROMPT_PERCENT ]] || unsetopt promptpercent
|
|
||||||
print -r -- "LAZY:$+functions[_omz_theme_browser]:$+functions[_omz_theme_preview]"
|
|
||||||
if [[ $2 == completion ]]; then
|
|
||||||
# Capture the real completion function's candidates without loading the
|
|
||||||
# user's completion setup or replacing any CLI/backend functions.
|
|
||||||
function _describe { print -rl -- "DESCRIBE:$1" "${(@P)2}"; }
|
|
||||||
CURRENT=3 words=(omz theme '')
|
|
||||||
print -r -- SUBCOMMANDS
|
|
||||||
_omz
|
|
||||||
print -r -- END_SUBCOMMANDS
|
|
||||||
for action in browse preview set use; do
|
|
||||||
CURRENT=4 words=(omz theme "$action" '')
|
|
||||||
print -r -- "CANDIDATES:$action"
|
|
||||||
_omz
|
|
||||||
print -r -- "END:$action"
|
|
||||||
done
|
|
||||||
print -r -- "STILL_LAZY:$+functions[_omz_theme_browser]:$+functions[_omz_theme_preview]"
|
|
||||||
print -r -- COMPLETIONS_FINISHED
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
if [[ $2 == reject* ]]; then
|
|
||||||
case $2 in
|
|
||||||
reject-stdin) omz theme browse </dev/null ;;
|
|
||||||
reject-stdout) omz theme browse >/dev/null ;;
|
|
||||||
*) omz theme browse ;;
|
|
||||||
esac
|
|
||||||
result=$?
|
|
||||||
print -r -- "REJECT:$result:$+functions[_omz_theme_browser]:$+functions[_omz_theme_preview]"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
function _omz::theme::use { calls+=("use:$1"); ZSH_THEME=$1; }
|
|
||||||
function _omz::theme::set { calls+=("set:$1"); ZSH_THEME=$1; }
|
|
||||||
function browser_test_hook { : parent-hook; }
|
|
||||||
function precmd { : parent-precmd; }
|
|
||||||
typeset -a calls=() precmd_functions=(browser_test_hook) chpwd_functions=(browser_test_hook)
|
|
||||||
ZSH_THEME=parent-theme PROMPT=parent-prompt RPROMPT=parent-rprompt
|
|
||||||
typeset original_hook=$functions[browser_test_hook] original_precmd=$functions[precmd]
|
|
||||||
typeset original_options=$(setopt) original_pwd=$PWD
|
|
||||||
stty rows 24 cols 100
|
|
||||||
# PENDIN is a transient kernel input-reprocessing flag, not a user mode.
|
|
||||||
typeset original_tty=$(stty -a)
|
|
||||||
original_tty=${${original_tty//-pendin/}//pendin/}
|
|
||||||
tty > "$TEST_SCRATCH/tty"
|
|
||||||
print -r -- READY
|
|
||||||
# An interactive script otherwise aborts on SIGINT instead of returning to
|
|
||||||
# the next prompt as an interactive command loop would.
|
|
||||||
trap ':' INT
|
|
||||||
case $BROWSER_TEST_EXIT_TRAP in
|
|
||||||
function) function TRAPEXIT { print -r -- EXIT_HOOK; } ;;
|
|
||||||
string) trap 'print -r -- EXIT_HOOK' EXIT ;;
|
|
||||||
esac
|
|
||||||
typeset original_exit_trap=${functions[TRAPEXIT]-}
|
|
||||||
omz theme browse "$2"
|
|
||||||
result=$?
|
|
||||||
if [[ -n $BROWSER_TEST_EXIT_TRAP ]]; then
|
|
||||||
[[ ${functions[TRAPEXIT]-} == "$original_exit_trap" ]] && print -r -- EXIT_FUNCTION_UNCHANGED
|
|
||||||
trap
|
|
||||||
trap - EXIT
|
|
||||||
fi
|
|
||||||
typeset restored_tty=$(stty -a)
|
|
||||||
restored_tty=${${restored_tty//-pendin/}//pendin/}
|
|
||||||
if [[ $restored_tty == "$original_tty" ]]; then
|
|
||||||
print -r -- TTY_RESTORED
|
|
||||||
else
|
|
||||||
print -r -- "TTY_MISMATCH:before=$original_tty after=$restored_tty"
|
|
||||||
fi
|
|
||||||
if [[ $PROMPT == parent-prompt && $RPROMPT == parent-rprompt &&
|
|
||||||
$functions[browser_test_hook] == "$original_hook" &&
|
|
||||||
$functions[precmd] == "$original_precmd" &&
|
|
||||||
${(j:,:)precmd_functions} == browser_test_hook &&
|
|
||||||
${(j:,:)chpwd_functions} == browser_test_hook &&
|
|
||||||
-o promptsubst && $(setopt) == "$original_options" && $PWD == "$original_pwd" &&
|
|
||||||
${BROWSER_TEST_LEAK-unset} == unset ]]; then
|
|
||||||
print -r -- PARENT_UNCHANGED
|
|
||||||
fi
|
|
||||||
print -r -- "RESULT:$result:${(j:,:)calls}:$ZSH_THEME"
|
|
||||||
print -r -- FINISHED
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
setopt err_exit pipe_fail
|
|
||||||
[[ -n $BROWSER_TEST_TRACE ]] && setopt xtrace
|
|
||||||
zmodload zsh/zpty
|
|
||||||
zmodload zsh/datetime
|
|
||||||
zmodload zsh/zselect
|
|
||||||
typeset -r repo=${0:A:h:h:h:h} self=${0:A}
|
|
||||||
typeset scratch=$(mktemp -d "${TMPDIR:-/tmp}/omz-browser-test.XXXXXXXX")
|
|
||||||
scratch=${scratch:A}
|
|
||||||
trap 'zpty -d 2>/dev/null; command rm -rf -- "$scratch"' EXIT
|
|
||||||
trap 'exit 130' INT
|
|
||||||
trap 'exit 143' TERM
|
|
||||||
mkdir -p "$scratch/home" "$scratch/custom/themes/nested" "$scratch/tmp"
|
|
||||||
export ZSH=$repo ZSH_CUSTOM=$scratch/custom HOME=$scratch/home ZDOTDIR=$scratch/home
|
|
||||||
export TMPDIR=$scratch/tmp TEST_SCRATCH=$scratch TERM=xterm-256color
|
|
||||||
unset ZSH_THEME
|
|
||||||
# Even a mistakenly enabled startup-file load must never reach real dotfiles.
|
|
||||||
print -r -- 'print STARTUP_RAN; exit 99' > "$HOME/.zshenv"
|
|
||||||
print -r -- 'PROMPT="nested fixture"' > "$ZSH_CUSTOM/themes/nested/browser-fixture.zsh-theme"
|
|
||||||
for number in {01..10}; do
|
|
||||||
print -r -- 'typeset -g BROWSER_TEST_LEAK=bad
|
|
||||||
ZSH_THEME=fixture-theme
|
|
||||||
precmd_functions=() chpwd_functions=()
|
|
||||||
function precmd { PROMPT="%F{red}FIXTURE_PREVIEW%f" }
|
|
||||||
RPROMPT="fixture-right"' > "$ZSH_CUSTOM/zz-omz-test-$number.zsh-theme"
|
|
||||||
done
|
|
||||||
print -r -- 'sleep 30 &
|
|
||||||
print -r -- $! > "$TEST_SCRATCH/slow-pid"
|
|
||||||
wait
|
|
||||||
PROMPT="SLOW_FINISHED"' > "$ZSH_CUSTOM/zz-omz-test-slow.zsh-theme"
|
|
||||||
typeset filter_probe='$(print HIT > $TEST_SCRATCH/filter-executed)'
|
|
||||||
typeset preview_probe='$(print HIT > $TEST_SCRATCH/preview-executed)'
|
|
||||||
# Emit literal preview output, rather than asking the worker to evaluate a
|
|
||||||
# prompt expression. Only a second evaluation by the browser can execute it.
|
|
||||||
print -rl -- "print -r -- ${(q)preview_probe}" 'PROMPT="literal-preview-ready"' > "$ZSH_CUSTOM/literal-browser.zsh-theme"
|
|
||||||
typeset backslash_probe='literal:\e[2J\n\c:end'
|
|
||||||
print -rl -- "print -r -- ${(q)backslash_probe}" 'PROMPT="backslash-preview-ready"' > "$ZSH_CUSTOM/backslash-browser.zsh-theme"
|
|
||||||
|
|
||||||
typeset buffer='' transcript='' chunk='' label=''
|
|
||||||
typeset -F browser_finished_at=0
|
|
||||||
function cleanup_pty {
|
|
||||||
local record group
|
|
||||||
for record in "${(@f)$(zpty)}"; do
|
|
||||||
[[ $record == \(<->\)\ browser:* ]] || continue
|
|
||||||
group=${${record#\(}%%\)*}
|
|
||||||
kill -HUP -- -$group 2>/dev/null || true
|
|
||||||
zselect -t 20 || true
|
|
||||||
# A renderer regression can loop without checking its cancellation flag.
|
|
||||||
kill -KILL -- -$group 2>/dev/null || true
|
|
||||||
done
|
|
||||||
zpty -d 2>/dev/null || true
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
function fail {
|
|
||||||
print -u2 -r -- "FAIL: $label: $1"
|
|
||||||
print -u2 -r -- "PTY transcript, last 4000 characters (escaped): ${(V)transcript[-4000,-1]}"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
function check {
|
|
||||||
"$@" || fail "$1 assertion failed"
|
|
||||||
}
|
|
||||||
function await {
|
|
||||||
local wanted=$1
|
|
||||||
local -F deadline=$(( EPOCHREALTIME + ${2:-6} ))
|
|
||||||
[[ $buffer == *"$wanted"* ]] && return 0
|
|
||||||
while (( EPOCHREALTIME < deadline )); do
|
|
||||||
if zpty -r browser chunk; then
|
|
||||||
buffer+=$chunk transcript+=$chunk
|
|
||||||
[[ $buffer == *"$wanted"* ]] && return 0
|
|
||||||
else
|
|
||||||
zselect -t 1 || true
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fail "timed out waiting for ${(V)wanted}"
|
|
||||||
}
|
|
||||||
function send {
|
|
||||||
buffer=''
|
|
||||||
zpty -w -n browser "$1"
|
|
||||||
}
|
|
||||||
function start {
|
|
||||||
label=$1 buffer='' transcript=''
|
|
||||||
local -a launch=("$commands[zsh]" -dfi "$self" --child "$2")
|
|
||||||
zpty -b browser exec "${(@q)launch}"
|
|
||||||
await 'LAZY:0:0'
|
|
||||||
await "$3"
|
|
||||||
}
|
|
||||||
function finish {
|
|
||||||
await FINISHED
|
|
||||||
# zpty -d can spend a second reaping an already-completed child. It is
|
|
||||||
# harness teardown, not browser cancellation/terminal-restoration latency.
|
|
||||||
browser_finished_at=$EPOCHREALTIME
|
|
||||||
check test "${transcript#*TTY_RESTORED}" != "$transcript"
|
|
||||||
check test "${transcript#*PARENT_UNCHANGED}" != "$transcript"
|
|
||||||
check test "${transcript#*RESULT:$1}" != "$transcript"
|
|
||||||
check test "${transcript#*$'\e[?1049l'}" != "$transcript"
|
|
||||||
check test "${transcript#*$'\e[?25h'}" != "$transcript"
|
|
||||||
check test "${transcript#*STARTUP_RAN}" = "$transcript"
|
|
||||||
zpty -d browser
|
|
||||||
[[ -z $BROWSER_TEST_TIMING ]] || print -r -- "TIMING: PTY deletion $(( EPOCHREALTIME - browser_finished_at ))s"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_completion {
|
|
||||||
start 'completion registration, commands, theme candidates, lazy loading' completion COMPLETIONS_FINISHED
|
|
||||||
check test "${transcript#*REGISTERED:_omz:omz}" != "$transcript"
|
|
||||||
local section=${${transcript#*SUBCOMMANDS}%END_SUBCOMMANDS*} action
|
|
||||||
check test "${section#*browse:Browse theme previews}" != "$section"
|
|
||||||
check test "${section#*preview:Preview a theme without applying it}" != "$section"
|
|
||||||
for action in browse preview set use; do
|
|
||||||
section=${${transcript#*CANDIDATES:$action}%END:$action*}
|
|
||||||
check test "${section#*DESCRIBE:theme}" != "$section"
|
|
||||||
for name in robbyrussell zz-omz-test-01 nested/browser-fixture; do
|
|
||||||
check test "${section#*$name}" != "$section"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
check test "${transcript#*STILL_LAZY:0:0}" != "$transcript"
|
|
||||||
check test "${transcript#*STARTUP_RAN}" = "$transcript"
|
|
||||||
zpty -d browser
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_rejection {
|
|
||||||
# Noninteractive rejection even with both descriptors attached to a PTY.
|
|
||||||
label=noninteractive
|
|
||||||
typeset -a launch=("$commands[zsh]" -df "$self" --child reject)
|
|
||||||
zpty -b browser exec "${(@q)launch}"
|
|
||||||
await 'REJECT:1:0:0'
|
|
||||||
check test "${transcript#*requires an interactive terminal}" != "$transcript"
|
|
||||||
zpty -d browser
|
|
||||||
for mode in stdin stdout; do
|
|
||||||
start "redirected $mode" "reject-$mode" 'REJECT:1:0:0'
|
|
||||||
check test "${transcript#*requires an interactive terminal}" != "$transcript"
|
|
||||||
zpty -d browser
|
|
||||||
done
|
|
||||||
label='noninteractive and redirected-I/O rejection'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_navigation {
|
|
||||||
start 'filter, navigation, actions/back, Esc isolation' zz-omz-test- '> zz-omz-test-01'
|
|
||||||
await FIXTURE_PREVIEW
|
|
||||||
send $'\e[B'; await '> zz-omz-test-02'
|
|
||||||
send $'\e[A'; await '> zz-omz-test-01'
|
|
||||||
send $'\x0e'; await '> zz-omz-test-02'
|
|
||||||
send $'\x10'; await '> zz-omz-test-01'
|
|
||||||
send $'\e[6~'; await '> zz-omz-test-05'
|
|
||||||
send $'\e[5~'; await '> zz-omz-test-01'
|
|
||||||
send '09'; await '> zz-omz-test-09'
|
|
||||||
send $'\x7f'; await '(9 themes)'
|
|
||||||
send $'\x15'; await 'Filter: ('
|
|
||||||
send 'ZZ-OMZ-TEST-03'; await '> zz-omz-test-03'
|
|
||||||
send $'\r'; await '[u] Use in session'
|
|
||||||
send b; await 'Enter: actions'
|
|
||||||
send $'\x15no-such-omz-fixture'; await 'No matching themes.'
|
|
||||||
send $'\r'; await 'No matching themes.'
|
|
||||||
send $'\e'
|
|
||||||
finish '0::parent-theme'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_use {
|
|
||||||
start 'explicit use dispatch' zz-omz-test-01 '> zz-omz-test-01'
|
|
||||||
send $'\r'; await '[u] Use in session'
|
|
||||||
send u
|
|
||||||
finish '0:use:zz-omz-test-01:zz-omz-test-01'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_promptsubst {
|
|
||||||
start 'literal filter/preview substitutions with parent promptsubst enabled' literal-browser '> literal-browser'
|
|
||||||
await "$preview_probe"
|
|
||||||
await literal-preview-ready
|
|
||||||
check test ! -e "$scratch/preview-executed"
|
|
||||||
send $'\x15'"$filter_probe"
|
|
||||||
await "Filter: $filter_probe"
|
|
||||||
await 'No matching themes.'
|
|
||||||
check test ! -e "$scratch/filter-executed"
|
|
||||||
send $'\x15literal-browser'
|
|
||||||
await "$preview_probe"
|
|
||||||
await literal-preview-ready
|
|
||||||
send $'\e'
|
|
||||||
finish '0::parent-theme'
|
|
||||||
check test ! -e "$scratch/filter-executed"
|
|
||||||
check test ! -e "$scratch/preview-executed"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_save {
|
|
||||||
start 'explicit save dispatch (stubbed)' zz-omz-test-02 '> zz-omz-test-02'
|
|
||||||
send $'\r'; await '[u] Use in session'
|
|
||||||
send s
|
|
||||||
finish '0:set:zz-omz-test-02:zz-omz-test-02'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_backslashes {
|
|
||||||
start 'literal backslashes in preview and filter' backslash-browser '> backslash-browser'
|
|
||||||
await "$backslash_probe"
|
|
||||||
await backslash-preview-ready
|
|
||||||
send $'\x15'"$backslash_probe"
|
|
||||||
await "Filter: $backslash_probe"
|
|
||||||
await 'No matching themes.'
|
|
||||||
send $'\e'
|
|
||||||
finish '0::parent-theme'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_promptpercent {
|
|
||||||
local -x BROWSER_TEST_NO_PROMPT_PERCENT=1
|
|
||||||
start 'renderer enables promptpercent without changing parent options' zz-omz-test-01 '> zz-omz-test-01'
|
|
||||||
await FIXTURE_PREVIEW
|
|
||||||
check test "${transcript#*'%<<'}" = "$transcript"
|
|
||||||
send $'\e'
|
|
||||||
finish '0::parent-theme'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_exittrap {
|
|
||||||
local -x BROWSER_TEST_EXIT_TRAP
|
|
||||||
local action
|
|
||||||
for BROWSER_TEST_EXIT_TRAP in function string; do
|
|
||||||
for action in use set cancel; do
|
|
||||||
start "inherited $BROWSER_TEST_EXIT_TRAP EXIT trap: $action" zz-omz-test-01 '> zz-omz-test-01'
|
|
||||||
await FIXTURE_PREVIEW
|
|
||||||
if [[ $action == cancel ]]; then
|
|
||||||
send $'\e'
|
|
||||||
finish '0::parent-theme'
|
|
||||||
else
|
|
||||||
send $'\r'; await '[u] Use in session'
|
|
||||||
send "${action[1]}"
|
|
||||||
finish "0:$action:zz-omz-test-01:zz-omz-test-01"
|
|
||||||
fi
|
|
||||||
check test "${transcript#*EXIT_FUNCTION_UNCHANGED}" != "$transcript"
|
|
||||||
if [[ $BROWSER_TEST_EXIT_TRAP == string ]]; then
|
|
||||||
check test "${transcript#*"trap -- 'print -r -- EXIT_HOOK' EXIT"}" != "$transcript"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_interrupt {
|
|
||||||
start 'Ctrl-C restores terminal' zz-omz-test-01 '> zz-omz-test-01'
|
|
||||||
send $'\x03'
|
|
||||||
finish '130::parent-theme'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_resize {
|
|
||||||
start 'resize small and back' zz-omz-test-01 '> zz-omz-test-01'
|
|
||||||
typeset terminal=$(<"$scratch/tty")
|
|
||||||
terminal=${terminal//$'\r'/}
|
|
||||||
buffer=''
|
|
||||||
stty rows 10 cols 30 < "$terminal"
|
|
||||||
await '40 columns x 16 rows.'
|
|
||||||
buffer=''
|
|
||||||
stty rows 24 cols 100 < "$terminal"
|
|
||||||
await '> zz-omz-test-01'
|
|
||||||
send $'\e'
|
|
||||||
finish '0::parent-theme'
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_slow {
|
|
||||||
local cancellation=$1
|
|
||||||
command rm -f "$scratch/slow-pid"
|
|
||||||
start "slow preview cancellation: $cancellation" zz-omz-test-slow '> zz-omz-test-slow'
|
|
||||||
for attempt in {1..150}; do
|
|
||||||
[[ -s "$scratch/slow-pid" ]] && break
|
|
||||||
zselect -t 1 || true
|
|
||||||
done
|
|
||||||
check test -s "$scratch/slow-pid"
|
|
||||||
typeset -F started=$EPOCHREALTIME
|
|
||||||
case $cancellation in
|
|
||||||
navigation)
|
|
||||||
send $'\x15zz-omz-test-01'
|
|
||||||
await FIXTURE_PREVIEW 2
|
|
||||||
[[ -z $BROWSER_TEST_TIMING ]] || print -r -- "TIMING: navigation preview $(( EPOCHREALTIME - started ))s"
|
|
||||||
(( EPOCHREALTIME - started < 2 )) || fail 'replacement preview exceeded 2 seconds'
|
|
||||||
send $'\e'
|
|
||||||
finish '0::parent-theme'
|
|
||||||
;;
|
|
||||||
escape) send $'\e'; finish '0::parent-theme' ;;
|
|
||||||
interrupt) send $'\x03'; finish '130::parent-theme' ;;
|
|
||||||
esac
|
|
||||||
[[ -z $BROWSER_TEST_TIMING ]] || print -r -- "TIMING: browser completed $(( browser_finished_at - started ))s; including teardown $(( EPOCHREALTIME - started ))s"
|
|
||||||
(( browser_finished_at - started < 2 )) || fail "browser completion exceeded 2 seconds: $(( browser_finished_at - started ))s"
|
|
||||||
typeset child=$(<"$scratch/slow-pid") child_state
|
|
||||||
for attempt in {1..100}; do
|
|
||||||
child_state=$(command ps -o stat= -p "$child" 2>/dev/null || true)
|
|
||||||
[[ -z "${child_state//[ ZN+]/}" ]] && break
|
|
||||||
zselect -t 1 || true
|
|
||||||
done
|
|
||||||
[[ -z $BROWSER_TEST_TIMING ]] || print -r -- "TIMING: descendant $child state=${child_state:-absent}, cleanup polls=$attempt"
|
|
||||||
[[ -z "${child_state//[ ZN+]/}" ]] || fail "preview descendant $child still running: $child_state"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Keep independent regressions running after a failed UI session.
|
|
||||||
unsetopt err_exit
|
|
||||||
typeset -i failures=0
|
|
||||||
for scenario in rejection completion navigation promptsubst backslashes promptpercent exittrap use save interrupt resize slow-navigation slow-escape slow-interrupt; do
|
|
||||||
[[ -z $1 || $scenario == "$1" ]] || continue
|
|
||||||
(
|
|
||||||
setopt err_exit
|
|
||||||
trap 'cleanup_pty' EXIT
|
|
||||||
if [[ $scenario == slow-* ]]; then
|
|
||||||
test_slow "${scenario#slow-}"
|
|
||||||
else
|
|
||||||
test_$scenario
|
|
||||||
fi
|
|
||||||
print -r -- "PASS: $label"
|
|
||||||
)
|
|
||||||
(( $? == 0 )) || (( failures++ ))
|
|
||||||
done
|
|
||||||
typeset -a leftovers
|
|
||||||
for attempt in {1..100}; do
|
|
||||||
leftovers=("$TMPDIR"/omz-preview.*(N))
|
|
||||||
(( $#leftovers == 0 )) && break
|
|
||||||
zselect -t 1 || true
|
|
||||||
done
|
|
||||||
if (( $#leftovers )); then
|
|
||||||
print -u2 -r -- "FAIL: $#leftovers preview temporary directories remain"
|
|
||||||
(( failures++ ))
|
|
||||||
fi
|
|
||||||
print -r -- "Theme browser regression groups failed: $failures"
|
|
||||||
(( failures == 0 ))
|
|
||||||
@@ -1,282 +0,0 @@
|
|||||||
#!/usr/bin/env zsh
|
|
||||||
# Run with: zsh -df tools/theme-browser/tests/preview_test.zsh
|
|
||||||
emulate -R zsh
|
|
||||||
setopt err_exit pipe_fail
|
|
||||||
typeset -r repo=${0:A:h:h:h:h}
|
|
||||||
source "$repo/tools/theme-browser/preview.zsh"
|
|
||||||
typeset scratch=$(mktemp -d "${TMPDIR:-/tmp}/omz-preview-test.XXXXXXXX")
|
|
||||||
scratch=${scratch:A}
|
|
||||||
trap 'command rm -rf -- "$scratch"' EXIT
|
|
||||||
trap 'exit 130' INT
|
|
||||||
trap 'exit 143' TERM
|
|
||||||
mkdir "$scratch/tmp"
|
|
||||||
export TMPDIR=$scratch/tmp
|
|
||||||
|
|
||||||
function check {
|
|
||||||
if ! "$@"; then
|
|
||||||
print -u2 -r -- "FAIL: ${(j: :)@}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
export ZSH=$scratch/omz ZSH_CUSTOM=$scratch/custom
|
|
||||||
mkdir -p "$ZSH/themes" "$ZSH_CUSTOM/themes/nested" "$scratch/home" "$scratch/work"
|
|
||||||
print -r -- "PROMPT='bundled'" > "$ZSH/themes/same.zsh-theme"
|
|
||||||
print -r -- "PROMPT='custom themes'" > "$ZSH_CUSTOM/themes/same.zsh-theme"
|
|
||||||
print -r -- "PROMPT='custom root'" > "$ZSH_CUSTOM/same.zsh-theme"
|
|
||||||
print -r -- "PROMPT='z'" > "$ZSH/themes/zebra.zsh-theme"
|
|
||||||
print -r -- "PROMPT='a'" > "$ZSH/themes/alpha.zsh-theme"
|
|
||||||
print -r -- "PROMPT='bad'" > "$ZSH/themes/"$'bad\nname.zsh-theme'
|
|
||||||
print -r -- "PROMPT='random'" > "$ZSH/themes/random.zsh-theme"
|
|
||||||
print -r -- "PROMPT='nested'" > "$ZSH_CUSTOM/themes/nested/example.zsh-theme"
|
|
||||||
check test "$(_omz_theme_names)" = $'alpha\nnested/example\nsame\nzebra'
|
|
||||||
check test "$(_omz_theme_resolve nested/example)" = "$ZSH_CUSTOM/themes/nested/example.zsh-theme"
|
|
||||||
check test "$(_omz_theme_resolve same)" = "$ZSH_CUSTOM/same.zsh-theme"
|
|
||||||
rm "$ZSH_CUSTOM/same.zsh-theme"
|
|
||||||
check test "$(_omz_theme_resolve same)" = "$ZSH_CUSTOM/themes/same.zsh-theme"
|
|
||||||
rm "$ZSH_CUSTOM/themes/same.zsh-theme"
|
|
||||||
check test "$(_omz_theme_resolve same)" = "$ZSH/themes/same.zsh-theme"
|
|
||||||
for name in ../same /same . .. nested/../same nested/./example nested//example random $'bad\nname' 'bad\name' missing ''; do
|
|
||||||
if _omz_theme_resolve "$name" > /dev/null 2>&1; then
|
|
||||||
print -u2 -r -- 'FAIL: accepted invalid/missing name'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# The fixtures intentionally write only inside this private, always-cleaned tree.
|
|
||||||
print -r -- 'print STARTUP_RAN; exit 99' > "$scratch/home/.zshenv"
|
|
||||||
export ZDOTDIR=$scratch/home PREVIEW_ENV=preserved
|
|
||||||
print -r -- '
|
|
||||||
typeset -g PREVIEW_LEAK=bad
|
|
||||||
export PREVIEW_ENV=changed
|
|
||||||
alias preview_leak=true
|
|
||||||
setopt noclobber
|
|
||||||
function precmd { PROMPT="hook:$PWD:$PREVIEW_ENV:%?" }
|
|
||||||
function second_hook { RPROMPT="second-hook:%?" }
|
|
||||||
precmd_functions=(second_hook)
|
|
||||||
' > "$ZSH_CUSTOM/isolation.zsh-theme"
|
|
||||||
typeset before_pwd=$PWD before_options=$(setopt) before_env=$PREVIEW_ENV
|
|
||||||
typeset output=$(_omz_theme_preview isolation 7)
|
|
||||||
check test "$PWD" = "$before_pwd"
|
|
||||||
check test "$(setopt)" = "$before_options"
|
|
||||||
check test "$PREVIEW_ENV" = "$before_env"
|
|
||||||
check test "${PREVIEW_LEAK-unset}" = unset
|
|
||||||
check test "${aliases[preview_leak]-unset}" = unset
|
|
||||||
check test "${functions[second_hook]-unset}" = unset
|
|
||||||
check test "${output#*hook:${PWD}:changed:7}" != "$output"
|
|
||||||
check test "${output#*second-hook:7}" != "$output"
|
|
||||||
check test "${output#*STARTUP_RAN}" = "$output"
|
|
||||||
|
|
||||||
print -r -- 'PROMPT="env:$PREVIEW_ENV cwd:$PWD %(?.success.failure)"' > "$ZSH_CUSTOM/status.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview status)
|
|
||||||
check test "${output#*env:preserved cwd:${PWD} success}" != "$output"
|
|
||||||
output=$(_omz_theme_preview status 1)
|
|
||||||
check test "${output#*failure}" != "$output"
|
|
||||||
if _omz_theme_preview status nope >/dev/null 2>&1; then exit 1; fi
|
|
||||||
|
|
||||||
# Values produced by parameters or helpers are prompt text, not shell code for
|
|
||||||
# a second substitution pass. Check both sides and the helper's incoming status.
|
|
||||||
export PREVIEW_REEXECUTED=$scratch/reexecuted
|
|
||||||
export PREVIEW_LITERAL='$(print reexecuted > "$PREVIEW_REEXECUTED")'
|
|
||||||
print -r -- '
|
|
||||||
function literal_helper { print -r -- "helper-status:$? $PREVIEW_LITERAL" }
|
|
||||||
PROMPT='"'"'$PREVIEW_LITERAL $(literal_helper) %?'"'"'
|
|
||||||
RPROMPT='"'"'$(literal_helper) $PREVIEW_LITERAL %?'"'"'
|
|
||||||
' > "$ZSH_CUSTOM/literal.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview literal 7)
|
|
||||||
check test ! -e "$PREVIEW_REEXECUTED"
|
|
||||||
check test "${output#*"$PREVIEW_LITERAL"}" != "$output"
|
|
||||||
check test "${output#*helper-status:7}" != "$output"
|
|
||||||
check test "${output#*"$PREVIEW_LITERAL 7"}" != "$output"
|
|
||||||
print -r -- 'unsetopt promptsubst; PROMPT='"'"'$PREVIEW_LITERAL %?'"'" > "$ZSH_CUSTOM/no-subst.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview no-subst 7)
|
|
||||||
check test "${output#*'$PREVIEW_LITERAL 7'}" != "$output"
|
|
||||||
|
|
||||||
print -r -- 'PROMPT="conditional prompt"; [[ -n ${OMZ_PREVIEW_UNSET_SSH-} ]] && RPROMPT="remote"' > "$ZSH_CUSTOM/final-false.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview final-false)
|
|
||||||
check test "${output#*conditional prompt}" != "$output"
|
|
||||||
print -r -- 'PROMPT=""' > "$ZSH_CUSTOM/empty.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview empty)
|
|
||||||
print -r -- 'RPROMPT="right-only"; false' > "$ZSH_CUSTOM/right-only.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview right-only)
|
|
||||||
check test "${output#*right-only}" != "$output"
|
|
||||||
|
|
||||||
# A helper can fail inside command substitution without making print -P fail.
|
|
||||||
# Its runtime diagnostic must remain visible in the sanitized partial preview.
|
|
||||||
print -r -- 'PROMPT='"'"'$( _omz_preview_missing_helper )'"'" > "$ZSH_CUSTOM/helper-failure.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview helper-failure 2>&1)
|
|
||||||
check test "${output#*command not found: _omz_preview_missing_helper}" != "$output"
|
|
||||||
|
|
||||||
# A failing precmd (or array hook) stops later hooks, as in interactive zsh.
|
|
||||||
# Preserve any partial preview, but report failure rather than silently claiming
|
|
||||||
# that an incomplete initialization is a faithful preview.
|
|
||||||
for hook_setup in 'precmd() { return 3 }; precmd_functions=(must_not_run)' \
|
|
||||||
'failed_hook() { return 4 }; precmd_functions=(failed_hook must_not_run)' \
|
|
||||||
'failed_hook() { _omz_preview_missing_command }; precmd_functions=(failed_hook must_not_run)'; do
|
|
||||||
print -rl -- 'PROMPT="partial prompt"; must_not_run() { print UNEXPECTED_HOOK; }' "$hook_setup" > "$ZSH_CUSTOM/hook-failure.zsh-theme"
|
|
||||||
if _omz_theme_preview hook-failure >"$scratch/hook-error" 2>&1; then
|
|
||||||
print -u2 -r -- 'FAIL: accepted failing precmd hook'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
output=$(<"$scratch/hook-error")
|
|
||||||
check test "${output#*UNEXPECTED_HOOK}" = "$output"
|
|
||||||
check test "${output#*remaining hooks skipped}" != "$output"
|
|
||||||
check test "${output#*partial prompt}" != "$output"
|
|
||||||
done
|
|
||||||
|
|
||||||
# No language runtime, timeout utility, or process-inspection utility is needed
|
|
||||||
# by the backend. The worker still has zsh's usual autoload/module search paths.
|
|
||||||
mkdir "$scratch/bin"
|
|
||||||
for name in zsh mktemp mkfifo rm; do
|
|
||||||
ln -s "$commands[$name]" "$scratch/bin/$name"
|
|
||||||
done
|
|
||||||
output=$(PATH="$scratch/bin" _omz_theme_preview status)
|
|
||||||
check test "${output#*success}" != "$output"
|
|
||||||
print -r -- '[[ ! -t 0 && ! -t 1 && ! -t 2 && ! -o interactive ]] || exit 9; PROMPT="non-tty"' > "$ZSH_CUSTOM/non-tty.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview non-tty)
|
|
||||||
check test "${output#*non-tty}" != "$output"
|
|
||||||
|
|
||||||
print -r -- 'print -n -- "\e]52;c;SECRET\a\e[2J\r\b\ePSECRET\e\\"; PROMPT="%F{red}safe%f"' > "$ZSH_CUSTOM/escapes.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview escapes)
|
|
||||||
check test "${output#*SECRET}" = "$output"
|
|
||||||
check test "${output#*$'\e[2J'}" = "$output"
|
|
||||||
check test "${output#*$'\r'}" = "$output"
|
|
||||||
check test "${output#*$'\e[31m'safe}" != "$output"
|
|
||||||
|
|
||||||
for code in 'return 1' 'exit 0' 'exit 7' 'if then' 'PROMPT="partial"; if then' \
|
|
||||||
'PROMPT="partial"; return 2' 'PROMPT="partial"; _omz_preview_missing_command'; do
|
|
||||||
print -r -- "$code" > "$ZSH_CUSTOM/broken.zsh-theme"
|
|
||||||
if _omz_theme_preview broken >"$scratch/error" 2>&1; then
|
|
||||||
print -u2 -r -- "FAIL: accepted broken theme: $code"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
print -r -- 'while true; do print -r -- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; done' > "$ZSH_CUSTOM/flood.zsh-theme"
|
|
||||||
if _omz_theme_preview flood >"$scratch/flood" 2>&1; then exit 1; fi
|
|
||||||
check test "$(wc -c < "$scratch/flood")" -le 32768
|
|
||||||
print -r -- 'printf "\377%.0s" {1..11000}; PROMPT="safe"' > "$ZSH_CUSTOM/bytes.zsh-theme"
|
|
||||||
_omz_theme_preview bytes >"$scratch/bytes" 2>&1
|
|
||||||
check test "$(wc -c < "$scratch/bytes")" -le 32768
|
|
||||||
check test "${$(<"$scratch/bytes")#*$'\xff'}" = "$(<"$scratch/bytes")"
|
|
||||||
print -r -- 'printf "\233m%.0s" {1..12000}; PROMPT="safe"' > "$ZSH_CUSTOM/csi-bytes.zsh-theme"
|
|
||||||
_omz_theme_preview csi-bytes >"$scratch/csi-bytes" 2>&1
|
|
||||||
check test "$(wc -c < "$scratch/csi-bytes")" -le 32768
|
|
||||||
|
|
||||||
print -r -- 'sleep 30 & print -r -- $! > "$PREVIEW_PID_FILE"; wait' > "$ZSH_CUSTOM/slow.zsh-theme"
|
|
||||||
export PREVIEW_PID_FILE=$scratch/child
|
|
||||||
zmodload zsh/datetime
|
|
||||||
typeset -F started=$EPOCHREALTIME
|
|
||||||
if _omz_theme_preview slow >"$scratch/timeout" 2>&1; then exit 1; fi
|
|
||||||
check test $(( EPOCHREALTIME - started < 5 )) = 1
|
|
||||||
check test "${$(<"$scratch/timeout")#*timed out}" != "$(<"$scratch/timeout")"
|
|
||||||
typeset child=$(<"$scratch/child")
|
|
||||||
# A killed orphan may briefly remain a zombie until the system reaps it.
|
|
||||||
typeset child_state=$(command ps -o stat= -p "$child" 2>/dev/null || true)
|
|
||||||
check test -z "${child_state//[ ZN+]/}"
|
|
||||||
|
|
||||||
for signal in INT TERM HUP; do
|
|
||||||
rm -f "$PREVIEW_PID_FILE"
|
|
||||||
_omz_theme_preview slow >"$scratch/cancel" 2>&1 &
|
|
||||||
typeset preview_job=$!
|
|
||||||
for attempt in {1..100}; do
|
|
||||||
[[ -s "$PREVIEW_PID_FILE" ]] && break
|
|
||||||
sleep 0.01
|
|
||||||
done
|
|
||||||
check test -s "$PREVIEW_PID_FILE"
|
|
||||||
# zsh adds a waiting wrapper around a backgrounded subshell function.
|
|
||||||
# Signal the supervisor itself; terminal interrupts reach it via the job group.
|
|
||||||
typeset supervisor='' candidate='' parent=''
|
|
||||||
for candidate parent in ${(z)$(command ps -A -o pid= -o ppid=)}; do
|
|
||||||
if [[ $parent == $preview_job ]]; then
|
|
||||||
supervisor=$candidate
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
check test -n "$supervisor"
|
|
||||||
kill -$signal "$supervisor"
|
|
||||||
typeset result=0
|
|
||||||
wait "$preview_job" || result=$?
|
|
||||||
if (( result != 130 && result != 143 && result != 129 )); then
|
|
||||||
print -u2 -r -- "Unexpected cancellation result: $result: $(<"$scratch/cancel")"
|
|
||||||
fi
|
|
||||||
if [[ $signal == INT ]]; then
|
|
||||||
check test "$result" = 130
|
|
||||||
elif [[ $signal == TERM ]]; then
|
|
||||||
check test "$result" = 143
|
|
||||||
else
|
|
||||||
check test "$result" = 129
|
|
||||||
fi
|
|
||||||
child=$(<"$PREVIEW_PID_FILE")
|
|
||||||
child_state=$(command ps -o stat= -p "$child" 2>/dev/null || true)
|
|
||||||
check test -z "${child_state//[ ZN+]/}"
|
|
||||||
done
|
|
||||||
|
|
||||||
print -r -- 'sleep 30 & print -r -- $! > "$PREVIEW_PID_FILE"; PROMPT="background"' > "$ZSH_CUSTOM/background.zsh-theme"
|
|
||||||
output=$(_omz_theme_preview background)
|
|
||||||
child=$(<"$PREVIEW_PID_FILE")
|
|
||||||
child_state=$(command ps -o stat= -p "$child" 2>/dev/null || true)
|
|
||||||
check test -z "${child_state//[ ZN+]/}"
|
|
||||||
|
|
||||||
# Match the browser's nested-PTY invocation, preserving other owned PTYs.
|
|
||||||
zmodload zsh/zpty
|
|
||||||
zpty -b unrelated 'exec sleep 30'
|
|
||||||
typeset -a nested_command=("$commands[zsh]" -dfc 'source "$1"; _omz_theme_preview status' zsh "$repo/tools/theme-browser/preview.zsh")
|
|
||||||
zpty -b browser exec "${(@q)nested_command}"
|
|
||||||
output=''
|
|
||||||
for attempt in {1..300}; do
|
|
||||||
if zpty -r browser chunk; then
|
|
||||||
output+=$chunk
|
|
||||||
elif ! zpty -t browser; then
|
|
||||||
break
|
|
||||||
else
|
|
||||||
sleep 0.01
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
check test "${output#*success}" != "$output"
|
|
||||||
check zpty -t unrelated
|
|
||||||
zpty -d browser unrelated
|
|
||||||
|
|
||||||
# Cancellation by the browser's outer process group must also clean the
|
|
||||||
# backend's separate inner PTY group and private FIFO directory.
|
|
||||||
rm -f "$PREVIEW_PID_FILE"
|
|
||||||
nested_command=("$commands[zsh]" -dfc 'source "$1"; _omz_theme_preview slow' zsh "$repo/tools/theme-browser/preview.zsh")
|
|
||||||
zpty -b browser exec "${(@q)nested_command}"
|
|
||||||
typeset browser_group record
|
|
||||||
for record in "${(@f)$(zpty)}"; do
|
|
||||||
[[ $record == \(<->\)\ browser:* ]] && browser_group=${${record#\(}%%\)*}
|
|
||||||
done
|
|
||||||
check test -n "$browser_group"
|
|
||||||
for attempt in {1..100}; do
|
|
||||||
[[ -s "$PREVIEW_PID_FILE" ]] && break
|
|
||||||
sleep 0.01
|
|
||||||
done
|
|
||||||
check test -s "$PREVIEW_PID_FILE"
|
|
||||||
child=$(<"$PREVIEW_PID_FILE")
|
|
||||||
kill -TERM -- -$browser_group
|
|
||||||
for attempt in {1..100}; do
|
|
||||||
child_state=$(command ps -o stat= -p "$child" 2>/dev/null || true)
|
|
||||||
[[ -z "${child_state//[ ZN+]/}" ]] && break
|
|
||||||
sleep 0.01
|
|
||||||
done
|
|
||||||
check test -z "${child_state//[ ZN+]/}"
|
|
||||||
zpty -d browser
|
|
||||||
|
|
||||||
# Real themes exercise synchronous git, top-level locals, command substitution,
|
|
||||||
# and hook-driven prompt construction against an isolated repository.
|
|
||||||
export ZSH=$repo
|
|
||||||
git -C "$scratch/work" init -q
|
|
||||||
git -C "$scratch/work" symbolic-ref HEAD refs/heads/preview-branch
|
|
||||||
output=$(zsh -dfc 'builtin cd "$1"; source tools/theme-browser/preview.zsh; builtin cd "$2"; _omz_theme_preview robbyrussell' zsh "$repo" "$scratch/work")
|
|
||||||
check test "${output#*preview-branch}" != "$output"
|
|
||||||
for name in robbyrussell dieter agnoster bira nicoulaj half-life; do
|
|
||||||
output=$(builtin cd "$scratch/work"; _omz_theme_preview "$name" 7)
|
|
||||||
check test "${output#*Left prompt}" != "$output"
|
|
||||||
check test "${output#*Right prompt}" != "$output"
|
|
||||||
check test "${output#*preview-branch}" != "$output"
|
|
||||||
if [[ $name == dieter || $name == bira ]]; then
|
|
||||||
check test "${output#*7 }" != "$output"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
typeset -a leftovers=("$TMPDIR"/omz-preview.*(N))
|
|
||||||
check test "$#leftovers" = 0
|
|
||||||
print -r -- 'PASS: theme preview resolution, isolation, single-pass expansion, conditional loads, hook failures, status, sanitization, limits, cancellation, descendant cleanup, and six bundled themes'
|
|
||||||
+3
-12
@@ -271,18 +271,9 @@ if LANG= git pull --quiet --rebase $remote $branch; then
|
|||||||
printf '%s %s %s %s /____/ %s %s %s %s\n' $RAINBOW $RESET
|
printf '%s %s %s %s /____/ %s %s %s %s\n' $RAINBOW $RESET
|
||||||
printf '\n'
|
printf '\n'
|
||||||
printf "${BLUE}%s${RESET}\n\n" "$message"
|
printf "${BLUE}%s${RESET}\n\n" "$message"
|
||||||
printf "${BLUE}${BOLD}%s %s %s %s${RESET}\n" \
|
printf "${BLUE}${BOLD}%s %s${RESET}\n" "To keep up with the latest news and updates, follow us on X:" "$(fmt_link @ohmyzsh https://x.com/ohmyzsh)"
|
||||||
"Follow along on X" "($(fmt_link @ohmyzsh https://x.com/ohmyzsh))" \
|
printf "${BLUE}${BOLD}%s %s${RESET}\n" "Want to get involved in the community? Join our Discord:" "$(fmt_link "Discord server" https://discord.gg/ohmyzsh)"
|
||||||
"or Bluesky" "($(fmt_link @ohmyz.sh https://bsky.app/profile/ohmyz.sh))"
|
printf "${BLUE}${BOLD}%s %s${RESET}\n" "Get your Oh My Zsh swag at:" "$(fmt_link "CommitGoods Shop" https://commitgoods.com/collections/oh-my-zsh)"
|
||||||
printf "${BLUE}${BOLD}%s %s${RESET}\n" \
|
|
||||||
"Questions or ideas? Join the community on" \
|
|
||||||
"$(fmt_link Discord https://discord.gg/ohmyzsh)"
|
|
||||||
printf "${BLUE}${BOLD}%s %s,${RESET}\n" \
|
|
||||||
"Help support the project: sponsor us on" \
|
|
||||||
"$(fmt_link "Open Collective" https://opencollective.com/ohmyzsh)"
|
|
||||||
printf "${BLUE}${BOLD}%s %s${RESET}\n" \
|
|
||||||
"or grab stickers, shirts, and swag from" \
|
|
||||||
"$(fmt_link CommitGoods https://commitgoods.com/ohmyzsh)"
|
|
||||||
elif [[ $verbose_mode == minimal ]]; then
|
elif [[ $verbose_mode == minimal ]]; then
|
||||||
printf "${BLUE}%s${RESET}\n" "$message"
|
printf "${BLUE}%s${RESET}\n" "$message"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user