mirror of
https://github.com/robbyrussell/oh-my-zsh.git
synced 2026-09-21 18:46:06 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de76990950 | ||
|
|
46aee25f27 |
@@ -12,7 +12,7 @@ dependencies:
|
||||
plugins/gradle:
|
||||
repo: gradle/gradle-completion
|
||||
branch: master
|
||||
version: e7c881dbef7462bc35ad05328397e1582fe25cb8
|
||||
version: 63578c9bc56134b80766e88957ba0239e6be2343
|
||||
precopy: |
|
||||
set -e
|
||||
find . ! -name _gradle ! -name LICENSE -delete
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
contents: write # this is needed to push commits and branches
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- macos-latest
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
- test
|
||||
steps:
|
||||
- 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:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
if: github.repository == 'ohmyzsh/ohmyzsh'
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -38,6 +38,7 @@ jobs:
|
||||
./lib/*.zsh \
|
||||
./plugins/*/*.plugin.zsh \
|
||||
./plugins/*/_* \
|
||||
./templates/generators/*/*.zsh-template \
|
||||
./themes/*.zsh-theme; do
|
||||
zsh -n "$file" || return 1
|
||||
done
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
if: github.repository == 'ohmyzsh/ohmyzsh'
|
||||
steps:
|
||||
- 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:
|
||||
egress-policy: audit
|
||||
- name: Authenticate as @ohmyzsh
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden the runner (Audit all outbound calls)
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -23,14 +23,6 @@ Twitter), and join us on [Discord](https://discord.gg/ohmyzsh).
|
||||
[](https://mstdn.social/@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>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
@@ -354,6 +346,10 @@ directory.
|
||||
If you have many functions that go well together, you can put them as a `XYZ.plugin.zsh` file in the
|
||||
`custom/plugins/` directory and then enable this plugin.
|
||||
|
||||
The quickest way to start one is `omz generate plugin <name>`. It creates the plugin directory with a
|
||||
commented `<name>.plugin.zsh`, a `README.md`, and (for plugins that wrap a command-line tool) a completion
|
||||
skeleton, then tells you how to try it out.
|
||||
|
||||
If you would like to override the functionality of a plugin distributed with Oh My Zsh, create a plugin of the
|
||||
same name in the `custom/plugins/` directory and it will be loaded instead of the one in `plugins/`.
|
||||
|
||||
|
||||
+382
-9
@@ -24,6 +24,7 @@ function _omz {
|
||||
local -a cmds subcmds
|
||||
cmds=(
|
||||
'changelog:Print the changelog'
|
||||
'generate:Run a generator, e.g. to create a custom plugin'
|
||||
'help:Usage information'
|
||||
'plugin:Manage plugins'
|
||||
'pr:Manage Oh My Zsh Pull Requests'
|
||||
@@ -41,6 +42,8 @@ function _omz {
|
||||
changelog) local -a refs
|
||||
refs=("${(@f)$(builtin cd -q "$ZSH"; command git for-each-ref --format="%(refname:short):%(subject)" refs/heads refs/tags)}")
|
||||
_describe 'command' refs ;;
|
||||
generate) subcmds=('plugin:Create a custom plugin')
|
||||
_describe 'generator' subcmds ;;
|
||||
plugin) subcmds=(
|
||||
'disable:Disable plugin(s)'
|
||||
'enable:Enable plugin(s)'
|
||||
@@ -56,6 +59,8 @@ function _omz {
|
||||
esac
|
||||
elif (( CURRENT == 4 )); then
|
||||
case "${words[2]}::${words[3]}" in
|
||||
generate::plugin)
|
||||
_omz::generate::plugin::complete_options ;;
|
||||
plugin::(disable|enable|load))
|
||||
local -aU valid_plugins
|
||||
|
||||
@@ -84,6 +89,8 @@ function _omz {
|
||||
esac
|
||||
elif (( CURRENT > 4 )); then
|
||||
case "${words[2]}::${words[3]}" in
|
||||
generate::plugin)
|
||||
_omz::generate::plugin::complete_options ;;
|
||||
plugin::(enable|disable|load))
|
||||
local -aU valid_plugins
|
||||
|
||||
@@ -169,15 +176,16 @@ Usage: omz <command> [options]
|
||||
|
||||
Available commands:
|
||||
|
||||
help Print this help message
|
||||
changelog Print the changelog
|
||||
plugin <command> Manage plugins
|
||||
pr <command> Manage Oh My Zsh Pull Requests
|
||||
reload Reload the current zsh session
|
||||
shop Open the Oh My Zsh shop
|
||||
theme <command> Manage themes
|
||||
update Update Oh My Zsh
|
||||
version Show the version
|
||||
help Print this help message
|
||||
changelog Print the changelog
|
||||
generate <generator> Run a generator, e.g. to create a custom plugin
|
||||
plugin <command> Manage plugins
|
||||
pr <command> Manage Oh My Zsh Pull Requests
|
||||
reload Reload the current zsh session
|
||||
shop Open the Oh My Zsh shop
|
||||
theme <command> Manage themes
|
||||
update Update Oh My Zsh
|
||||
version Show the version
|
||||
|
||||
EOF
|
||||
}
|
||||
@@ -202,6 +210,371 @@ EOF
|
||||
ZSH="$ZSH" command zsh -f "$ZSH/tools/changelog.sh" "$version" "${2:-}" "$format"
|
||||
}
|
||||
|
||||
function _omz::generate {
|
||||
(( $# > 0 && $+functions[$0::$1] )) || {
|
||||
cat >&2 <<EOF
|
||||
Usage: ${(j: :)${(s.::.)0#_}} <generator> [options]
|
||||
|
||||
Available generators:
|
||||
|
||||
plugin [<name>] Create a custom plugin in \$ZSH_CUSTOM/plugins
|
||||
|
||||
EOF
|
||||
return 1
|
||||
}
|
||||
|
||||
local command="$1"
|
||||
shift
|
||||
|
||||
$0::$command "$@"
|
||||
}
|
||||
|
||||
function _omz::generate::plugin {
|
||||
setopt localoptions extendedglob
|
||||
|
||||
local -A opts
|
||||
zparseopts -D -E -A opts -- d: -description: c: -command: -no-completion -enable y -yes h -help || return 1
|
||||
|
||||
if (( ${+opts[-h]} || ${+opts[--help]} )); then
|
||||
_omz::generate::plugin::usage
|
||||
return 0
|
||||
fi
|
||||
|
||||
# zparseopts -E leaves anything it doesn't recognise in $@
|
||||
local arg
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == -* ]]; then
|
||||
_omz::log error "unknown option '$arg'."
|
||||
_omz::generate::plugin::usage
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
if (( $# > 1 )); then
|
||||
_omz::generate::plugin::usage
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Only ask questions when there is someone there to answer them
|
||||
local interactive=0
|
||||
if [[ -o interactive && -t 0 ]] && (( ! ${+opts[-y]} && ! ${+opts[--yes]} )); then
|
||||
interactive=1
|
||||
fi
|
||||
|
||||
local custom="${ZSH_CUSTOM:-${ZSH:+$ZSH/custom}}"
|
||||
if [[ -z "$custom" ]]; then
|
||||
_omz::log error "\$ZSH is not set. Is Oh My Zsh loaded?"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local templates="$ZSH/templates/generators/plugin"
|
||||
if [[ ! -d "$templates" ]]; then
|
||||
_omz::log error "templates not found at '${templates/#$HOME/\~}'. Try running 'omz update'."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check we can write to $ZSH_CUSTOM/plugins, or the closest directory that exists
|
||||
local probe="$custom/plugins"
|
||||
while [[ ! -e "$probe" && "$probe" != "${probe:h}" ]]; do
|
||||
probe="${probe:h}"
|
||||
done
|
||||
if [[ ! -w "$probe" ]]; then
|
||||
_omz::log error "cannot write to '${probe/#$HOME/\~}'. Set \$ZSH_CUSTOM to a directory you own."
|
||||
return 1
|
||||
fi
|
||||
|
||||
## Gather answers. Nothing is written until all of them are in.
|
||||
|
||||
local name="$1" attempts=0
|
||||
if [[ -n "$name" ]]; then
|
||||
_omz::generate::plugin::validate_name "$name" || return 1
|
||||
elif (( interactive )); then
|
||||
while true; do
|
||||
_omz::generate::plugin::ask "Plugin name" || return 1
|
||||
name="$REPLY"
|
||||
_omz::generate::plugin::validate_name "$name" && break
|
||||
if (( ++attempts >= 3 )); then
|
||||
_omz::log error "giving up."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
else
|
||||
_omz::generate::plugin::usage
|
||||
return 1
|
||||
fi
|
||||
|
||||
local dir="$custom/plugins/$name"
|
||||
if [[ -e "$dir" ]]; then
|
||||
_omz::log error "'$name' already exists at '${dir/#$HOME/\~}'. Remove it or pick another name."
|
||||
return 1
|
||||
fi
|
||||
if [[ -d "$ZSH/plugins/$name" ]]; then
|
||||
_omz::log warn "'$name' is also a built-in plugin. Your custom plugin will override it."
|
||||
if (( interactive )); then
|
||||
_omz::confirm "Continue? [y/N] "
|
||||
if [[ "$REPLY" != [yY] ]]; then
|
||||
_omz::log info "aborted."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
local description="${opts[-d]:-${opts[--description]:-}}"
|
||||
if [[ -z "$description" ]]; then
|
||||
description="$name plugin for Oh My Zsh"
|
||||
if (( interactive )); then
|
||||
_omz::generate::plugin::ask "Short description" "$description" || return 1
|
||||
description="$REPLY"
|
||||
fi
|
||||
fi
|
||||
# The description goes into a comment and a README line: keep it on one line
|
||||
description="${description//[[:cntrl:]]/ }"
|
||||
|
||||
local cmd="${opts[-c]:-${opts[--command]:-}}"
|
||||
if [[ -n "$cmd" ]]; then
|
||||
_omz::generate::plugin::validate_command "$cmd" || return 1
|
||||
elif (( interactive )); then
|
||||
local default_cmd=""
|
||||
(( $+commands[$name] )) && default_cmd="$name"
|
||||
attempts=0
|
||||
while true; do
|
||||
if [[ -n "$default_cmd" ]]; then
|
||||
_omz::generate::plugin::ask "Command-line tool this plugin wraps (or 'none')" "$default_cmd" || return 1
|
||||
else
|
||||
_omz::generate::plugin::ask "Command-line tool this plugin wraps (blank for none)" || return 1
|
||||
fi
|
||||
cmd="$REPLY"
|
||||
[[ "$cmd" != (none|-) ]] || cmd=""
|
||||
[[ -n "$cmd" ]] || break
|
||||
_omz::generate::plugin::validate_command "$cmd" && break
|
||||
if (( ++attempts >= 3 )); then
|
||||
_omz::log error "giving up."
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# completion: "" (none), "file" (a _<cmd> skeleton) or "cached" (the tool generates it)
|
||||
local completion="" compgen=""
|
||||
if [[ -n "$cmd" ]] && (( ! ${+opts[--no-completion]} )); then
|
||||
completion=file
|
||||
if (( interactive )); then
|
||||
_omz::confirm "Add a completion function for $cmd? [Y/n] "
|
||||
if [[ "$REPLY" == [nN] ]]; then
|
||||
completion=""
|
||||
else
|
||||
_omz::confirm "Does $cmd generate its own zsh completion (e.g. '$cmd completion zsh')? [y/N] "
|
||||
if [[ "$REPLY" == [yY] ]]; then
|
||||
completion=cached
|
||||
_omz::generate::plugin::ask "Command that prints the completion script" "$cmd completion zsh" || return 1
|
||||
compgen="$REPLY"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
local enable=${+opts[--enable]}
|
||||
if (( interactive && ! enable )); then
|
||||
_omz::confirm "Add $name to plugins=() in your .zshrc now? [y/N] "
|
||||
[[ "$REPLY" != [yY] ]] || enable=1
|
||||
fi
|
||||
|
||||
## Write the files. If anything fails, remove only what we created.
|
||||
|
||||
local -a created
|
||||
local block="" cache="" ok=0
|
||||
{
|
||||
if [[ ! -d "$custom/plugins" ]]; then
|
||||
command mkdir -p "$custom/plugins" || return 1
|
||||
_omz::generate::plugin::created "$custom/plugins"
|
||||
fi
|
||||
command mkdir "$dir" || return 1
|
||||
_omz::generate::plugin::created "$dir"
|
||||
|
||||
local plugin_tpl=plugin.zsh-template readme_tpl=README.md-template
|
||||
if [[ -z "$cmd" ]]; then
|
||||
plugin_tpl=plugin-generic.zsh-template
|
||||
readme_tpl=README-generic.md-template
|
||||
elif [[ "$completion" == cached ]]; then
|
||||
block="$(_omz::generate::plugin::template completion-cached.zsh-template)" || return 1
|
||||
cache="$(_omz::generate::plugin::template README-cache.md-template)" || return 1
|
||||
else
|
||||
block="$(_omz::generate::plugin::template completion-note.zsh-template)" || return 1
|
||||
fi
|
||||
|
||||
_omz::generate::plugin::render "$plugin_tpl" "$dir/$name.plugin.zsh" || return 1
|
||||
_omz::generate::plugin::render "$readme_tpl" "$dir/README.md" || return 1
|
||||
if [[ "$completion" == file ]]; then
|
||||
_omz::generate::plugin::render completion.zsh-template "$dir/_$cmd" || return 1
|
||||
fi
|
||||
ok=1
|
||||
} always {
|
||||
if (( ! ok )); then
|
||||
_omz::log error "could not generate the plugin. Cleaning up..."
|
||||
(( ${#created} )) && command rm -f -- "${created[@]}"
|
||||
[[ ! -d "$dir" ]] || command rmdir -- "$dir" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
print
|
||||
_omz::log info "plugin '$name' generated."
|
||||
print
|
||||
print -r -- "Next steps:"
|
||||
print
|
||||
print -r -- " 1. Edit it: ${EDITOR:-vim} ${dir/#$HOME/\~}/$name.plugin.zsh"
|
||||
print -r -- " 2. Try it now: omz plugin load $name"
|
||||
(( enable )) || print -r -- " 3. Keep it: omz plugin enable $name"
|
||||
print
|
||||
print -r -- "Docs: https://github.com/ohmyzsh/ohmyzsh/wiki/Customization#overriding-and-adding-plugins"
|
||||
|
||||
# Last thing we do: in an interactive shell this restarts zsh
|
||||
if (( enable )); then
|
||||
print
|
||||
if (( ${plugins[(Ie)$name]} )); then
|
||||
# Already enabled (e.g. a custom override of a built-in): just reload
|
||||
_omz::log info "'$name' is already in your plugins list."
|
||||
[[ ! -o interactive ]] || _omz::reload
|
||||
else
|
||||
_omz::plugin::enable "$name"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function _omz::generate::plugin::usage {
|
||||
cat >&2 <<EOF
|
||||
Usage: omz generate plugin [<name>] [options]
|
||||
|
||||
Creates a custom plugin in \$ZSH_CUSTOM/plugins/<name>. Anything not given as an
|
||||
option is asked for interactively. In a non-interactive shell (or with --yes)
|
||||
defaults are used instead.
|
||||
|
||||
Options:
|
||||
-d, --description <text> One-line description for the README and file header
|
||||
-c, --command <cmd> Command-line tool this plugin wraps. Adds a check
|
||||
that it is installed and scaffolds its completion
|
||||
--no-completion Don't scaffold a completion function
|
||||
--enable Add the plugin to plugins=() in .zshrc when done
|
||||
(restarts your shell)
|
||||
-y, --yes Never prompt; use defaults for anything not given
|
||||
-h, --help Show this help
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
function _omz::generate::plugin::complete_options {
|
||||
local -a opts
|
||||
opts=(
|
||||
'--description:One-line description for the README'
|
||||
'--command:Command-line tool this plugin wraps'
|
||||
'--no-completion:Skip the completion scaffold'
|
||||
'--enable:Enable the plugin when done'
|
||||
'--yes:Never prompt'
|
||||
)
|
||||
_describe -o 'options' opts
|
||||
}
|
||||
|
||||
# The name ends up in a mkdir path and, via --enable, inside the awk script that
|
||||
# rewrites .zshrc. This is the one place it gets checked.
|
||||
function _omz::generate::plugin::validate_name {
|
||||
setopt localoptions extendedglob
|
||||
local name="$1"
|
||||
|
||||
if [[ -z "$name" ]]; then
|
||||
_omz::log error "plugin name cannot be empty."
|
||||
elif (( ${#name} > 64 )); then
|
||||
_omz::log error "plugin name is too long (64 characters max)."
|
||||
elif [[ "$name" != "${name:l}" ]]; then
|
||||
_omz::log error "plugin names must be lowercase. Did you mean '${name:l}'?"
|
||||
elif [[ "$name" != [a-z0-9][a-z0-9_-]# ]]; then
|
||||
_omz::log error "invalid plugin name: use only lowercase letters, digits, '-' and '_', starting with a letter or digit."
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# The command name ends up in $+commands[...], _comps[...] and a filename
|
||||
function _omz::generate::plugin::validate_command {
|
||||
setopt localoptions extendedglob
|
||||
|
||||
if (( ${#1} > 64 )) || [[ "$1" != [[:alnum:]_][[:alnum:]_.+-]# ]]; then
|
||||
_omz::log error "invalid command name: use only letters, digits, '.', '_', '+' and '-'."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Ask a question and leave the answer in $REPLY. An empty answer takes the
|
||||
# default. Returns 1 when there is no more input (Ctrl-D).
|
||||
function _omz::generate::plugin::ask {
|
||||
setopt localoptions extendedglob
|
||||
local question="$1" default="$2"
|
||||
[[ -z "$default" ]] || question+=" [$default]"
|
||||
|
||||
_omz::log prompt "$question: " "omz::generate::plugin"
|
||||
if ! builtin read -r; then
|
||||
print >&2
|
||||
_omz::log info "aborted." "omz::generate::plugin"
|
||||
return 1
|
||||
fi
|
||||
|
||||
[[ -n "$REPLY" ]] || REPLY="$default"
|
||||
# Answers are single-line values: flatten control characters and trim
|
||||
REPLY="${REPLY//[[:cntrl:]]/ }"
|
||||
REPLY="${${REPLY##[[:space:]]#}%%[[:space:]]#}"
|
||||
}
|
||||
|
||||
# Print a template file with its %placeholders% turned into private markers,
|
||||
# or explain which one is missing
|
||||
function _omz::generate::plugin::template {
|
||||
if [[ ! -f "$templates/$1" ]]; then
|
||||
_omz::log error "missing template '${templates/#$HOME/\~}/$1'." "omz::generate::plugin"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local content="$(<"$templates/$1")" token m=$'\x1f'
|
||||
for token in completion cache name command description compgen; do
|
||||
content="${content//\%${token}\%/${m}${token}${m}}"
|
||||
done
|
||||
print -r -- "$content"
|
||||
}
|
||||
|
||||
# Fill in the placeholders of a template and write it to a file. Values come
|
||||
# from the caller: $name, $cmd, $description, $compgen, $block and $cache.
|
||||
#
|
||||
# Placeholders are matched as the markers that ::template produced, and the
|
||||
# marker character is stripped from every value, so a value that happens to
|
||||
# look like a placeholder (e.g. -d '%name%') is written out literally.
|
||||
function _omz::generate::plugin::render {
|
||||
setopt localoptions extendedglob
|
||||
local content m=$'\x1f'
|
||||
content="$(_omz::generate::plugin::template "$1")" || return 1
|
||||
|
||||
# Blocks go first: they are templates too and carry markers of their own
|
||||
content="${content//${m}completion${m}/$block}"
|
||||
content="${content//${m}cache${m}/$cache}"
|
||||
content="${content//${m}name${m}/${name//$m/}}"
|
||||
content="${content//${m}command${m}/${cmd//$m/}}"
|
||||
content="${content//${m}description${m}/${description//$m/}}"
|
||||
content="${content//${m}compgen${m}/${compgen//$m/}}"
|
||||
# Drop blank lines left behind by an empty placeholder at the end
|
||||
content="${content%%$'\n'##}"
|
||||
|
||||
created+=("$2")
|
||||
print -r -- "$content" > "$2" || return 1
|
||||
_omz::generate::plugin::created "$2"
|
||||
}
|
||||
|
||||
function _omz::generate::plugin::created {
|
||||
# Colour the verb with print -P, but print the path with print -r so that a
|
||||
# '%' somewhere in the path isn't treated as a prompt escape.
|
||||
# Keep the output plain when it is being piped.
|
||||
if [[ -t 1 ]]; then
|
||||
print -Pn " %F{green}create%f "
|
||||
else
|
||||
print -n " create "
|
||||
fi
|
||||
print -r -- "${1/#$HOME/\~}"
|
||||
}
|
||||
|
||||
function _omz::plugin {
|
||||
(( $# > 0 && $+functions[$0::$1] )) || {
|
||||
cat >&2 <<EOF
|
||||
|
||||
@@ -21,7 +21,6 @@ function chruby_prompt_info \
|
||||
azure_prompt_info \
|
||||
tf_prompt_info \
|
||||
conda_prompt_info \
|
||||
go_prompt_info \
|
||||
{
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/zsh -df
|
||||
|
||||
# Tests for `omz generate plugin`. Run with: zsh lib/tests/generate-plugin.test.zsh
|
||||
|
||||
ZSH="${0:A:h:h:h}"
|
||||
ZSH_CUSTOM="$(mktemp -d)"
|
||||
trap 'command rm -rf "$ZSH_CUSTOM"' EXIT
|
||||
|
||||
source "$ZSH/lib/cli.zsh"
|
||||
|
||||
failures=0
|
||||
pass() { print -u2 "\e[32mSuccess\e[0m: $1" }
|
||||
fail() { print -u2 "\e[31mError\e[0m: $1"; (( failures++ )) }
|
||||
|
||||
# assert_files <plugin> <expected files, space separated>
|
||||
assert_files() {
|
||||
local actual="$(print -l "$ZSH_CUSTOM"/plugins/$1/*(N:t) "$ZSH_CUSTOM"/plugins/$1/_*(N:t) | sort -u | tr '\n' ' ')"
|
||||
local expected="$(print -l ${=2} | sort -u | tr '\n' ' ')"
|
||||
if [[ "$actual" == "$expected" ]]; then
|
||||
pass "$1 has files: $expected"
|
||||
else
|
||||
fail "$1 has files '$actual', expected '$expected'"
|
||||
fi
|
||||
}
|
||||
|
||||
# assert_syntax <plugin>: every generated file must pass zsh -n, like CI does
|
||||
assert_syntax() {
|
||||
local file
|
||||
for file in "$ZSH_CUSTOM"/plugins/$1/*.plugin.zsh(N) "$ZSH_CUSTOM"/plugins/$1/_*(N); do
|
||||
if zsh -n "$file"; then
|
||||
pass "${file:t} passes zsh -n"
|
||||
else
|
||||
fail "${file:t} fails zsh -n"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# assert_contains <file> <literal string>
|
||||
assert_contains() {
|
||||
if grep -qF -- "$2" "$1"; then
|
||||
pass "${1:t} contains '$2'"
|
||||
else
|
||||
fail "${1:t} does not contain '$2'"
|
||||
fi
|
||||
}
|
||||
|
||||
## Templates must be valid zsh even before substitution (CI checks this too)
|
||||
|
||||
for file in "$ZSH"/templates/generators/plugin/*.zsh-template; do
|
||||
if zsh -n "$file"; then
|
||||
pass "template ${file:t} passes zsh -n"
|
||||
else
|
||||
fail "template ${file:t} fails zsh -n"
|
||||
fi
|
||||
done
|
||||
|
||||
## A plugin that wraps a command
|
||||
|
||||
description='Shortcuts & stuff $(id) `id` 100%'
|
||||
if omz generate plugin foo -d "$description" -c foo --yes >/dev/null 2>&1; then
|
||||
pass "generates a command-wrapping plugin"
|
||||
else
|
||||
fail "generating a command-wrapping plugin failed"
|
||||
fi
|
||||
assert_files foo "README.md _foo foo.plugin.zsh"
|
||||
assert_syntax foo
|
||||
assert_contains "$ZSH_CUSTOM/plugins/foo/README.md" 'plugins=(... foo)'
|
||||
assert_contains "$ZSH_CUSTOM/plugins/foo/README.md" "$description"
|
||||
assert_contains "$ZSH_CUSTOM/plugins/foo/foo.plugin.zsh" "$description"
|
||||
assert_contains "$ZSH_CUSTOM/plugins/foo/foo.plugin.zsh" '$+commands[foo]'
|
||||
assert_contains "$ZSH_CUSTOM/plugins/foo/_foo" '#compdef foo'
|
||||
if grep -q '%[a-z]*%' "$ZSH_CUSTOM"/plugins/foo/*; then
|
||||
fail "foo still has unfilled placeholders"
|
||||
else
|
||||
pass "foo has no unfilled placeholders"
|
||||
fi
|
||||
|
||||
## Values that look like placeholders are written literally
|
||||
|
||||
omz generate plugin lit -d '%compgen% and %name% stay' -c lit --yes >/dev/null 2>&1
|
||||
assert_contains "$ZSH_CUSTOM/plugins/lit/README.md" '%compgen% and %name% stay'
|
||||
assert_contains "$ZSH_CUSTOM/plugins/lit/lit.plugin.zsh" '%compgen% and %name% stay'
|
||||
|
||||
## A plugin with no command
|
||||
|
||||
if omz generate plugin bar --yes >/dev/null 2>&1; then
|
||||
pass "generates a generic plugin"
|
||||
else
|
||||
fail "generating a generic plugin failed"
|
||||
fi
|
||||
assert_files bar "README.md bar.plugin.zsh"
|
||||
assert_syntax bar
|
||||
assert_contains "$ZSH_CUSTOM/plugins/bar/README.md" 'This plugin does not add any aliases.'
|
||||
assert_contains "$ZSH_CUSTOM/plugins/bar/bar.plugin.zsh" 'bar plugin for Oh My Zsh'
|
||||
|
||||
## --no-completion, and the rails-style output
|
||||
|
||||
output="$(omz generate plugin baz -c baz --no-completion --yes 2>/dev/null)"
|
||||
assert_files baz "README.md baz.plugin.zsh"
|
||||
create_lines=$(print -r -- "$output" | grep -c '^ create ')
|
||||
if (( create_lines == 3 )); then
|
||||
pass "prints one create line per path"
|
||||
else
|
||||
fail "expected 3 create lines, got $create_lines"
|
||||
fi
|
||||
if [[ "$output" == *"omz plugin load baz"* ]]; then
|
||||
pass "prints next steps"
|
||||
else
|
||||
fail "next steps missing from output"
|
||||
fi
|
||||
|
||||
## Bad names are rejected without touching the filesystem
|
||||
|
||||
before="$(print -l "$ZSH_CUSTOM"/plugins/*(N:t))"
|
||||
for bad in '' 'Foo' 'a b' '../evil' 'a/b' '.hidden' '.' '..' '-x' 'foo`id`' 'foo"$(id)"' $'a\nb' "$(printf 'x%.0s' {1..65})"; do
|
||||
if omz generate plugin "$bad" --yes >/dev/null 2>&1; then
|
||||
fail "accepted bad name ${(qq)bad}"
|
||||
else
|
||||
pass "rejected bad name ${(qq)bad}"
|
||||
fi
|
||||
done
|
||||
after="$(print -l "$ZSH_CUSTOM"/plugins/*(N:t))"
|
||||
if [[ "$before" == "$after" ]]; then
|
||||
pass "bad names created nothing"
|
||||
else
|
||||
fail "bad names changed \$ZSH_CUSTOM/plugins"
|
||||
fi
|
||||
|
||||
## Bad command names are rejected
|
||||
|
||||
for bad in 'a b' '../x' 'foo;id' 'foo$(id)'; do
|
||||
if omz generate plugin qux -c "$bad" --yes >/dev/null 2>&1; then
|
||||
fail "accepted bad command ${(qq)bad}"
|
||||
else
|
||||
pass "rejected bad command ${(qq)bad}"
|
||||
fi
|
||||
done
|
||||
|
||||
## Existing plugin, unknown option, missing templates
|
||||
|
||||
if omz generate plugin foo --yes >/dev/null 2>&1; then
|
||||
fail "overwrote an existing plugin"
|
||||
else
|
||||
pass "refuses to overwrite an existing plugin"
|
||||
fi
|
||||
|
||||
if omz generate plugin quux --bogus --yes >/dev/null 2>&1; then
|
||||
fail "accepted an unknown option"
|
||||
else
|
||||
pass "rejects an unknown option"
|
||||
fi
|
||||
|
||||
if ( ZSH=/nonexistent; omz generate plugin quux --yes >/dev/null 2>&1 ); then
|
||||
fail "ran without templates"
|
||||
else
|
||||
pass "fails cleanly when templates are missing"
|
||||
fi
|
||||
[[ -e "$ZSH_CUSTOM/plugins/quux" ]] && fail "quux was created by a failed run"
|
||||
|
||||
## A failure after the first file is written removes everything it created
|
||||
|
||||
broken="$(mktemp -d)"
|
||||
mkdir -p "$broken/templates/generators/plugin" "$broken/plugins"
|
||||
cp "$ZSH/templates/generators/plugin/plugin.zsh-template" \
|
||||
"$ZSH/templates/generators/plugin/completion-note.zsh-template" "$broken/templates/generators/plugin/"
|
||||
# README.md-template is missing, so the plugin file is written and then the README fails
|
||||
if ( ZSH="$broken"; omz generate plugin partial -c partial --yes >/dev/null 2>&1 ); then
|
||||
fail "succeeded with a missing README template"
|
||||
else
|
||||
pass "fails when a later template is missing"
|
||||
fi
|
||||
if [[ -e "$ZSH_CUSTOM/plugins/partial" ]]; then
|
||||
fail "partial plugin directory was left behind: $(ls "$ZSH_CUSTOM/plugins/partial")"
|
||||
else
|
||||
pass "cleans up the partial plugin directory"
|
||||
fi
|
||||
command rm -rf "$broken"
|
||||
|
||||
## The prompt helper
|
||||
|
||||
_omz::generate::plugin::ask "Q" "dflt" 2>/dev/null < <(print '')
|
||||
[[ "$REPLY" == "dflt" ]] && pass "ask: empty answer takes the default" || fail "ask: got '$REPLY', expected 'dflt'"
|
||||
|
||||
_omz::generate::plugin::ask "Q" "dflt" 2>/dev/null < <(print ' hi there ')
|
||||
[[ "$REPLY" == "hi there" ]] && pass "ask: trims whitespace" || fail "ask: got '$REPLY', expected 'hi there'"
|
||||
|
||||
if _omz::generate::plugin::ask "Q" 2>/dev/null < /dev/null; then
|
||||
fail "ask: did not fail on EOF"
|
||||
else
|
||||
pass "ask: fails on EOF"
|
||||
fi
|
||||
|
||||
print -u2
|
||||
if (( failures )); then
|
||||
print -u2 "\e[31m$failures test(s) failed\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
print -u2 "\e[32mAll tests passed\e[0m"
|
||||
+7
-17
@@ -64,7 +64,7 @@ if [[ ! -w "$ZSH_CACHE_DIR" ]]; then
|
||||
fi
|
||||
|
||||
# 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)
|
||||
|
||||
# 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_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
|
||||
zcompdump_refresh=0
|
||||
if ! _omz_compdump_has_metadata; then
|
||||
if ! command grep -q -Fx "$zcompdump_revision" "$ZSH_COMPDUMP" 2>/dev/null \
|
||||
|| ! command grep -q -Fx "$zcompdump_fpath" "$ZSH_COMPDUMP" 2>/dev/null; then
|
||||
command rm -f "$ZSH_COMPDUMP"
|
||||
zcompdump_refresh=1
|
||||
fi
|
||||
@@ -142,8 +134,9 @@ else
|
||||
compinit -u -d "$ZSH_COMPDUMP"
|
||||
fi
|
||||
|
||||
# Append zcompdump metadata if missing (compinit may have regenerated the file)
|
||||
if (( zcompdump_refresh )) || ! _omz_compdump_has_metadata; then
|
||||
# Append zcompdump metadata if missing
|
||||
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
|
||||
# See https://github.com/ohmyzsh/ohmyzsh/commit/dd1a7269#commitcomment-39003489
|
||||
tee -a "$ZSH_COMPDUMP" &>/dev/null <<EOF
|
||||
@@ -153,12 +146,9 @@ $zcompdump_fpath
|
||||
EOF
|
||||
fi
|
||||
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.
|
||||
# Test that first so the lock directory and zrecompile are skipped when it's fresh.
|
||||
if [[ ! "${ZSH_COMPDUMP}.zwc" -nt "$ZSH_COMPDUMP" ]] \
|
||||
&& command mkdir "${ZSH_COMPDUMP}.lock" 2>/dev/null; then
|
||||
if command mkdir "${ZSH_COMPDUMP}.lock" 2>/dev/null; then
|
||||
zrecompile -q -p "$ZSH_COMPDUMP"
|
||||
command rm -rf "$ZSH_COMPDUMP.zwc.old" "${ZSH_COMPDUMP}.lock"
|
||||
fi
|
||||
|
||||
@@ -39,18 +39,3 @@ plugins=(... golang)
|
||||
| gov | `go vet` | Vet examines Go source code and reports suspicious constructs |
|
||||
| gove | `go version` | Prints Go version |
|
||||
| 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 gove='go version'
|
||||
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=[]: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.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.installations.auto-detect=[]' \
|
||||
'-Dorg.gradle.java.installations.auto-download=[]' \
|
||||
@@ -302,6 +299,8 @@ __gradle_subcommand() {
|
||||
'-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.tooling.parallel=[]' \
|
||||
'-Dorg.gradle.unsafe.isolated-projects.diagnostics=[]' \
|
||||
'-Dorg.gradle.unsafe.isolated-projects=[]' \
|
||||
'-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.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' \
|
||||
(--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)' \
|
||||
(--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.]' \
|
||||
(--build-cache)'--no-build-cache[Disables the Gradle build 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)]' \
|
||||
(--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.]' \
|
||||
(--isolated-projects)'--no-isolated-projects[Disables Isolated Projects. (incubating)]' \
|
||||
(--parallel)'--no-parallel[Disables parallel project execution.]' \
|
||||
(--problems-report)'--no-problems-report[Disables the HTML problems report. (incubating)]' \
|
||||
{-a,--no-rebuild}'[Disables rebuilding of project dependencies.]' \
|
||||
@@ -424,9 +421,6 @@ _gradle() {
|
||||
'-Dorg.gradle.debug.suspend=[]:->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.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.installations.auto-detect=[]:->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.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.unsafe.isolated-projects.diagnostics=[]:->argument-expected' \
|
||||
'-Dorg.gradle.unsafe.isolated-projects=[]:->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.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' \
|
||||
(--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' \
|
||||
(--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' \
|
||||
(--build-cache)'--no-build-cache[Disables the Gradle build 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)]' \
|
||||
(--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.]' \
|
||||
(--isolated-projects)'--no-isolated-projects[Disables Isolated Projects. (incubating)]' \
|
||||
(--parallel)'--no-parallel[Disables parallel project execution.]' \
|
||||
(--problems-report)'--no-problems-report[Disables the HTML problems report. (incubating)]' \
|
||||
{-a,--no-rebuild}'[Disables rebuilding of project dependencies.]' \
|
||||
|
||||
@@ -19,54 +19,35 @@ plugins=(... jj)
|
||||
| jjbd | `jj bookmark delete` |
|
||||
| jjbf | `jj bookmark forget` |
|
||||
| jjbl | `jj bookmark list` |
|
||||
| jjblt | `jj bookmark list --tracked` |
|
||||
| jjbm | `jj bookmark move` |
|
||||
| jjbr | `jj bookmark rename` |
|
||||
| jjbs | `jj bookmark set` |
|
||||
| jjbt | `jj bookmark track` |
|
||||
| jjbu | `jj bookmark untrack` |
|
||||
| jjc | `jj commit` |
|
||||
| jjcfg | `jj config` |
|
||||
| jjcfgl | `jj config list` |
|
||||
| jjcmsg | `jj commit --message` |
|
||||
| jjd | `jj diff` |
|
||||
| jjdmsg | `jj desc --message` |
|
||||
| jjds | `jj desc` |
|
||||
| jjdst | `jj diff --stat` |
|
||||
| jje | `jj edit` |
|
||||
| jjev | `jj evolog` |
|
||||
| jjf | `jj file` |
|
||||
| jjfl | `jj file list` |
|
||||
| jjg | `jj git` |
|
||||
| jjgcl | `jj git clone` |
|
||||
| jjgf | `jj git fetch` |
|
||||
| jjgfa | `jj git fetch --all-remotes` |
|
||||
| jjgi | `jj git init` |
|
||||
| jjgp | `jj git push` |
|
||||
| jjgpa | `jj git push --all` |
|
||||
| jjgpd | `jj git push --deleted` |
|
||||
| jjgpt | `jj git push --tracked` |
|
||||
| jjgrl | `jj git remote list` |
|
||||
| jjl | `jj log` |
|
||||
| jjla | `jj log -r "all()"` |
|
||||
| jjn | `jj new` |
|
||||
| jjnt | `jj new "trunk()"` |
|
||||
| jjop | `jj op` |
|
||||
| jjopl | `jj op log` |
|
||||
| jjor | `jj op restore` |
|
||||
| jjrb | `jj rebase` |
|
||||
| jjrbm | `jj rebase -d "trunk()"` |
|
||||
| jjrs | `jj restore` |
|
||||
| jjrt | `cd "$(jj root \|\| echo .)"` |
|
||||
| jjs | `jj show` |
|
||||
| jjsp | `jj split` |
|
||||
| jjsq | `jj squash` |
|
||||
| jjst | `jj status` |
|
||||
| jju | `jj undo` |
|
||||
| jjw | `jj workspace` |
|
||||
| jjwa | `jj workspace add` |
|
||||
| jjwf | `jj workspace forget` |
|
||||
| jjwl | `jj workspace list` |
|
||||
|
||||
## Prompt usage
|
||||
|
||||
|
||||
@@ -45,51 +45,34 @@ alias jjbc='jj bookmark create'
|
||||
alias jjbd='jj bookmark delete'
|
||||
alias jjbf='jj bookmark forget'
|
||||
alias jjbl='jj bookmark list'
|
||||
alias jjblt='jj bookmark list --tracked'
|
||||
alias jjbm='jj bookmark move'
|
||||
alias jjbr='jj bookmark rename'
|
||||
alias jjbs='jj bookmark set'
|
||||
alias jjbt='jj bookmark track'
|
||||
alias jjbu='jj bookmark untrack'
|
||||
alias jjc='jj commit'
|
||||
alias jjcfg='jj config'
|
||||
alias jjcfgl='jj config list'
|
||||
alias jjcmsg='jj commit --message'
|
||||
alias jjd='jj diff'
|
||||
alias jjdmsg='jj desc --message'
|
||||
alias jjds='jj desc'
|
||||
alias jjdst='jj diff --stat'
|
||||
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 jjgf='jj git fetch'
|
||||
alias jjgfa='jj git fetch --all-remotes'
|
||||
alias jjgi='jj git init'
|
||||
alias jjgp='jj git push'
|
||||
alias jjgpa='jj git push --all'
|
||||
alias jjgpd='jj git push --deleted'
|
||||
alias jjgpt='jj git push --tracked'
|
||||
alias jjgrl='jj git remote list'
|
||||
alias jjl='jj log'
|
||||
alias jjla='jj log -r "all()"'
|
||||
alias jjn='jj new'
|
||||
alias jjnt='jj new "trunk()"'
|
||||
alias jjop='jj op'
|
||||
alias jjopl='jj op log'
|
||||
alias jjor='jj op restore'
|
||||
alias jjrb='jj rebase'
|
||||
alias jjrbm='jj rebase -d "trunk()"'
|
||||
alias jjrs='jj restore'
|
||||
alias jjrt='cd "$(jj root || echo .)"'
|
||||
alias jjs='jj show'
|
||||
alias jjsp='jj split'
|
||||
alias jjsq='jj squash'
|
||||
alias jjst='jj status'
|
||||
alias jju='jj undo'
|
||||
alias jjw='jj workspace'
|
||||
alias jjwa='jj workspace add'
|
||||
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 jeb='juju export-bundle'
|
||||
alias jex='juju expose'
|
||||
alias junex='juju unexpose'
|
||||
alias jh='juju help'
|
||||
alias jkc='juju kill-controller -y -t 0'
|
||||
alias jm='juju models'
|
||||
|
||||
@@ -71,7 +71,6 @@ plugins=(... kubectl)
|
||||
| | | **Secret management** |
|
||||
| kgsec | `kubectl get secret` | Get secret for decoding |
|
||||
| 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 |
|
||||
| kdelsec | `kubectl delete secret` | Delete the secret |
|
||||
| | | **Deployment management** |
|
||||
|
||||
@@ -93,7 +93,6 @@ alias kdelcm='kubectl delete configmap'
|
||||
# Secret management
|
||||
alias kgsec='kubectl get secret'
|
||||
alias kgseca='kubectl get secret --all-namespaces'
|
||||
alias kesec='kubectl edit secret'
|
||||
alias kdsec='kubectl describe secret'
|
||||
alias kdelsec='kubectl delete secret'
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ plugins=(... laravel)
|
||||
| `pami` | `php artisan make:interface` |
|
||||
| `pamtr` | `php artisan make:trait` |
|
||||
| `pamv` | `php artisan make:view` |
|
||||
| `pammig` | `php artisan make:migration` |
|
||||
|
||||
## Clears
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ alias pamen='php artisan make:enum'
|
||||
alias pami='php artisan make:interface'
|
||||
alias pamtr='php artisan make:trait'
|
||||
alias pamv='php artisan make:view'
|
||||
alias pammig='php artisan make:migration'
|
||||
|
||||
|
||||
# Clears
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
# opencode plugin
|
||||
|
||||
This plugin adds completion and aliases for the [OpenCode](https://opencode.ai) CLI.
|
||||
Install OpenCode using its [installation instructions](https://opencode.ai/docs/#install),
|
||||
and make sure `opencode` is available on your `$PATH`.
|
||||
|
||||
To enable it, add `opencode` to the plugins array in your `.zshrc`:
|
||||
|
||||
```zsh
|
||||
plugins=(... opencode)
|
||||
```
|
||||
|
||||
## Learning OpenCode from the terminal
|
||||
|
||||
Use tab completion to explore commands and their descriptions without leaving the
|
||||
shell. For example, these are some of the candidates shown by the CLI:
|
||||
|
||||
```text
|
||||
$ opencode <TAB>
|
||||
agent -- manage agents
|
||||
models -- list all available models
|
||||
run -- run opencode with a message
|
||||
session -- manage sessions
|
||||
stats -- show token usage and cost statistics
|
||||
...
|
||||
|
||||
$ opencode session <TAB>
|
||||
delete -- delete a session
|
||||
list -- list sessions
|
||||
|
||||
$ opencode run --<TAB>
|
||||
--agent -- agent to use
|
||||
--continue -- continue the last session
|
||||
--file -- file(s) to attach to message
|
||||
--model -- model to use in the format of provider/model
|
||||
...
|
||||
```
|
||||
|
||||
Completion works through the aliases too. Type a partial command or option and
|
||||
press Tab to finish it:
|
||||
|
||||
```text
|
||||
$ opc session li<TAB>
|
||||
$ opc session list
|
||||
|
||||
$ opcr --att<TAB>
|
||||
$ opcr --attach
|
||||
|
||||
$ opcc --log-l<TAB>
|
||||
$ opcc --log-level
|
||||
```
|
||||
|
||||
Candidates depend on your installed OpenCode version. In OpenCode 1.18.29, the
|
||||
CLI's completion output omits top-level TUI flags such as `--model` and `--fork`,
|
||||
even though those flags work when typed. Use `opencode --help` or
|
||||
`opencode run --help` for the full options, and see the
|
||||
[CLI reference](https://opencode.ai/docs/cli/) for more workflows.
|
||||
|
||||
## Aliases
|
||||
|
||||
| Alias | Command | Description |
|
||||
| ------ | --------------------- | ----------------------------------- |
|
||||
| `opc` | `opencode` | Launch the terminal UI |
|
||||
| `opcc` | `opencode --continue` | Continue the last session |
|
||||
| `opcr` | `opencode run` | Run a prompt without opening the UI |
|
||||
|
||||
To keep completion but skip the aliases, set this in your `.zshrc`, above the line
|
||||
that sources Oh My Zsh:
|
||||
|
||||
```zsh
|
||||
# ~/.zshrc
|
||||
zstyle ':omz:plugins:opencode' aliases no
|
||||
|
||||
plugins=(... opencode)
|
||||
|
||||
source $ZSH/oh-my-zsh.sh
|
||||
```
|
||||
|
||||
## Common workflows
|
||||
|
||||
All aliases accept additional arguments:
|
||||
|
||||
```zsh
|
||||
# Open a project
|
||||
opc ~/projects/my-app
|
||||
|
||||
# Explore a different approach by forking the last session
|
||||
opcc --fork
|
||||
|
||||
# Ask a question without entering the terminal UI
|
||||
opcr "Explain the test setup in this project"
|
||||
|
||||
# Reuse an already running backend to avoid MCP server cold starts
|
||||
opcr --attach http://localhost:4096 "Explain this project's architecture"
|
||||
```
|
||||
|
||||
## Completion
|
||||
|
||||
Completion queries the installed OpenCode CLI on demand for commands and options,
|
||||
including through the aliases above. It falls back to Zsh's default completion when
|
||||
the CLI returns no candidates. No OpenCode process is started at shell startup,
|
||||
and no generated completion cache is needed.
|
||||
|
||||
## Credits
|
||||
|
||||
Based on the OpenCode plugin proposals by
|
||||
[pranavavva](https://github.com/pranavavva) in
|
||||
[#13545](https://github.com/ohmyzsh/ohmyzsh/pull/13545) and
|
||||
[mskadu](https://github.com/mskadu) in
|
||||
[#13794](https://github.com/ohmyzsh/ohmyzsh/pull/13794).
|
||||
The completion adapter is derived from OpenCode's `opencode completion` output.
|
||||
@@ -1,12 +0,0 @@
|
||||
#compdef opencode
|
||||
|
||||
# Adapted from `opencode completion`, using the CLI's live Yargs completions.
|
||||
local -a reply
|
||||
reply=("${(@f)$(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" \
|
||||
command opencode --get-yargs-completions "${words[@]}" < /dev/null 2> /dev/null)}")
|
||||
|
||||
if [[ -n "${reply[1]}" ]]; then
|
||||
_describe 'values' reply
|
||||
else
|
||||
_default
|
||||
fi
|
||||
@@ -1,7 +0,0 @@
|
||||
if (( ! $+commands[opencode] )); then
|
||||
return
|
||||
fi
|
||||
|
||||
alias opc='opencode'
|
||||
alias opcc='opencode --continue'
|
||||
alias opcr='opencode run'
|
||||
@@ -23,7 +23,7 @@ _togglePoetryShell() {
|
||||
|
||||
# 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
|
||||
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
|
||||
if [[ "$venv_dir" == "." ]]; then
|
||||
venv_dir="$PWD/.venv"
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
# - https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Console/Resources/completion.bash
|
||||
#
|
||||
_sf_console() {
|
||||
local lastParam out comp sf_cmd
|
||||
local -a completions flagPrefix requestComp inputs
|
||||
local lastParam flagPrefix requestComp out comp
|
||||
local -a completions
|
||||
|
||||
# The user could have moved the cursor backwards on the command-line.
|
||||
# We need to trigger completion from the $CURRENT location, so we need
|
||||
@@ -29,20 +29,11 @@ _sf_console() {
|
||||
setopt local_options BASH_REMATCH
|
||||
if [[ "${lastParam}" =~ '-.*=' ]]; then
|
||||
# We are dealing with a flag with an =
|
||||
flagPrefix=(-P "${BASH_REMATCH}")
|
||||
flagPrefix="-P ${BASH_REMATCH}"
|
||||
fi
|
||||
|
||||
# Prepare the command to obtain completions. An alias is resolved here,
|
||||
# because the request is no longer read again by the shell.
|
||||
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))")
|
||||
|
||||
# Prepare the command to obtain completions
|
||||
requestComp="${words[0]} ${words[1]} _complete --no-interaction -szsh -a1 -c$((CURRENT-1))" i=""
|
||||
for w in ${words[@]}; do
|
||||
w=$(printf -- '%b' "$w")
|
||||
# remove quotes from typed values
|
||||
@@ -56,18 +47,19 @@ _sf_console() {
|
||||
fi
|
||||
# empty values are ignored
|
||||
if [ ! -z "$w" ]; then
|
||||
inputs+=("-i$w")
|
||||
i="${i}-i${w} "
|
||||
fi
|
||||
done
|
||||
|
||||
# Ensure at least 1 input
|
||||
if (( ! $#inputs )); then
|
||||
inputs=(-i' ')
|
||||
if [ "${i}" = "" ]; then
|
||||
requestComp="${requestComp} -i\" \""
|
||||
else
|
||||
requestComp="${requestComp} ${i}"
|
||||
fi
|
||||
|
||||
# The request is run without being read again by the shell, so that a
|
||||
# "$(...)" or a backtick typed on the command line is not executed
|
||||
out=$(SHELL_VERBOSITY=0 "${requestComp[@]}" "${inputs[@]}" 2>/dev/null)
|
||||
# Use eval to handle any environment variables and such
|
||||
out=$(eval ${requestComp} 2>/dev/null)
|
||||
|
||||
while IFS='\n' read -r comp; do
|
||||
if [ -n "$comp" ]; then
|
||||
@@ -83,7 +75,7 @@ _sf_console() {
|
||||
done < <(printf "%s\n" "${out[@]}")
|
||||
|
||||
# Let inbuilt _describe handle completions
|
||||
_describe "completions" completions "${flagPrefix[@]}"
|
||||
eval _describe "completions" completions $flagPrefix
|
||||
return $?
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ case $state in
|
||||
(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'
|
||||
esac
|
||||
;;
|
||||
|
||||
@@ -51,11 +51,6 @@ Available search contexts are:
|
||||
| `npmpkg` | `https://www.npmjs.com/search?q=` |
|
||||
| `packagist` | `https://packagist.org/?query=` |
|
||||
| `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=` |
|
||||
| `claudeai` | `https://claude.ai/new?q=` |
|
||||
| `grokcom` | `https://grok.com/?q=` |
|
||||
|
||||
@@ -32,11 +32,6 @@ function web_search() {
|
||||
npmpkg "https://www.npmjs.com/search?q="
|
||||
packagist "https://packagist.org/?query="
|
||||
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="
|
||||
grok "https://grok.com/?q="
|
||||
claudeai "https://claude.ai/new?q="
|
||||
@@ -97,11 +92,6 @@ alias gems='web_search gems'
|
||||
alias npmpkg='web_search npmpkg'
|
||||
alias packagist='web_search packagist'
|
||||
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 grokcom='web_search grok'
|
||||
alias claudeai='web_search claudeai'
|
||||
@@ -126,3 +116,4 @@ if [[ ${#ZSH_WEB_SEARCH_ENGINES} -gt 0 ]]; then
|
||||
done
|
||||
unset engines key
|
||||
fi
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
## 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/_%command%`.
|
||||
@@ -0,0 +1,11 @@
|
||||
# %name% plugin
|
||||
|
||||
%description%
|
||||
|
||||
To use it, add `%name%` to the plugins array in your zshrc file:
|
||||
|
||||
```zsh
|
||||
plugins=(... %name%)
|
||||
```
|
||||
|
||||
This plugin does not add any aliases.
|
||||
@@ -0,0 +1,20 @@
|
||||
# %name% plugin
|
||||
|
||||
%description%
|
||||
|
||||
To use it, add `%name%` to the plugins array in your zshrc file:
|
||||
|
||||
```zsh
|
||||
plugins=(... %name%)
|
||||
```
|
||||
|
||||
## Aliases
|
||||
|
||||
| Alias | Command | Description |
|
||||
| :----------- | ------------------ | :-------------------- |
|
||||
| `%command%s` | `%command% status` | Show %command% status |
|
||||
|
||||
## Requirements
|
||||
|
||||
This plugin requires [%command%](https://example.com) to be installed.
|
||||
%cache%
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Completion
|
||||
#
|
||||
# %command% generates its own zsh completion, so we cache it instead of
|
||||
# maintaining a `_%command%` file by hand.
|
||||
#
|
||||
# On the first shell after installing this plugin the cache file doesn't exist
|
||||
# yet, so compinit hasn't bound it. Do that manually here.
|
||||
if [[ ! -f "$ZSH_CACHE_DIR/completions/_%command%" ]]; then
|
||||
typeset -g -A _comps
|
||||
autoload -Uz _%command%
|
||||
_comps[%command%]=_%command%
|
||||
fi
|
||||
|
||||
# Regenerate the cache in the background so it never blocks shell startup.
|
||||
# TMPPREFIX puts the temp file next to the destination, which keeps the move
|
||||
# atomic.
|
||||
zmodload -F zsh/files b:zf_mv
|
||||
() {
|
||||
local TMPPREFIX="$ZSH_CACHE_DIR/completions/_%command%"
|
||||
zf_mv -f -- =( %compgen% ) "$TMPPREFIX"
|
||||
} &|
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Completion
|
||||
#
|
||||
# Oh My Zsh adds this directory to $fpath, so a file named `_%command%` next to
|
||||
# this one is picked up automatically as the completion for %command%.
|
||||
#
|
||||
@@ -0,0 +1,32 @@
|
||||
#compdef %command%
|
||||
#
|
||||
# Completion for %command%.
|
||||
#
|
||||
# This is a starting point. Delete what you don't need. Two references:
|
||||
# https://zsh.sourceforge.io/Doc/Release/Completion-System.html
|
||||
# https://github.com/zsh-users/zsh/blob/master/Etc/completion-style-guide
|
||||
|
||||
local -a subcommands
|
||||
subcommands=(
|
||||
'status:Show the current status'
|
||||
'run:Run something'
|
||||
'help:Show help for a command'
|
||||
)
|
||||
|
||||
_arguments -C \
|
||||
'(-h --help)'{-h,--help}'[show help]' \
|
||||
'(-v --version)'{-v,--version}'[show the version]' \
|
||||
'1: :->subcommand' \
|
||||
'*:: :->args'
|
||||
|
||||
case $state in
|
||||
subcommand)
|
||||
_describe -t commands '%command% subcommand' subcommands
|
||||
;;
|
||||
args)
|
||||
case $words[1] in
|
||||
status) _arguments '--short[one-line output]' ;;
|
||||
run) _files ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,48 @@
|
||||
# %name% plugin
|
||||
#
|
||||
# %description%
|
||||
#
|
||||
# This file is sourced by Oh My Zsh in every new shell, so keep it fast.
|
||||
# Avoid running external commands at the top level unless you really need to.
|
||||
#
|
||||
# Wrapping a command-line tool? Guard everything so people who don't have it
|
||||
# installed don't end up with broken aliases:
|
||||
#
|
||||
# if (( ! $+commands[sometool] )); then
|
||||
# return
|
||||
# fi
|
||||
|
||||
#
|
||||
# Aliases
|
||||
#
|
||||
# Document every alias in README.md. Short, obvious, and few beats many.
|
||||
#
|
||||
|
||||
# alias %name%='echo "hello from %name%"'
|
||||
|
||||
#
|
||||
# Functions
|
||||
#
|
||||
# Anything that needs arguments in the middle, or more than one command,
|
||||
# belongs here rather than in an alias.
|
||||
#
|
||||
|
||||
# function %name%_hello() {
|
||||
# echo "hello, ${1:-world}"
|
||||
# }
|
||||
|
||||
#
|
||||
# Completion
|
||||
#
|
||||
# Oh My Zsh adds this directory to $fpath, so a file named `_sometool` next to
|
||||
# this one is picked up automatically as the completion for `sometool`.
|
||||
#
|
||||
|
||||
#
|
||||
# Need the path to this plugin's own directory (for data files, a lib/ dir...)?
|
||||
# This is the standard way to get it, since $0 is not reliable on its own:
|
||||
# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
|
||||
#
|
||||
# 0="${ZERO:-${${0:#$ZSH_ARGZERO}:-${(%):-%N}}}"
|
||||
# 0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
# source "${0:A:h}/lib/helpers.zsh"
|
||||
@@ -0,0 +1,43 @@
|
||||
# %name% plugin
|
||||
#
|
||||
# %description%
|
||||
#
|
||||
# This file is sourced by Oh My Zsh in every new shell, so keep it fast.
|
||||
# Avoid running external commands at the top level unless you really need to.
|
||||
|
||||
# Only define anything if the tool is actually installed. Without this guard,
|
||||
# people who don't have %command% get aliases that fail with "command not found".
|
||||
if (( ! $+commands[%command%] )); then
|
||||
return
|
||||
fi
|
||||
|
||||
#
|
||||
# Aliases
|
||||
#
|
||||
# Document every alias in README.md. Short, obvious, and few beats many.
|
||||
# The one below is just an example: replace it with something %command% can do.
|
||||
#
|
||||
|
||||
alias %command%s='%command% status'
|
||||
|
||||
#
|
||||
# Functions
|
||||
#
|
||||
# Anything that needs arguments in the middle, or more than one command,
|
||||
# belongs here rather than in an alias.
|
||||
#
|
||||
|
||||
# function %name%_current() {
|
||||
# %command% status --short "$@"
|
||||
# }
|
||||
|
||||
%completion%
|
||||
|
||||
#
|
||||
# Need the path to this plugin's own directory (for data files, a lib/ dir...)?
|
||||
# This is the standard way to get it, since $0 is not reliable on its own:
|
||||
# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
|
||||
#
|
||||
# 0="${ZERO:-${${0:#$ZSH_ARGZERO}:-${(%):-%N}}}"
|
||||
# 0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
# source "${0:A:h}/lib/helpers.zsh"
|
||||
@@ -4,8 +4,8 @@ export LSCOLORS=dxFxCxDxBxegedabagacad
|
||||
|
||||
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}
|
||||
%{%(#~$fg[red]~$fg[green])%}╰%(#~#~\$) %{$reset_color%}"
|
||||
PROMPT="%{$fg[green]%}╭─%n@%m %{$reset_color%}%{$fg[yellow]%}in %~ %{$reset_color%}${git_branch}
|
||||
%{$fg[green]%}╰\$ %{$reset_color%}"
|
||||
|
||||
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[yellow]%}on "
|
||||
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%}"
|
||||
|
||||
@@ -23,32 +23,12 @@ zstyle -s ':omz:update' mode update_mode || {
|
||||
# - the automatic update is disabled
|
||||
# - the current user doesn't have write permissions nor owns the $ZSH directory
|
||||
# - 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
|
||||
# - $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
|
||||
unset update_mode
|
||||
return
|
||||
|
||||
+3
-4
@@ -528,10 +528,9 @@ print_success() {
|
||||
"$(fmt_code "$(fmt_link ".zshrc" "file://$zdot/.zshrc" --text)")" \
|
||||
"file to select plugins, themes, and options."
|
||||
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' "• Questions or ideas? Join the community on $(fmt_link Discord 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' " or grab stickers, shirts, and swag from $(fmt_link CommitGoods https://commitgoods.com/ohmyzsh)"
|
||||
printf '%s\n' "• Follow us on X: $(fmt_link @ohmyzsh https://x.com/ohmyzsh)"
|
||||
printf '%s\n' "• Join our Discord community: $(fmt_link "Discord server" https://discord.gg/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' $FMT_RESET
|
||||
}
|
||||
|
||||
|
||||
+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 '\n'
|
||||
printf "${BLUE}%s${RESET}\n\n" "$message"
|
||||
printf "${BLUE}${BOLD}%s %s %s %s${RESET}\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 "${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)"
|
||||
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)"
|
||||
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)"
|
||||
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)"
|
||||
elif [[ $verbose_mode == minimal ]]; then
|
||||
printf "${BLUE}%s${RESET}\n" "$message"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user