diff --git a/.github/dependencies.yml b/.github/dependencies.yml index 46e7727b8..23168b91a 100644 --- a/.github/dependencies.yml +++ b/.github/dependencies.yml @@ -30,7 +30,7 @@ dependencies: plugins/wd: repo: mfaerevaag/wd branch: master - version: tag:v0.9.3 + version: tag:v0.10.0 precopy: | set -e rm -r test @@ -38,7 +38,7 @@ dependencies: plugins/z: branch: master repo: agkozak/zsh-z - version: dd94ef04acc41748ba171eb219971cb455e0040b + version: cf9225feebfae55e557e103e95ce20eca5eff270 precopy: | set -e test -e README.md && mv -f README.md MANUAL.md diff --git a/.github/workflows/dependencies/requirements.txt b/.github/workflows/dependencies/requirements.txt index f2044a5f5..e73c1b5ca 100644 --- a/.github/workflows/dependencies/requirements.txt +++ b/.github/workflows/dependencies/requirements.txt @@ -1,5 +1,5 @@ -certifi==2025.1.31 -charset-normalizer==3.4.1 +certifi==2025.4.26 +charset-normalizer==3.4.2 idna==3.10 PyYAML==6.0.2 requests==2.32.3 diff --git a/lib/cli.zsh b/lib/cli.zsh index 3b6308313..0b144e4e7 100644 --- a/lib/cli.zsh +++ b/lib/cli.zsh @@ -72,6 +72,10 @@ function _omz { local -aU plugins plugins=("$ZSH"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t) "$ZSH_CUSTOM"/plugins/*/{_*,*.plugin.zsh}(-.N:h:t)) _describe 'plugin' plugins ;; + plugin::list) + local -a opts + opts=('--enabled:List enabled plugins only') + _describe -o 'options' opts ;; theme::(set|use)) local -aU themes themes=("$ZSH"/themes/*.zsh-theme(-.N:t:r) "$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::)) @@ -206,7 +210,7 @@ Available commands: disable Disable plugin(s) enable Enable plugin(s) info Get information of a plugin - list List all available Oh My Zsh plugins + list [--enabled] List Oh My Zsh plugins load Load plugin(s) EOF @@ -449,8 +453,21 @@ function _omz::plugin::info { function _omz::plugin::list { local -a custom_plugins builtin_plugins - custom_plugins=("$ZSH_CUSTOM"/plugins/*(-/N:t)) - builtin_plugins=("$ZSH"/plugins/*(-/N:t)) + + # If --enabled is provided, only list what's enabled + if [[ "$1" == "--enabled" ]]; then + local plugin + for plugin in "${plugins[@]}"; do + if [[ -d "${ZSH_CUSTOM}/plugins/${plugin}" ]]; then + custom_plugins+=("${plugin}") + elif [[ -d "${ZSH}/plugins/${plugin}" ]]; then + builtin_plugins+=("${plugin}") + fi + done + else + custom_plugins=("$ZSH_CUSTOM"/plugins/*(-/N:t)) + builtin_plugins=("$ZSH"/plugins/*(-/N:t)) + fi # If the command is being piped, print all found line by line if [[ ! -t 1 ]]; then diff --git a/lib/git.zsh b/lib/git.zsh index a1b4d1587..f4d4229cb 100644 --- a/lib/git.zsh +++ b/lib/git.zsh @@ -39,6 +39,105 @@ function _omz_git_prompt_info() { echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${ref:gs/%/%%}${upstream:gs/%/%%}$(parse_git_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}" } +function _omz_git_prompt_status() { + [[ "$(__git_prompt_git config --get oh-my-zsh.hide-status 2>/dev/null)" = 1 ]] && return + + # Maps a git status prefix to an internal constant + # This cannot use the prompt constants, as they may be empty + local -A prefix_constant_map + prefix_constant_map=( + '\?\? ' 'UNTRACKED' + 'A ' 'ADDED' + 'M ' 'MODIFIED' + 'MM ' 'MODIFIED' + ' M ' 'MODIFIED' + 'AM ' 'MODIFIED' + ' T ' 'MODIFIED' + 'R ' 'RENAMED' + ' D ' 'DELETED' + 'D ' 'DELETED' + 'UU ' 'UNMERGED' + 'ahead' 'AHEAD' + 'behind' 'BEHIND' + 'diverged' 'DIVERGED' + 'stashed' 'STASHED' + ) + + # Maps the internal constant to the prompt theme + local -A constant_prompt_map + constant_prompt_map=( + 'UNTRACKED' "$ZSH_THEME_GIT_PROMPT_UNTRACKED" + 'ADDED' "$ZSH_THEME_GIT_PROMPT_ADDED" + 'MODIFIED' "$ZSH_THEME_GIT_PROMPT_MODIFIED" + 'RENAMED' "$ZSH_THEME_GIT_PROMPT_RENAMED" + 'DELETED' "$ZSH_THEME_GIT_PROMPT_DELETED" + 'UNMERGED' "$ZSH_THEME_GIT_PROMPT_UNMERGED" + 'AHEAD' "$ZSH_THEME_GIT_PROMPT_AHEAD" + 'BEHIND' "$ZSH_THEME_GIT_PROMPT_BEHIND" + 'DIVERGED' "$ZSH_THEME_GIT_PROMPT_DIVERGED" + 'STASHED' "$ZSH_THEME_GIT_PROMPT_STASHED" + ) + + # The order that the prompt displays should be added to the prompt + local status_constants + status_constants=( + UNTRACKED ADDED MODIFIED RENAMED DELETED + STASHED UNMERGED AHEAD BEHIND DIVERGED + ) + + local status_text + status_text="$(__git_prompt_git status --porcelain -b 2> /dev/null)" + + # Don't continue on a catastrophic failure + if [[ $? -eq 128 ]]; then + return 1 + fi + + # A lookup table of each git status encountered + local -A statuses_seen + + if __git_prompt_git rev-parse --verify refs/stash &>/dev/null; then + statuses_seen[STASHED]=1 + fi + + local status_lines + status_lines=("${(@f)${status_text}}") + + # If the tracking line exists, get and parse it + if [[ "$status_lines[1]" =~ "^## [^ ]+ \[(.*)\]" ]]; then + local branch_statuses + branch_statuses=("${(@s/,/)match}") + for branch_status in $branch_statuses; do + if [[ ! $branch_status =~ "(behind|diverged|ahead) ([0-9]+)?" ]]; then + continue + fi + local last_parsed_status=$prefix_constant_map[$match[1]] + statuses_seen[$last_parsed_status]=$match[2] + done + fi + + # For each status prefix, do a regex comparison + for status_prefix in ${(k)prefix_constant_map}; do + local status_constant="${prefix_constant_map[$status_prefix]}" + local status_regex=$'(^|\n)'"$status_prefix" + + if [[ "$status_text" =~ $status_regex ]]; then + statuses_seen[$status_constant]=1 + fi + done + + # Display the seen statuses in the order specified + local status_prompt + for status_constant in $status_constants; do + if (( ${+statuses_seen[$status_constant]} )); then + local next_display=$constant_prompt_map[$status_constant] + status_prompt="$next_display$status_prompt" + fi + done + + echo $status_prompt +} + # Use async version if setting is enabled, or unset but zsh version is at least 5.0.6. # This avoids async prompt issues caused by previous zsh versions: # - https://github.com/ohmyzsh/ohmyzsh/issues/12331 @@ -246,105 +345,6 @@ function git_prompt_long_sha() { SHA=$(__git_prompt_git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER" } -function _omz_git_prompt_status() { - [[ "$(__git_prompt_git config --get oh-my-zsh.hide-status 2>/dev/null)" = 1 ]] && return - - # Maps a git status prefix to an internal constant - # This cannot use the prompt constants, as they may be empty - local -A prefix_constant_map - prefix_constant_map=( - '\?\? ' 'UNTRACKED' - 'A ' 'ADDED' - 'M ' 'MODIFIED' - 'MM ' 'MODIFIED' - ' M ' 'MODIFIED' - 'AM ' 'MODIFIED' - ' T ' 'MODIFIED' - 'R ' 'RENAMED' - ' D ' 'DELETED' - 'D ' 'DELETED' - 'UU ' 'UNMERGED' - 'ahead' 'AHEAD' - 'behind' 'BEHIND' - 'diverged' 'DIVERGED' - 'stashed' 'STASHED' - ) - - # Maps the internal constant to the prompt theme - local -A constant_prompt_map - constant_prompt_map=( - 'UNTRACKED' "$ZSH_THEME_GIT_PROMPT_UNTRACKED" - 'ADDED' "$ZSH_THEME_GIT_PROMPT_ADDED" - 'MODIFIED' "$ZSH_THEME_GIT_PROMPT_MODIFIED" - 'RENAMED' "$ZSH_THEME_GIT_PROMPT_RENAMED" - 'DELETED' "$ZSH_THEME_GIT_PROMPT_DELETED" - 'UNMERGED' "$ZSH_THEME_GIT_PROMPT_UNMERGED" - 'AHEAD' "$ZSH_THEME_GIT_PROMPT_AHEAD" - 'BEHIND' "$ZSH_THEME_GIT_PROMPT_BEHIND" - 'DIVERGED' "$ZSH_THEME_GIT_PROMPT_DIVERGED" - 'STASHED' "$ZSH_THEME_GIT_PROMPT_STASHED" - ) - - # The order that the prompt displays should be added to the prompt - local status_constants - status_constants=( - UNTRACKED ADDED MODIFIED RENAMED DELETED - STASHED UNMERGED AHEAD BEHIND DIVERGED - ) - - local status_text - status_text="$(__git_prompt_git status --porcelain -b 2> /dev/null)" - - # Don't continue on a catastrophic failure - if [[ $? -eq 128 ]]; then - return 1 - fi - - # A lookup table of each git status encountered - local -A statuses_seen - - if __git_prompt_git rev-parse --verify refs/stash &>/dev/null; then - statuses_seen[STASHED]=1 - fi - - local status_lines - status_lines=("${(@f)${status_text}}") - - # If the tracking line exists, get and parse it - if [[ "$status_lines[1]" =~ "^## [^ ]+ \[(.*)\]" ]]; then - local branch_statuses - branch_statuses=("${(@s/,/)match}") - for branch_status in $branch_statuses; do - if [[ ! $branch_status =~ "(behind|diverged|ahead) ([0-9]+)?" ]]; then - continue - fi - local last_parsed_status=$prefix_constant_map[$match[1]] - statuses_seen[$last_parsed_status]=$match[2] - done - fi - - # For each status prefix, do a regex comparison - for status_prefix in ${(k)prefix_constant_map}; do - local status_constant="${prefix_constant_map[$status_prefix]}" - local status_regex=$'(^|\n)'"$status_prefix" - - if [[ "$status_text" =~ $status_regex ]]; then - statuses_seen[$status_constant]=1 - fi - done - - # Display the seen statuses in the order specified - local status_prompt - for status_constant in $status_constants; do - if (( ${+statuses_seen[$status_constant]} )); then - local next_display=$constant_prompt_map[$status_constant] - status_prompt="$next_display$status_prompt" - fi - done - - echo $status_prompt -} - # Outputs the name of the current user # Usage example: $(git_current_user_name) function git_current_user_name() { diff --git a/lib/history.zsh b/lib/history.zsh index 35da57de2..781a0e9de 100644 --- a/lib/history.zsh +++ b/lib/history.zsh @@ -18,10 +18,10 @@ function omz_history { print -u2 History file deleted. elif [[ $# -eq 0 ]]; then # if no arguments provided, show full history starting from 1 - builtin fc $stamp -l 1 + builtin fc "${stamp[@]}" -l 1 else # otherwise, run `fc -l` with a custom format - builtin fc $stamp -l "$@" + builtin fc "${stamp[@]}" -l "$@" fi } diff --git a/lib/termsupport.zsh b/lib/termsupport.zsh index d2fbf42cd..994c9c322 100644 --- a/lib/termsupport.zsh +++ b/lib/termsupport.zsh @@ -17,7 +17,7 @@ function title { : ${2=$1} case "$TERM" in - cygwin|xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty*|st*|foot*|contour*) + cygwin|xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty*|st*|foot*|contour*|wezterm*) print -Pn "\e]2;${2:q}\a" # set window name print -Pn "\e]1;${1:q}\a" # set tab name ;; diff --git a/oh-my-zsh.sh b/oh-my-zsh.sh index b1032841c..2e885219c 100644 --- a/oh-my-zsh.sh +++ b/oh-my-zsh.sh @@ -192,7 +192,7 @@ _omz_source() { fi } -# Load all of the lib files in ~/oh-my-zsh/lib that end in .zsh +# Load all of the lib files in ~/.oh-my-zsh/lib that end in .zsh # TIP: Add files you don't want in git to .gitignore for lib_file ("$ZSH"/lib/*.zsh); do _omz_source "lib/${lib_file:t}" diff --git a/plugins/debian/debian.plugin.zsh b/plugins/debian/debian.plugin.zsh index 5ef4cfb67..980440c0f 100644 --- a/plugins/debian/debian.plugin.zsh +++ b/plugins/debian/debian.plugin.zsh @@ -83,9 +83,9 @@ else } alias ac="su -ls '$apt_pref clean' root" alias ad="su -lc '$apt_pref update' root" - alias adg="su -lc '$apt_pref update && aptitude $apt_upgr' root" - alias adu="su -lc '$apt_pref update && aptitude dist-upgrade' root" - alias afu="su -lc '$apt-file update'" + alias adg="su -lc '$apt_pref update && $apt_pref $apt_upgr' root" + alias adu="su -lc '$apt_pref update && $apt_pref dist-upgrade' root" + alias afu="su -lc 'apt-file update'" alias au="su -lc '$apt_pref $apt_upgr' root" function ai() { cmd="su -lc '$apt_pref install $@' root" diff --git a/plugins/emacs/emacs.plugin.zsh b/plugins/emacs/emacs.plugin.zsh index 5aa621803..3ed6cee19 100644 --- a/plugins/emacs/emacs.plugin.zsh +++ b/plugins/emacs/emacs.plugin.zsh @@ -35,7 +35,7 @@ alias eeval="$EMACS_PLUGIN_LAUNCHER --eval" alias eframe='emacsclient --alternate-editor="" --create-frame' # Emacs ANSI Term tracking -if [[ -n "$INSIDE_EMACS" ]]; then +if [[ -n "$INSIDE_EMACS" ]] && [[ "$INSIDE_EMACS" != "vterm" ]]; then chpwd_emacs() { print -P "\033AnSiTc %d"; } print -P "\033AnSiTc %d" # Track current working directory print -P "\033AnSiTu %n" # Track username diff --git a/plugins/jj/README.md b/plugins/jj/README.md index cd43ed11b..541b8f907 100644 --- a/plugins/jj/README.md +++ b/plugins/jj/README.md @@ -20,6 +20,7 @@ plugins=(... jj) | jje | `jj edit` | | jjgcl | `jj git clone` | | jjgf | `jj git fetch` | +| jjgfa | `jj git fetch --all-remotes` | | jjgp | `jj git push` | | jjl | `jj log` | | jjla | `jj log -r "all()"` | diff --git a/plugins/jj/jj.plugin.zsh b/plugins/jj/jj.plugin.zsh index 06c04958b..825460517 100644 --- a/plugins/jj/jj.plugin.zsh +++ b/plugins/jj/jj.plugin.zsh @@ -42,6 +42,7 @@ alias jjds='jj desc' alias jje='jj edit' alias jjgcl='jj git clone' alias jjgf='jj git fetch' +alias jjgfa='jj git fetch --all-remotes' alias jjgp='jj git push' alias jjl='jj log' alias jjla='jj log -r "all()"' diff --git a/plugins/kamal/README.md b/plugins/kamal/README.md new file mode 100644 index 000000000..af5716826 --- /dev/null +++ b/plugins/kamal/README.md @@ -0,0 +1,16 @@ +# Kamal + +This plugin provides completion for [Kamal](https://kamal-deploy.org/) as well as some +aliases for frequent Kamal commands. + +To use it, add kamal to the plugins array of your zshrc file: + +```zsh +plugins=(... kamal) +``` + +## Aliase + +| Alias | Command | Description | +|-----------|----------------------------------|----------------------------------------------------------------------------------| +| kad | `kamal deploy` | Deploy app to servers | diff --git a/plugins/kamal/_kamal b/plugins/kamal/_kamal new file mode 100644 index 000000000..52b29e814 --- /dev/null +++ b/plugins/kamal/_kamal @@ -0,0 +1,691 @@ +#compdef kamal + +# Description +# ----------- +# zsh completion for Kamal (https://kamal-deploy.org/) +# ------------------------------------------------------------------------- +# Authors +# ------- +# * Igor Aleksandrov +# ------------------------------------------------------------------------- +# Inspiration +# ----------- +# * docker-compose ohmyzsh completion script by @sdurrheimer Steve Durrheimer +# ------------------------------------------------------------------------- + +# _kamal_commands() { +# # Only initialize if empty +# if (( ${#kamal_commands} == 0 )); then +# kamal_commands=( +# accessory +# app +# audit +# build +# config +# deploy +# details +# docs +# help +# init +# lock +# proxy +# prune +# redeploy +# registry +# remove +# rollback +# secrets +# server +# setup +# upgrade +# version +# ) +# fi + +# _values 'Kamal commands' $kamal_commands +# } + +typeset -gr _kamal_commands=( + 'accessory:Control accessory services' + 'app:Control application deployment' + 'audit:Audit security of deployment' + 'build:Build and manage app images' + 'config:Show effective configuration' + 'deploy:Deploy app to servers' + 'details:Show details about deployment' + 'docs:Open documentation in browser' + 'help:Show command help' + 'init:Initialize new Kamal project' + 'lock:Manage deployment locks' + 'proxy:Control reverse proxy' + 'prune:Clean up containers and images' + 'redeploy:Redeploy current version' + 'registry:Manage Docker registry access' + 'remove:Remove app from servers' + 'rollback:Rollback to a previous version' + 'secrets:Manage deployment secrets' + 'server:Control server configuration' + 'setup:Setup initial deployment' + 'upgrade:Upgrade deployment' + 'version:Show Kamal version' +) + +# Helper function to display messages +_kamal_message() { + local msg="$1" + _kamal_message "==> $msg" +} + +# Helper function to extract destination names from ./config/deploy.*.yml +_kamal_destinations() { + local -a dests + local file + + # Check if config directory exists + if [[ ! -d "config" ]]; then + _kamal_message "Cannot find Kamal configuration directory at ./config" && return 1 + fi + + for file in config/deploy.*.yml(N); do + [[ $file =~ config/deploy\.(.+)\.yml ]] && dests+=("${match[1]}") + done + + _values 'Destination' $dests +} + +# Define global _kamal_flags array +typeset -ga _kamal_flags +_kamal_flags=( + '(-v --verbose )'{-v,--verbose}'[Detailed logging]' + '(--no-verbose --skip-verbose)'{--no-verbose,--skip-verbose}'[No detailed logging]' + '(-q --quiet --no-quiet --skip-quiet)'{-q,--quiet}'[Minimal logging]' + '(-q --quiet --no-quiet --skip-quiet)'{--no-quiet,--skip-quiet}'[No minimal logging]' + '--version=[Run commands against a specific app version]:version' + '(-p --primary --no-primary --skip-primary)'{-p,--primary}'[Run commands only on primary host instead of all]' + '(-p --primary --no-primary --skip-primary)'{--no-primary,--skip-primary}'[Do not run commands only on primary host]' + '(-h --hosts)'{-h,--hosts=}'[Run commands on these hosts instead of all]:hosts' + '(-r --roles)'{-r,--roles=}'[Run commands on these roles instead of all]:roles' + '(-c --config-file)'{-c,--config-file=}'[Path to config file]:config file:_files' + '(-d --destination)'{-d,--destination=}'[Specify destination to be used for config file]:destination:_kamal_destinations' + '(-H --skip-hooks)'{-H,--skip-hooks}'[Do not run hooks]' +) + +_kamal() { + local context state state_descr line curcontext="$curcontext" + typeset -A opt_args + + local ret=1 + + _arguments -C \ + $_kamal_flags \ + '1: :->command' \ + '*:: :->args' && ret=0 + + case $state in + (command) + # First argument - show available commands + _describe -t kamal-commands "Kamal commands" _kamal_commands && ret=0 + ;; + (args) + # Subsequent arguments - handle based on the command + case $words[1] in + (accessory) + _kamal_accessory && ret=0 + ;; + (app) + _kamal_app && ret=0 + ;; + (audit) + _arguments $_kamal_flags && ret=0 + ;; + (build) + _kamal_build && ret=0 + ;; + (config) + _arguments $_kamal_flags && ret=0 + ;; + (deploy) + _arguments $_kamal_flags && ret=0 + ;; + (details) + _arguments $_kamal_flags && ret=0 + ;; + (docs) + _arguments $_kamal_flags && ret=0 + ;; + (help) + _kamal_help && ret=0 + ;; + (init) + local -a init_flags + init_flags=( + $_kamal_flags + '(--bundle --no-bundle --skip-bundle)--bundle[Add Kamal to the Gemfile and create a bin/kamal binstub]' + '(--bundle --no-bundle --skip-bundle)--no-bundle[Do not add Kamal to the Gemfile and create a bin/kamal binstub]' + '(--bundle --no-bundle --skip-bundle)--skip-bundle[Skip add Kamal to the Gemfile and create a bin/kamal binstub]' + ) + _arguments $init_flags && ret=0 + ;; + (lock) + _kamal_lock && ret=0 + ;; + (proxy) + _kamal_proxy && ret=0 + ;; + (prune) + _kamal_prune && ret=0 + ;; + (redeploy) + _arguments $_kamal_flags && ret=0 + ;; + (registry) + _kamal_registry && ret=0 + ;; + (remove) + local -a remove_flags + remove_flags=( + $_kamal_flags + '(-y --confirmed --no-confirmed --skip-confirmed)'{-y,--confirmed}'[Proceed without confirmation question]' + '(-y --confirmed --no-confirmed --skip-confirmed)--no-confirmed[Proceed without confirmation question]' + '(-y --confirmed --no-confirmed --skip-confirmed)--skip-confirmed[Proceed without confirmation question]' + ) + _arguments $remove_flags && ret=0 + ;; + (rollback) + if (( CURRENT == 2 )); then + _kamal_message "Enter the version to rollback to" && ret=0 + else + _values $_kamal_flags && ret=0 + fi + ;; + (secrets) + _kamal_secrets && ret=0 + ;; + (server) + _kamal_server && ret=0 + ;; + (setup) + local -a setup_flags + setup_flags=( + $_kamal_flags + '(-P --skip-push)'{-P,--skip-push}'[Skip image build and push]' + ) + _arguments $setup_flags && ret=0 + ;; + (upgrade) + local -a upgrade_flags + upgrade_flags=( + $_kamal_flags + '(-y --confirmed --no-confirmed --skip-confirmed)'{-y,--confirmed}'[Proceed without confirmation question]' + '(-y --confirmed --no-confirmed --skip-confirmed)--no-confirmed[Do not proceed without confirmation question]' + '(-y --confirmed --no-confirmed --skip-confirmed)--skip-confirmed[Skip confirmation question]' + '(--rolling --no-rolling --skip-rolling)--rolling[Upgrade one host at a time]' + '(--rolling --no-rolling --skip-rolling)--no-rolling[Do not upgrade one host at a time]' + '(--rolling --no-rolling --skip-rolling)--skip-rolling[Skip rolling upgrade]' + ) + _arguments $upgrade_flags && ret=0 + ;; + (version) + _arguments $_kamal_flags && ret=0 + esac + ;; + esac + + return ret +} + +_kamal_accessory() { + local context state line + typeset -A opt_args + local ret=1 + + # Define accessory subcommands + local -a accessory_subcommands + accessory_subcommands=( + "boot:Boot new accessory service on host (use NAME=all to boot all accessories)" + "details:Show details about accessory on host (use NAME=all to show all accessories)" + "exec:Execute a custom command on servers within the accessory container (use --help to show options)" + "help:Describe subcommands or one specific subcommand" + "logs:Show log lines from accessory on host (use --help to show options)" + "reboot:Reboot existing accessory on host (stop container, remove container, start new container; use NAME=all to boot all accessories)" + "remove:Remove accessory container, image and data directory from host (use NAME=all to remove all accessories)" + "restart:Restart existing accessory container on host" + "start:Start existing accessory container on host" + "stop:Stop existing accessory container on host" + "upgrade:Upgrade accessories from Kamal 1.x to 2.0 (restart them in 'kamal' network)" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t accessory-commands "Kamal accessory commands" accessory_subcommands && ret=0 + ;; + (args) + case $words[1] in + (boot|details|exec|logs|reboot|remove|restart|start|stop) + # These commands require a NAME parameter + if (( CURRENT == 2 )); then + # At the NAME position - we could add accessory name completion here + # if we had a way to list available accessories + _kamal_message "Specify an accessory name (or 'all' for all accessories)" && ret=0 + elif [[ "$words[1]" == "exec" && CURRENT == 3 ]]; then + # For exec, the 3rd argument is a command + _kamal_message "Enter a command to execute" && ret=0 + elif (( CURRENT > 2 )) && [[ "$words[1]" != "exec" || CURRENT > 3 ]]; then + _values $_kamal_flags && ret=0 + fi + ;; + (help) + # Remove help itself from the list of commands + accessory_subcommands=("${(@)accessory_subcommands:#help*}") + _describe -t accessory-help-commands "Kamal accessory help commands" accessory_subcommands + ;; + (upgrade) + # For upgrade, show flags immediately + _arguments $_kamal_flags && ret=0 + ;; + esac + ;; + esac + + return ret +} + +_kamal_app() { + local context state line + typeset -A opt_args + local ret=1 + + local -a app_subcommands + app_subcommands=( + "boot:Boot app on servers (or reboot app if already running)" + "containers:Show app containers on servers" + "details:Show details about app containers" + "exec:Execute a custom command on servers within the app container (use --help to show options)" + "help:Describe subcommands or one specific subcommand" + "images:Show app images on servers" + "logs:Show log lines from app on servers (use --help to show options)" + "remove:Remove app containers and images from servers" + "stale_containers:Detect app stale containers" + "start:Start existing app container on servers" + "stop:Stop app container on servers" + "version:Show app version currently running on servers" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t app-commands "Kamal app commands" app_subcommands && ret=0 + ;; + (args) + case $words[1] in + (boot|containers|details|images|logs|remove|stale_containers|start|stop) + _arguments $_kamal_flags && ret=0 + ;; + (exec) + # For exec, the next argument is a command + if (( CURRENT == 2 )); then + _kamal_message "Enter a command to execute" && ret=0 + else + _values $_kamal_flags && ret=0 + fi + ;; + (help) + # Remove help itself from the list of commands + app_subcommands=("${(@)app_subcommands:#help*}") + _describe -t app-help-commands "Kamal app help commands" app_subcommands + ;; + esac + ;; + esac + + return ret +} + +_kamal_build() { + local context state line + typeset -A opt_args + local ret=1 + + local -a build_subcommands + build_subcommands=( + "create:Create a build setup" + "deliver:Build app and push app image to registry then pull image on servers" + "details:Show build setup" + "dev:Build using the working directory, tag it as dirty, and push to local image store." + "help:Describe subcommands or one specific subcommand" + "pull:Pull app image from registry onto servers" + "push:Build and push app image to registry" + "remove:Remove build setup" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t build-commands "Kamal build commands" build_subcommands && ret=0 + ;; + (args) + case $words[1] in + (create|deliver|details|dev|pull|push|remove) + _arguments $_kamal_flags && ret=0 + ;; + (help) + # Remove help itself from the list of commands + build_subcommands=("${(@)build_subcommands:#help*}") + _describe -t build-help-commands "Kamal build help commands" build_subcommands + ;; + esac + ;; + esac + + return ret +} + +_kamal_help() { + local ret=1 + + # Make sure kamal_commands is initialized properly + # if (( ${#kamal_commands} == 0 )); then + # _kamal_commands >/dev/null + # fi + + # If we already have a command after "help", return without suggestions + if (( CURRENT > 2 )); then + ret=0 + else + local -a help_commands + # Filter out help from the list of commands + help_commands=("${(@)_kamal_commands:#help}") + + _values 'Kamal help' $help_commands && ret=0 + fi + + return ret +} + +_kamal_lock() { + local context state line + typeset -A opt_args + local ret=1 + + local -a lock_subcommands + lock_subcommands=( + "acquire:Acquire the deploy lock" + "help:Describe subcommands or one specific subcommand" + "release:Release the deploy lock" + "status:Report lock status" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t lock-commands "Kamal lock commands" lock_subcommands && ret=0 + ;; + (args) + case $words[1] in + (acquire) + local -a acquire_flags + acquire_flags=( + $_kamal_flags + '(-m --message)'{-m,--message=}'[A lock message]:message:' # Required flag + ) + _arguments $acquire_flags && ret=0 + ;; + (release|status) + _arguments $_kamal_flags && ret=0 + ;; + (help) + # Remove help itself from the list of commands + lock_subcommands=("${(@)lock_subcommands:#help*}") + _describe -t lock-help-commands "Kamal lock help commands" lock_subcommands + ;; + esac + ;; + esac + + return ret +} + +_kamal_proxy() { + local context state line + typeset -A opt_args + local ret=1 + + local -a proxy_subcommands + proxy_subcommands=( + "boot:Boot proxy on servers" + "boot_config:Manage kamal-proxy boot configuration" + "details:Show details about proxy container from servers" + "help:Describe subcommands or one specific subcommand" + "logs:Show log lines from proxy on servers" + "reboot:Reboot proxy on servers (stop container, remove container, start new container)" + "remove:Remove proxy container and image from servers" + "restart:Restart existing proxy container on servers" + "start:Start existing proxy container on servers" + "stop:Stop existing proxy container on servers" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t proxy-commands "Kamal proxy commands" proxy_subcommands && ret=0 + ;; + (args) + case $words[1] in + (boot|details|logs|reboot|remove|restart|start|stop) + _arguments $_kamal_flags && ret=0 + ;; + (boot_config) + if (( CURRENT == 2 )); then + local -a boot_config_commands=( + "set:Set boot configuration" + "get:Get boot configuration" + "reset:Reset boot configuration" + ) + _describe -t boot-config-commands "Boot config commands" boot_config_commands && ret=0 + else + _values $_kamal_flags && ret=0 + fi + ;; + (help) + # Remove help itself from the list of commands + proxy_subcommands=("${(@)proxy_subcommands:#help*}") + _describe -t proxy-help-commands "Kamal proxy help commands" proxy_subcommands + ;; + esac + ;; + esac + + return ret +} + +_kamal_prune() { + local context state line + typeset -A opt_args + local ret=1 + + local -a prune_subcommands + prune_subcommands=( + "all:Prune unused images and stopped containers" + "containers:Prune all stopped containers, except the last n (default 5)" + "help:Describe subcommands or one specific subcommand" + "images:Prune unused images" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t prune-commands "Kamal prune commands" prune_subcommands && ret=0 + ;; + (args) + case $words[1] in + (all|containers|images) + _arguments $_kamal_flags && ret=0 + ;; + (help) + # Remove help itself from the list of commands + prune_subcommands=("${(@)prune_subcommands:#help*}") + _describe -t prune-help-commands "Kamal prune help commands" prune_subcommands + ;; + esac + ;; + esac + + return ret +} + +_kamal_registry() { + local context state line + typeset -A opt_args + local ret=1 + + local -a registry_subcommands + registry_subcommands=( + "help:Describe subcommands or one specific subcommand" + "login:Log in to registry locally and remotely" + "logout:Log out of registry locally and remotely" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t registry-commands "Kamal registry commands" registry_subcommands && ret=0 + ;; + (args) + case $words[1] in + (help) + # Remove help itself from the list of commands + registry_subcommands=("${(@)registry_subcommands:#help*}") + _describe -t registry-help-commands "Kamal registry help commands" registry_subcommands + ;; + (login|logout) + _arguments $_kamal_flags && ret=0 + ;; + esac + ;; + esac + + return ret +} + +_kamal_secrets() { + local context state line + typeset -A opt_args + local ret=1 + + local -a secrets_subcommands + secrets_subcommands=( + "extract:Extract a single secret from the results of a fetch call" + "fetch:Fetch secrets from a vault" + "help:Describe subcommands or one specific subcommand" + "print:Print the secrets (for debugging)" + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t secrets-commands "Kamal secrets commands" secrets_subcommands && ret=0 + ;; + (args) + case $words[1] in + (fetch) + local -a fetch_flags + fetch_flags=( + $_kamal_flags + '(-a --adapter)'{-a,--adapter=}'[Secret storage adapter]:adapter:(aws-parameter-store)' + ) + _arguments $fetch_flags && ret=0 + ;; + (extract|print) + _arguments $_kamal_flags && ret=0 + ;; + (help) + # Remove help itself from the list of commands + secrets_subcommands=("${(@)secrets_subcommands:#help*}") + _describe -t secrets-help-commands "Kamal secrets help commands" secrets_subcommands + ;; + esac + ;; + esac + + return ret +} + +_kamal_server() { + local context state line + typeset -A opt_args + local ret=1 + + local -a server_subcommands + server_subcommands=( + "bootstrap:Set up Docker to run Kamal apps" + "exec:Run a custom command on the server (use --help to show options)" + "help:Describe subcommands or one specific subcommand" + ) + + local -a server_flags + server_flags=( + $_kamal_flags + '(-i --interactive --no-interactive --skip-interactive)'{-i,--interactive}'[Run the command interactively]' + '(-i --interactive --no-interactive --skip-interactive)--no-interactive[Do not run the command interactively]' + '(-i --interactive --no-interactive --skip-interactive)--skip-interactive[Skip interactive mode]' + ) + + _arguments -C \ + '1: :->subcmd' \ + '*:: :->args' && ret=0 + + case $state in + (subcmd) + _describe -t server-commands "Kamal server commands" server_subcommands && ret=0 + ;; + (args) + case $words[1] in + (bootstrap) + _arguments $server_flags && ret=0 + ;; + (exec) + if (( CURRENT == 2 )); then + # For exec, the next argument is a command + _kamal_message "Enter a command to execute" && ret=0 + else + _values $server_flags && ret=0 + fi + ;; + (help) + # Remove help itself from the list of commands + server_subcommands=("${(@)server_subcommands:#help*}") + _describe -t server-help-commands "Kamal server help commands" server_subcommands + ;; + esac + ;; + esac + + return ret +} + +_kamal "$@" \ No newline at end of file diff --git a/plugins/kamal/kamal.plugin.zsh b/plugins/kamal/kamal.plugin.zsh new file mode 100644 index 000000000..e21ab4f92 --- /dev/null +++ b/plugins/kamal/kamal.plugin.zsh @@ -0,0 +1,25 @@ +# Find kamal binary (local ./bin/kamal or global) +function _kamal_command () { + if [ -x "./bin/kamal" ]; then + ./bin/kamal "$@" + else + command kamal "$@" + fi +} + +function which-kamal() { + if [ -x "./bin/kamal" ]; then + echo "Using local ./bin/kamal" + else + echo "Using global $(command -v kamal)" + fi +} + +# Use `_kamal_command`` function for `kamal` command +alias kamal='_kamal_command' + +# Aliases +alias kad='kamal deploy' + +# Hook up completion +compdef _kamal_command=kamal diff --git a/plugins/laravel/README.md b/plugins/laravel/README.md index d722770c9..c5375f270 100644 --- a/plugins/laravel/README.md +++ b/plugins/laravel/README.md @@ -21,6 +21,7 @@ plugins=(... laravel) | `pamfs` | `php artisan migrate:fresh --seed` | | `pamr` | `php artisan migrate:rollback` | | `pads` | `php artisan db:seed` | +| `padw` | `php artisan db:wipe` | ## Makers diff --git a/plugins/laravel/laravel.plugin.zsh b/plugins/laravel/laravel.plugin.zsh index ef462b13c..20a1c473e 100644 --- a/plugins/laravel/laravel.plugin.zsh +++ b/plugins/laravel/laravel.plugin.zsh @@ -12,6 +12,7 @@ alias pamf='php artisan migrate:fresh' alias pamfs='php artisan migrate:fresh --seed' alias pamr='php artisan migrate:rollback' alias pads='php artisan db:seed' +alias padw='php artisan db:wipe' # Makers alias pamm='php artisan make:model' diff --git a/plugins/mvn/README.md b/plugins/mvn/README.md index 4181fedc5..bcb26482e 100644 --- a/plugins/mvn/README.md +++ b/plugins/mvn/README.md @@ -33,6 +33,8 @@ if it's found, or the mvn command otherwise. | `mvnct` | `mvn clean test` | | `mvncv` | `mvn clean verify` | | `mvncvst` | `mvn clean verify -DskipTests` | +| `mvnv` | `mvn verify` | +| `mvnvst` | `mvn verify -DskipTests` | | `mvndp` | `mvn deploy` | | `mvndocs` | `mvn dependency:resolve -Dclassifier=javadoc` | | `mvndt` | `mvn dependency:tree` | diff --git a/plugins/mvn/mvn.plugin.zsh b/plugins/mvn/mvn.plugin.zsh index 7bffce36e..8477722b0 100644 --- a/plugins/mvn/mvn.plugin.zsh +++ b/plugins/mvn/mvn.plugin.zsh @@ -62,6 +62,8 @@ alias mvncp='mvn clean package' alias mvnct='mvn clean test' alias mvncv='mvn clean verify' alias mvncvst='mvn clean verify -DskipTests' +alias mvnv='mvn verify' +alias mvnvst='mvn verify -DskipTests' alias mvndp='mvn deploy' alias mvndocs='mvn dependency:resolve -Dclassifier=javadoc' alias mvndt='mvn dependency:tree' diff --git a/plugins/pip/README.md b/plugins/pip/README.md index 70d40c79f..9d1daca9f 100644 --- a/plugins/pip/README.md +++ b/plugins/pip/README.md @@ -20,17 +20,17 @@ the next time you autocomplete `pip install`. ## Aliases -| Alias | Description | -| :------- | :-------------------------------------------- | -| pipi | Install packages | -| pipig | Install package from GitHub repository | -| pipigb | Install package from GitHub branch | -| pipigp | Install package from GitHub pull request | -| pipu | Upgrade packages | -| pipun | Uninstall packages | -| pipgi | Grep through installed packages | -| piplo | List outdated packages | -| pipreq | Create requirements file | -| pipir | Install packages from `requirements.txt` file | -| pipupall | Update all installed packages | -| pipunall | Uninstall all installed packages | +| Alias | Command | Description | +| :--------|:----------------------------------------------------------------------------------|:--------------------------------------------- | +| pipi | `pip install` | Install packages | +| pipig | `pip install "git+https://github.com/user/repo.git"` | Install package from GitHub repository | +| pipigb | `pip install "git+https://github.com/user/repo.git@branch"` | Install package from GitHub branch | +| pipigp | `pip install "git+https://github.com/user/repo.git@refs/pull/PR_NUMBER/head"` | Install package from GitHub pull request | +| pipu | `pip install --upgrade` | Upgrade packages | +| pipun | `pip uninstall` | Uninstall packages | +| pipgi | `pip freeze \| grep` | Grep through installed packages | +| piplo | `pip list --outdated` | List outdated packages | +| pipreq | `pip freeze > requirements.txt` | Create requirements file | +| pipir | `pip install -r requirements.txt` | Install packages from `requirements.txt` file | +| pipupall | `pip list --outdated \| awk 'NR > 2 { print $1 }' \| xargs pip install --upgrade` | Update all installed packages | +| pipunall | `pip list --format freeze \| cut -d= -f1 \| xargs pip uninstall` | Uninstall all installed packages | diff --git a/plugins/python/README.md b/plugins/python/README.md index 490cf88f1..ca424ea55 100644 --- a/plugins/python/README.md +++ b/plugins/python/README.md @@ -34,7 +34,7 @@ virtual environments: `/bin/activate`, and automatically deactivate it when navigating out of it (keeps venv activated in subdirectories). - To enable the feature, set `PYTHON_AUTO_VRUN=true` before sourcing oh-my-zsh. - - The plugin activates the first existing virtual environment, in order, appearing in `$PYTON_VENV_NAMES`. + - The plugin activates the first existing virtual environment, in order, appearing in `$PYTHON_VENV_NAMES`. The default virtual environment name is `venv`. To use a different name, set `PYTHON_VENV_NAME=`. For example: `PYTHON_VENV_NAME=".venv"` diff --git a/plugins/rsync/README.md b/plugins/rsync/README.md index 032ee7f3b..04d16c88b 100644 --- a/plugins/rsync/README.md +++ b/plugins/rsync/README.md @@ -1,16 +1,26 @@ # rsync -This plugin adds aliases for frequent [rsync](https://rsync.samba.org/) commands. +This plugin adds aliases for frequent [rsync](https://rsync.samba.org/) commands, simplifying file transfer and synchronization tasks. -To use it add `rsync` to the plugins array in you zshrc file. +To use it add `rsync` to the plugins array in you `.zshrc` file. ```zsh plugins=(... rsync) ``` -| Alias | Command | -| ------------------- | ------------------------------------------------ | -| *rsync-copy* | `rsync -avz --progress -h` | -| *rsync-move* | `rsync -avz --progress -h --remove-source-files` | -| *rsync-update* | `rsync -avzu --progress -h` | -| *rsync-synchronize* | `rsync -avzu --delete --progress -h` | +| Alias | Command | Description | +| ------------------- | ------------------------------------------------ | ------------| +| `rsync-copy` | `rsync -avz --progress -h` | Recursively copy files and directories, preserving permissions, timestamps, and symbolic links. Compression is enabled for faster transfers. Progress is displayed in a human-readable format. | +| `rsync-move` | `rsync -avz --progress -h --remove-source-files` | Same as rsync-copy, but removes the source files after a successful transfer (effectively performing a move). | +| `rsync-update` | `rsync -avzu --progress -h` | Like rsync-copy, but only updates files if the source is newer than the destination (or if the destination file is missing). | +| `rsync-synchronize` | `rsync -avzu --delete --progress -h` | Performs bidirectional-style sync: updates files as in rsync-update and deletes files in the destination that no longer exist in the source. Useful for directory synchronization. | + +Explanation of Flags: + - -a: Archive mode; preserves symbolic links, permissions, timestamps, etc. + - -v: Verbose; shows details of the transfer process. + - -z: Compress file data during transfer for efficiency. + - -u: Skip files that are newer on the receiver. + - --progress: Show progress during file transfer. + - -h: Output numbers in human-readable format (e.g., 1K, 234M). + - --remove-source-files: Deletes source files after they are copied (used in rsync-move). + - --delete: Deletes files in the destination that are not present in the source (used in rsync-synchronize). diff --git a/plugins/terraform/README.md b/plugins/terraform/README.md index feaf21d40..6c139ac51 100644 --- a/plugins/terraform/README.md +++ b/plugins/terraform/README.md @@ -15,25 +15,26 @@ plugins=(... terraform) ## Aliases -| Alias | Command | -|---------|----------------------------------| -| `tf` | `terraform` | -| `tfa` | `terraform apply` | -| `tfaa` | `terraform apply -auto-approve` | -| `tfc` | `terraform console` | -| `tfd` | `terraform destroy` | -| `tfd!` | `terraform destroy -auto-approve`| -| `tff` | `terraform fmt` | -| `tffr` | `terraform fmt -recursive` | -| `tfi` | `terraform init` | -| `tfiu` | `terraform init -upgrade` | -| `tfo` | `terraform output` | -| `tfp` | `terraform plan` | -| `tfv` | `terraform validate` | -| `tfs` | `terraform state` | -| `tft` | `terraform test` | -| `tfsh` | `terraform show` | - +| Alias | Command | +| ------- | -------------------------------------- | +| `tf` | `terraform` | +| `tfa` | `terraform apply` | +| `tfaa` | `terraform apply -auto-approve` | +| `tfc` | `terraform console` | +| `tfd` | `terraform destroy` | +| `tfd!` | `terraform destroy -auto-approve` | +| `tff` | `terraform fmt` | +| `tffr` | `terraform fmt -recursive` | +| `tfi` | `terraform init` | +| `tfir` | `terraform init -reconfigure` | +| `tfiu` | `terraform init -upgrade` | +| `tfiur` | `terraform init -upgrade -reconfigure` | +| `tfo` | `terraform output` | +| `tfp` | `terraform plan` | +| `tfv` | `terraform validate` | +| `tfs` | `terraform state` | +| `tft` | `terraform test` | +| `tfsh` | `terraform show` | ## Prompt function diff --git a/plugins/terraform/terraform.plugin.zsh b/plugins/terraform/terraform.plugin.zsh index 046fabb03..0982fa193 100644 --- a/plugins/terraform/terraform.plugin.zsh +++ b/plugins/terraform/terraform.plugin.zsh @@ -24,7 +24,9 @@ alias 'tfd!'='terraform destroy -auto-approve' alias tff='terraform fmt' alias tffr='terraform fmt -recursive' alias tfi='terraform init' +alias tfir='terraform init -reconfigure' alias tfiu='terraform init -upgrade' +alias tfiur='terraform init -upgrade -reconfigure' alias tfo='terraform output' alias tfp='terraform plan' alias tfv='terraform validate' diff --git a/plugins/universalarchive/README.md b/plugins/universalarchive/README.md index 93a1bd9fc..bcd33cea0 100644 --- a/plugins/universalarchive/README.md +++ b/plugins/universalarchive/README.md @@ -1,46 +1,76 @@ # universalarchive plugin -Lets you compress files by a command `ua `, supporting various -compression formats (e.g. 7z, tar.gz, lzma, ...). +The `universalarchive` plugin provides a convenient command-line interface for archiving files and directories using a wide variety of compression formats - without having to remember the exact syntax for each tool. -To enable it, add `universalarchive` to the plugins array in your zshrc file: +To enable it, add `universalarchive` to the plugins array in your `.zshrc` file: ```zsh plugins=(... universalarchive) ``` +## Features + - Compress files and directories using a simple, unified command: ua + - Automatically detects file/directory names to generate appropriate output names + - Supports fallback naming if an output file already exists + - Works with many common and advanced compression formats + - Designed for simplicity and quick use in the terminal + ## Usage -Run `ua ` to compress `` into an archive file using ``. -For example: - +Basic command format: ```sh -ua xz *.html +ua +``` +- ``: the archive format to use (e.g., `zip`, `tar.gz`, `xz`, `7z`, etc.) +- ``: one or more files or directories to compress + +## Examples: + +Compresses `notes.txt` and `images` into `notes.zip` +```sh +ua zip notes.txt images/ ``` -this command will compress all `.html` files in directory `folder` into `folder.xz`. +Creates `myproject.tar.gz` +```sh +ua tar.gz myproject/ +``` -This plugin saves you from having to remember which command line arguments compress a file. +Compresses all .log files into `current_folder.xz` +```sh +ua xz *.log +``` -## Supported compression formats +The plugin will generate a default archive filename based on the input: + - For a file, the output is derived from the file name without its extension. + - For a directory, it uses the directory name. + - For multiple files, it uses the name of the common parent directory. -| Extension | Description | -|:-----------------|:-------------------------------| -| `7z` | 7zip file | -| `bz2` | Bzip2 file | -| `gz` | Gzip file | -| `lzma` | LZMA archive | -| `lzo` | LZO archive | -| `rar` | WinRAR archive | -| `tar` | Tarball | -| `tbz`/`tar.bz2` | Tarball with bzip2 compression | -| `tgz`/`tar.gz` | Tarball with gzip compression | -| `tlz`/`tar.lzma` | Tarball with lzma compression | -| `txz`/`tar.xz` | Tarball with lzma2 compression | -| `tZ`/`tar.Z` | Tarball with LZW compression | -| `xz` | LZMA2 archive | -| `Z` | Z archive (LZW) | -| `zip` | Zip archive | -| `zst` | Zstd archive | + If the output file already exists, a unique filename is generated using `mktemp`. -See [list of archive formats](https://en.wikipedia.org/wiki/List_of_archive_formats) for more information regarding the archive formats. +## Supported Archive Formats + +| Format | Description | Tool Used | +|:-----------------|:-------------------------------|:-----------------| +| `7z` | 7zip archive | `7z` | +| `bz2` | Bzip2-compressed file | `bzip2` | +| `gz` | Gzip-compressed file | `gzip` | +| `lzma` | LZMA-compressed file | `lzma` | +| `lzo` | LZO-compressed file | `lzop` | +| `rar` | WinRAR archive | `rar` | +| `tar` | Uncompressed tarball | `tar` | +| `tbz`,`tar.bz2` | Tarball compressed with Bzip2 | `tar + bzip2` | +| `tgz`,`tar.gz` | Tarball compressed with Gzip | `tar + gzip` | +| `tlz`,`tar.lzma` | Tarball compressed with LZMA | `tar + lzma` | +| `txz`,`tar.xz` | Tarball compressed with LZMA2 | `tar + xz` | +| `tZ`,`tar.Z` | Tarball compressed with LZW | `tar + compress` | +| `xz` | XZ-compressed file | `xz` | +| `Z` | LZW-compressed file | `compress` | +| `zip` | Standard Zip archive | `zip` | +| `zst` | Zstandard-compressed file | `zstd` | + + > Note: Some formats may require specific tools to be installed on your system (e.g. `7z`, `rar`, `lzop`, `zstd`). Make sure these tools are available in your `$PATH`. + +## Auto-Completion + +The plugin provides tab-completion for supported formats and input files. Type `ua ` to see available formats, and `ua ` to browse files. diff --git a/plugins/vi-mode/README.md b/plugins/vi-mode/README.md index 6e781f296..bc78cfa3d 100644 --- a/plugins/vi-mode/README.md +++ b/plugins/vi-mode/README.md @@ -46,7 +46,7 @@ hasn't been defined by theme, *Insert mode* is not displayed by default. You can change these indicators by setting the `MODE_INDICATOR` (*Normal mode*) and `INSERT_MODE_INDICATORS` (*Insert mode*) variables. -This settings support Prompt Expansion sequences. For example: +These settings support Prompt Expansion sequences. For example: ```zsh MODE_INDICATOR="%F{white}+%f" @@ -157,6 +157,27 @@ NOTE: delete/kill commands (`dd`, `D`, `c{motion}`, `C`, `x`,`X`) and yank comma (`y`, `Y`) will copy to the clipboard. Contents can then be put back using paste commands (`P`, `p`). +## Text objects + +Standard text objects are supported with `i` ("inside") and `a` ("around"), e.g., for words; thus, you can select the word the cursor is in with `viw`, or delete the current word, including surrounding spaces, with `daw`. + +For other text objects, you can rely on the built-in functionality of Zsh and enable it accordingly. +For example, for quoted strings, you can copy the commented snippet of : place this in your `.zsrhc` file, e.g., after sourcing oh-my-zsh: + +```sh +autoload -U select-quoted +zle -N select-quoted +for m in visual viopp; do + for c in {a,i}{\',\",\`}; do + bindkey -M $m $c select-quoted + done +done +``` + +Now, in normal mode, you can select everything inside a double-quoted string with `vi"`. +Note that this works even if you're not already inside a quoted string. +For example, you can replace everything inside a single-quoted string in the current line, from wherever the cursor is, with `ci'`. + ## Known issues ### Low `$KEYTIMEOUT` diff --git a/plugins/wd/_wd.sh b/plugins/wd/_wd.sh index 46b032f78..7c416086d 100644 --- a/plugins/wd/_wd.sh +++ b/plugins/wd/_wd.sh @@ -37,6 +37,7 @@ function _wd() { 'rm:Removes the given warp point' 'list:Outputs all stored warp points' 'ls:Show files from given warp point' + 'open:Open warp point in the default file explorer' 'path:Show path to given warp point' 'show:Outputs all warp points that point to the current directory or shows a specific target directory for a point' 'help:Show this extremely helpful text' @@ -73,6 +74,9 @@ function _wd() { ls) _describe -t points "Warp points" warp_points && ret=0 ;; + open) + _describe -t points "Warp points" warp_points && ret=0 + ;; path) _describe -t points "Warp points" warp_points && ret=0 ;; diff --git a/plugins/wd/wd.sh b/plugins/wd/wd.sh index f8b27828f..f7a22ff7d 100755 --- a/plugins/wd/wd.sh +++ b/plugins/wd/wd.sh @@ -8,7 +8,7 @@ # @github.com/mfaerevaag/wd # version -readonly WD_VERSION=0.9.3 +readonly WD_VERSION=0.10.0 # colors readonly WD_BLUE="\033[96m" @@ -86,6 +86,7 @@ Commands: show Print warp points to current directory list Print all stored warp points ls Show files from given warp point (ls) + open Open the warp point in the default file explorer (open / xdg-open) path Show the path to given warp point (pwd) clean Remove points warping to nonexistent directories (will prompt unless --force is used) @@ -377,6 +378,21 @@ wd_ls() ls "${dir/#\~/$HOME}" } +wd_open() +{ + wd_getdir "$1" + if command -v open >/dev/null 2>&1; then + # MacOS, Ubuntu (alias) + open "${dir/#\~/$HOME}" + elif command -v xdg-open >/dev/null 2>&1; then + # Most Linux desktops + xdg-open "${dir/#\~/$HOME}" + else + echo "No known file opener found (need 'open' or 'xdg-open')." >&2 + exit 1 + fi +} + wd_path() { wd_getdir "$1" @@ -521,7 +537,7 @@ do done < "$wd_config_file" # get opts -args=$(getopt -o a:r:c:lhs -l add:,rm:,clean,list,ls:,path:,help,show -- $*) +args=$(getopt -o a:r:c:lhs -l add:,rm:,clean,list,ls:,open:,path:,help,show -- $*) # check if no arguments were given, and that version is not set if [[ ($? -ne 0 || $#* -eq 0) && -z $wd_print_version ]] @@ -571,6 +587,10 @@ else wd_ls "$2" break ;; + "-o"|"--open"|"open") + wd_open "$2" + break + ;; "-p"|"--path"|"path") wd_path "$2" break diff --git a/plugins/z/LICENSE b/plugins/z/LICENSE index 162cba8d1..b36aeb408 100644 --- a/plugins/z/LICENSE +++ b/plugins/z/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018-2024 Alexandros Kozak +Copyright (c) 2018-2025 Alexandros Kozak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/plugins/z/z.plugin.zsh b/plugins/z/z.plugin.zsh index bf15b01de..39b832292 100644 --- a/plugins/z/z.plugin.zsh +++ b/plugins/z/z.plugin.zsh @@ -4,7 +4,7 @@ # # https://github.com/agkozak/zsh-z # -# Copyright (c) 2018-2024 Alexandros Kozak +# Copyright (c) 2018-2025 Alexandros Kozak # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -294,7 +294,16 @@ zshz() { owner=${ZSHZ_OWNER:-${_Z_OWNER}} if (( ZSHZ[USE_FLOCK] )); then - ${ZSHZ[MV]} "$tempfile" "$datafile" 2> /dev/null || ${ZSHZ[RM]} -f "$tempfile" + # An unsual case: if inside Docker container where datafile could be bind + # mounted + if [[ -r '/proc/1/cgroup' && "$(< '/proc/1/cgroup')" == *docker* ]]; then + print "$(< "$tempfile")" > "$datafile" 2> /dev/null + ${ZSHZ[RM]} -f "$tempfile" + # All other cases + else + ${ZSHZ[MV]} "$tempfile" "$datafile" 2> /dev/null || + ${ZSHZ[RM]} -f "$tempfile" + fi if [[ -n $owner ]]; then ${ZSHZ[CHOWN]} ${owner}:"$(id -ng ${owner})" "$datafile" diff --git a/themes/blinks.zsh-theme b/themes/blinks.zsh-theme index ddb32f7c3..736683c9a 100644 --- a/themes/blinks.zsh-theme +++ b/themes/blinks.zsh-theme @@ -11,11 +11,11 @@ function _prompt_char() { # This theme works with both the "dark" and "light" variants of the # Solarized color schema. Set the SOLARIZED_THEME variable to one of # these two values to choose. If you don't specify, we'll assume you're -# using the "dark" variant. +# using neither variant. case ${SOLARIZED_THEME:-dark} in light) bkg=white;; - *) bkg=black;; + *) bkg=default;; esac ZSH_THEME_GIT_PROMPT_PREFIX=" [%{%B%F{blue}%}"