diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e16ebb39b..1b1340554 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,5 +1,9 @@ # Plugin owners +plugins/archlinux/ @ratijas plugins/aws/ @maksyms -plugins/git-lfs/ @vietduc01100001 +plugins/genpass/ @atoponce +plugins/git-lfs/ @hellovietduc plugins/gitfast/ @felipec plugins/sdk/ @rgoldberg +plugins/universalarchive/ @Konfekt +plugins/wp-cli/ @joshmedeski diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 611d8ebae..88a6b814d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,7 @@ --- name: Bug report about: Create a report to help us improve Oh My Zsh +labels: 'Bug' --- diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c6b4cef42..3ddd72a15 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: true contact_links: + - name: Support + url: https://github.com/ohmyzsh/ohmyzsh/discussions + about: Ask the community for support - name: Get help on Discord url: https://discord.gg/ohmyzsh about: Have a quick question? Join the Discord server and ask on the appropriate channel. diff --git a/.github/ISSUE_TEMPLATE/support.md b/.github/ISSUE_TEMPLATE/support.md deleted file mode 100644 index 8c4f08044..000000000 --- a/.github/ISSUE_TEMPLATE/support.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Support -about: Request support for any problem you're having with Oh My Zsh -labels: 'Support' - ---- - -1. Look for similar issues already posted (including closed ones) -2. Include as much relevant information as possible -3. Try to make sure the issue is due to Oh My Zsh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index be67e93b0..4903584ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,16 +11,22 @@ issues and pull requests. Please read them closely. Foremost, be so kind as to [search](#use-the-search-luke). This ensures any contribution you would make is not already covered. -* [Issues](#reporting-issues) - * [You have a problem](#you-have-a-problem) - * [You have a suggestion](#you-have-a-suggestion) -* [Pull Requests](#submitting-pull-requests) - * [Getting started](#getting-started) - * [You have a solution](#you-have-a-solution) - * [You have an addition](#you-have-an-addition) -* [Information sources (_aka_ search)](#use-the-search-luke) + -**BONUS:** [Volunteering](#you-have-spare-time-to-volunteer) +- [Reporting Issues](#reporting-issues) + - [You have a problem](#you-have-a-problem) + - [You have a suggestion](#you-have-a-suggestion) +- [Submitting Pull Requests](#submitting-pull-requests) + - [Getting started](#getting-started) + - [You have a solution](#you-have-a-solution) + - [You have an addition](#you-have-an-addition) +- [Use the Search, Luke](#use-the-search-luke) +- [Commit Guidelines](#commit-guidelines) + - [Format](#format) + - [Style](#style) +- [Volunteer](#volunteer) + + ## Reporting Issues @@ -117,7 +123,100 @@ and [create an issue](#reporting-issues) or [submit a PR](#submitting-pull-reque ---- -### You have spare time to volunteer +## Commit Guidelines + +Oh My Zsh uses the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) +specification. The automatic changelog tool uses these to automatically generate +a changelog based on the commit messages. Here's a guide to writing a commit message +to allow this: + +### Format + +``` +type(scope)!: subject +``` + +- `type`: the type of the commit is one of the following: + + - `feat`: new features. + - `fix`: bug fixes. + - `docs`: documentation changes. + - `refactor`: refactor of a particular code section without introducing + new features or bug fixes. + - `style`: code style improvements. + - `perf`: performance improvements. + - `test`: changes to the test suite. + - `ci`: changes to the CI system. + - `build`: changes to the build system (we don't yet have one so this shouldn't apply). + - `chore`: for other changes that don't match previous types. This doesn't appear + in the changelog. + +- `scope`: section of the codebase that the commit makes changes to. If it makes changes to + many sections, or if no section in particular is modified, leave blank without the parentheses. + Examples: + + - Commit that changes the `git` plugin: + ``` + feat(git): add alias for `git commit` + ``` + + - Commit that changes many plugins: + ``` + style: fix inline declaration of arrays + ``` + + For changes to plugins or themes, the scope should be the plugin or theme name: + + - ✅ `fix(agnoster): commit subject` + - ❌ `fix(theme/agnoster): commit subject` + +- `!`: this goes after the `scope` (or the `type` if scope is empty), to indicate that the commit + introduces breaking changes. + + Optionally, you can specify a message that the changelog tool will display to the user to indicate + what's changed and what they can do to deal with it. You can use multiple lines to type this message; + the changelog parser will keep reading until the end of the commit message or until it finds an empty + line. + + Example (made up): + + ``` + style(agnoster)!: change dirty git repo glyph + + BREAKING CHANGE: the glyph to indicate when a git repository is dirty has + changed from a Powerline character to a standard UTF-8 emoji. You can + change it back by setting `ZSH_THEME_DIRTY_GLYPH`. + + Fixes #420 + + Co-authored-by: Username + ``` + +- `subject`: a brief description of the changes. This will be displayed in the changelog. If you need + to specify other details you can use the commit body but it won't be visible. + + Formatting tricks: the commit subject may contain: + + - Links to related issues or PRs by writing `#issue`. This will be highlighted by the changelog tool: + ``` + feat(archlinux): add support for aura AUR helper (#9467) + ``` + + - Formatted inline code by using backticks: the text inbetween backticks will also be highlighted by + the changelog tool: + ``` + feat(shell-proxy): enable unexported `DEFAULT_PROXY` setting (#9774) + ``` + +### Style + +Try to keep the first commit line short. This is harder to do using this commit style but try to be +concise and if you need more space, you can use the commit body. Try to make sure that the commit +subject is clear and precise enough that users will know what change by just looking at the changelog. + +---- + +## Volunteer Very nice!! :) diff --git a/LICENSE.txt b/LICENSE.txt index 45ba85a37..becd6a7bd 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2009-2020 Robby Russell and contributors (https://github.com/ohmyzsh/ohmyzsh/contributors) +Copyright (c) 2009-2021 Robby Russell and contributors (https://github.com/ohmyzsh/ohmyzsh/contributors) 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/README.md b/README.md index 86037f199..3ebea91e0 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ Thank you so much! We're on social media: - [@ohmyzsh](https://twitter.com/ohmyzsh) on Twitter. You should follow it. -- [FaceBook](https://www.facebook.com/Oh-My-Zsh-296616263819290/) poke us. +- [Facebook](https://www.facebook.com/Oh-My-Zsh-296616263819290/) poke us. - [Instagram](https://www.instagram.com/_ohmyzsh/) tag us in your post showing Oh My Zsh! - [Discord](https://discord.gg/ohmyzsh) to chat with us! diff --git a/lib/cli.zsh b/lib/cli.zsh index b1478a89f..38e2f72f8 100644 --- a/lib/cli.zsh +++ b/lib/cli.zsh @@ -1,360 +1,426 @@ #!/usr/bin/env zsh function omz { - [[ $# -gt 0 ]] || { - _omz::help - return 1 - } + [[ $# -gt 0 ]] || { + _omz::help + return 1 + } - local command="$1" - shift + local command="$1" + shift - # Subcommand functions start with _ so that they don't - # appear as completion entries when looking for `omz` - (( $+functions[_omz::$command] )) || { - _omz::help - return 1 - } + # Subcommand functions start with _ so that they don't + # appear as completion entries when looking for `omz` + (( $+functions[_omz::$command] )) || { + _omz::help + return 1 + } - _omz::$command "$@" + _omz::$command "$@" } function _omz { - local -a cmds subcmds - cmds=( - 'help:Usage information' - 'plugin:Commands for Oh My Zsh plugins management' - 'pr:Commands for Oh My Zsh Pull Requests management' - 'theme:Commands for Oh My Zsh themes management' - 'update:Update Oh My Zsh' - ) + local -a cmds subcmds + cmds=( + 'changelog:Print the changelog' + 'help:Usage information' + 'plugin:Manage plugins' + 'pr:Manage Oh My Zsh Pull Requests' + 'theme:Manage themes' + 'update:Update Oh My Zsh' + ) - if (( CURRENT == 2 )); then - _describe 'command' cmds - elif (( CURRENT == 3 )); then - case "$words[2]" in - plugin) subcmds=('list:List plugins') - _describe 'command' subcmds ;; - pr) subcmds=('test:Test a Pull Request' 'clean:Delete all Pull Request branches') - _describe 'command' subcmds ;; - theme) subcmds=('use:Load a theme' 'list:List themes') - _describe 'command' subcmds ;; - esac - elif (( CURRENT == 4 )); then - case "$words[2]::$words[3]" in - theme::use) compadd "$ZSH"/themes/*.zsh-theme(.N:t:r) \ - "$ZSH_CUSTOM"/**/*.zsh-theme(.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::) ;; - esac - fi + if (( CURRENT == 2 )); then + _describe 'command' cmds + elif (( CURRENT == 3 )); then + case "$words[2]" in + changelog) local -a refs + refs=("${(@f)$(command git for-each-ref --format="%(refname:short):%(subject)" refs/heads refs/tags)}") + _describe 'command' refs ;; + plugin) subcmds=('info:Get plugin information' 'list:List plugins') + _describe 'command' subcmds ;; + pr) subcmds=('test:Test a Pull Request' 'clean:Delete all Pull Request branches') + _describe 'command' subcmds ;; + theme) subcmds=('use:Load a theme' 'list:List themes') + _describe 'command' subcmds ;; + esac + elif (( CURRENT == 4 )); then + case "$words[2]::$words[3]" in + plugin::info) compadd "$ZSH"/plugins/*/README.md(.N:h:t) \ + "$ZSH_CUSTOM"/plugins/*/README.md(.N:h:t) ;; + theme::use) compadd "$ZSH"/themes/*.zsh-theme(.N:t:r) \ + "$ZSH_CUSTOM"/**/*.zsh-theme(.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::) ;; + esac + fi - return 0 + return 0 } compdef _omz omz +## Utility functions + +function _omz::confirm { + # If question supplied, ask it before reading the answer + # NOTE: uses the logname of the caller function + if [[ -n "$1" ]]; then + _omz::log prompt "$1" "${${functrace[1]#_}%:*}" + fi + + # Read one character + read -r -k 1 + + # If no newline entered, add a newline + if [[ "$REPLY" != $'\n' ]]; then + echo + fi +} + +function _omz::log { + # if promptsubst is set, a message with `` or $() + # will be run even if quoted due to `print -P` + setopt localoptions nopromptsubst + + # $1 = info|warn|error|debug + # $2 = text + # $3 = (optional) name of the logger + + local logtype=$1 + local logname=${3:-${${functrace[1]#_}%:*}} + + # Don't print anything if debug is not active + if [[ $logtype = debug && -z $_OMZ_DEBUG ]]; then + return + fi + + # Choose coloring based on log type + case "$logtype" in + prompt) print -Pn "%S%F{blue}$logname%f%s: $2" ;; + debug) print -P "%F{white}$logname%f: $2" ;; + info) print -P "%F{green}$logname%f: $2" ;; + warn) print -P "%S%F{yellow}$logname%f%s: $2" ;; + error) print -P "%S%F{red}$logname%f%s: $2" ;; + esac >&2 +} + +## User-facing commands function _omz::help { - cat < [options] Available commands: - help Print this help message - plugin Manage plugins - pr Manage Oh My Zsh Pull Requests - theme Manage themes - update Update Oh My Zsh + help Print this help message + changelog Print the changelog + plugin Manage plugins + pr Manage Oh My Zsh Pull Requests + theme Manage themes + update Update Oh My Zsh EOF } -function _omz::confirm { - # If question supplied, ask it before reading the answer - # NOTE: uses the logname of the caller function - if [[ -n "$1" ]]; then - _omz::log prompt "$1" "${${functrace[1]#_}%:*}" - fi +function _omz::changelog { + local version=${1:-HEAD} format=${3:-"--text"} - # Read one character - read -r -k 1 + if ! command git -C "$ZSH" show-ref --verify refs/heads/$version &>/dev/null && \ + ! command git -C "$ZSH" show-ref --verify refs/tags/$version &>/dev/null && \ + ! command git -C "$ZSH" rev-parse --verify "${version}^{commit}" &>/dev/null; then + cat < must be a valid branch, tag or commit. +EOF + return 1 + fi -function _omz::log { - # if promptsubst is set, a message with `` or $() - # will be run even if quoted due to `print -P` - setopt localoptions nopromptsubst - - # $1 = info|warn|error|debug - # $2 = text - # $3 = (optional) name of the logger - - local logtype=$1 - local logname=${3:-${${functrace[1]#_}%:*}} - - # Don't print anything if debug is not active - if [[ $logtype = debug && -z $_OMZ_DEBUG ]]; then - return - fi - - # Choose coloring based on log type - case "$logtype" in - prompt) print -Pn "%S%F{blue}$logname%f%s: $2" ;; - debug) print -P "%F{white}$logname%f: $2" ;; - info) print -P "%F{green}$logname%f: $2" ;; - warn) print -P "%S%F{yellow}$logname%f%s: $2" ;; - error) print -P "%S%F{red}$logname%f%s: $2" ;; - esac >&2 + "$ZSH/tools/changelog.sh" "$version" "${2:-}" "$format" } function _omz::plugin { - (( $# > 0 && $+functions[_omz::plugin::$1] )) || { - cat < 0 && $+functions[_omz::plugin::$1] )) || { + cat < [options] Available commands: - list List all available Oh My Zsh plugins + info Get information of a plugin + list List all available Oh My Zsh plugins EOF - return 1 - } + return 1 + } - local command="$1" - shift + local command="$1" + shift - _omz::plugin::$command "$@" + _omz::plugin::$command "$@" +} + +function _omz::plugin::info { + if [[ -z "$1" ]]; then + echo >&2 "Usage: omz plugin info " + return 1 + fi + + local readme + for readme in "$ZSH_CUSTOM/plugins/$1/README.md" "$ZSH/plugins/$1/README.md"; do + if [[ -f "$readme" ]]; then + (( ${+commands[less]} )) && less "$readme" || cat "$readme" + return 0 + fi + done + + if [[ -d "$ZSH_CUSTOM/plugins/$1" || -d "$ZSH/plugins/$1" ]]; then + _omz::log error "the '$1' plugin doesn't have a README file" + else + _omz::log error "'$1' plugin not found" + fi + + return 1 } function _omz::plugin::list { - local -a custom_plugins builtin_plugins - custom_plugins=("$ZSH_CUSTOM"/plugins/*(-/N:t)) - builtin_plugins=("$ZSH"/plugins/*(-/N:t)) + local -a custom_plugins builtin_plugins + custom_plugins=("$ZSH_CUSTOM"/plugins/*(-/N:t)) + builtin_plugins=("$ZSH"/plugins/*(-/N:t)) - # If the command is being piped, print all found line by line - if [[ ! -t 1 ]]; then - print -l ${(q-)custom_plugins} ${(q-)builtin_plugins} - return - fi + # If the command is being piped, print all found line by line + if [[ ! -t 1 ]]; then + print -l ${(q-)custom_plugins} ${(q-)builtin_plugins} + return + fi - if (( ${#custom_plugins} )); then - print -P "%U%BCustom plugins%b%u:" - print -l ${(q-)custom_plugins} | column - fi + if (( ${#custom_plugins} )); then + print -P "%U%BCustom plugins%b%u:" + print -l ${(q-)custom_plugins} | column + fi - if (( ${#builtin_plugins} )); then - (( ${#custom_plugins} )) && echo # add a line of separation + if (( ${#builtin_plugins} )); then + (( ${#custom_plugins} )) && echo # add a line of separation - print -P "%U%BBuilt-in plugins%b%u:" - print -l ${(q-)builtin_plugins} | column - fi + print -P "%U%BBuilt-in plugins%b%u:" + print -l ${(q-)builtin_plugins} | column + fi } function _omz::pr { - (( $# > 0 && $+functions[_omz::pr::$1] )) || { - cat < 0 && $+functions[_omz::pr::$1] )) || { + cat < [options] Available commands: - clean Delete all PR branches (ohmyzsh/pull-*) - test Fetch PR #NUMBER and rebase against master + clean Delete all PR branches (ohmyzsh/pull-*) + test Fetch PR #NUMBER and rebase against master EOF - return 1 - } + return 1 + } - local command="$1" - shift + local command="$1" + shift - _omz::pr::$command "$@" + _omz::pr::$command "$@" } function _omz::pr::clean { - ( - set -e - builtin cd -q "$ZSH" + ( + set -e + builtin cd -q "$ZSH" - # Check if there are PR branches - local fmt branches - fmt="%(color:bold blue)%(align:18,right)%(refname:short)%(end)%(color:reset) %(color:dim bold red)%(objectname:short)%(color:reset) %(color:yellow)%(contents:subject)" - branches="$(command git for-each-ref --sort=-committerdate --color --format="$fmt" "refs/heads/ohmyzsh/pull-*")" + # Check if there are PR branches + local fmt branches + fmt="%(color:bold blue)%(align:18,right)%(refname:short)%(end)%(color:reset) %(color:dim bold red)%(objectname:short)%(color:reset) %(color:yellow)%(contents:subject)" + branches="$(command git for-each-ref --sort=-committerdate --color --format="$fmt" "refs/heads/ohmyzsh/pull-*")" - # Exit if there are no PR branches - if [[ -z "$branches" ]]; then - _omz::log info "there are no Pull Request branches to remove." - return - fi - - # Print found PR branches - echo "$branches\n" - # Confirm before removing the branches - _omz::confirm "do you want remove these Pull Request branches? [Y/n] " - # Only proceed if the answer is a valid yes option - [[ "$REPLY" != [yY$'\n'] ]] && return - - _omz::log info "removing all Oh My Zsh Pull Request branches..." - command git branch --list 'ohmyzsh/pull-*' | while read branch; do - command git branch -D "$branch" - done - ) -} - -function _omz::pr::test { - # Allow $1 to be a URL to the pull request - if [[ "$1" = https://* ]]; then - 1="${1:t}" + # Exit if there are no PR branches + if [[ -z "$branches" ]]; then + _omz::log info "there are no Pull Request branches to remove." + return fi - # Check the input - if ! [[ -n "$1" && "$1" =~ ^[[:digit:]]+$ ]]; then - echo >&2 "Usage: omz pr test " - return 1 - fi - - # Save current git HEAD - local branch - branch=$(builtin cd -q "$ZSH"; git symbolic-ref --short HEAD) || { - _omz::log error "error when getting the current git branch. Aborting..." - return 1 - } - - - # Fetch PR onto ohmyzsh/pull- branch and rebase against master - # If any of these operations fail, undo the changes made - ( - set -e - builtin cd -q "$ZSH" - - # Get the ohmyzsh git remote - command git remote -v | while read remote url _; do - case "$url" in - https://github.com/ohmyzsh/ohmyzsh(|.git)) found=1; break ;; - git@github.com:ohmyzsh/ohmyzsh(|.git)) found=1; break ;; - esac - done - - (( $found )) || { - _omz::log error "could not found the ohmyzsh git remote. Aborting..." - return 1 - } - - # Fetch pull request head - _omz::log info "fetching PR #$1 to ohmyzsh/pull-$1..." - command git fetch -f "$remote" refs/pull/$1/head:ohmyzsh/pull-$1 || { - _omz::log error "error when trying to fetch PR #$1." - return 1 - } - - # Rebase pull request branch against the current master - _omz::log info "rebasing PR #$1..." - command git rebase master ohmyzsh/pull-$1 || { - command git rebase --abort &>/dev/null - _omz::log warn "could not rebase PR #$1 on top of master." - _omz::log warn "you might not see the latest stable changes." - _omz::log info "run \`zsh\` to test the changes." - return 1 - } - - _omz::log info "fetch of PR #${1} successful." - ) - - # If there was an error, abort running zsh to test the PR - [[ $? -eq 0 ]] || return 1 - - # Run zsh to test the changes - _omz::log info "running \`zsh\` to test the changes. Run \`exit\` to go back." - command zsh -l - - # After testing, go back to the previous HEAD if the user wants - _omz::confirm "do you want to go back to the previous branch? [Y/n] " + # Print found PR branches + echo "$branches\n" + # Confirm before removing the branches + _omz::confirm "do you want remove these Pull Request branches? [Y/n] " # Only proceed if the answer is a valid yes option [[ "$REPLY" != [yY$'\n'] ]] && return - ( - set -e - builtin cd -q "$ZSH" + _omz::log info "removing all Oh My Zsh Pull Request branches..." + command git branch --list 'ohmyzsh/pull-*' | while read branch; do + command git branch -D "$branch" + done + ) +} - command git checkout "$branch" -- || { - _omz::log error "could not go back to the previous branch ('$branch')." - return 1 - } - ) +function _omz::pr::test { + # Allow $1 to be a URL to the pull request + if [[ "$1" = https://* ]]; then + 1="${1:t}" + fi + + # Check the input + if ! [[ -n "$1" && "$1" =~ ^[[:digit:]]+$ ]]; then + echo >&2 "Usage: omz pr test " + return 1 + fi + + # Save current git HEAD + local branch + branch=$(builtin cd -q "$ZSH"; git symbolic-ref --short HEAD) || { + _omz::log error "error when getting the current git branch. Aborting..." + return 1 + } + + + # Fetch PR onto ohmyzsh/pull- branch and rebase against master + # If any of these operations fail, undo the changes made + ( + set -e + builtin cd -q "$ZSH" + + # Get the ohmyzsh git remote + command git remote -v | while read remote url _; do + case "$url" in + https://github.com/ohmyzsh/ohmyzsh(|.git)) found=1; break ;; + git@github.com:ohmyzsh/ohmyzsh(|.git)) found=1; break ;; + esac + done + + (( $found )) || { + _omz::log error "could not found the ohmyzsh git remote. Aborting..." + return 1 + } + + # Fetch pull request head + _omz::log info "fetching PR #$1 to ohmyzsh/pull-$1..." + command git fetch -f "$remote" refs/pull/$1/head:ohmyzsh/pull-$1 || { + _omz::log error "error when trying to fetch PR #$1." + return 1 + } + + # Rebase pull request branch against the current master + _omz::log info "rebasing PR #$1..." + command git rebase master ohmyzsh/pull-$1 || { + command git rebase --abort &>/dev/null + _omz::log warn "could not rebase PR #$1 on top of master." + _omz::log warn "you might not see the latest stable changes." + _omz::log info "run \`zsh\` to test the changes." + return 1 + } + + _omz::log info "fetch of PR #${1} successful." + ) + + # If there was an error, abort running zsh to test the PR + [[ $? -eq 0 ]] || return 1 + + # Run zsh to test the changes + _omz::log info "running \`zsh\` to test the changes. Run \`exit\` to go back." + command zsh -l + + # After testing, go back to the previous HEAD if the user wants + _omz::confirm "do you want to go back to the previous branch? [Y/n] " + # Only proceed if the answer is a valid yes option + [[ "$REPLY" != [yY$'\n'] ]] && return + + ( + set -e + builtin cd -q "$ZSH" + + command git checkout "$branch" -- || { + _omz::log error "could not go back to the previous branch ('$branch')." + return 1 + } + ) } function _omz::theme { - (( $# > 0 && $+functions[_omz::theme::$1] )) || { - cat < 0 && $+functions[_omz::theme::$1] )) || { + cat < [options] Available commands: - list List all available Oh My Zsh themes - use Load an Oh My Zsh theme + list List all available Oh My Zsh themes + use Load an Oh My Zsh theme EOF - return 1 - } + return 1 + } - local command="$1" - shift + local command="$1" + shift - _omz::theme::$command "$@" + _omz::theme::$command "$@" } function _omz::theme::list { - local -a custom_themes builtin_themes - custom_themes=("$ZSH_CUSTOM"/**/*.zsh-theme(.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::)) - builtin_themes=("$ZSH"/themes/*.zsh-theme(.N:t:r)) + local -a custom_themes builtin_themes + custom_themes=("$ZSH_CUSTOM"/**/*.zsh-theme(-.N:r:gs:"$ZSH_CUSTOM"/themes/:::gs:"$ZSH_CUSTOM"/:::)) + builtin_themes=("$ZSH"/themes/*.zsh-theme(-.N:t:r)) - # If the command is being piped, print all found line by line - if [[ ! -t 1 ]]; then - print -l ${(q-)custom_themes} ${(q-)builtin_themes} - return - fi + # If the command is being piped, print all found line by line + if [[ ! -t 1 ]]; then + print -l ${(q-)custom_themes} ${(q-)builtin_themes} + return + fi - if (( ${#custom_themes} )); then - print -P "%U%BCustom themes%b%u:" - print -l ${(q-)custom_themes} | column - fi + if (( ${#custom_themes} )); then + print -P "%U%BCustom themes%b%u:" + print -l ${(q-)custom_themes} | column + fi - if (( ${#builtin_themes} )); then - (( ${#custom_themes} )) && echo # add a line of separation + if (( ${#builtin_themes} )); then + (( ${#custom_themes} )) && echo # add a line of separation - print -P "%U%BBuilt-in themes%b%u:" - print -l ${(q-)builtin_themes} | column - fi + print -P "%U%BBuilt-in themes%b%u:" + print -l ${(q-)builtin_themes} | column + fi } function _omz::theme::use { - if [[ -z "$1" ]]; then - echo >&2 "Usage: omz theme use " - return 1 - fi + if [[ -z "$1" ]]; then + echo >&2 "Usage: omz theme use " + return 1 + fi - # Respect compatibility with old lookup order - if [[ -f "$ZSH_CUSTOM/$1.zsh-theme" ]]; then - source "$ZSH_CUSTOM/$1.zsh-theme" - elif [[ -f "$ZSH_CUSTOM/themes/$1.zsh-theme" ]]; then - source "$ZSH_CUSTOM/themes/$1.zsh-theme" - elif [[ -f "$ZSH/themes/$1.zsh-theme" ]]; then - source "$ZSH/themes/$1.zsh-theme" - else - _omz::log error "theme '$1' not found" - return 1 - fi + # Respect compatibility with old lookup order + if [[ -f "$ZSH_CUSTOM/$1.zsh-theme" ]]; then + source "$ZSH_CUSTOM/$1.zsh-theme" + elif [[ -f "$ZSH_CUSTOM/themes/$1.zsh-theme" ]]; then + source "$ZSH_CUSTOM/themes/$1.zsh-theme" + elif [[ -f "$ZSH/themes/$1.zsh-theme" ]]; then + source "$ZSH/themes/$1.zsh-theme" + else + _omz::log error "theme '$1' not found" + return 1 + fi } function _omz::update { - # Run update script - env ZSH="$ZSH" sh "$ZSH/tools/upgrade.sh" - # Update last updated file - zmodload zsh/datetime - echo "LAST_EPOCH=$(( EPOCHSECONDS / 60 / 60 / 24 ))" >! "${ZSH_CACHE_DIR}/.zsh-update" - # Remove update lock if it exists - command rm -rf "$ZSH/log/update.lock" + local last_commit=$(cd "$ZSH"; git rev-parse HEAD) + + # Run update script + if [[ "$1" != --unattended ]]; then + ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" --interactive + else + ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" + fi + + # Update last updated file + zmodload zsh/datetime + echo "LAST_EPOCH=$(( EPOCHSECONDS / 60 / 60 / 24 ))" >! "${ZSH_CACHE_DIR}/.zsh-update" + # Remove update lock if it exists + command rm -rf "$ZSH/log/update.lock" + + # Restart the zsh session if there were changes + if [[ "$1" != --unattended && "$(cd "$ZSH"; git rev-parse HEAD)" != "$last_commit" ]]; then + # Old zsh versions don't have ZSH_ARGZERO + local zsh="${ZSH_ARGZERO:-${functrace[-1]%:*}}" + # Check whether to run a login shell + [[ "$zsh" = -* || -o login ]] && exec -l "${zsh#-}" || exec "$zsh" + fi } diff --git a/lib/completion.zsh b/lib/completion.zsh index 2b62785d5..ebaab0856 100644 --- a/lib/completion.zsh +++ b/lib/completion.zsh @@ -32,9 +32,9 @@ zstyle ':completion:*' list-colors '' zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;34=0=01' if [[ "$OSTYPE" = solaris* ]]; then - zstyle ':completion:*:*:*:*:processes' command "ps -u $USER -o pid,user,comm" + zstyle ':completion:*:*:*:*:processes' command "ps -u $USERNAME -o pid,user,comm" else - zstyle ':completion:*:*:*:*:processes' command "ps -u $USER -o pid,user,comm -w -w" + zstyle ':completion:*:*:*:*:processes' command "ps -u $USERNAME -o pid,user,comm -w -w" fi # disable named-directories autocompletion diff --git a/lib/diagnostics.zsh b/lib/diagnostics.zsh index 001de42b7..650520797 100644 --- a/lib/diagnostics.zsh +++ b/lib/diagnostics.zsh @@ -112,7 +112,7 @@ function _omz_diag_dump_one_big_text() { command uname -a builtin echo OSTYPE=$OSTYPE builtin echo ZSH_VERSION=$ZSH_VERSION - builtin echo User: $USER + builtin echo User: $USERNAME builtin echo umask: $(umask) builtin echo _omz_diag_dump_os_specific_version diff --git a/lib/functions.zsh b/lib/functions.zsh index 15526cd5f..c4340f16c 100644 --- a/lib/functions.zsh +++ b/lib/functions.zsh @@ -1,7 +1,7 @@ function zsh_stats() { fc -l 1 \ | awk '{ CMD[$2]++; count++; } END { for (a in CMD) print CMD[a] " " CMD[a]*100/count "% " a }' \ - | grep -v "./" | sort -nr | head -n20 | column -c3 -s " " -t | nl + | grep -v "./" | sort -nr | head -20 | column -c3 -s " " -t | nl } function uninstall_oh_my_zsh() { @@ -9,17 +9,8 @@ function uninstall_oh_my_zsh() { } function upgrade_oh_my_zsh() { - if (( $+functions[_omz::update] )); then - echo >&2 "${fg[yellow]}Note: \`$0\` is deprecated. Use \`omz update\` instead.$reset_color" - fi - - # Run update script - env ZSH="$ZSH" sh "$ZSH/tools/upgrade.sh" - # Update last updated file - zmodload zsh/datetime - echo "LAST_EPOCH=$(( EPOCHSECONDS / 60 / 60 / 24 ))" >! "${ZSH_CACHE_DIR}/.zsh-update" - # Remove update lock if it exists - command rm -rf "$ZSH/log/update.lock" + echo >&2 "${fg[yellow]}Note: \`$0\` is deprecated. Use \`omz update\` instead.$reset_color" + omz update } function take() { diff --git a/lib/git.zsh b/lib/git.zsh index 53d39609e..c9363274c 100644 --- a/lib/git.zsh +++ b/lib/git.zsh @@ -9,14 +9,27 @@ function __git_prompt_git() { GIT_OPTIONAL_LOCKS=0 command git "$@" } -# Outputs current branch info in prompt format function git_prompt_info() { - local ref - if [[ "$(__git_prompt_git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]]; then - ref=$(__git_prompt_git symbolic-ref HEAD 2> /dev/null) || \ - ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) || return 0 - echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX" + # If we are on a folder not tracked by git, get out. + # Otherwise, check for hide-info at global and local repository level + if ! __git_prompt_git rev-parse --git-dir &> /dev/null \ + || [[ "$(__git_prompt_git config --get oh-my-zsh.hide-info 2>/dev/null)" == 1 ]]; then + return 0 fi + + local ref + ref=$(__git_prompt_git symbolic-ref --short HEAD 2> /dev/null) \ + || ref=$(__git_prompt_git rev-parse --short HEAD 2> /dev/null) \ + || return 0 + + # Use global ZSH_THEME_GIT_SHOW_UPSTREAM=1 for including upstream remote info + local upstream + if (( ${+ZSH_THEME_GIT_SHOW_UPSTREAM} )); then + upstream=$(__git_prompt_git rev-parse --abbrev-ref --symbolic-full-name "@{upstream}" 2>/dev/null) \ + && upstream=" -> ${upstream}" + fi + + echo "${ZSH_THEME_GIT_PROMPT_PREFIX}${ref}${upstream}$(parse_git_dirty)${ZSH_THEME_GIT_PROMPT_SUFFIX}" } # Checks if working tree is dirty @@ -38,7 +51,7 @@ function parse_git_dirty() { FLAGS+="--ignore-submodules=${GIT_STATUS_IGNORE_SUBMODULES:-dirty}" ;; esac - STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -n1) + STATUS=$(__git_prompt_git status ${FLAGS} 2> /dev/null | tail -1) fi if [[ -n $STATUS ]]; then echo "$ZSH_THEME_GIT_PROMPT_DIRTY" @@ -157,7 +170,7 @@ function git_prompt_status() { '\?\? ' 'UNTRACKED' 'A ' 'ADDED' 'M ' 'ADDED' - 'MM ' 'ADDED' + 'MM ' 'MODIFIED' ' M ' 'MODIFIED' 'AM ' 'MODIFIED' ' T ' 'MODIFIED' diff --git a/lib/prompt_info_functions.zsh b/lib/prompt_info_functions.zsh index 5069c4b21..48f033da6 100644 --- a/lib/prompt_info_functions.zsh +++ b/lib/prompt_info_functions.zsh @@ -18,6 +18,7 @@ function chruby_prompt_info \ vi_mode_prompt_info \ virtualenv_prompt_info \ jenv_prompt_info \ + tf_prompt_info \ { return 1 } diff --git a/lib/termsupport.zsh b/lib/termsupport.zsh index 778f12bca..33451ef1f 100644 --- a/lib/termsupport.zsh +++ b/lib/termsupport.zsh @@ -10,7 +10,7 @@ function title { emulate -L zsh setopt prompt_subst - [[ "$EMACS" == *term* ]] && return + [[ "$INSIDE_EMACS" == *term* ]] && return # if $2 is unset use $1 as default # if it is set and empty, leave it as is diff --git a/plugins/ansible/ansible.plugin.zsh b/plugins/ansible/ansible.plugin.zsh index f68ff23a5..75393b704 100644 --- a/plugins/ansible/ansible.plugin.zsh +++ b/plugins/ansible/ansible.plugin.zsh @@ -4,7 +4,7 @@ function ansible-version(){ } function ansible-role-init(){ - if ! [ -z $1] ; then + if ! [ -z $1 ] ; then echo "Ansible Role : $1 Creating...." ansible-galaxy init $1 tree $1 @@ -25,4 +25,4 @@ alias ainv='ansible-inventory ' alias adoc='ansible-doc ' alias agal='ansible-galaxy ' alias apull='ansible-pull ' -alias aval='ansible-vault' \ No newline at end of file +alias aval='ansible-vault' diff --git a/plugins/archlinux/README.md b/plugins/archlinux/README.md index 5882c7603..d6b41ee40 100644 --- a/plugins/archlinux/README.md +++ b/plugins/archlinux/README.md @@ -1,4 +1,4 @@ -# Archlinux plugin +# Arch Linux plugin This plugin adds some aliases and functions to work with Arch Linux. @@ -10,145 +10,189 @@ plugins=(... archlinux) ## Features -#### YAY +### Pacman -| Alias | Command | Description | -|---------|------------------------------------|---------------------------------------------------------------------| -| yaconf | yay -Pg | Print current configuration | -| yain | yay -S | Install packages from the repositories | -| yains | yay -U | Install a package from a local file | -| yainsd | yay -S --asdeps | Install packages as dependencies of another package | -| yaloc | yay -Qi | Display information about a package in the local database | -| yalocs | yay -Qs | Search for packages in the local database | -| yalst | yay -Qe | List installed packages including from AUR (tagged as "local") | -| yamir | yay -Syy | Force refresh of all package lists after updating mirrorlist | -| yaorph | yay -Qtd | Remove orphans using yay | -| yare | yay -R | Remove packages, keeping its settings and dependencies | -| yarem | yay -Rns | Remove packages, including its settings and unneeded dependencies | -| yarep | yay -Si | Display information about a package in the repositories | -| yareps | yay -Ss | Search for packages in the repositories | -| yaupg | yay -Syu | Sync with repositories before upgrading packages | -| yasu | yay -Syu --no-confirm | Same as `yaupg`, but without confirmation | +| Alias | Command | Description | +|--------------|----------------------------------------|------------------------------------------------------------------| +| pacin | `sudo pacman -S` | Install packages from the repositories | +| pacins | `sudo pacman -U` | Install a package from a local file | +| pacinsd | `sudo pacman -S --asdeps` | Install packages as dependencies of another package | +| pacloc | `pacman -Qi` | Display information about a package in the local database | +| paclocs | `pacman -Qs` | Search for packages in the local database | +| paclsorphans | `sudo pacman -Qdt` | List all orphaned packages | +| pacmir | `sudo pacman -Syy` | Force refresh of all package lists after updating mirrorlist | +| pacre | `sudo pacman -R` | Remove packages, keeping its settings and dependencies | +| pacrem | `sudo pacman -Rns` | Remove packages, including its settings and dependencies | +| pacrep | `pacman -Si` | Display information about a package in the repositories | +| pacreps | `pacman -Ss` | Search for packages in the repositories | +| pacrmorphans | `sudo pacman -Rs $(pacman -Qtdq)` | Delete all orphaned packages | +| pacupd | `sudo pacman -Sy` | Update and refresh local package, ABS and AUR databases | +| pacupg | `sudo pacman -Syu` | Sync with repositories before upgrading packages | +| pacfileupg | `sudo pacman -Fy` | Download fresh package databases from the server | +| pacfiles | `pacman -F` | Search package file names for matching strings | +| pacls | `pacman -Ql` | List files in a package | +| pacown | `pacman -Qo` | Show which package owns a file | +| upgrade[²](#f2) | `sudo pacman -Syu` | Sync with repositories before upgrading packages | -#### TRIZEN +| Function | Description | +|----------------|-----------------------------------------------------------| +| pacdisowned | List all disowned files in your system | +| paclist | List all explicitly installed packages with a description | +| pacmanallkeys | Get all keys for developers and trusted users | +| pacmansignkeys | Locally trust all keys passed as parameters | +| pacweb | Open the website of an ArchLinux package | -| Alias | Command | Description | -|---------|------------------------------------|---------------------------------------------------------------------| -| trconf | trizen -C | Fix all configuration files with vimdiff | -| trin | trizen -S | Install packages from the repositories | -| trins | trizen -U | Install a package from a local file | -| trinsd | trizen -S --asdeps | Install packages as dependencies of another package | -| trloc | trizen -Qi | Display information about a package in the local database | -| trlocs | trizen -Qs | Search for packages in the local database | -| trlst | trizen -Qe | List installed packages including from AUR (tagged as "local") | -| trmir | trizen -Syy | Force refresh of all package lists after updating mirrorlist | -| trorph | trizen -Qtd | Remove orphans using yaourt | -| trre | trizen -R | Remove packages, keeping its settings and dependencies | -| trrem | trizen -Rns | Remove packages, including its settings and unneeded dependencies | -| trrep | trizen -Si | Display information about a package in the repositories | -| trreps | trizen -Ss | Search for packages in the repositories | -| trupd | trizen -Sy && sudo abs && sudo aur | Update and refresh local package, ABS and AUR databases | -| trupd | trizen -Sy && sudo abs | Update and refresh the local package and ABS databases | -| trupd | trizen -Sy && sudo aur | Update and refresh the local package and AUR databases | -| trupd | trizen -Sy | Update and refresh the local package database | -| trupg | trizen -Syua | Sync with repositories before upgrading all packages (from AUR too) | -| trsu | trizen -Syua --no-confirm | Same as `trupg`, but without confirmation | -| upgrade | trizen -Syu | Sync with repositories before upgrading packages | +Note: paclist used to print packages with a description which are (1) explicitly installed +and (2) available for upgrade. Due to flawed scripting, it also printed all packages if no +upgrades were available. Use `pacman -Que` instead. -#### YAOURT +### AUR helpers -| Alias | Command | Description | -|---------|------------------------------------|---------------------------------------------------------------------| -| yaconf | yaourt -C | Fix all configuration files with vimdiff | -| yain | yaourt -S | Install packages from the repositories | -| yains | yaourt -U | Install a package from a local file | -| yainsd | yaourt -S --asdeps | Install packages as dependencies of another package | -| yaloc | yaourt -Qi | Display information about a package in the local database | -| yalocs | yaourt -Qs | Search for packages in the local database | -| yalst | yaourt -Qe | List installed packages including from AUR (tagged as "local") | -| yamir | yaourt -Syy | Force refresh of all package lists after updating mirrorlist | -| yaorph | yaourt -Qtd | Remove orphans using yaourt | -| yare | yaourt -R | Remove packages, keeping its settings and dependencies | -| yarem | yaourt -Rns | Remove packages, including its settings and unneeded dependencies | -| yarep | yaourt -Si | Display information about a package in the repositories | -| yareps | yaourt -Ss | Search for packages in the repositories | -| yaupd | yaourt -Sy && sudo abs && sudo aur | Update and refresh local package, ABS and AUR databases | -| yaupd | yaourt -Sy && sudo abs | Update and refresh the local package and ABS databases | -| yaupd | yaourt -Sy && sudo aur | Update and refresh the local package and AUR databases | -| yaupd | yaourt -Sy | Update and refresh the local package database | -| yaupg | yaourt -Syua | Sync with repositories before upgrading all packages (from AUR too) | -| yasu | yaourt -Syua --no-confirm | Same as `yaupg`, but without confirmation | -| upgrade | yaourt -Syu | Sync with repositories before upgrading packages | +#### Aura -#### PACAUR +| Alias | Command | Description | +|---------|-------------------------------------------------|-------------------------------------------------------------------------| +| auin | `sudo aura -S` | Install packages from the repositories | +| aurin | `sudo aura -A` | Install packages from the repositories | +| auins | `sudo aura -U` | Install a package from a local file | +| auinsd | `sudo aura -S --asdeps` | Install packages as dependencies of another package (repositories only) | +| aurinsd | `sudo aura -A --asdeps` | Install packages as dependencies of another package (AUR only) | +| auloc | `aura -Qi` | Display information about a package in the local database | +| aulocs | `aura -Qs` | Search for packages in the local database | +| auls | `aura -Qql` | List all files owned by a given package | +| aulst | `aura -Qe` | List installed packages including from AUR (tagged as "local") | +| aumir | `sudo aura -Syy` | Force refresh of all package lists after updating mirrorlist | +| aurph | `sudo aura -Oj` | Remove orphans using aura | +| auown | `aura -Qqo` | Search for packages that own the specified file(s) | +| aure | `sudo aura -R` | Remove packages, keeping its settings and dependencies | +| aurem | `sudo aura -Rns` | Remove packages, including its settings and unneeded dependencies | +| aurep | `aura -Si` | Display information about a package in the repositories | +| aurrep | `aura -Ai` | Display information about a package from AUR | +| aureps | `aura -As --both` | Search for packages in the repositories and AUR | +| auras | `aura -As --both` | Same as above | +| auupd | `sudo aura -Sy` | Update and refresh local package, ABS and AUR databases | +| auupg | `sudo sh -c "aura -Syu && aura -Au"` | Sync with repositories before upgrading all packages (from AUR too) | +| ausu | `sudo sh -c "aura -Syu --no-confirm && aura -Au --no-confirm"` | Same as `auupg`, but without confirmation | +| upgrade[²](#f2) | `sudo aura -Syu` | Sync with repositories before upgrading packages | -| Alias | Command | Description | -|---------|------------------------------------|---------------------------------------------------------------------| -| pain | pacaur -S | Install packages from the repositories | -| pains | pacaur -U | Install a package from a local file | -| painsd | pacaur -S --asdeps | Install packages as dependencies of another package | -| paloc | pacaur -Qi | Display information about a package in the local database | -| palocs | pacaur -Qs | Search for packages in the local database | -| palst | pacaur -Qe | List installed packages including from AUR (tagged as "local") | -| pamir | pacaur -Syy | Force refresh of all package lists after updating mirrorlist | -| paorph | pacaur -Qtd | Remove orphans using pacaur | -| pare | pacaur -R | Remove packages, keeping its settings and dependencies | -| parem | pacaur -Rns | Remove packages, including its settings and unneeded dependencies | -| parep | pacaur -Si | Display information about a package in the repositories | -| pareps | pacaur -Ss | Search for packages in the repositories | -| paupd | pacaur -Sy && sudo abs && sudo aur | Update and refresh local package, ABS and AUR databases | -| paupd | pacaur -Sy && sudo abs | Update and refresh the local package and ABS databases | -| paupd | pacaur -Sy && sudo aur | Update and refresh the local package and AUR databases | -| paupd | pacaur -Sy | Update and refresh the local package database | -| paupg | pacaur -Syua | Sync with repositories before upgrading all packages (from AUR too) | -| pasu | pacaur -Syua --no-confirm | Same as `paupg`, but without confirmation | -| upgrade | pacaur -Syu | Sync with repositories before upgrading packages | +| Function | Description | +|-----------------|---------------------------------------------------------------------| +| auownloc _file_ | Display information about a package that owns the specified file(s) | +| auownls _file_ | List all files owned by a package that owns the specified file(s) | -#### PACMAN +#### Pacaur -| Alias | Command | Description | -|--------------|-----------------------------------------|--------------------------------------------------------------| -| pacin | sudo pacman -S | Install packages from the repositories | -| pacins | sudo pacman -U | Install a package from a local file | -| pacinsd | sudo pacman -S --asdeps | Install packages as dependencies of another package | -| pacloc | pacman -Qi | Display information about a package in the local database | -| paclocs | pacman -Qs | Search for packages in the local database | -| paclsorphans | sudo pacman -Qdt | List all orphaned packages | -| pacmir | sudo pacman -Syy | Force refresh of all package lists after updating mirrorlist | -| pacre | sudo pacman -R | Remove packages, keeping its settings and dependencies | -| pacrem | sudo pacman -Rns | Remove packages, including its settings and dependencies | -| pacrep | pacman -Si | Display information about a package in the repositories | -| pacreps | pacman -Ss | Search for packages in the repositories | -| pacrmorphans | sudo pacman -Rs $(pacman -Qtdq) | Delete all orphaned packages | -| pacupd | sudo pacman -Sy && sudo abs && sudo aur | Update and refresh the local package, ABS and AUR databases | -| pacupd | sudo pacman -Sy && sudo abs | Update and refresh the local package and ABS databases | -| pacupd | sudo pacman -Sy && sudo aur | Update and refresh the local package and AUR databases | -| pacupd | sudo pacman -Sy | Update and refresh the local package database | -| pacupg | sudo pacman -Syu | Sync with repositories before upgrading packages | -| upgrade | sudo pacman -Syu | Sync with repositories before upgrading packages | -| pacfileupg | sudo pacman -Fy | Download fresh package databases from the server | -| pacfiles | pacman -F | Search package file names for matching strings | -| pacls | pacman -Ql | List files in a package | -| pacown | pacman -Qo | Show which package owns a file | +| Alias | Command | Description | +|---------|-----------------------------------|---------------------------------------------------------------------| +| pain | `pacaur -S` | Install packages from the repositories | +| pains | `pacaur -U` | Install a package from a local file | +| painsd | `pacaur -S --asdeps` | Install packages as dependencies of another package | +| paloc | `pacaur -Qi` | Display information about a package in the local database | +| palocs | `pacaur -Qs` | Search for packages in the local database | +| palst | `pacaur -Qe` | List installed packages including from AUR (tagged as "local") | +| pamir | `pacaur -Syy` | Force refresh of all package lists after updating mirrorlist | +| paorph | `pacaur -Qtd` | Remove orphans using pacaur | +| pare | `pacaur -R` | Remove packages, keeping its settings and dependencies | +| parem | `pacaur -Rns` | Remove packages, including its settings and unneeded dependencies | +| parep | `pacaur -Si` | Display information about a package in the repositories | +| pareps | `pacaur -Ss` | Search for packages in the repositories | +| paupd | `pacaur -Sy` | Update and refresh local package, ABS and AUR databases | +| paupg | `pacaur -Syua` | Sync with repositories before upgrading all packages (from AUR too) | +| pasu | `pacaur -Syua --no-confirm` | Same as `paupg`, but without confirmation | +| upgrade[²](#f2) | `pacaur -Syu` | Sync with repositories before upgrading packages | -| Function | Description | -|----------------|------------------------------------------------------| -| pacdisowned | List all disowned files in your system | -| paclist | List all installed packages with a short description | -| pacmanallkeys | Get all keys for developers and trusted users | -| pacmansignkeys | Locally trust all keys passed as parameters | -| pacweb | Open the website of an ArchLinux package | +#### Trizen + +| Alias | Command | Description | +|---------|-----------------------------------|---------------------------------------------------------------------| +| trconf | `trizen -C` | Fix all configuration files with vimdiff | +| trin | `trizen -S` | Install packages from the repositories | +| trins | `trizen -U` | Install a package from a local file | +| trinsd | `trizen -S --asdeps` | Install packages as dependencies of another package | +| trloc | `trizen -Qi` | Display information about a package in the local database | +| trlocs | `trizen -Qs` | Search for packages in the local database | +| trlst | `trizen -Qe` | List installed packages including from AUR (tagged as "local") | +| trmir | `trizen -Syy` | Force refresh of all package lists after updating mirrorlist | +| trorph | `trizen -Qtd` | Remove orphans using yaourt | +| trre | `trizen -R` | Remove packages, keeping its settings and dependencies | +| trrem | `trizen -Rns` | Remove packages, including its settings and unneeded dependencies | +| trrep | `trizen -Si` | Display information about a package in the repositories | +| trreps | `trizen -Ss` | Search for packages in the repositories | +| trupd | `trizen -Sy` | Update and refresh local package, ABS and AUR databases | +| trupg | `trizen -Syua` | Sync with repositories before upgrading all packages (from AUR too) | +| trsu | `trizen -Syua --no-confirm` | Same as `trupg`, but without confirmation | +| upgrade[²](#f2) | `trizen -Syu` | Sync with repositories before upgrading packages | + +#### Yaourt[¹](#f1) + +| Alias | Command | Description | +|---------|-----------------------------------|---------------------------------------------------------------------| +| yaconf | `yaourt -C` | Fix all configuration files with vimdiff | +| yain | `yaourt -S` | Install packages from the repositories | +| yains | `yaourt -U` | Install a package from a local file | +| yainsd | `yaourt -S --asdeps` | Install packages as dependencies of another package | +| yaloc | `yaourt -Qi` | Display information about a package in the local database | +| yalocs | `yaourt -Qs` | Search for packages in the local database | +| yalst | `yaourt -Qe` | List installed packages including from AUR (tagged as "local") | +| yamir | `yaourt -Syy` | Force refresh of all package lists after updating mirrorlist | +| yaorph | `yaourt -Qtd` | Remove orphans using yaourt | +| yare | `yaourt -R` | Remove packages, keeping its settings and dependencies | +| yarem | `yaourt -Rns` | Remove packages, including its settings and unneeded dependencies | +| yarep | `yaourt -Si` | Display information about a package in the repositories | +| yareps | `yaourt -Ss` | Search for packages in the repositories | +| yaupd | `yaourt -Sy` | Update and refresh local package, ABS and AUR databases | +| yaupg | `yaourt -Syua` | Sync with repositories before upgrading all packages (from AUR too) | +| yasu | `yaourt -Syua --no-confirm` | Same as `yaupg`, but without confirmation | +| upgrade[²](#f2) | `yaourt -Syu` | Sync with repositories before upgrading packages | + +#### Yay[¹](#f1) + +| Alias | Command | Description | +|---------|--------------------------------|-------------------------------------------------------------------| +| yaconf | `yay -Pg` | Print current configuration | +| yain | `yay -S` | Install packages from the repositories | +| yains | `yay -U` | Install a package from a local file | +| yainsd | `yay -S --asdeps` | Install packages as dependencies of another package | +| yaloc | `yay -Qi` | Display information about a package in the local database | +| yalocs | `yay -Qs` | Search for packages in the local database | +| yalst | `yay -Qe` | List installed packages including from AUR (tagged as "local") | +| yamir | `yay -Syy` | Force refresh of all package lists after updating mirrorlist | +| yaorph | `yay -Qtd` | Remove orphans using yay | +| yare | `yay -R` | Remove packages, keeping its settings and dependencies | +| yarem | `yay -Rns` | Remove packages, including its settings and unneeded dependencies | +| yarep | `yay -Si` | Display information about a package in the repositories | +| yareps | `yay -Ss` | Search for packages in the repositories | +| yaupd | `yay -Sy` | Update and refresh local package, ABS and AUR databases | +| yaupg | `yay -Syu` | Sync with repositories before upgrading packages | +| yasu | `yay -Syu --no-confirm` | Same as `yaupg`, but without confirmation | +| upgrade[²](#f2) | `yay -Syu` | Sync with repositories before upgrading packages | --- +¹ +Yay and Yaourt aliases overlap. If both are installed, yay will take precedence. + +² +The `upgrade` alias is set for all package managers. Its value will depend on +whether the package manager is installed, checked in the following order: + +1. `yay` +2. `yaourt` +3. `trizen` +4. `pacaur` +5. `aura` +6. `pacman` + ## Contributors - Benjamin Boudreau - dreurmail@gmail.com - Celso Miranda - contacto@celsomiranda.net +- ratijas (ivan tkachenko) - me@ratijas.tk +- Juraj Fiala - doctorjellyface@riseup.net - KhasMek - Boushh@gmail.com +- Majora320 (Moses Miller) - Majora320@gmail.com - Martin Putniorz - mputniorz@gmail.com - MatthR3D - matthr3d@gmail.com - ornicar - thibault.duplessis@gmail.com -- Juraj Fiala - doctorjellyface@riseup.net -- Majora320 (Moses Miller) - Majora320@gmail.com - Ybalrid (Arthur Brainville) - ybalrid@ybalrid.info +- Jeff M. Hubbard - jeffmhubbard@gmail.com diff --git a/plugins/archlinux/archlinux.plugin.zsh b/plugins/archlinux/archlinux.plugin.zsh index 4d39bd86b..c94fb8f6c 100644 --- a/plugins/archlinux/archlinux.plugin.zsh +++ b/plugins/archlinux/archlinux.plugin.zsh @@ -1,138 +1,6 @@ -if (( $+commands[trizen] )); then - alias trconf='trizen -C' - alias trupg='trizen -Syua' - alias trsu='trizen -Syua --noconfirm' - alias trin='trizen -S' - alias trins='trizen -U' - alias trre='trizen -R' - alias trrem='trizen -Rns' - alias trrep='trizen -Si' - alias trreps='trizen -Ss' - alias trloc='trizen -Qi' - alias trlocs='trizen -Qs' - alias trlst='trizen -Qe' - alias trorph='trizen -Qtd' - alias trinsd='trizen -S --asdeps' - alias trmir='trizen -Syy' - - - if (( $+commands[abs] && $+commands[aur] )); then - alias trupd='trizen -Sy && sudo abs && sudo aur' - elif (( $+commands[abs] )); then - alias trupd='trizen -Sy && sudo abs' - elif (( $+commands[aur] )); then - alias trupd='trizen -Sy && sudo aur' - else - alias trupd='trizen -Sy' - fi -fi - -if (( $+commands[yaourt] )); then - alias yaconf='yaourt -C' - alias yaupg='yaourt -Syua' - alias yasu='yaourt -Syua --noconfirm' - alias yain='yaourt -S' - alias yains='yaourt -U' - alias yare='yaourt -R' - alias yarem='yaourt -Rns' - alias yarep='yaourt -Si' - alias yareps='yaourt -Ss' - alias yaloc='yaourt -Qi' - alias yalocs='yaourt -Qs' - alias yalst='yaourt -Qe' - alias yaorph='yaourt -Qtd' - alias yainsd='yaourt -S --asdeps' - alias yamir='yaourt -Syy' - - - if (( $+commands[abs] && $+commands[aur] )); then - alias yaupd='yaourt -Sy && sudo abs && sudo aur' - elif (( $+commands[abs] )); then - alias yaupd='yaourt -Sy && sudo abs' - elif (( $+commands[aur] )); then - alias yaupd='yaourt -Sy && sudo aur' - else - alias yaupd='yaourt -Sy' - fi -fi - -if (( $+commands[yay] )); then - alias yaconf='yay -Pg' - alias yaupg='yay -Syu' - alias yasu='yay -Syu --noconfirm' - alias yain='yay -S' - alias yains='yay -U' - alias yare='yay -R' - alias yarem='yay -Rns' - alias yarep='yay -Si' - alias yareps='yay -Ss' - alias yaloc='yay -Qi' - alias yalocs='yay -Qs' - alias yalst='yay -Qe' - alias yaorph='yay -Qtd' - alias yainsd='yay -S --asdeps' - alias yamir='yay -Syy' - - - if (( $+commands[abs] && $+commands[aur] )); then - alias yaupd='yay -Sy && sudo abs && sudo aur' - elif (( $+commands[abs] )); then - alias yaupd='yay -Sy && sudo abs' - elif (( $+commands[aur] )); then - alias yaupd='yay -Sy && sudo aur' - else - alias yaupd='yay -Sy' - fi -fi - -if (( $+commands[pacaur] )); then - alias paupg='pacaur -Syu' - alias pasu='pacaur -Syu --noconfirm' - alias pain='pacaur -S' - alias pains='pacaur -U' - alias pare='pacaur -R' - alias parem='pacaur -Rns' - alias parep='pacaur -Si' - alias pareps='pacaur -Ss' - alias paloc='pacaur -Qi' - alias palocs='pacaur -Qs' - alias palst='pacaur -Qe' - alias paorph='pacaur -Qtd' - alias painsd='pacaur -S --asdeps' - alias pamir='pacaur -Syy' - - if (( $+commands[abs] && $+commands[aur] )); then - alias paupd='pacaur -Sy && sudo abs && sudo aur' - elif (( $+commands[abs] )); then - alias paupd='pacaur -Sy && sudo abs' - elif (( $+commands[aur] )); then - alias paupd='pacaur -Sy && sudo aur' - else - alias paupd='pacaur -Sy' - fi -fi - -if (( $+commands[trizen] )); then - function upgrade() { - trizen -Syu - } -elif (( $+commands[pacaur] )); then - function upgrade() { - pacaur -Syu - } -elif (( $+commands[yaourt] )); then - function upgrade() { - yaourt -Syu - } -elif (( $+commands[yay] )); then - function upgrade() { - yay -Syu - } -else - function upgrade() { - sudo pacman -Syu - } -fi +####################################### +# Pacman # +####################################### # Pacman - https://wiki.archlinux.org/index.php/Pacman_Tips alias pacupg='sudo pacman -Syu' @@ -152,33 +20,24 @@ alias pacfileupg='sudo pacman -Fy' alias pacfiles='pacman -F' alias pacls='pacman -Ql' alias pacown='pacman -Qo' - - -if (( $+commands[abs] && $+commands[aur] )); then - alias pacupd='sudo pacman -Sy && sudo abs && sudo aur' -elif (( $+commands[abs] )); then - alias pacupd='sudo pacman -Sy && sudo abs' -elif (( $+commands[aur] )); then - alias pacupd='sudo pacman -Sy && sudo aur' -else - alias pacupd='sudo pacman -Sy' -fi +alias pacupd="sudo pacman -Sy" +alias upgrade='sudo pacman -Syu' function paclist() { - # Source: https://bbs.archlinux.org/viewtopic.php?id=93683 - LC_ALL=C pacman -Qei $(pacman -Qu | cut -d " " -f 1) | \ - awk 'BEGIN {FS=":"} /^Name/{printf("\033[1;36m%s\033[1;37m", $2)} /^Description/{print $2}' + # Based on https://bbs.archlinux.org/viewtopic.php?id=93683 + pacman -Qqe | \ + xargs -I '{}' \ + expac "${bold_color}% 20n ${fg_no_bold[white]}%d${reset_color}" '{}' } function pacdisowned() { - emulate -L zsh - + local tmp db fs tmp=${TMPDIR-/tmp}/pacman-disowned-$UID-$$ db=$tmp/db fs=$tmp/fs mkdir "$tmp" - trap 'rm -rf "$tmp"' EXIT + trap 'rm -rf "$tmp"' EXIT pacman -Qlq | sort -u > "$db" @@ -188,16 +47,11 @@ function pacdisowned() { comm -23 "$fs" "$db" } -function pacmanallkeys() { - emulate -L zsh - curl -s https://www.archlinux.org/people/{developers,trustedusers}/ | \ - awk -F\" '(/pgp.mit.edu/) { sub(/.*search=0x/,""); print $1}' | \ - xargs sudo pacman-key --recv-keys -} +alias pacmanallkeys='sudo pacman-key --refresh-keys' function pacmansignkeys() { - emulate -L zsh - for key in $*; do + local key + for key in $@; do sudo pacman-key --recv-keys $key sudo pacman-key --lsign-key $key printf 'trust\n3\n' | sudo gpg --homedir /etc/pacman.d/gnupg \ @@ -207,13 +61,135 @@ function pacmansignkeys() { if (( $+commands[xdg-open] )); then function pacweb() { - pkg="$1" - infos="$(LANG=C pacman -Si "$pkg")" + if [[ $# = 0 || "$1" =~ '--help|-h' ]]; then + local underline_color="\e[${color[underline]}m" + echo "$0 - open the website of an ArchLinux package" + echo + echo "Usage:" + echo " $bold_color$0$reset_color ${underline_color}target${reset_color}" + return 1 + fi + + local pkg="$1" + local infos="$(LANG=C pacman -Si "$pkg")" if [[ -z "$infos" ]]; then return fi - repo="$(grep -m 1 '^Repo' <<< "$infos" | grep -oP '[^ ]+$')" - arch="$(grep -m 1 '^Arch' <<< "$infos" | grep -oP '[^ ]+$')" + local repo="$(grep -m 1 '^Repo' <<< "$infos" | grep -oP '[^ ]+$')" + local arch="$(grep -m 1 '^Arch' <<< "$infos" | grep -oP '[^ ]+$')" xdg-open "https://www.archlinux.org/packages/$repo/$arch/$pkg/" &>/dev/null } fi + +####################################### +# AUR helpers # +####################################### + +if (( $+commands[aura] )); then + alias auin='sudo aura -S' + alias aurin='sudo aura -A' + alias auins='sudo aura -U' + alias auinsd='sudo aura -S --asdeps' + alias aurinsd='sudo aura -A --asdeps' + alias auloc='aura -Qi' + alias aulocs='aura -Qs' + alias aulst='aura -Qe' + alias aumir='sudo aura -Syy' + alias aurph='sudo aura -Oj' + alias aure='sudo aura -R' + alias aurem='sudo aura -Rns' + alias aurep='aura -Si' + alias aurrep='aura -Ai' + alias aureps='aura -As --both' + alias auras='aura -As --both' + alias auupd="sudo aura -Sy" + alias auupg='sudo sh -c "aura -Syu && aura -Au"' + alias ausu='sudo sh -c "aura -Syu --no-confirm && aura -Au --no-confirm"' + alias upgrade='sudo aura -Syu' + + # extra bonus specially for aura + alias auown="aura -Qqo" + alias auls="aura -Qql" + function auownloc() { aura -Qi $(aura -Qqo $@); } + function auownls () { aura -Qql $(aura -Qqo $@); } +fi + +if (( $+commands[pacaur] )); then + alias paupg='pacaur -Syu' + alias pasu='pacaur -Syu --noconfirm' + alias pain='pacaur -S' + alias pains='pacaur -U' + alias pare='pacaur -R' + alias parem='pacaur -Rns' + alias parep='pacaur -Si' + alias pareps='pacaur -Ss' + alias paloc='pacaur -Qi' + alias palocs='pacaur -Qs' + alias palst='pacaur -Qe' + alias paorph='pacaur -Qtd' + alias painsd='pacaur -S --asdeps' + alias pamir='pacaur -Syy' + alias paupd="pacaur -Sy" + alias upgrade='pacaur -Syu' +fi + +if (( $+commands[trizen] )); then + alias trconf='trizen -C' + alias trupg='trizen -Syua' + alias trsu='trizen -Syua --noconfirm' + alias trin='trizen -S' + alias trins='trizen -U' + alias trre='trizen -R' + alias trrem='trizen -Rns' + alias trrep='trizen -Si' + alias trreps='trizen -Ss' + alias trloc='trizen -Qi' + alias trlocs='trizen -Qs' + alias trlst='trizen -Qe' + alias trorph='trizen -Qtd' + alias trinsd='trizen -S --asdeps' + alias trmir='trizen -Syy' + alias trupd="trizen -Sy" + alias upgrade='trizen -Syu' +fi + +if (( $+commands[yaourt] )); then + alias yaconf='yaourt -C' + alias yaupg='yaourt -Syua' + alias yasu='yaourt -Syua --noconfirm' + alias yain='yaourt -S' + alias yains='yaourt -U' + alias yare='yaourt -R' + alias yarem='yaourt -Rns' + alias yarep='yaourt -Si' + alias yareps='yaourt -Ss' + alias yaloc='yaourt -Qi' + alias yalocs='yaourt -Qs' + alias yalst='yaourt -Qe' + alias yaorph='yaourt -Qtd' + alias yainsd='yaourt -S --asdeps' + alias yamir='yaourt -Syy' + alias yaupd="yaourt -Sy" + alias upgrade='yaourt -Syu' +fi + +if (( $+commands[yay] )); then + alias yaconf='yay -Pg' + alias yaupg='yay -Syu' + alias yasu='yay -Syu --noconfirm' + alias yain='yay -S' + alias yains='yay -U' + alias yare='yay -R' + alias yarem='yay -Rns' + alias yarep='yay -Si' + alias yareps='yay -Ss' + alias yaloc='yay -Qi' + alias yalocs='yay -Qs' + alias yalst='yay -Qe' + alias yaorph='yay -Qtd' + alias yainsd='yay -S --asdeps' + alias yamir='yay -Syy' + alias yaupd="yay -Sy" + alias upgrade='yay -Syu' +fi + diff --git a/plugins/aws/aws.plugin.zsh b/plugins/aws/aws.plugin.zsh index ef435fe3b..e1566b113 100644 --- a/plugins/aws/aws.plugin.zsh +++ b/plugins/aws/aws.plugin.zsh @@ -50,32 +50,39 @@ function acp() { # First, if the profile has MFA configured, lets get the token and session duration local mfa_serial="$(aws configure get mfa_serial --profile $profile)" + local sess_duration="$(aws configure get duration_seconds --profile $profile)" if [[ -n "$mfa_serial" ]]; then local -a mfa_opt - local mfa_token sess_duration + local mfa_token echo -n "Please enter your MFA token for $mfa_serial: " read -r mfa_token - echo -n "Please enter the session duration in seconds (900-43200; default: 3600, which is the default maximum for a role): " - read -r sess_duration + if [[ -z "$sess_duration" ]]; then + echo -n "Please enter the session duration in seconds (900-43200; default: 3600, which is the default maximum for a role): " + read -r sess_duration + fi mfa_opt=(--serial-number "$mfa_serial" --token-code "$mfa_token" --duration-seconds "${sess_duration:-3600}") # Now see whether we need to just MFA for the current role, or assume a different one local role_arn="$(aws configure get role_arn --profile $profile)" + local sess_name="$(aws configure get role_session_name --profile $profile)" if [[ -n "$role_arn" ]]; then # Means we need to assume a specified role aws_command=(aws sts assume-role --role-arn "$role_arn" "${mfa_opt[@]}") # Check whether external_id is configured to use while assuming the role - local external_id="$(aws configure get external_id --profile "$profile")" + local external_id="$(aws configure get external_id --profile $profile)" if [[ -n "$external_id" ]]; then aws_command+=(--external-id "$external_id") fi # Get source profile to use to assume role - local source_profile="$(aws configure get source_profile --profile "$profile")" - aws_command+=(--profile="${source_profile:-profile}" --role-session-name "${source_profile:-profile}") + local source_profile="$(aws configure get source_profile --profile $profile)" + if [[ -z "$sess_name" ]]; then + sess_name="${source_profile:-profile}" + fi + aws_command+=(--profile="${source_profile:-profile}" --role-session-name "${sess_name}") echo "Assuming role $role_arn using profile ${source_profile:-profile}" else @@ -122,13 +129,13 @@ function aws_change_access_key() { return 1 fi - echo Insert the credentials when asked. + echo "Insert the credentials when asked." asp "$1" || return 1 AWS_PAGER="" aws iam create-access-key AWS_PAGER="" aws configure --profile "$1" - echo You can now safely delete the old access key running \`aws iam delete-access-key --access-key-id ID\` - echo Your current keys are: + echo "You can now safely delete the old access key running \`aws iam delete-access-key --access-key-id ID\`" + echo "Your current keys are:" AWS_PAGER="" aws iam list-access-keys } diff --git a/plugins/brew/README.md b/plugins/brew/README.md index b714b7ac0..bf952bf01 100644 --- a/plugins/brew/README.md +++ b/plugins/brew/README.md @@ -10,17 +10,17 @@ plugins=(... brew) ## Aliases -| Alias | Command | Description | -|----------|------------------------------------------------------------- |---------------------------------------------------------------------| -| `brewp` | `brew pin` | Pin a specified formula so that it's not upgraded. | -| `brews` | `brew list -1` | List installed formulae or the installed files for a given formula. | -| `brewsp` | `brew list --pinned` | List pinned formulae, or show the version of a given formula. | -| `bubo` | `brew update && brew outdated` | Update Homebrew data, then list outdated formulae and casks. | -| `bubc` | `brew upgrade && brew cleanup` | Upgrade outdated formulae and casks, then run cleanup. | -| `bubu` | `bubo && bubc` | Do the last two operations above. | -| `buf` | `brew upgrade --formula` | Upgrade only formulas (not casks). | -| `bcubo` | `brew update && brew outdated --cask` | Update Homebrew data, then list outdated casks. | -| `bcubc` | `brew cask reinstall $(brew outdated --cask) && brew cleanup` | Update outdated casks, then run cleanup. | +| Alias | Command | Description | +|----------|---------------------------------------|---------------------------------------------------------------------| +| `brewp` | `brew pin` | Pin a specified formula so that it's not upgraded. | +| `brews` | `brew list -1` | List installed formulae or the installed files for a given formula. | +| `brewsp` | `brew list --pinned` | List pinned formulae, or show the version of a given formula. | +| `bubo` | `brew update && brew outdated` | Update Homebrew data, then list outdated formulae and casks. | +| `bubc` | `brew upgrade && brew cleanup` | Upgrade outdated formulae and casks, then run cleanup. | +| `bubu` | `bubo && bubc` | Do the last two operations above. | +| `buf` | `brew upgrade --formula` | Upgrade only formulas (not casks). | +| `bcubo` | `brew update && brew outdated --cask` | Update Homebrew data, then list outdated casks. | +| `bcubc` | `brew upgrade --cask && brew cleanup` | Update outdated casks, then run cleanup. | ## Completion diff --git a/plugins/brew/brew.plugin.zsh b/plugins/brew/brew.plugin.zsh index 30eb135bb..532dd9be7 100644 --- a/plugins/brew/brew.plugin.zsh +++ b/plugins/brew/brew.plugin.zsh @@ -6,4 +6,4 @@ alias bubc='brew upgrade && brew cleanup' alias bubu='bubo && bubc' alias buf='brew upgrade --formula' alias bcubo='brew update && brew outdated --cask' -alias bcubc='brew cask reinstall $(brew outdated --cask) && brew cleanup' +alias bcubc='brew upgrade --cask && brew cleanup' diff --git a/plugins/colorize/colorize.plugin.zsh b/plugins/colorize/colorize.plugin.zsh index cb5ac36f5..8ea98f80a 100644 --- a/plugins/colorize/colorize.plugin.zsh +++ b/plugins/colorize/colorize.plugin.zsh @@ -96,7 +96,7 @@ colorize_less() { # which assumes that his LESSOPEN has been executed. local LESSCLOSE="" - LESS="$LESS" LESSOPEN="$LESSOPEN" LESSCLOSE="$LESSCLOSE" less "$@" + LESS="$LESS" LESSOPEN="$LESSOPEN" LESSCLOSE="$LESSCLOSE" command less "$@" } if [ -t 0 ]; then diff --git a/plugins/command-not-found/README.md b/plugins/command-not-found/README.md index 1cf4ba66e..f267f0c89 100644 --- a/plugins/command-not-found/README.md +++ b/plugins/command-not-found/README.md @@ -28,5 +28,6 @@ It works out of the box with the command-not-found packages for: - [macOS (Homebrew)](https://github.com/Homebrew/homebrew-command-not-found) - [Fedora](https://fedoraproject.org/wiki/Features/PackageKitCommandNotFound) - [NixOS](https://github.com/NixOS/nixpkgs/tree/master/nixos/modules/programs/command-not-found) +- [Termux](https://github.com/termux/command-not-found) You can add support for other platforms by submitting a Pull Request. diff --git a/plugins/command-not-found/command-not-found.plugin.zsh b/plugins/command-not-found/command-not-found.plugin.zsh index 81d76e638..cbf9a0a8e 100644 --- a/plugins/command-not-found/command-not-found.plugin.zsh +++ b/plugins/command-not-found/command-not-found.plugin.zsh @@ -1,38 +1,62 @@ -# Uses the command-not-found package zsh support -# as seen in https://www.porcheron.info/command-not-found-for-zsh/ -# this is installed in Ubuntu +## Platforms with a built-in command-not-found handler init file -[[ -e /etc/zsh_command_not_found ]] && source /etc/zsh_command_not_found +for file ( + # Arch Linux. Must have pkgfile installed: https://wiki.archlinux.org/index.php/Pkgfile#Command_not_found + /usr/share/doc/pkgfile/command-not-found.zsh + # macOS (M1 and classic Homebrew): https://github.com/Homebrew/homebrew-command-not-found + /opt/homebrew/Library/Taps/homebrew/homebrew-command-not-found/handler.sh + /usr/local/Homebrew/Library/Taps/homebrew/homebrew-command-not-found/handler.sh +); do + if [[ -r "$file" ]]; then + source "$file" + unset file + return 0 + fi +done +unset file -# Arch Linux command-not-found support, you must have package pkgfile installed -# https://wiki.archlinux.org/index.php/Pkgfile#.22Command_not_found.22_hook -[[ -e /usr/share/doc/pkgfile/command-not-found.zsh ]] && source /usr/share/doc/pkgfile/command-not-found.zsh -# Fedora command-not-found support -if [ -f /usr/libexec/pk-command-not-found ]; then - command_not_found_handler () { - runcnf=1 - retval=127 - [ ! -S /var/run/dbus/system_bus_socket ] && runcnf=0 - [ ! -x /usr/libexec/packagekitd ] && runcnf=0 - if [ $runcnf -eq 1 ] - then - /usr/libexec/pk-command-not-found $@ - retval=$? - fi - return $retval - } +## Platforms with manual command_not_found_handler() setup + +# Debian and derivatives: https://launchpad.net/ubuntu/+source/command-not-found +if [[ -x /usr/lib/command-not-found || -x /usr/share/command-not-found/command-not-found ]]; then + command_not_found_handler() { + if [[ -x /usr/lib/command-not-found ]]; then + /usr/lib/command-not-found -- "$1" + return $? + elif [[ -x /usr/share/command-not-found/command-not-found ]]; then + /usr/share/command-not-found/command-not-found -- "$1" + return $? + else + printf "zsh: command not found: %s\n" "$1" >&2 + return 127 + fi + } fi -# OSX command-not-found support -# https://github.com/Homebrew/homebrew-command-not-found -if [[ -s '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-command-not-found/handler.sh' ]]; then - source '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-command-not-found/handler.sh' +# Fedora: https://fedoraproject.org/wiki/Features/PackageKitCommandNotFound +if [[ -x /usr/libexec/pk-command-not-found ]]; then + command_not_found_handler() { + if [[ -S /var/run/dbus/system_bus_socket && -x /usr/libexec/packagekitd ]]; then + /usr/libexec/pk-command-not-found -- "$@" + return $? + fi + + printf "zsh: command not found: %s\n" "$1" >&2 + return 127 + } fi -# NixOS command-not-found support -if [ -x /run/current-system/sw/bin/command-not-found ]; then - command_not_found_handler () { - /run/current-system/sw/bin/command-not-found $@ - } +# NixOS: https://github.com/NixOS/nixpkgs/tree/master/nixos/modules/programs/command-not-found +if [[ -x /run/current-system/sw/bin/command-not-found ]]; then + command_not_found_handler() { + /run/current-system/sw/bin/command-not-found -- "$@" + } +fi + +# Termux: https://github.com/termux/command-not-found +if [[ -x /data/data/com.termux/files/usr/libexec/termux/command-not-found ]]; then + command_not_found_handler() { + /data/data/com.termux/files/usr/libexec/termux/command-not-found -- "$1" + } fi diff --git a/plugins/common-aliases/README.md b/plugins/common-aliases/README.md index d198a29ac..b6f34cb54 100644 --- a/plugins/common-aliases/README.md +++ b/plugins/common-aliases/README.md @@ -40,11 +40,13 @@ plugins=(... common-aliases) | Alias | Command | Description | |-------|-----------------------------------------------------|-----------------------------------------| -| fd | `find . -type d -name` | Find a directory with the given name | +| fd\* | `find . -type d -name` | Find a directory with the given name | | ff | `find . -type f -name` | Find a file with the given name | | grep | `grep --color` | Searches for a query string | | sgrep | `grep -R -n -H -C 5 --exclude-dir={.git,.svn,CVS}` | Useful for searching within files | +\* Only if the [`fd`](https://github.com/sharkdp/fd) command isn't installed. + ### Other Aliases | Alias | Command | Description | diff --git a/plugins/common-aliases/common-aliases.plugin.zsh b/plugins/common-aliases/common-aliases.plugin.zsh index a9d4f1a3d..4e5ff848f 100644 --- a/plugins/common-aliases/common-aliases.plugin.zsh +++ b/plugins/common-aliases/common-aliases.plugin.zsh @@ -34,7 +34,7 @@ alias -g P="2>&1| pygmentize -l pytb" alias dud='du -d 1 -h' alias duf='du -sh *' -alias fd='find . -type d -name' +(( $+commands[fd] )) || alias fd='find . -type d -name' alias ff='find . -type f -name' alias h='history' diff --git a/plugins/composer/composer.plugin.zsh b/plugins/composer/composer.plugin.zsh index 75b03ffe7..218a13e5f 100644 --- a/plugins/composer/composer.plugin.zsh +++ b/plugins/composer/composer.plugin.zsh @@ -51,7 +51,7 @@ alias cget='curl -s https://getcomposer.org/installer | php' # Add Composer's global binaries to PATH, using Composer if available. if (( $+commands[composer] )); then - autoload -Uz _store_cache _retrieve_cache + autoload -Uz _store_cache _retrieve_cache _cache_invalid _retrieve_cache composer diff --git a/plugins/debian/debian.plugin.zsh b/plugins/debian/debian.plugin.zsh index 68c6df1ae..108396784 100644 --- a/plugins/debian/debian.plugin.zsh +++ b/plugins/debian/debian.plugin.zsh @@ -66,7 +66,7 @@ if [[ $use_sudo -eq 1 ]]; then alias di="sudo dpkg -i" # Remove ALL kernel images and headers EXCEPT the one in use - alias kclean='sudo aptitude remove -P ?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))' + alias kclean='sudo aptitude remove -P "?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))"' # commands using su ######### @@ -105,7 +105,7 @@ else alias di='su -lc "dpkg -i" root' # Remove ALL kernel images and headers EXCEPT the one in use - alias kclean='su -lc "aptitude remove -P ?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))" root' + alias kclean='su -lc "aptitude remove -P \"?and(~i~nlinux-(ima|hea) ?not(~n$(uname -r)))\"" root' fi # Completion ################################################################ diff --git a/plugins/deno/.gitignore b/plugins/deno/.gitignore new file mode 100644 index 000000000..cba5b03e8 --- /dev/null +++ b/plugins/deno/.gitignore @@ -0,0 +1 @@ +_deno diff --git a/plugins/deno/README.md b/plugins/deno/README.md new file mode 100644 index 000000000..828e6af39 --- /dev/null +++ b/plugins/deno/README.md @@ -0,0 +1,18 @@ +# Deno Plugin + +This plugin sets up completion and aliases for [Deno](https://deno.land). + +## Aliases + +| Alias | Full command | +| ----- | ---------------- | +| db | deno bundle | +| dc | deno compile | +| dca | deno cache | +| dfmt | deno fmt | +| dh | deno help | +| dli | deno lint | +| drn | deno run | +| drw | deno run --watch | +| dts | deno test | +| dup | deno upgrade | diff --git a/plugins/deno/deno.plugin.zsh b/plugins/deno/deno.plugin.zsh new file mode 100644 index 000000000..a37b3bec4 --- /dev/null +++ b/plugins/deno/deno.plugin.zsh @@ -0,0 +1,23 @@ +# ALIASES +alias db='deno bundle' +alias dc='deno compile' +alias dca='deno cache' +alias dfmt='deno fmt' +alias dh='deno help' +alias dli='deno lint' +alias drn='deno run' +alias drw='deno run --watch' +alias dts='deno test' +alias dup='deno upgrade' + +# COMPLETION FUNCTION +if (( $+commands[deno] )); then + if [[ ! -f $ZSH_CACHE_DIR/deno_version ]] \ + || [[ "$(deno --version)" != "$(< "$ZSH_CACHE_DIR/deno_version")" ]] \ + || [[ ! -f $ZSH/plugins/deno/_deno ]]; then + deno completions zsh > $ZSH/plugins/deno/_deno + deno --version > $ZSH_CACHE_DIR/deno_version + fi + autoload -Uz _deno + _comps[deno]=_deno +fi diff --git a/plugins/dirhistory/dirhistory.plugin.zsh b/plugins/dirhistory/dirhistory.plugin.zsh index 35c43d76a..ec1606940 100644 --- a/plugins/dirhistory/dirhistory.plugin.zsh +++ b/plugins/dirhistory/dirhistory.plugin.zsh @@ -108,16 +108,16 @@ function dirhistory_forward() { # Bind keys to history navigation function dirhistory_zle_dirhistory_back() { # Erase current line in buffer - zle kill-buffer - dirhistory_back - zle accept-line + zle .kill-buffer + dirhistory_back + zle .accept-line } function dirhistory_zle_dirhistory_future() { # Erase current line in buffer - zle kill-buffer + zle .kill-buffer dirhistory_forward - zle accept-line + zle .accept-line } zle -N dirhistory_zle_dirhistory_back @@ -160,15 +160,15 @@ function dirhistory_down() { # Bind keys to hierarchy navigation function dirhistory_zle_dirhistory_up() { - zle kill-buffer # Erase current line in buffer + zle .kill-buffer # Erase current line in buffer dirhistory_up - zle accept-line + zle .accept-line } function dirhistory_zle_dirhistory_down() { - zle kill-buffer # Erase current line in buffer + zle .kill-buffer # Erase current line in buffer dirhistory_down - zle accept-line + zle .accept-line } zle -N dirhistory_zle_dirhistory_up diff --git a/plugins/docker-compose/README.md b/plugins/docker-compose/README.md index a81c2c78e..13f3c2cea 100644 --- a/plugins/docker-compose/README.md +++ b/plugins/docker-compose/README.md @@ -11,21 +11,22 @@ plugins=(... docker-compose) ## Aliases -| Alias | Command | Description | -|-----------|--------------------------|------------------------------------------------------------------| -| dco | `docker-compose` | Docker-compose main command | -| dcb | `docker-compose build` | Build containers | -| dce | `docker-compose exec` | Execute command inside a container | -| dcps | `docker-compose ps` | List containers | -| dcrestart | `docker-compose restart` | Restart container | -| dcrm | `docker-compose rm` | Remove container | -| dcr | `docker-compose run` | Run a command in container | -| dcstop | `docker-compose stop` | Stop a container | -| dcup | `docker-compose up` | Build, (re)create, start, and attach to containers for a service | -| dcupd | `docker-compose up -d` | Same as `dcup`, but starts as daemon | -| dcdn | `docker-compose down` | Stop and remove containers | -| dcl | `docker-compose logs` | Show logs of container | -| dclf | `docker-compose logs -f` | Show logs and follow output | -| dcpull | `docker-compose pull` | Pull image of a service | -| dcstart | `docker-compose start` | Start a container | -| dck | `docker-compose kill` | Kills containers | +| Alias | Command | Description | +|-----------|--------------------------------|------------------------------------------------------------------| +| dco | `docker-compose` | Docker-compose main command | +| dcb | `docker-compose build` | Build containers | +| dce | `docker-compose exec` | Execute command inside a container | +| dcps | `docker-compose ps` | List containers | +| dcrestart | `docker-compose restart` | Restart container | +| dcrm | `docker-compose rm` | Remove container | +| dcr | `docker-compose run` | Run a command in container | +| dcstop | `docker-compose stop` | Stop a container | +| dcup | `docker-compose up` | Build, (re)create, start, and attach to containers for a service | +| dcupb | `docker-compose up --build` | Same as `dcup`, but build images before starting containers | +| dcupd | `docker-compose up -d` | Same as `dcup`, but starts as daemon | +| dcdn | `docker-compose down` | Stop and remove containers | +| dcl | `docker-compose logs` | Show logs of container | +| dclf | `docker-compose logs -f` | Show logs and follow output | +| dcpull | `docker-compose pull` | Pull image of a service | +| dcstart | `docker-compose start` | Start a container | +| dck | `docker-compose kill` | Kills containers | diff --git a/plugins/docker-compose/docker-compose.plugin.zsh b/plugins/docker-compose/docker-compose.plugin.zsh index 5b25b63b9..85e03d343 100644 --- a/plugins/docker-compose/docker-compose.plugin.zsh +++ b/plugins/docker-compose/docker-compose.plugin.zsh @@ -18,6 +18,7 @@ alias dcrm='docker-compose rm' alias dcr='docker-compose run' alias dcstop='docker-compose stop' alias dcup='docker-compose up' +alias dcupb='docker-compose up --build' alias dcupd='docker-compose up -d' alias dcdn='docker-compose down' alias dcl='docker-compose logs' diff --git a/plugins/docker/_docker b/plugins/docker/_docker index 10c19e233..7fe204313 100644 --- a/plugins/docker/_docker +++ b/plugins/docker/_docker @@ -624,7 +624,8 @@ __docker_container_subcommand() { "($help)--entrypoint=[Overwrite the default entrypoint of the image]:entry point: " "($help)*--env-file=[Read environment variables from a file]:environment file:_files" "($help)*--expose=[Expose a port from the container without publishing it]: " - "($help)*--group=[Set one or more supplementary user groups for the container]:group:_groups" + "($help)*--gpus=[GPU devices to add to the container ('all' to pass all GPUs)]:device: " + "($help)*--group-add=[Set one or more supplementary user groups for the container]:group:_groups" "($help -h --hostname)"{-h=,--hostname=}"[Container host name]:hostname:_hosts" "($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]" "($help)--init[Run an init inside the container that forwards signals and reaps processes]" @@ -750,6 +751,7 @@ __docker_container_subcommand() { $opts_attach_exec_run_start \ "($help -d --detach)"{-d,--detach}"[Detached mode: leave the container running in the background]" \ "($help)*"{-e=,--env=}"[Set environment variables]:environment variable: " \ + "($help)*--env-file=[Read environment variables from a file]:environment file:_files" \ "($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]" \ "($help)--privileged[Give extended Linux capabilities to the command]" \ "($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]" \ @@ -791,7 +793,7 @@ __docker_container_subcommand() { "($help -f --follow)"{-f,--follow}"[Follow log output]" \ "($help -s --since)"{-s=,--since=}"[Show logs since this timestamp]:timestamp: " \ "($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \ - "($help)--tail=[Output the last K lines]:lines:(1 10 20 50 all)" \ + "($help -n --tail)"{-n=,--tail=}"[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \ "($help -)*:containers:__docker_complete_containers" && ret=0 ;; (ls|list) @@ -1018,6 +1020,7 @@ __docker_image_subcommand() { "($help)*--shm-size=[Size of '/dev/shm' (format is '')]:shm size: " \ "($help)--squash[Squash newly built layers into a single new layer]" \ "($help -t --tag)*"{-t=,--tag=}"[Repository, name and tag for the image]: :__docker_complete_repositories_with_tags" \ + "($help)--target=[Set the target build stage to build.]" \ "($help)*--ulimit=[ulimit options]:ulimit: " \ "($help)--userns=[Container user namespace]:user namespace:(host)" \ "($help -):path or URL:_directories" && ret=0 @@ -1958,6 +1961,8 @@ __docker_service_subcommand() { opts_help=("(: -)--help[Print usage]") opts_create_update=( + "($help)*--cap-add=[Add Linux capabilities]:capability: " + "($help)*--cap-drop=[Drop Linux capabilities]:capability: " "($help)*--constraint=[Placement constraints]:constraint: " "($help)--endpoint-mode=[Placement constraints]:mode:(dnsrr vip)" "($help)*"{-e=,--env=}"[Set environment variables]:env: " @@ -1970,6 +1975,7 @@ __docker_service_subcommand() { "($help)*--label=[Service labels]:label: " "($help)--limit-cpu=[Limit CPUs]:value: " "($help)--limit-memory=[Limit Memory]:value: " + "($help)--limit-pids[Limit maximum number of processes (default 0 = unlimited)]" "($help)--log-driver=[Logging driver for service]:logging driver:__docker_complete_log_drivers" "($help)*--log-opt=[Logging driver options]:log driver options:__docker_complete_log_options" "($help)*--mount=[Attach a filesystem mount to the service]:mount: " @@ -2012,6 +2018,7 @@ __docker_service_subcommand() { "($help)*--dns-option=[Set DNS options]:DNS option: " \ "($help)*--dns-search=[Set custom DNS search domains]:DNS search: " \ "($help)*--env-file=[Read environment variables from a file]:environment file:_files" \ + "($help)*--group=[Set one or more supplementary user groups for the container]:group: _groups " \ "($help)--mode=[Service Mode]:mode:(global replicated)" \ "($help)--name=[Service name]:name: " \ "($help)*--placement-pref=[Add a placement preference]:pref:__docker_service_complete_placement_pref" \ @@ -2035,7 +2042,7 @@ __docker_service_subcommand() { "($help)--no-task-ids[Do not include task IDs]" \ "($help)--no-trunc[Do not truncate output]" \ "($help)--since=[Show logs since timestamp]:timestamp: " \ - "($help)--tail=[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \ + "($help -n --tail)"{-n=,--tail=}"[Number of lines to show from the end of the logs]:lines:(1 10 20 50 all)" \ "($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \ "($help -)1:service:__docker_complete_services" && ret=0 ;; @@ -2639,6 +2646,8 @@ __docker_subcommand() { "($help)*--cluster-store-opt=[Cluster store options]:Cluster options:->cluster-store-options" \ "($help)--config-file=[Path to daemon configuration file]:Config File:_files" \ "($help)--containerd=[Path to containerd socket]:socket:_files -g \"*.sock\"" \ + "($help)--containerd-namespace=[Containerd namespace to use]:containerd namespace:" \ + "($help)--containerd-plugins-namespace=[Containerd namespace to use for plugins]:containerd namespace:" \ "($help)--data-root=[Root directory of persisted Docker data]:path:_directories" \ "($help -D --debug)"{-D,--debug}"[Enable debug mode]" \ "($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \ diff --git a/plugins/emacs/emacsclient.sh b/plugins/emacs/emacsclient.sh index 0aa8d6f40..04a2c2afd 100755 --- a/plugins/emacs/emacsclient.sh +++ b/plugins/emacs/emacsclient.sh @@ -20,8 +20,8 @@ _emacsfun() # tempfile. (first argument will be `--no-wait` passed in by the plugin.zsh) if [ "$#" -ge "2" -a "$2" = "-" ] then - tempfile="$(mktemp --tmpdir emacs-stdin-$USER.XXXXXXX 2>/dev/null \ - || mktemp -t emacs-stdin-$USER)" # support BSD mktemp + tempfile="$(mktemp --tmpdir emacs-stdin-$USERNAME.XXXXXXX 2>/dev/null \ + || mktemp -t emacs-stdin-$USERNAME)" # support BSD mktemp cat - > "$tempfile" _emacsfun --no-wait $tempfile else diff --git a/plugins/emotty/emotty.plugin.zsh b/plugins/emotty/emotty.plugin.zsh index e288b5cfb..4511275d6 100644 --- a/plugins/emotty/emotty.plugin.zsh +++ b/plugins/emotty/emotty.plugin.zsh @@ -29,7 +29,7 @@ function emotty() { # Parse tty number via prompt expansion. %l equals: # - N if tty = /dev/ttyN # - pts/N if tty = /dev/pts/N - local tty = ${${(%):-%l}##pts/} + local tty=${${(%):-%l}##pts/} # Normalize it to an emotty set index (( tty = (tty % ${#${=emotty}}) + 1 )) diff --git a/plugins/fossil/fossil.plugin.zsh b/plugins/fossil/fossil.plugin.zsh index 1ae166e62..25a8d121d 100644 --- a/plugins/fossil/fossil.plugin.zsh +++ b/plugins/fossil/fossil.plugin.zsh @@ -73,9 +73,9 @@ function _fossil_prompt () { local is_prompt=`echo $PROMPT | grep git` if [ "$is_prompt" = "" ]; then - export RPROMPT="$_rprompt"'$(fossil_prompt_info)' + RPROMPT="$_rprompt"'$(fossil_prompt_info)' else - export PROMPT="$_prompt"'$(fossil_prompt_info) ' + PROMPT="$_prompt"'$(fossil_prompt_info) ' fi _FOSSIL_PROMPT="1" diff --git a/plugins/fzf/fzf.plugin.zsh b/plugins/fzf/fzf.plugin.zsh index 524089983..a979fe222 100644 --- a/plugins/fzf/fzf.plugin.zsh +++ b/plugins/fzf/fzf.plugin.zsh @@ -7,6 +7,7 @@ function setup_using_base_dir() { fzfdirs=( "${HOME}/.fzf" "${HOME}/.nix-profile/share/fzf" + "${XDG_DATA_HOME:-$HOME/.local/share}/fzf" "/usr/local/opt/fzf" "/usr/share/fzf" "/usr/local/share/examples/fzf" @@ -64,11 +65,21 @@ function setup_using_debian_package() { # NOTE: There is no need to configure PATH for debian package, all binaries # are installed to /usr/bin by default - # Determine completion file path: first bullseye/sid, then buster/stretch - local completions="/usr/share/doc/fzf/examples/completion.zsh" - [[ -f "$completions" ]] || completions="/usr/share/zsh/vendor-completions/_fzf" + local completions key_bindings - local key_bindings="/usr/share/doc/fzf/examples/key-bindings.zsh" + case $PREFIX in + *com.termux*) + # Support Termux package + completions="${PREFIX}/share/fzf/completion.zsh" + key_bindings="${PREFIX}/share/fzf/key-bindings.zsh" + ;; + *) + # Determine completion file path: first bullseye/sid, then buster/stretch + completions="/usr/share/doc/fzf/examples/completion.zsh" + [[ -f "$completions" ]] || completions="/usr/share/zsh/vendor-completions/_fzf" + key_bindings="/usr/share/doc/fzf/examples/key-bindings.zsh" + ;; + esac # Auto-completion if [[ -o interactive && "$DISABLE_FZF_AUTO_COMPLETION" != "true" ]]; then diff --git a/plugins/genpass/README.md b/plugins/genpass/README.md new file mode 100644 index 000000000..a5ff4a876 --- /dev/null +++ b/plugins/genpass/README.md @@ -0,0 +1,66 @@ +# genpass + +This plugin provides three unique password generators for ZSH. Each generator +has at least a 128-bit security margin and generates passwords from the +cryptographically secure `/dev/urandom`. Each generator can also take an +optional numeric argument to generate multiple passwords. + +To use it from an interactive ZSH, add `genpass` to the plugins array in your +zshrc file: + + plugins=(... genpass) + +You can also invoke password generators directly (they are implemented as +standalone executable files), which can be handy when you need to generate +passwords in a script: + + ~/.oh-my-zsh/plugins/genpass/genpass-apple 3 + +## genpass-apple + +Generates a pronounceable pseudoword passphrase of the "cvccvc" consonant/vowel +syntax, inspired by [Apple's iCloud Keychain password generator][1]. Each +password has exactly 1 digit placed at the edge of a "word" and exactly 1 +capital letter to satisfy most password security requirements. + + % genpass-apple + gelcyv-foqtam-fotqoh-viMleb-lexduv-6ixfuk + + % genpass-apple 3 + japvyz-qyjti4-kajrod-nubxaW-hukkan-dijcaf + vydpig-fucnul-3ukpog-voggom-zygNad-jepgad + zocmez-byznis-hegTaj-jecdyq-qiqmiq-5enwom + +[1]: https://developer.apple.com/password-rules/ + +## genpass-monkey + +Generates visually unambiguous random meaningless strings using [Crockford's +base32][2]. + + % genpass-monkey + xt7gn976e7jj3fstgpy27330x3 + + % genpass-monkey 3 + n1qqwtzgejwgqve9yzf2gxvx4m + r2n3f5s6vbqs2yx7xjnmahqewy + 296w9y9rts3p5r9yay0raek8e5 + +[2]: https://www.crockford.com/base32.html + +## genpass-xkcd + +Generates passphrases from `/usr/share/dict/words` inspired by the [famous (and +slightly misleading) XKCD comic][3]. Each passphrase is prepended with a digit +showing the number of words in the passphrase to adhere to password security +requirements that require digits. Each word is 6 characters or less. + + % genpass-xkcd + 9-eaten-Slav-rife-aired-hill-cordon-splits-welsh-napes + + % genpass-xkcd 3 + 9-worker-Vlad-horde-shrubs-smite-thwart-paw-alters-prawns + 9-tutors-stink-rhythm-junk-snappy-hooray-barbs-mewl-clomp + 9-vital-escape-Angkor-Huff-wet-Mayra-abbés-putts-guzzle + +[3]: https://xkcd.com/936/ diff --git a/plugins/genpass/genpass-apple b/plugins/genpass/genpass-apple new file mode 100755 index 000000000..963ab6447 --- /dev/null +++ b/plugins/genpass/genpass-apple @@ -0,0 +1,79 @@ +#!/usr/bin/env zsh +# +# Usage: genpass-apple [NUM] +# +# Generate a password made of 6 pseudowords of 6 characters each +# with the security margin of at least 128 bits. +# +# Example password: xudmec-4ambyj-tavric-mumpub-mydVop-bypjyp +# +# If given a numerical argument, generate that many passwords. + +emulate -L zsh -o no_unset -o warn_create_global -o warn_nested_var + +if [[ ARGC -gt 1 || ${1-1} != ${~:-<1-$((16#7FFFFFFF))>} ]]; then + print -ru2 -- "usage: $0 [NUM]" + return 1 +fi + +zmodload zsh/system zsh/mathfunc || return + +{ + local -r vowels=aeiouy + local -r consonants=bcdfghjklmnpqrstvwxz + local -r digits=0123456789 + + # Sets REPLY to a uniformly distributed random number in [1, $1]. + # Requires: $1 <= 256. + function -$0-rand() { + local c + while true; do + sysread -s1 c || return + # Avoid bias towards smaller numbers. + (( #c < 256 / $1 * $1 )) && break + done + typeset -g REPLY=$((#c % $1 + 1)) + } + + local REPLY chars + + repeat ${1-1}; do + # Generate 6 pseudowords of the form cvccvc where c and v + # denote random consonants and vowels respectively. + local words=() + repeat 6; do + words+=('') + repeat 2; do + for chars in $consonants $vowels $consonants; do + -$0-rand $#chars || return + words[-1]+=$chars[REPLY] + done + done + done + + local pwd=${(j:-:)words} + + # Replace either the first or the last character in one of + # the words with a random digit. + -$0-rand $#digits || return + local digit=$digits[REPLY] + -$0-rand $((2 * $#words)) || return + pwd[REPLY/2*7+2*(REPLY%2)-1]=$digit + + # Convert one lower-case character to upper case. + while true; do + -$0-rand $#pwd || return + [[ $vowels$consonants == *$pwd[REPLY]* ]] && break + done + # NOTE: We aren't using ${(U)c} here because its results are + # locale-dependent. For example, when upper-casing 'i' in Turkish + # locale we would get 'İ', a.k.a. latin capital letter i with dot + # above. We could set LC_CTYPE=C locally but then we would run afoul + # of this zsh bug: https://www.zsh.org/mla/workers/2020/msg00588.html. + local c=$pwd[REPLY] + printf -v c '%o' $((#c - 32)) + printf "%s\\$c%s\\n" "$pwd[1,REPLY-1]" "$pwd[REPLY+1,-1]" || return + done +} always { + unfunction -m -- "-${(b)0}-*" +} } ]]; then + print -ru2 -- "usage: $0 [NUM]" + return 1 +fi + +zmodload zsh/system || return + +{ + local -r chars=abcdefghjkmnpqrstvwxyz0123456789 + local c + repeat ${1-1}; do + repeat 26; do + sysread -s1 c || return + # There is uniform because $#chars divides 256. + print -rn -- $chars[#c%$#chars+1] + done + print + done +} } ]]; then + print -ru2 -- "usage: $0 [NUM]" + return 1 +fi + +zmodload zsh/system zsh/mathfunc || return + +local -r dict=/usr/share/dict/words + +if [[ ! -e $dict ]]; then + print -ru2 -- "$0: file not found: $dict" + return 1 +fi + +# Read all dictionary words and leave only those made of 1-6 characters. +local -a words +words=(${(M)${(f)"$(<$dict)"}:#[a-zA-Z](#c1,6)}) || return + +if (( $#words < 2 )); then + print -ru2 -- "$0: not enough suitable words in $dict" + return 1 +fi + +if (( $#words > 16#7FFFFFFF )); then + print -ru2 -- "$0: too many words in $dict" + return 1 +fi + +# Figure out how many words we need for 128 bits of security margin. +# Each word adds log2($#words) bits. +local -i n=$((ceil(128. / (log($#words) / log(2))))) + +{ + local c + repeat ${1-1}; do + print -rn -- $n + repeat $n; do + while true; do + # Generate a random number in [0, 2**31). + local -i rnd=0 + repeat 4; do + sysread -s1 c || return + (( rnd = (~(1 << 23) & rnd) << 8 | #c )) + done + # Avoid bias towards words in the beginning of the list. + (( rnd < 16#7FFFFFFF / $#words * $#words )) || continue + print -rn -- -$words[rnd%$#words+1] + break + done + done + print + done +} /dev/null` && - dir=`command git rev-parse --git-dir` && - [[ ! -f $dir/NO_AUTO_FETCH ]] && - (( `date +%s` - `date -r $dir/FETCH_LOG +%s 2>/dev/null || echo 0` > $GIT_AUTO_FETCH_INTERVAL )) && - GIT_SSH_COMMAND="command ssh -o BatchMode=yes" \ - command git fetch --all 2>/dev/null &>! $dir/FETCH_LOG &) + ( + # Get git root directory + if ! gitdir="$(command git rev-parse --git-dir 2>/dev/null)"; then + return 0 + fi + + # Do nothing if auto-fetch disabled + if [[ -z "$gitdir" || -f "$gitdir/NO_AUTO_FETCH" ]]; then + return 0 + fi + + # Get time (seconds) when auto-fetch was last run + lastrun="$(zstat +mtime "$gitdir/FETCH_LOG" 2>/dev/null || echo 0)" + # Do nothing if not enough time has passed since last auto-fetch + if (( EPOCHSECONDS - lastrun < $GIT_AUTO_FETCH_INTERVAL )); then + return 0 + fi + + # Fetch all remotes (avoid ssh passphrase prompt) + GIT_SSH_COMMAND="command ssh -o BatchMode=yes" \ + command git fetch --all 2>/dev/null &>! "$gitdir/FETCH_LOG" + ) &| } function git-auto-fetch { - `command git rev-parse --is-inside-work-tree 2>/dev/null` || return - guard="`command git rev-parse --git-dir`/NO_AUTO_FETCH" + # Do nothing if not in a git repository + command git rev-parse --is-inside-work-tree &>/dev/null || return 0 - (rm $guard 2>/dev/null && - echo "${fg_bold[green]}enabled${reset_color}") || - (touch $guard && - echo "${fg_bold[red]}disabled${reset_color}") + # Remove or create guard file depending on its existence + local guard="$(command git rev-parse --git-dir)/NO_AUTO_FETCH" + if [[ -f "$guard" ]]; then + command rm "$guard" && echo "${fg_bold[green]}enabled${reset_color}" + else + command touch "$guard" && echo "${fg_bold[red]}disabled${reset_color}" + fi } -# Override zle-line-init if it exists -if (( $+functions[zle-line-init] )); then - eval "override-git-auto-fetch-$(declare -f zle-line-init)" - - function zle-line-init () { - git-fetch-all - override-git-auto-fetch-zle-line-init - } -else - function zle-line-init () { - git-fetch-all - } -fi - -zle -N zle-line-init +# zle-line-init widget (don't redefine if already defined) +(( ! ${+functions[_git-auto-fetch_zle-line-init]} )) || return 0 + +case "$widgets[zle-line-init]" in + # Simply define the function if zle-line-init doesn't yet exist + builtin|"") function _git-auto-fetch_zle-line-init() { + git-fetch-all + } ;; + # Override the current zle-line-init widget, calling the old one + user:*) zle -N _git-auto-fetch_orig_zle-line-init "${widgets[zle-line-init]#user:}" + function _git-auto-fetch_zle-line-init() { + git-fetch-all + zle _git-auto-fetch_orig_zle-line-init -- "$@" + } ;; +esac + +zle -N zle-line-init _git-auto-fetch_zle-line-init diff --git a/plugins/git-flow/git-flow.plugin.zsh b/plugins/git-flow/git-flow.plugin.zsh index eab969d8a..916cd5693 100644 --- a/plugins/git-flow/git-flow.plugin.zsh +++ b/plugins/git-flow/git-flow.plugin.zsh @@ -36,7 +36,6 @@ alias gflff='git flow feature finish' alias gflfp='git flow feature publish' alias gflhf='git flow hotfix finish' alias gflrf='git flow release finish' -alias gflfp='git flow feature publish' alias gflhp='git flow hotfix publish' alias gflrp='git flow release publish' alias gflfpll='git flow feature pull' diff --git a/plugins/git-prompt/README.md b/plugins/git-prompt/README.md index 83948f536..c6610fa94 100644 --- a/plugins/git-prompt/README.md +++ b/plugins/git-prompt/README.md @@ -24,6 +24,7 @@ The prompt may look like the following: - `(master|✖2✚3)`: on branch `master`, 2 conflicts, 3 files changed - `(experimental↓2↑3|✔)`: on branch `experimental`; your branch has diverged by 3 commits, remote by 2 commits; the repository is otherwise clean - `(:70c2952|✔)`: not on any branch; parent commit has hash `70c2952`; the repository is otherwise clean +- `(master|⚑2)`: on branch `master`, there are 2 stashed changes ## Prompt Structure @@ -43,6 +44,7 @@ The symbols are as follows: | ●n | there are `n` staged files | | ✖n | there are `n` unmerged files | | ✚n | there are `n` unstaged files | +| ⚑n | there are `n` stashed changes | | … | there are some untracked files | ### Branch Tracking Symbols diff --git a/plugins/git-prompt/git-prompt.plugin.zsh b/plugins/git-prompt/git-prompt.plugin.zsh index da674af98..a4c952471 100644 --- a/plugins/git-prompt/git-prompt.plugin.zsh +++ b/plugins/git-prompt/git-prompt.plugin.zsh @@ -40,6 +40,8 @@ function update_current_git_vars() { GIT_CONFLICTS=$__CURRENT_GIT_STATUS[5] GIT_CHANGED=$__CURRENT_GIT_STATUS[6] GIT_UNTRACKED=$__CURRENT_GIT_STATUS[7] + GIT_STASHED=$__CURRENT_GIT_STATUS[8] + GIT_CLEAN=$__CURRENT_GIT_STATUS[9] } git_super_status() { @@ -63,9 +65,12 @@ git_super_status() { STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED%{${reset_color}%}" fi if [ "$GIT_UNTRACKED" -ne "0" ]; then - STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED%{${reset_color}%}" + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED$GIT_UNTRACKED%{${reset_color}%}" fi - if [ "$GIT_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then + if [ "$GIT_STASHED" -ne "0" ]; then + STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STASHED$GIT_STASHED%{${reset_color}%}" + fi + if [ "$GIT_CLEAN" -eq "1" ]; then STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN" fi STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX" @@ -83,7 +88,8 @@ ZSH_THEME_GIT_PROMPT_CONFLICTS="%{$fg[red]%}%{✖%G%}" ZSH_THEME_GIT_PROMPT_CHANGED="%{$fg[blue]%}%{✚%G%}" ZSH_THEME_GIT_PROMPT_BEHIND="%{↓%G%}" ZSH_THEME_GIT_PROMPT_AHEAD="%{↑%G%}" -ZSH_THEME_GIT_PROMPT_UNTRACKED="%{…%G%}" +ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg[cyan]%}%{…%G%}" +ZSH_THEME_GIT_PROMPT_STASHED="%{$fg_bold[blue]%}%{⚑%G%}" ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[green]%}%{✔%G%}" # Set the prompt. diff --git a/plugins/git-prompt/gitstatus.py b/plugins/git-prompt/gitstatus.py index 300365d71..786274a71 100644 --- a/plugins/git-prompt/gitstatus.py +++ b/plugins/git-prompt/gitstatus.py @@ -11,11 +11,11 @@ def get_tagname_or_hash(): """return tagname if exists else hash""" # get hash hash_cmd = ['git', 'rev-parse', '--short', 'HEAD'] - hash_ = check_output(hash_cmd).strip() + hash_ = check_output(hash_cmd).decode('utf-8').strip() # get tagname tags_cmd = ['git', 'for-each-ref', '--points-at=HEAD', '--count=2', '--sort=-version:refname', '--format=%(refname:short)', 'refs/tags'] - tags = check_output(tags_cmd).split() + tags = check_output(tags_cmd).decode('utf-8').split() if tags: return tags[0] + ('+' if len(tags) > 1 else '') @@ -23,6 +23,18 @@ def get_tagname_or_hash(): return hash_ return None +# Re-use method from https://github.com/magicmonty/bash-git-prompt to get stashs count +def get_stash(): + cmd = Popen(['git', 'rev-parse', '--git-dir'], stdout=PIPE, stderr=PIPE) + so, se = cmd.communicate() + stash_file = '%s%s' % (so.decode('utf-8').rstrip(), '/logs/refs/stash') + + try: + with open(stash_file) as f: + return sum(1 for _ in f) + except IOError: + return 0 + # `git status --porcelain --branch` can collect all information # branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind @@ -68,6 +80,12 @@ for st in status: elif st[0] != ' ': staged.append(st) +stashed = get_stash() +if not changed and not staged and not conflicts and not untracked and not stashed: + clean = 1 +else: + clean = 0 + out = ' '.join([ branch, str(ahead), @@ -76,5 +94,7 @@ out = ' '.join([ str(len(conflicts)), str(len(changed)), str(len(untracked)), + str(stashed), + str(clean) ]) print(out, end='') diff --git a/plugins/git/README.md b/plugins/git/README.md index b7f216813..6ad19543e 100644 --- a/plugins/git/README.md +++ b/plugins/git/README.md @@ -124,6 +124,7 @@ plugins=(... git) | grbd | git rebase develop | | grbi | git rebase -i | | grbm | git rebase $(git_main_branch) | +| grbo | git rebase --onto | | grbs | git rebase --skip | | grev | git revert | | grh | git reset | @@ -136,6 +137,7 @@ plugins=(... git) | grs | git restore | | grset | git remote set-url | | grss | git restore --source | +| grst | git restore --staged | | grt | cd "$(git rev-parse --show-toplevel \|\| echo .)" | | gru | git reset -- | | grup | git remote update | diff --git a/plugins/git/git.plugin.zsh b/plugins/git/git.plugin.zsh index bf2619976..e815d0787 100644 --- a/plugins/git/git.plugin.zsh +++ b/plugins/git/git.plugin.zsh @@ -31,6 +31,7 @@ function work_in_progress() { # Check if main exists and use instead of master function git_main_branch() { + command git rev-parse --git-dir &>/dev/null || return local branch for branch in main trunk; do if command git show-ref -q --verify refs/heads/$branch; then @@ -223,6 +224,7 @@ alias grbc='git rebase --continue' alias grbd='git rebase develop' alias grbi='git rebase -i' alias grbm='git rebase $(git_main_branch)' +alias grbo='git rebase --onto' alias grbs='git rebase --skip' alias grev='git revert' alias grh='git reset' @@ -235,6 +237,7 @@ alias grrm='git remote remove' alias grs='git restore' alias grset='git remote set-url' alias grss='git restore --source' +alias grst='git restore --staged' alias grt='cd "$(git rev-parse --show-toplevel || echo .)"' alias gru='git reset --' alias grup='git remote update' @@ -260,7 +263,7 @@ alias gstd='git stash drop' alias gstl='git stash list' alias gstp='git stash pop' alias gsts='git stash show --text' -alias gstu='git stash --include-untracked' +alias gstu='gsta --include-untracked' alias gstall='git stash --all' alias gsu='git submodule update' alias gsw='git switch' diff --git a/plugins/gitfast/_git b/plugins/gitfast/_git index aaea581d5..988f5b1c6 100644 --- a/plugins/gitfast/_git +++ b/plugins/gitfast/_git @@ -45,71 +45,49 @@ fi local old_complete="$functions[complete]" functions[complete]=: +COMP_WORDBREAKS=':' GIT_SOURCING_ZSH_COMPLETION=y . "$script" functions[complete]="$old_complete" +__gitcompadd () +{ + compadd -Q -p "${2-}" -S "${3- }" ${@[4,-1]} -- ${=1} && _ret=0 +} + __gitcomp () { emulate -L zsh local cur_="${3-$cur}" - case "$cur_" in - --*=) - ;; - --no-*) - local c IFS=$' \t\n' - local -a array - for c in ${=1}; do - if [[ $c == "--" ]]; then - continue - fi - c="$c${4-}" - case $c in - --*=|*.) ;; - *) c="$c " ;; - esac - array+=("$c") - done - compset -P '*[=:]' - compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 - ;; - *) - local c IFS=$' \t\n' - local -a array - for c in ${=1}; do - if [[ $c == "--" ]]; then - c="--no-...${4-}" - array+=("$c ") - break - fi - c="$c${4-}" - case $c in - --*=|*.) ;; - *) c="$c " ;; - esac - array+=("$c") - done - compset -P '*[=:]' - compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 - ;; - esac -} + [[ "$cur_" == *= ]] && return -__gitcomp_direct () -{ - emulate -L zsh + local c IFS=$' \t\n' sfx + for c in ${=1}; do + if [[ $c == "--" ]]; then + [[ "$cur_" == --no-* ]] && continue + __gitcompadd "--no-..." + break + fi - compset -P '*[=:]' - compadd -Q -S '' -- ${(f)1} && _ret=0 + if [[ -z "${4-}" ]]; then + case $c in + *=) c="${c%=}"; sfx="=" ;; + *.) sfx="" ;; + *) sfx=" " ;; + esac + else + sfx="$4" + fi + __gitcompadd "$c" "${2-}" "$sfx" -q + done } __gitcomp_nl () { emulate -L zsh - compset -P '*[=:]' - compadd -Q -S "${4- }" -p "${2-}" -- ${(f)1} && _ret=0 + IFS=$'\n' __gitcompadd "$1" "${2-}" "${4- }" } __gitcomp_file () @@ -119,14 +97,9 @@ __gitcomp_file () compadd -f -p "${2-}" -- ${(f)1} && _ret=0 } -__gitcomp_direct_append () +__gitcomp_direct () { - __gitcomp_direct "$@" -} - -__gitcomp_nl_append () -{ - __gitcomp_nl "$@" + __gitcomp_nl "$1" "" "" "" } __gitcomp_file_direct () @@ -134,20 +107,35 @@ __gitcomp_file_direct () __gitcomp_file "$1" "" } +__gitcomp_nl_append () +{ + __gitcomp_nl "$@" +} + +__gitcomp_direct_append () +{ + __gitcomp_direct "$@" +} + _git_zsh () { - __gitcomp "v1.0" + __gitcomp "v1.2" } __git_complete_command () { emulate -L zsh + compset -P '*[=:]' + local command="$1" local completion_func="_git_${command//-/_}" if (( $+functions[$completion_func] )); then emulate ksh -c $completion_func return 0 + elif emulate ksh -c "__git_support_parseopt_helper $command"; then + emulate ksh -c "__git_complete_common $command" + return 0 else return 1 fi @@ -218,24 +206,27 @@ __git_zsh_main () { local curcontext="$curcontext" state state_descr line typeset -A opt_args - local -a orig_words + local -a orig_words __git_C_args orig_words=( ${words[@]} ) _arguments -C \ - '(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \ - '(-p --paginate)--no-pager[do not pipe git output into a pager]' \ - '--git-dir=-[set the path to the repository]: :_directories' \ - '--bare[treat the repository as a bare repository]' \ + '(-p --paginate -P --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \ + '(-p --paginate -P --no-pager)'{-P,--no-pager}'[do not pipe git output into a pager]' \ + '(--bare)--git-dir=[set the path to the repository]: :_directories' \ + '(--git-dir)--bare[treat the repository as a bare repository]' \ '(- :)--version[prints the git suite version]' \ - '--exec-path=-[path to where your core git programs are installed]:: :_directories' \ - '--html-path[print the path where git''s HTML documentation is installed]' \ - '--info-path[print the path where the Info files are installed]' \ - '--man-path[print the manpath (see `man(1)`) for the man pages]' \ - '--work-tree=-[set the path to the working tree]: :_directories' \ - '--namespace=-[set the git namespace]' \ + '--exec-path=[path to where your core git programs are installed]: :_directories' \ + '(- :)--exec-path[print the path where your core git programs are installed]' \ + '(- :)--html-path[print the path where git''s HTML documentation is installed]' \ + '(- :)--info-path[print the path where the Info files are installed]' \ + '(- :)--man-path[print the manpath (see `man(1)`) for the man pages]' \ + '--work-tree=[set the path to the working tree]: :_directories' \ + '--namespace=[set the git namespace]:' \ '--no-replace-objects[do not use replacement refs to replace git objects]' \ '(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \ + '*-C[run as if git was started in the given path]: :_directories' \ + '*-c[pass a configuration parameter to the command]: :->config' \ '(-): :->command' \ '(-)*:: :->arg' && return @@ -249,15 +240,23 @@ __git_zsh_main () let _ret || break done ;; + (config) + compset -P '*[=:]' + emulate ksh -c __git_complete_config_variable_name_and_value + ;; (arg) local command="${words[1]}" __git_dir if (( $+opt_args[--bare] )); then __git_dir='.' else - __git_dir=${opt_args[--git-dir]} + __git_dir=${~opt_args[--git-dir]} fi + for x in ${(s.:.)opt_args[-C]}; do + __git_C_args+=('-C' ${~x}) + done + (( $+opt_args[--help] )) && command='help' words=( ${orig_words[@]} ) diff --git a/plugins/gitfast/git-completion.bash b/plugins/gitfast/git-completion.bash index b93706d17..4497a294f 100644 --- a/plugins/gitfast/git-completion.bash +++ b/plugins/gitfast/git-completion.bash @@ -45,11 +45,6 @@ # When set to "1" suggest all options, including options which are # typically hidden (e.g. '--allow-empty' for 'git commit'). -case "$COMP_WORDBREAKS" in -*:*) : great ;; -*) COMP_WORDBREAKS="$COMP_WORDBREAKS:" -esac - # Discovers the path to the git repository taking any '--git-dir=' and # '-C ' options into account and stores it in the $__git_repo_path # variable. @@ -347,7 +342,7 @@ __gitcomp () local cur_="${3-$cur}" case "$cur_" in - --*=) + *=) ;; --no-*) local c i=0 IFS=$' \t\n' @@ -519,7 +514,7 @@ __gitcomp_builtin () local incl="${2-}" local excl="${3-}" - local var=__gitcomp_builtin_"${cmd/-/_}" + local var=__gitcomp_builtin_"${cmd//-/_}" local options eval "options=\${$var-}" @@ -1231,26 +1226,44 @@ __git_pretty_aliases () # __git_aliased_command requires 1 argument __git_aliased_command () { - local word cmdline=$(__git config --get "alias.$1") - for word in $cmdline; do - case "$word" in - \!gitk|gitk) - echo "gitk" + local cur=$1 last list word cmdline + + while [[ -n "$cur" ]]; do + if [[ "$list" == *" $cur "* ]]; then + # loop detected return - ;; - \!*) : shell command alias ;; - -*) : option ;; - *=*) : setting env ;; - git) : git itself ;; - \(\)) : skip parens of shell function definition ;; - {) : skip start of shell helper function ;; - :) : skip null command ;; - \'*) : skip opening quote after sh -c ;; - *) - echo "$word" - return - esac + fi + + cmdline=$(__git config --get "alias.$cur") + list=" $cur $list" + last=$cur + cur= + + for word in $cmdline; do + case "$word" in + \!gitk|gitk) + cur="gitk" + break + ;; + \!*) : shell command alias ;; + -*) : option ;; + *=*) : setting env ;; + git) : git itself ;; + \(\)) : skip parens of shell function definition ;; + {) : skip start of shell helper function ;; + :) : skip null command ;; + \'*) : skip opening quote after sh -c ;; + *) + cur="$word" + break + esac + done done + + cur=$last + if [[ "$cur" != "$1" ]]; then + echo "$cur" + fi } # Check whether one of the given words is present on the command line, @@ -2723,10 +2736,10 @@ __git_complete_config_variable_name () return ;; branch.*) - local pfx="${cur%.*}." - cur_="${cur#*.}" + local pfx="${cur_%.*}." + cur_="${cur_#*.}" __gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")" - __gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_" "$sfx" + __gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_" "${sfx:- }" return ;; guitool.*.*) @@ -2760,7 +2773,7 @@ __git_complete_config_variable_name () local pfx="${cur_%.*}." cur_="${cur_#*.}" __git_compute_all_commands - __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" "$sfx" + __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" "${sfx:- }" return ;; remote.*.*) @@ -2776,7 +2789,7 @@ __git_complete_config_variable_name () local pfx="${cur_%.*}." cur_="${cur_#*.}" __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "." - __gitcomp_nl_append "pushDefault" "$pfx" "$cur_" "$sfx" + __gitcomp_nl_append "pushDefault" "$pfx" "$cur_" "${sfx:- }" return ;; url.*.*) diff --git a/plugins/gitfast/update b/plugins/gitfast/update index d0947e7d8..5311065a1 100755 --- a/plugins/gitfast/update +++ b/plugins/gitfast/update @@ -1,7 +1,7 @@ #!/bin/sh url="https://raw.githubusercontent.com/felipec/git-completion" -version="1.0" +version="1.2" curl -s -o _git "${url}/v${version}/git-completion.zsh" && curl -s -o git-completion.bash "${url}/v${version}/git-completion.bash" && diff --git a/plugins/grc/README.md b/plugins/grc/README.md new file mode 100644 index 000000000..515e87640 --- /dev/null +++ b/plugins/grc/README.md @@ -0,0 +1,15 @@ +# Generic Colouriser plugin + +This plugin adds wrappers for commands supported by [Generic Colouriser](https://github.com/garabik/grc): + +To use it, add `grc` to the plugins array in your zshrc file: + +```zsh +plugins=(... grc) +``` + +## Commands + +The plugin sources the bundled alias generator from the installation, available at `/etc/grc.zsh`. +The complete list of wrapped commands may vary depending on the installed version of `grc`, look +at the file mentioned above (`/etc/grc.zsh`) to see which commands are wrapped. diff --git a/plugins/grc/grc.plugin.zsh b/plugins/grc/grc.plugin.zsh new file mode 100644 index 000000000..b709b9e02 --- /dev/null +++ b/plugins/grc/grc.plugin.zsh @@ -0,0 +1,17 @@ +#!/usr/bin/env zsh + +# common grc.zsh paths +files=( + /etc/grc.zsh # default + /usr/local/etc/grc.zsh # homebrew +) + +# verify the file is readable and source it +for file in $files; do + if [[ -r "$file" ]]; then + source "$file" + break + fi +done + +unset file files diff --git a/plugins/hanami/README.md b/plugins/hanami/README.md index 3ac8defbb..c9e09f4f2 100644 --- a/plugins/hanami/README.md +++ b/plugins/hanami/README.md @@ -1,32 +1,45 @@ -# Hanami Plugin # -This plugin adds convenient ways to work with [Hanami](https://hanamirb.org/) via console. +# Hanami Plugin + +This plugin adds convenient aliases to work with [Hanami](https://hanamirb.org/) via console. It's inspired by Rails plugin, so if you've used it, you'll feel like home. -## Usage ## +To use it, add `hanami` to the plugins array in your zshrc file: + +```zsh +plugins=(... hanami) +``` + +## Usage For example, type `hc` into your console when you're within Hanami project directory to run the application console. Have a look at available shortcuts below. You can read more about these commands [on the official website](https://hanamirb.org/guides/command-line/applications/). -## Aliases ## +## Aliases -| Alias | Command | Description | -|-------|---------------------------|---------------------------------------------------------| -| HED | HANAMI_ENV=development | Set environment variable HANAMI_ENV to development | -| HEP | HANAMI_ENV=production | Set environment variable HANAMI_ENV to production | -| HET | HANAMI_ENV=test | Set environment variable HANAMI_ENV to test | -| hc | hanami console | Run application console | -| hd | hanami destroy | Remove specified hanami resource | -| hg | hanami generate | Create specified hanami resource | -| hgm | hanami generate migration | Create migration file | -| hs | hanami server | Launch server with hanami application | -| hsp | hanami server -p | Launch server with specified port | -| hr | hanami routes | List application routes | -| hdc | hanami db create | Create application database | -| hdd | hanami db drop | Delete application database | -| hdp | hanami db prepare | Prepare database for the current environment | -| hda | hanami db apply | Recreates a fresh schema after migrations (destructive) | -| hdv | hanami db version | Print current database version | -| hdrs | hdd && hdp | Drop and recreate application database | -| hdtp | HET hdp | Actualize test environment database | -| hrg | hr | grep | Grep hanami routes with specified pattern | +| Alias | Command | Description | +|-------|-----------------------------|---------------------------------------------------------| +| HED\* | `HANAMI_ENV=development` | Set environment variable HANAMI_ENV to development | +| HEP\* | `HANAMI_ENV=production` | Set environment variable HANAMI_ENV to production | +| HET\* | `HANAMI_ENV=test` | Set environment variable HANAMI_ENV to test | +| hc | `hanami console` | Run application console | +| hd | `hanami destroy` | Remove specified hanami resource | +| hg | `hanami generate` | Create specified hanami resource | +| hgm | `hanami generate migration` | Create migration file | +| hs | `hanami server` | Launch server with hanami application | +| hsp | `hanami server -p` | Launch server with specified port | +| hr | `hanami routes` | List application routes | +| hdc | `hanami db create` | Create application database | +| hdd | `hanami db drop` | Delete application database | +| hdp | `hanami db prepare` | Prepare database for the current environment | +| hda | `hanami db apply` | Recreates a fresh schema after migrations (destructive) | +| hdv | `hanami db version` | Print current database version | +| hdrs | `hdd && hdp` | Drop and recreate application database | +| hdtp | `HET hdp` | Actualize test environment database | +| hrg | `hr | grep` | Grep hanami routes with specified pattern | + +\* You should use these at the beginning of a command, for example: + +```console +$ HED hdd # equivalent to 'HANAMI_ENV=development hanami db drop' +``` diff --git a/plugins/hanami/hanami.plugin.zsh b/plugins/hanami/hanami.plugin.zsh index 349c42cae..42143b428 100644 --- a/plugins/hanami/hanami.plugin.zsh +++ b/plugins/hanami/hanami.plugin.zsh @@ -1,6 +1,6 @@ -alias -g HED='HANAMI_ENV=development' -alias -g HEP='HANAMI_ENV=production' -alias -g HET='HANAMI_ENV=test' +alias HED='HANAMI_ENV=development ' +alias HEP='HANAMI_ENV=production ' +alias HET='HANAMI_ENV=test ' alias hc='hanami console' alias hd='hanami destroy' diff --git a/plugins/hitchhiker/.gitignore b/plugins/hitchhiker/.gitignore new file mode 100644 index 000000000..63c2b54c4 --- /dev/null +++ b/plugins/hitchhiker/.gitignore @@ -0,0 +1 @@ +fortunes/hitchhiker.dat diff --git a/plugins/hitchhiker/README.md b/plugins/hitchhiker/README.md new file mode 100644 index 000000000..d12a1e93f --- /dev/null +++ b/plugins/hitchhiker/README.md @@ -0,0 +1,44 @@ +# hitchhiker + +This plugin adds quotes from The Hitchhiker's Guide to the Galaxy, from Douglas Adams. + +To use it, add `hitchhiker` to the plugins array in your zshrc file: + +```zsh +plugins=(... hitchhiker) +``` + +## Aliases + +- `hitchhiker`: displays a quote from the book using `fortune`. +- `hitchhiker_cow`: displays a quote from the book using `cowthink`. + +```console +$ hitchhiker_cow + _______________________________________ +( "OK, so ten out of ten for style, but ) +( minus several million for good ) +( thinking, yeah? " ) + --------------------------------------- + o ^__^ + o (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` + +## Requirements + +- `fortune` and `strfile`. +- `cowthink` if using the `hitchhiker_cow` command. + +## Credits + +Fortune file: Andreas Gohr ([splitbrain.org](https://www.splitbrain.org/projects/fortunes/hg2g)) + +Spelling and formatting fixes: grok@resist.ca + +Original quotes from: + +- https://web.archive.org/web/20120106083254/http://tatooine.fortunecity.com/vonnegut/29/hitch/parhaat.html +- https://web.archive.org/web/20011112065737/http://www-personal.umd.umich.edu/~nhughes/dna/faqs/quotedir.html diff --git a/plugins/hitchhiker/fortunes/hitchhiker b/plugins/hitchhiker/fortunes/hitchhiker new file mode 100644 index 000000000..825b86cd6 --- /dev/null +++ b/plugins/hitchhiker/fortunes/hitchhiker @@ -0,0 +1,275 @@ +"`...You hadn't exactly gone out of your way to call attention to them had you? I mean like actually telling anyone or anything.' `But the plans were on display...' `On display? I eventually had to go down to the cellar to find them.' `That's the display department.' `With a torch.' `Ah, well the lights had probably gone.' `So had the stairs.' `But look you found the notice didn't you?' `Yes,' said Arthur, `yes I did. It was on display in the bottom of a locked filing cabinet stuck in a disused lavatory with a sign on the door saying "Beware of The Leopard".'" + +- Arthur singing the praises of the local council planning department. +% +"`Time is an illusion. Lunchtime doubly so.' `Very deep,' said Arthur, `you should send that in to the "Reader's Digest". They've got a page for people like you.'" + +- Ford convincing Arthur to drink three pints in ten minutes at lunchtime. +% +"`This must be Thursday,' said Arthur to himself, sinking low over his beer, `I never could get the hang of Thursdays.'" + +- Arthur, on what was to be his last Thursday on Earth. +% +"Pages one and two [of Zaphod's presidential speech] had been salvaged by a Damogran Frond Crested Eagle and had already become incorporated into an extraordinary new form of nest which the eagle had invented. It was constructed largely of papier mache and it was virtually impossible for a newly hatched baby eagle to break out of it. The Damogran Frond Crested Eagle had heard of the notion of survival of the species but wanted no truck with it." + +- An example of Damogran wildlife. +% +"`How do you feel?' he asked him. `Like a military academy,' said Arthur, `bits of me keep passing out.'" .... `We're safe,' he said. `Oh good,' said Arthur. `We're in a small galley cabin,' said Ford, `in one of the spaceships of the Vogon Constructor Fleet.' `Ah,' said Arthur, `this is obviously some strange usage of the word "safe" that I wasn't previously aware of.' + +- Arthur after his first ever teleport ride. +% +"`The best way to get a drink out of a Vogon is to stick your finger down his throat...'" + +- The Book, on one of the Vogon's social inadequacies. +% +"`You'd better be prepared for the jump into hyperspace. It's unpleasantly like being drunk.' `What's so unpleasant about being drunk?' `You ask a glass of water.'" + +- Arthur getting ready for his first jump into hyperspace. +% +"`You know,' said Arthur, `it's at times like this, when I'm trapped in a Vogon airlock with a man from Betelgeuse, and about to die from asphyxiation in deep space that I really wish I'd listened to what my mother told me when I was young.' `Why, what did she tell you?' `I don't know, I didn't listen.'" + +- Arthur coping with certain death as best as he could. +% +"`Ford, you're turning into a penguin. Stop it.'" + +- Arthur experiences the improbability drive at work. +% +"`I think you ought to know that I'm feeling very depressed.'" "`Life, don't talk to me about life.'" "`Here I am, brain the size of a planet and they ask me to take you down to the bridge. Call that "job satisfaction"? 'Cos I don't.'" "`I've got this terrible pain in all the diodes down my left side.'" + +- Guess who. +% +"`If there's anything more important than my ego around, I want it caught and shot now.'" + +- Zaphod. +% +"`In those days spirits were brave, the stakes were high, men were REAL men, women were REAL women, and small furry creatures from Alpha Centauri were REAL small furry creatures from Aplha Centauri.'" + +- The Book getting all nostalgic. +% +"`Hey this is terrific!' Zaphod said. `Someone down there is trying to kill us!' `Terrific,' said Arthur. `But don't you see what this means?' `Yes. We are going to die.' `Yes, but apart from that.' `APART from that?' `It means we must be on to something!' `How soon can we get off it?'" + +- Zaphod and Arthur in a certain death situation over Magrathea. +% +"And wow! Hey! What's this thing coming towards me very fast? Very very fast. So big and flat and round, it needs a big wide sounding word like... ow... ound... round... ground! That's it! That's a good name - ground! I wonder if it will be friends with me?" + +- For the sperm whale, it wasn't. +% +"Oh no, not again." + +- A bowl of petunias on it's way to certain death. +% +"`Er, hey Earthman...' `Arthur,' said Arthur. `Yeah, could you just sort of keep this robot with you and guard this end of the passageway. OK?' `Guard?' said Arthur. `What from? You just said there's no one here.' `Yeah, well, just for safety, OK?' said Zaphod. `Whose? Yours or mine?'" + +- Arthur drawing the short straw on Magrathea. +% +"There are of course many problems connected with life, of which some of the most popular are `Why are people born?' `Why do they die?' `Why do they spend so much of the intervening time wearing digital watches?'" + +- The Book. +% +"`Right,' said Ford, `I'm going to have a look.' He glanced round at the others. `Is no one going to say, "No you can't possibly, let me go instead"?' They all shook their heads. `Oh well.'" + +- Ford attempting to be heroic whilst being seiged by Shooty and Bangbang. +% +"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." - The Book just recapping what happened in the last book. "`I am so amazingly cool you could keep a side of meat in me for a month. I am so hip I have difficulty seeing over my pelvis.'" + +- Zaphod being cool. +% +"`You ARE Zaphod Beeblebrox?' `Yeah,' said Zaphod, `but don't shout it out or they'll all want one.' `THE Zaphod Beeblebrox?' `No, just A Zaphod Bebblebrox, didn't you hear I come in six packs?' `But sir,' it squealed, `I just heard on the sub-ether radio report. It said you were dead...' `Yeah, that's right, I just haven't stopped moving yet.'" + +- Zaphod and the Guide's receptionist. +% +"The fronting for the eighty-yard-long marble-topped bar had been made by stitching together nearly twenty thousand Antarean Mosaic Lizard skins, despite the fact that the twenty thousand lizards concerned had needed them to keep their insides in." + +- The Book decribing Milliways' politically incorrect decor. +% +"`...and the Universe,' continued the waiter, determined not to be deflected on his home stretch, `will explode later for your pleasure.' Ford's head swivelled slowly towards him. He spoke with feeling. `Wow,' he said, `What sort of drinks do you serve in this place?' The waiter laughed a polite little waiter's laugh. `Ah,' he said, `I think sir has perhaps misunderstood me.' `Oh, I hope not,' breathed Ford." + +- Ford in paradise. +% +"Zaphod grinned two manic grins, sauntered over to the bar and bought most of it." + +- Zaphod in paradise. +% +"`Maybe somebody here tipped off the Galactic Police,' said Trillian. `Everybody saw you come in.' `You mean they want to arrest me over the phone?' said Zaphod, `Could be. I'm a pretty dangerous dude when I'm cornered.' `Yeah,' said a voice from under the table [Ford's now completely rat-arsed at this point], `you go to pieces so fast people get hit by the shrapnel.'" + +- Zaphod getting paranoid over a phone call. +% +"`Hand me the rap-rod, Plate Captain.' The little waiter's eyebrows wandered about his forehead in confusion. `I beg your pardon, sir?' he said. `The phone, waiter,' said Zaphod, grabbing it off him. `Shee, you guys are so unhip it's a wonder your bums don't fall off.'" + +- Zaphod discovers that waiters are the least hip people in the Universe. +% +"The main reception foyer was almost empty but Ford nevertheless weaved his way through it." + +- Ford making his way out of Milliways whilst under the influence of enough alcohol to make a rhino sing. +% +"`The first ten million years were the worst,' said Marvin, `and the second ten million, they were the worst too. The third ten million I didn't enjoy at all. After that I went into a bit of a decline.'" + +- Marvin reflecting back on his 576,000,003,579 year career as Milliways' car park attendent. +% +"`Incidentally,' he said, `what does teleport mean?' Another moment passed. Slowly, the others turned to face him. `Probably the wrong moment to ask,' said Arthur, `It's just I remember you use the word a short while ago and I only bring it up because...' `Where,' said Ford quietly, `does it say teleport?' `Well, just over here in fact,' said Arthur, pointing at a dark control box in the rear of the cabin, `Just under the word "emergency", above the word "system" and beside the sign saying "out of order".'" + +- Arthur finding an escape route from a certain death situation. +% +"I teleported home one night With Ron and Sid and Meg. Ron stole Meggie's heart away And I got Sidney's leg." + +- A poem about matter transference beams. +% +"Anyone who is capable of getting themselves made President should on no account be allowed to do the job." + +- Some wisdom from The Book. +% +"`We've got to find out what people want from fire, how they relate to it, what sort of image it has for them.' The crowd were tense. They were expecting something wonderful from Ford. `Stick it up your nose,' he said. `Which is precisely the sort of thing we need to know,' insisted the girl, `Do people want fire that can be fitted nasally?'" + +- Ford "debating" what to do with fire with a marketing girl. +% +"The story goes that I first had the idea for THHGTTG while lying drunk in a field in Innsbruck (or `Spain' as the BBC TV publicity department authoritatively has it, probably because it's easier to spell)." - Foreward by DNA. + +FORD Six pints of bitter. And quickly please, the world's about to end. BARMAN Oh yes, sir? Nice weather for it. +% +BOOK Meanwhile, the starship has landed on the surface of Magrathea and Trillian is about to make one of the most important statements of her life. Its importance is not immediately recognised by her companions. TRILL. Hey, my white mice have escaped. ZAPHOD Nuts to your white mice. +% +BOOK ...Man had always assumed that he was more intelligent than dolphins because he had achieved so much... the wheel, New York, wars, and so on, whilst all the dolphins had ever done was muck about in the water having a good time. But conversely the dolphins believed themselves to be more intelligent than man for precisely the same reasons. +% +ARTHUR What is an Algolian Zylatburger anyway? FORD They're a kind of meatburger made from the most unpleasant parts of a creature well known for its total lack of any pleasant parts. ARTHUR So you mean that the Universe does actually end not with a bang but with a Wimpy? + +- Cut dialogue from Fit the Fifth. +% +BOOK There is a theory which states that if ever anyone discovers exactly what the Universe is for and why it is here, it will instantly disappear and be replaced by something even more bizarrely inexplicable. There is another theory which states that this has already happened. + +- Introduction to Fit the Seventh. +% +FORD Tell me Arthur... ARTHUR Yes? FORD This boulder we're stuck under, how big would you say it was? Roughly? ARTHUR Oh, about the size of Coventry Cathedral. FORD Do you think we could move it? (Arthur doesn't reply) Just asking. + +- Ford and Arthur in a tricky situation, Fit the Eighth. +% +BOOK What to do if you find yourself stuck in a crack in the ground underneath a giant boulder you can't move, with no hope of rescue. Consider how lucky you are that life has been good to you so far. Alternatively, if life hasn't been good to you so far, which given your current circumstances seems more likely, consider how lucky you are that it won't be troubling you much longer. + +- Comforting advice for Ford and Arthur in this current situation, Fit the Eighth. +% +ZAPHOD Hey, this rock... FORD Marble... ZAPHOD Marble... FORD Ice-covered marble... ZAPHOD Right... it's as slippery as... as... What's the slipperiest thing you can think of? FORD At the moment? This marble. ZAPHOD Right. This marble is as slippery as this marble. + +- Zaphod and Ford trying to get a grip on things in Brontitall, Fit the Tenth. +% +ARTHUR It's not a question of whose habitat it is, it's a question of how hard you hit it. + +- Arthur pointing out one of the disadvantages of gravity, Fit the Tenth. +% +ARTHUR It probably seems a terrible thing to say, but you know what I sometimes think would be useful in these situations? LINT. What? ARTHUR A gun of some sort. LINT.2 Will this help? ARTHUR What is it? LINT.2 A gun of some sort. ARTHUR Oh, that'll help. Can you make it fire? LINT. Er... F/X DEAFENING ROAR LINT. Yes. + +- Arthur and the Lintillas gaining the upper hand, Fit the Twelfth. +% +"He stood up straight and looked the world squarely in the fields and hills. To add weight to his words he stuck the rabbit bone in his hair. He spread his arms out wide. `I will go mad!' he announced." + +- Arthur discovering a way of coping with life on Prehistoric Earth. +% +"`... then I decided that I was a lemon for a couple of weeks. I kept myself amused all that time jumping in and out of a gin and tonic.' Arthur cleared his throat, and then did it again. `Where,' he said, `did you...?' `Find a gin and tonic?' said Ford brightly. `I found a small lake that thought it was a gin and tonic, and jumped in and out of that. At least, I think it thought it was a gin and tonic.' `I may,' he addded with a grin which would have sent sane men scampering into the trees, `have been imagining it.'" + +- Ford updating Arthur about what he's been doing for the past four years. +% +"`Eddies,' said Ford, `in the space-time continuum.' `Ah,' nodded Arthur, `is he? Is he?'" + +- Arthur failing in his first lesson of galactic physics in four years. +% +"Ford grabbed him by the lapels of his dressing gown and spoke to him as slowly and distinctly and patiently as if he were somebody from a telephone company accounts department." + +- Ford trying to rectify that situation. +% +"...[Arthur] leapt to his feet like an author hearing the phone ring..." + +- Who says that the character of Arthur isn't autobiographical? +% +"Arthur's consciousness approached his body as from a great distance, and reluctantly. It had had some bad times in there. Slowly, nervously, it entered and settled down into its accustomed position. Arthur sat up. `Where am I?' he said. `Lord's Cricket Ground,' said Ford. `Fine,' said Arthur, and his consciousness stepped out again for a quick breather. His body flopped back on the grass." + +- Arthur coping with his return to Earth as best as he could. +% +"`A curse,' said Slartibartfast, `which will engulf the Galaxy in fire and destruction, and possibly bring the Universe to a premature doom. I mean it,' he added. `Sounds like a bad time,' said Ford, `with luck I'll be drunk enough not to notice.'" + +- Ford ensuring everyone knew where his priorities lay. +% +"`My doctor says that I have a malformed public-duty gland and a natural deficiency in moral fibre, and that I am therefore excused from saving Universes.'" + +- Ford's last-ditch attempt to get out of helping Slartibartfast. +% +"Trillian did a little research in the ship's copy of THHGTTG. It had some advice to offer on drunkenness. `Go to it,' it said, `and good luck.' It was cross-referenced to the entry concerning the size of the Universe and ways of coping with that." + +- One of the more preferable pieces of advice contained in the Guide. +% +"His eyes seemed to be popping out of his head. He wasn't certain if this was because they were trying to see more clearly, or if they simply wanted to leave at this point."QUOTEHERESTRINGMAGIC1234- Arthur trying to see who had diverted him from going to a party. +% +"Arthur yawed wildly as his skin tried to jump one way and his skeleton the other, whilst his brain tried to work out which of his ears it most wanted to crawl out of. `Bet you weren't expecting to see me again,' said the monster, which Arthur couldn't help thinking was a strange remark for it to make, seeing as he had never met the creature before. He could tell that he hadn't met the creature before from the simple fact that he was able to sleep at nights."QUOTEHERESTRINGMAGIC1234- Arthur discovering who had diverted him from going to a party. +% +"`That young girl is one of the least benightedly unintelligent organic life forms it has been my profound lack of pleasure not to be able to avoid meeting.'"QUOTEHERESTRINGMAGIC1234- Marvin's first ever compliment about anybody. +% +"Arthur hoped and prayed that there wasn't an afterlife. Then he realised there was a contradiction there and merely hoped that there wasn't an afterlife."QUOTEHERESTRINGMAGIC1234- Arthur realising that he's in a certain death situation with a supernova bomb that is shaped like a cricket ball. +% +"`Credit?' he said. `Aaaargggh...' These two words are usually coupled together in the Old Pink Dog Bar."QUOTEHERESTRINGMAGIC1234- Ford in a spot of bother. +% +"`...we might as well start with where your hand is now.' Arthur said, `So which way do I go?' `Down,' said Fenchurch, `on this occasion.' He moved his hand. `Down,' she said, `is in fact the other way.' `Oh yes.'"QUOTEHERESTRINGMAGIC1234- Arthur trying to discover which part of Fenchurch is wrong. +% +"There was a point to this story, but it has temporarily escaped the chronicler's mind."QUOTEHERESTRINGMAGIC1234- This line perhaps best sums up the whole book. +% +"The last time anybody made a list of the top hundred character attributes of New Yorkers, common sense snuck in at number 79. .... When it's fall in New York, the air smells as if someone's been frying goats in it, and if you are keen to breathe the best plan is to open a window and stick your head in a building."QUOTEHERESTRINGMAGIC1234- Nuff said?? +% +"`What's been happening here?' he demanded. `Oh just the nicest things, sir, just the nicest things. can I sit on your lap please?'" "`Colin, I am going to abandon you to your fate.' `I'm so happy.'" "`It will be very, very nasty for you, and that's just too bad. Got it?' `I gurgle with pleasure.'"QUOTEHERESTRINGMAGIC1234- Ford and Colin the robot. +% +"What the hell, he thought, you're only young once, and threw himself out of the window. That would at least keep the element of surprise on his side."QUOTEHERESTRINGMAGIC1234- Ford outwitting a Vogon with a rocket launcher by going into another certain death situation. +% +"The major difference between a thing that might go wrong and a thing that cannot possibly go wrong is that when a thing that cannot possibly go wrong goes wrong it usually turns out to be impossible to get at or repair."QUOTEHERESTRINGMAGIC1234- One of the laws of computers and programming revealed. +% +"`You know they've reintroduced the death penalty for insurance company directors?' `Really?' said Arthur. `No I didn't. For what offence?' Trillian frowned. `What do you mean, offence?' `I see.'"QUOTEHERESTRINGMAGIC1234- Evidence that there will be some justice in the Universe eventually. +% +"`She hit me on the head with the rock again.' `I think I can confirm that that was my daughter.' `Sweet kid.' `You have to get to know her,' said Arthur. `She eases up does she?' `No,' said Arthur, `but you get a better sense of when to duck.'"QUOTEHERESTRINGMAGIC1234- Ford and Arthur on Random. +% +"Far out in the uncharted backwaters of the unfashionable end of the western spiral arm of the Galaxy lies a small unregarded yellow sun. " +% +"Ah, " said Arthur, "this is obviously some strange usage of the word safe that I wasn't previously aware of. " +% +"I don't know, " said the voice on the PA, "apathetic bloody planet, I've no sympathy at all. " +% +"Now it is such a bizarrely improbable coincidence that anything so mindboggingly useful could have evolved purely by chance that some thinkers have chosen to see it as the final and clinching proof of the non-existence of God. "The argument goes something like this: `I refuse to prove that I exist,' says God, `for proof denies faith, and without faith I am nothing.' "`But,' says Man, `The Babel fish is a dead giveaway, isn't it? It could not have evolved by chance. It proves you exist, and so therefore, by your own arguments, you don't. QED.' +% +"Prostetnic Vogon Jeltz smiled very slowly. This was done not so much for effect as because he was trying to remember the sequence of muscle movements. " +% +"OK, so ten out of ten for style, but minus several million for good thinking, yeah? " +% +"In those days spirits were brave, the stakes were high, men were real men, women were real women, and small furry creatures from Alpha Centauri were real small furry creatures from Alpha Centauri. " +% +"For a moment, nothing happened. Then, after a second or so, nothing continued to happen. " +% +(aikamuotojen k�ytt� aikamatkustuksessa) "You can arrive (mayan arivan on-when) for any sitting you like without prior (late fore-when) reservation because you can book retrospectively, as it were when you return to your own time. (you can have on-book haventa forewhen presooning returningwenta retrohome.) " +% +"The suit into which the man's body had been stuffed looked as if it's only purpose in life was to demonstrate how difficult it was to get this sort of body into a suit. " +% +"He dropped his voice still lower. In the stillness, a fly would not have dared clear its throat. " +% +"And finally, " said Max, quieting the audience down and putting on his solemn face, "finally I believe we have with us here tonight, a party of believers, very devout believers, from the Church of the Second Coming of the Great Prophet Zarquon. " ... "There they are, " said Max, "sitting there, patiently. He said he'd come again, and he's kept you waiting a long time, so let's hope he's hurrying fellas, because he's only got eight minutes left! " +% +"As he came into the light they could see his black and gold uniform on which the buttons were so highly polished that they shone with an intensity that would have made an approaching motorist flash his lights in annoyance. " +% +"You're very sure of your facts, " he said at last, "I couldn't trust the thinking of a man who takes the Universe - if there is one - for granted. " +% +"What are you talking about? " "Never mind, eat the fruit. " "You know, this place almost looks like the Garden of Eden. " "Eat the fruit. " "Sounds quite like it too. " +% +"Rome wasn't burned in a day. " +% +"Does it worry you that you don't talk any kind of sense? " +% +"One's never alone with a rubber duck. " +% +"Another world, another day, another dawn. " +% +"He expanded his chest to make it totally clear that here was the sort of man you only dared to cross if you had a team of Sherpas with you. " +% +"It was real. At least, if it wasn't real, it did support them, and as that is what sofas are supposed to do, this, by any test that mattered, was a real sofa. " +% +Arthur said, "So which way do I go? " "Down, " said Fenchurch, "on this occasion. " He moved his hand. "Down, " she said, "is in fact the other way. " "Oh yes. " +% +"You're one hundred percent positive that the ship which is crashed on the bottom of this ocean is the ship which you said you were one hundred percent positive could one hundred percent positively never crash? " +% +"Yes, it's the right planet, all right, " he said again. "Right planet, wrong universe. " +% +"Ford had his own code of ethics. It wasn't much of one, but it was his and he stuck by it, more or less. One rule he made was never to buy his own drinks. He wasn't sure if that counted as an ethic, but you have to go with what you've got. " +% +"Arthur felt at a bit of a loss. There was a whole Galaxy of stuff out there for him, and he wondered if it was churlish of him to complain to himself that it lacked just two things: the world he was born on and the woman he loved. " +% +"What was the self-sacrifice? " "I jettisoned half of a much loved and I think irreplaceable pair of shoes. " "Why was that self-sacrifice? " "Because they were mine! " said Ford crossly. "I think we have different value systems. " "Well mine's better. " "That's according to your... oh never mind. " diff --git a/plugins/hitchhiker/hitchhiker.plugin.zsh b/plugins/hitchhiker/hitchhiker.plugin.zsh new file mode 100644 index 000000000..aeafaf01e --- /dev/null +++ b/plugins/hitchhiker/hitchhiker.plugin.zsh @@ -0,0 +1,23 @@ +HITCHHIKER_DIR="${0:h}/fortunes" + +# Aliases +alias hitchhiker="fortune -a $HITCHHIKER_DIR" +alias hitchhiker_cow="hitchhiker | cowthink" + +() { + # Don't generate hitchhiker.dat if it exists and is up-to-date + if [[ -f "$HITCHHIKER_DIR/hitchhiker.dat" ]] && ! [[ "$HITCHHIKER_DIR/hitchhiker.dat" -ot "$HITCHHIKER_DIR/hitchhiker" ]]; then + return + fi + + # If strfile is not found: some systems install strfile in /usr/sbin but it's not in $PATH + if ! command -v strfile &>/dev/null && ! [[ -f /usr/sbin/strfile ]]; then + echo "[oh-my-zsh] hitchhiker depends on strfile, which is not installed" >&2 + echo "[oh-my-zsh] strfile is often provided as part of the 'fortune' package" >&2 + return + fi + + "${commands[strfile]:-/usr/sbin/strfile}" "$HITCHHIKER_DIR/hitchhiker" "$HITCHHIKER_DIR/hitchhiker.dat" >/dev/null +} + +unset HITCHHIKER_DIR diff --git a/plugins/jake-node/jake-node.plugin.zsh b/plugins/jake-node/jake-node.plugin.zsh index 3b692f899..c2dad28af 100644 --- a/plugins/jake-node/jake-node.plugin.zsh +++ b/plugins/jake-node/jake-node.plugin.zsh @@ -6,7 +6,7 @@ # Inspiration : https://weblog.rubyonrails.org/2006/3/9/fast-rake-task-completion-for-zsh function _jake () { - if [ -f Jakefile ]||[ -f jakefile ]; then + if [ -f Jakefile ] || [ -f jakefile ] || [ -f Jakefile.js ] || [ -f jakefile.js ]; then compadd `jake -T | cut -d " " -f 2 | sed -E "s/.\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"` fi } diff --git a/plugins/kubectl/README.md b/plugins/kubectl/README.md index 7a6cdaa59..8937b2b80 100644 --- a/plugins/kubectl/README.md +++ b/plugins/kubectl/README.md @@ -49,7 +49,7 @@ plugins=(... kubectl) | kdeli | `kubectl delete ingress` | Delete ingress resources matching passed argument | | | | **Namespace management** | | kgns | `kubectl get namespaces` | List the current namespaces in a cluster | -| kcn | `kubectl config set-context ...` | Change current namespace | +| kcn | `kubectl config set-context --current --namespace` | Change current namespace | | kens | `kubectl edit namespace` | Edit namespace resource from the default editor | | kdns | `kubectl describe namespace` | Describe namespace resource in detail | | kdelns | `kubectl delete namespace` | Delete the namespace. WARNING! This deletes everything in the namespace | diff --git a/plugins/kubectl/kubectl.plugin.zsh b/plugins/kubectl/kubectl.plugin.zsh index d509d8795..56135274f 100644 --- a/plugins/kubectl/kubectl.plugin.zsh +++ b/plugins/kubectl/kubectl.plugin.zsh @@ -71,7 +71,7 @@ alias kgns='kubectl get namespaces' alias kens='kubectl edit namespace' alias kdns='kubectl describe namespace' alias kdelns='kubectl delete namespace' -alias kcn='kubectl config set-context $(kubectl config current-context) --namespace' +alias kcn='kubectl config set-context --current --namespace' # ConfigMap management alias kgcm='kubectl get configmaps' diff --git a/plugins/last-working-dir/README.md b/plugins/last-working-dir/README.md index ced9e0370..b5cc55828 100644 --- a/plugins/last-working-dir/README.md +++ b/plugins/last-working-dir/README.md @@ -1,15 +1,33 @@ # last-working-dir plugin Keeps track of the last used working directory and automatically jumps into it -for new shells, unless: +for new shells, unless the starting directory is not `$HOME`. -- The plugin is already loaded. -- The current `$PWD` is not `$HOME`. - -Also adds `lwd` function to jump to the last working directory. +Also adds a `lwd` function to jump to the last working directory. To use it, add `last-working-dir` to the plugins array in your zshrc file: ```zsh plugins=(... last-working-dir) ``` + +## Features + +### Use separate last-working-dir files with different SSH keys + +If the same user account is used by multiple users connecting via different SSH keys, you can +configure SSH to map them to different `SSH_USER`s and the plugin will use separate lwd files +for each one. + +Make sure that your SSH server allows environment variables. You can enable this feature +within the `/etc/sshd/sshd_config` file: + +``` +PermitUserEnvironment yes +``` + +Then, add `environment="SSH_USER="` before the SSH keys in your `authorized_keys` file: + +``` +environment="SSH_USER=a.test@example.com" ssh-ed25519 AAAAC3Nz... +``` diff --git a/plugins/last-working-dir/last-working-dir.plugin.zsh b/plugins/last-working-dir/last-working-dir.plugin.zsh index fd21705ae..905a02a70 100644 --- a/plugins/last-working-dir/last-working-dir.plugin.zsh +++ b/plugins/last-working-dir/last-working-dir.plugin.zsh @@ -5,16 +5,18 @@ typeset -g ZSH_LAST_WORKING_DIRECTORY autoload -U add-zsh-hook add-zsh-hook chpwd chpwd_last_working_dir chpwd_last_working_dir() { - if [ "$ZSH_SUBSHELL" = 0 ]; then - local cache_file="$ZSH_CACHE_DIR/last-working-dir" - pwd >| "$cache_file" - fi + # Don't run in subshells + [[ "$ZSH_SUBSHELL" -eq 0 ]] || return 0 + # Add ".$SSH_USER" suffix to cache file if $SSH_USER is set and non-empty + local cache_file="$ZSH_CACHE_DIR/last-working-dir${SSH_USER:+.$SSH_USER}" + pwd >| "$cache_file" } # Changes directory to the last working directory lwd() { - local cache_file="$ZSH_CACHE_DIR/last-working-dir" - [[ -r "$cache_file" ]] && cd "$(cat "$cache_file")" + # Add ".$SSH_USER" suffix to cache file if $SSH_USER is set and non-empty + local cache_file="$ZSH_CACHE_DIR/last-working-dir${SSH_USER:+.$SSH_USER}" + [[ -r "$cache_file" ]] && cd "$(cat "$cache_file")" } # Jump to last directory automatically unless: diff --git a/plugins/macports/_port b/plugins/macports/_port index 6a9ebe0c6..897598a46 100644 --- a/plugins/macports/_port +++ b/plugins/macports/_port @@ -43,6 +43,7 @@ subcmds=( 'provides' 'rdependents' 'rdeps' +'reclaim' 'rpmpackage' 'search' 'selfupdate' diff --git a/plugins/magic-enter/magic-enter.plugin.zsh b/plugins/magic-enter/magic-enter.plugin.zsh index 2d4d578b6..55b893535 100644 --- a/plugins/magic-enter/magic-enter.plugin.zsh +++ b/plugins/magic-enter/magic-enter.plugin.zsh @@ -1,27 +1,38 @@ -# Bind quick stuff to enter! -# -# Pressing enter in a git directory runs `git status` -# in other directories `ls` -magic-enter () { - # If commands are not already set, use the defaults - [ -z "$MAGIC_ENTER_GIT_COMMAND" ] && MAGIC_ENTER_GIT_COMMAND="git status -u ." - [ -z "$MAGIC_ENTER_OTHER_COMMAND" ] && MAGIC_ENTER_OTHER_COMMAND="ls -lh ." +# Default commands +: ${MAGIC_ENTER_GIT_COMMAND:="git status -u ."} # run when in a git repository +: ${MAGIC_ENTER_OTHER_COMMAND:="ls -lh ."} # run anywhere else - if [[ -z $BUFFER ]]; then - echo "" - if git rev-parse --is-inside-work-tree &>/dev/null; then - eval "$MAGIC_ENTER_GIT_COMMAND" - else - eval "$MAGIC_ENTER_OTHER_COMMAND" - fi - zle redisplay +magic-enter() { + # Only run MAGIC_ENTER commands when in PS1 and command line is empty + # http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#User_002dDefined-Widgets + if [[ -n "$BUFFER" || "$CONTEXT" != start ]]; then + return + fi + + if command git rev-parse --is-inside-work-tree &>/dev/null; then + BUFFER="$MAGIC_ENTER_GIT_COMMAND" else - zle accept-line + BUFFER="$MAGIC_ENTER_OTHER_COMMAND" fi } -zle -N magic-enter +# Wrapper for the accept-line zle widget (run when pressing Enter) -bindkey -M emacs "^M" magic-enter -bindkey -M vicmd "^M" magic-enter -bindkey -M viins "^M" magic-enter +# If the wrapper already exists don't redefine it +(( ! ${+functions[_magic-enter_accept-line]} )) || return 0 + +case "$widgets[accept-line]" in + # Override the current accept-line widget, calling the old one + user:*) zle -N _magic-enter_orig_accept-line "${widgets[accept-line]#user:}" + function _magic-enter_accept-line() { + magic-enter + zle _magic-enter_orig_accept-line -- "$@" + } ;; + # If no user widget defined, call the original accept-line widget + builtin) function _magic-enter_accept-line() { + magic-enter + zle .accept-line + } ;; +esac + +zle -N accept-line _magic-enter_accept-line diff --git a/plugins/mongocli/README.md b/plugins/mongocli/README.md new file mode 100644 index 000000000..e245f2a4a --- /dev/null +++ b/plugins/mongocli/README.md @@ -0,0 +1,19 @@ +# mongocli plugin + +The plugin adds several aliases for common [mongocli](https://docs.mongodb.com/mongocli/stable/) commands. + +To use it, add `mongocli` to the plugins array of your zshrc file: + +```zsh +plugins=(... mongocli) +``` + +## Aliases + +| Alias | Command | Description | +|----------|-------------------------------------------------------------|--------------------------------------------------------| +| `ma` | `mongocli atlas` | Shortcut for mongocli Atlas commands. | +| `mcm` | `mongocli cloud-manager` | Shortcut for mongocli Cloud Manager commands. | +| `mom` | `mongocli ops-manager` | Shortcut for mongocli Cloud Manager commands. | +| `miam` | `mongocli iam` | Shortcut for mongocli IAM commands. | + diff --git a/plugins/mongocli/mongocli.plugin.zsh b/plugins/mongocli/mongocli.plugin.zsh new file mode 100644 index 000000000..0ca877e61 --- /dev/null +++ b/plugins/mongocli/mongocli.plugin.zsh @@ -0,0 +1,4 @@ +alias ma='mongocli atlas' +alias mcm='mongocli cloud-manager' +alias mom='mongocli ops-manager' +alias miam='mongocli iam' diff --git a/plugins/npm/README.md b/plugins/npm/README.md index 0b1a2280f..47d153619 100644 --- a/plugins/npm/README.md +++ b/plugins/npm/README.md @@ -15,8 +15,10 @@ plugins=(... npm) | `npmg` | `npm i -g` | Install dependencies globally | | `npmS` | `npm i -S` | Install and save to dependencies in your package.json | | `npmD` | `npm i -D` | Install and save to dev-dependencies in your package.json | +| `npmF` | `npm i -f` | Force install from remote registries ignoring local cache | | `npmE` | `PATH="$(npm bin)":"$PATH"` | Run command from node_modules folder based on current directory | | `npmO` | `npm outdated` | Check which npm modules are outdated | +| `npmU` | `npm update` | Update all the packages listed to the latest version | | `npmV` | `npm -v` | Check package versions | | `npmL` | `npm list` | List installed packages | | `npmL0` | `npm ls --depth=0` | List top-level installed packages | @@ -25,3 +27,5 @@ plugins=(... npm) | `npmR` | `npm run` | Run npm scripts | | `npmP` | `npm publish` | Run npm publish | | `npmI` | `npm init` | Run npm init | +| `npmi` | `npm info` | Run npm info | +| `npmSe` | `npm search` | Run npm search | diff --git a/plugins/npm/npm.plugin.zsh b/plugins/npm/npm.plugin.zsh index 87c68f3fb..f7d6d3939 100644 --- a/plugins/npm/npm.plugin.zsh +++ b/plugins/npm/npm.plugin.zsh @@ -27,6 +27,9 @@ alias npmS="npm i -S " # npmd is used by https://github.com/dominictarr/npmd alias npmD="npm i -D " +# Force npm to fetch remote resources even if a local copy exists on disk. +alias npmF='npm i -f' + # Execute command from node_modules folder based on current directory # i.e npmE gulp alias npmE='PATH="$(npm bin)":"$PATH"' @@ -34,6 +37,9 @@ alias npmE='PATH="$(npm bin)":"$PATH"' # Check which npm modules are outdated alias npmO="npm outdated" +# Update all the packages listed to the latest version +alias npmU="npm update" + # Check package versions alias npmV="npm -v" @@ -57,3 +63,9 @@ alias npmP="npm publish" # Run npm init alias npmI="npm init" + +# Run npm info +alias npmi="npm info" + +# Run npm search +alias npmSe="npm search" diff --git a/plugins/nvm/README.md b/plugins/nvm/README.md index 749a43403..700613085 100644 --- a/plugins/nvm/README.md +++ b/plugins/nvm/README.md @@ -11,9 +11,11 @@ plugins=(... nvm) ## Settings -- **`NVM_DIR`**: if you have installed nvm in a directory other than `$HOME/.nvm`, set and export `NVM_DIR` - to be the directory where you installed nvm. - +If you installed nvm in a directory other than `$HOME/.nvm`, set and export `NVM_DIR` to be the directory +where you installed nvm. + +These settings should go in your zshrc file, before Oh My Zsh is sourced: + - **`NVM_HOMEBREW`**: if you installed nvm via Homebrew, in a directory other than `/usr/local/opt/nvm`, you can set `NVM_HOMEBREW` to be the directory where you installed it. diff --git a/plugins/rails/README.md b/plugins/rails/README.md index 9fb1cecf1..efdb8f8ba 100644 --- a/plugins/rails/README.md +++ b/plugins/rails/README.md @@ -21,6 +21,8 @@ plugins=(... rails) | `rgen`| `rails generate` | Generate boilerplate code | | `rgm` | `rails generate migration` | Generate a db migration | | `rp` | `rails plugin` | Run a Rails plugin command | +| `rr` | `rails routes` | List all defined routes | +| `rrg` | `rails routes \| grep` | List and filter the defined routes | | `ru` | `rails runner` | Run Ruby code in the context of Rails | | `rs` | `rails server` | Launch a web server | | `rsd` | `rails server --debugger` | Launch a web server with debugger | @@ -43,8 +45,6 @@ plugins=(... rails) | `rdsl` | `rake db:schema:load` | Load the database schema | | `rlc` | `rake log:clear` | Clear Rails logs | | `rn` | `rake notes` | Search for notes (`FIXME`, `TODO`) in code comments | -| `rr` | `rake routes` | List all defined routes | -| `rrg` | `rake routes \| grep` | List and filter the defined routes | | `rt` | `rake test` | Run Rails tests | | `rmd` | `rake middleware` | Interact with Rails middlewares | | `rsts` | `rake stats` | Print code statistics | diff --git a/plugins/rails/rails.plugin.zsh b/plugins/rails/rails.plugin.zsh index 1fd5f0f86..5b0be4f85 100644 --- a/plugins/rails/rails.plugin.zsh +++ b/plugins/rails/rails.plugin.zsh @@ -46,6 +46,8 @@ alias rdb='rails dbconsole' alias rgen='rails generate' alias rgm='rails generate migration' alias rp='rails plugin' +alias rr='rails routes' +alias rrg='rails routes | grep' alias ru='rails runner' alias rs='rails server' alias rsd='rails server --debugger' @@ -65,8 +67,6 @@ alias rdmtc='rake db:migrate db:test:clone' alias rdsl='rake db:schema:load' alias rlc='rake log:clear' alias rn='rake notes' -alias rr='rake routes' -alias rrg='rake routes | grep' alias rt='rake test' alias rmd='rake middleware' alias rsts='rake stats' diff --git a/plugins/react-native/react-native.plugin.zsh b/plugins/react-native/react-native.plugin.zsh index b33dedfed..8323c27bd 100644 --- a/plugins/react-native/react-native.plugin.zsh +++ b/plugins/react-native/react-native.plugin.zsh @@ -27,6 +27,9 @@ alias rniosxr='react-native run-ios --simulator "iPhone Xʀ"' alias rnios11='react-native run-ios --simulator "iPhone 11"' alias rnios11p='react-native run-ios --simulator "iPhone 11 Pro"' alias rnios11pm='react-native run-ios --simulator "iPhone 11 Pro Max"' +alias rnios12='react-native run-ios --simulator "iPhone 12"' +alias rnios12p='react-native run-ios --simulator "iPhone 12 Pro"' +alias rnios12pm='react-native run-ios --simulator "iPhone 12 Pro Max"' # iPad diff --git a/plugins/screen/screen.plugin.zsh b/plugins/screen/screen.plugin.zsh index 7009e7a91..c1db8ad92 100644 --- a/plugins/screen/screen.plugin.zsh +++ b/plugins/screen/screen.plugin.zsh @@ -2,7 +2,7 @@ # of the tab window should be. if [[ "$TERM" == screen* ]]; then if [[ $_GET_PATH == '' ]]; then - _GET_PATH='echo $PWD | sed "s/^\/Users\//~/;s/^\/home\//~/;s/^~$USER/~/"' + _GET_PATH='echo $PWD | sed "s/^\/Users\//~/;s/^\/home\//~/;s/^~$USERNAME/~/"' fi if [[ $_GET_HOST == '' ]]; then _GET_HOST='echo $HOST | sed "s/\..*//"' @@ -51,4 +51,4 @@ if [[ "$TERM" == screen* ]]; then eval "tab_hardstatus=$TAB_HARDSTATUS_PREFIX:$TAB_HARDSTATUS_PROMPT" screen_set $tab_title $tab_hardstatus } -fi \ No newline at end of file +fi diff --git a/plugins/shell-proxy/proxy.py b/plugins/shell-proxy/proxy.py index 2b62f6cb5..97f4cf873 100755 --- a/plugins/shell-proxy/proxy.py +++ b/plugins/shell-proxy/proxy.py @@ -9,8 +9,9 @@ user_proxy = os.environ.get("CONFIG_PROXY", os.path.expandvars("$HOME/.config/pr def get_http_proxy(): - if "DEFAULT_PROXY" in os.environ: - return os.environ["DEFAULT_PROXY"] + default_proxy = os.environ.get("DEFAULT_PROXY") + if default_proxy: + return default_proxy if os.path.isfile(user_proxy): return check_output(user_proxy).decode("utf-8").strip() raise Exception("Not found, Proxy configuration") @@ -30,7 +31,7 @@ def merge(mapping: dict): class CommandSet: proxies = make_proxies(get_http_proxy()) aliases = { - _: "env NAME=%s %s" % (_, ssh_agent) + _: "env __SSH_PROGRAM_NAME__=%s %s" % (_, ssh_agent) for _ in ("ssh", "sftp", "scp", "slogin", "ssh-copy-id") } diff --git a/plugins/shell-proxy/shell-proxy.plugin.zsh b/plugins/shell-proxy/shell-proxy.plugin.zsh index fd0e2fe79..315ade665 100644 --- a/plugins/shell-proxy/shell-proxy.plugin.zsh +++ b/plugins/shell-proxy/shell-proxy.plugin.zsh @@ -4,7 +4,7 @@ __PROXY__="${0:A:h}/proxy.py" proxy() { - source <("$__PROXY__" "$1") + source <(env "DEFAULT_PROXY=$DEFAULT_PROXY" "$__PROXY__" "$1") } _proxy() { diff --git a/plugins/shell-proxy/ssh-agent.py b/plugins/shell-proxy/ssh-agent.py index 61cf84c0b..4ee24b755 100755 --- a/plugins/shell-proxy/ssh-agent.py +++ b/plugins/shell-proxy/ssh-agent.py @@ -6,7 +6,7 @@ import sys ssh_proxy = os.path.join(os.path.dirname(__file__), "ssh-proxy.py") argv = [ - os.environ.get("NAME", "ssh"), + os.environ.get("__SSH_PROGRAM_NAME__", "ssh"), "-o", "ProxyCommand={} %h %p".format(ssh_proxy), "-o", diff --git a/plugins/ssh-agent/README.md b/plugins/ssh-agent/README.md index 0b96d9bb5..8765a9c7e 100644 --- a/plugins/ssh-agent/README.md +++ b/plugins/ssh-agent/README.md @@ -9,7 +9,7 @@ To enable it, add `ssh-agent` to your plugins: plugins=(... ssh-agent) ``` -## Instructions +## Settings **IMPORTANT: put these settings _before_ the line that sources oh-my-zsh** @@ -19,12 +19,16 @@ To enable **agent forwarding support** add the following to your zshrc file: zstyle :omz:plugins:ssh-agent agent-forwarding on ``` +---- + To **load multiple identities** use the `identities` style, For example: ```zsh zstyle :omz:plugins:ssh-agent identities id_rsa id_rsa2 id_github ``` +---- + To **set the maximum lifetime of the identities**, use the `lifetime` style. The lifetime may be specified in seconds or as described in sshd_config(5) (see _TIME FORMATS_). If left unspecified, the default lifetime is forever. @@ -33,6 +37,24 @@ The lifetime may be specified in seconds or as described in sshd_config(5) zstyle :omz:plugins:ssh-agent lifetime 4h ``` +---- + +To **pass arguments to the `ssh-add` command** that adds the identities on startup, +use the `ssh-add-args` setting. You can pass multiple arguments separated by spaces: + +```zsh +zstyle :omz:plugins:ssh-agent ssh-add-args -K -c -a /run/user/1000/ssh-auth +``` + +These will then be passed the the `ssh-add` call as if written directly. The example +above will turn into: + +```zsh +ssh-add -K -c -a /run/user/1000/ssh-auth +``` + +For valid `ssh-add` arguments run `ssh-add --help` or `man ssh-add`. + ## Credits Based on code from Joseph M. Reagle: https://www.cygwin.com/ml/cygwin/2001-06/msg00537.html diff --git a/plugins/ssh-agent/ssh-agent.plugin.zsh b/plugins/ssh-agent/ssh-agent.plugin.zsh index 6ab041c21..d45406f63 100644 --- a/plugins/ssh-agent/ssh-agent.plugin.zsh +++ b/plugins/ssh-agent/ssh-agent.plugin.zsh @@ -48,7 +48,9 @@ function _add_identities() { fi done - [[ -n "$not_loaded" ]] && ssh-add ${^not_loaded} + local args + zstyle -a :omz:plugins:ssh-agent ssh-add-args args + [[ -n "$not_loaded" ]] && ssh-add "${args[@]}" ${^not_loaded} } # Get the filename to store/lookup the environment from @@ -59,11 +61,11 @@ zstyle -b :omz:plugins:ssh-agent agent-forwarding _agent_forwarding if [[ $_agent_forwarding == "yes" && -n "$SSH_AUTH_SOCK" ]]; then # Add a nifty symlink for screen/tmux if agent forwarding - [[ -L $SSH_AUTH_SOCK ]] || ln -sf "$SSH_AUTH_SOCK" /tmp/ssh-agent-$USER-screen + [[ -L $SSH_AUTH_SOCK ]] || ln -sf "$SSH_AUTH_SOCK" /tmp/ssh-agent-$USERNAME-screen elif [[ -f "$_ssh_env_cache" ]]; then # Source SSH settings, if applicable . $_ssh_env_cache > /dev/null - if [[ $USER == "root" ]]; then + if [[ $USERNAME == "root" ]]; then FILTER="ax" else FILTER="x" diff --git a/plugins/systemadmin/README.md b/plugins/systemadmin/README.md index 243db03f2..052fc6edc 100644 --- a/plugins/systemadmin/README.md +++ b/plugins/systemadmin/README.md @@ -10,17 +10,17 @@ plugins=(... systemadmin) ## Aliases -| Alias | Command | Description | -|---------|------------------------------------------------------------------------|--------------------------------------------------------------------| -| ping | `ping -c 5` | Sends only 5 ICMP Messages | -| clr | `clear; echo Currently logged in on $TTY, as $USER in directory $PWD.` | Clears the screen and prints the current user, TTY, and directory | -| path | `print -l $path` | Displays PATH with each entry on a separate line | -| mkdir | `mkdir -pv` | Automatically create parent directories and display verbose output | -| psmem | `ps -e -orss=,args= \| sort -b -k1 -nr` | Display the processes using the most memory | -| psmem10 | `ps -e -orss=,args= \| sort -b -k1 -nr \| head -10` | Display the top 10 processes using the most memory | -| pscpu | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr` | Display the top processes using the most CPU | -| pscpu10 | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr \| head -10` | Display the top 10 processes using the most CPU | -| hist10 | `print -l ${(o)history%% *} \| uniq -c \| sort -nr \| head -n 10` | Display the top 10 most used commands in the history | +| Alias | Command | Description | +|---------|----------------------------------------------------------------------------|--------------------------------------------------------------------| +| ping | `ping -c 5` | Sends only 5 ICMP Messages | +| clr | `clear; echo Currently logged in on $TTY, as $USERNAME in directory $PWD.` | Clears the screen and prints the current user, TTY, and directory | +| path | `print -l $path` | Displays PATH with each entry on a separate line | +| mkdir | `mkdir -pv` | Automatically create parent directories and display verbose output | +| psmem | `ps -e -orss=,args= \| sort -b -k1 -nr` | Display the processes using the most memory | +| psmem10 | `ps -e -orss=,args= \| sort -b -k1 -nr \| head -10` | Display the top 10 processes using the most memory | +| pscpu | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr` | Display the top processes using the most CPU | +| pscpu10 | `ps -e -o pcpu,cpu,nice,state,cputime,args \|sort -k1 -nr \| head -10` | Display the top 10 processes using the most CPU | +| hist10 | `print -l ${(o)history%% *} \| uniq -c \| sort -nr \| head -n 10` | Display the top 10 most used commands in the history | ## Functions diff --git a/plugins/systemadmin/systemadmin.plugin.zsh b/plugins/systemadmin/systemadmin.plugin.zsh index 03064c035..a77f0069b 100644 --- a/plugins/systemadmin/systemadmin.plugin.zsh +++ b/plugins/systemadmin/systemadmin.plugin.zsh @@ -21,7 +21,7 @@ function retlog() { } alias ping='ping -c 5' -alias clr='clear; echo Currently logged in on $TTY, as $USER in directory $PWD.' +alias clr='clear; echo Currently logged in on $TTY, as $USERNAME in directory $PWD.' alias path='print -l $path' alias mkdir='mkdir -pv' # get top process eating memory @@ -131,7 +131,8 @@ d0() { # gather external ip address geteip() { - curl -s -S https://icanhazip.com + curl -s -S -4 https://icanhazip.com + curl -s -S -6 https://icanhazip.com } # determine local IP address(es) diff --git a/plugins/term_tab/README b/plugins/term_tab/README new file mode 100644 index 000000000..316062e73 --- /dev/null +++ b/plugins/term_tab/README @@ -0,0 +1,16 @@ + +term_tab - 'cwd' for all open zsh sessions +****************************************** + +What it does: +************* +This plugin allows to complete the 'cwd' of other Zsh sessions. Sounds +complicated but is rather simple. E.g. if you have three zsh sessions open, in +each session you are in a different folder, you can hit Ctrl+v in one session +to show you the current working directory of the other open zsh sessions. + +How it works: +************* +* It uses 'pidof zsh' to determine all zsh PIDs +* It reads procfs to get the current working directory of this session +* Everything is fed into zsh's completion magic diff --git a/plugins/term_tab/term_tab.plugin.zsh b/plugins/term_tab/term_tab.plugin.zsh new file mode 100644 index 000000000..1b612df68 --- /dev/null +++ b/plugins/term_tab/term_tab.plugin.zsh @@ -0,0 +1,41 @@ +# Copyright (C) 2014 Julian Vetter +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +function _term_list(){ + local -a expl + local -au dirs + + PREFIX="$IPREFIX$PREFIX" + IPREFIX= + SUFFIX="$SUFFIX$ISUFFIX" + ISUFFIX= + + [[ -o magicequalsubst ]] && compset -P '*=' + + case $OSTYPE in + solaris*) dirs=( ${(M)${${(f)"$(pgrep -U $UID -x zsh|xargs pwdx)"}:#$$:*}%%/*} ) ;; + linux*) dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) ;; + esac + dirs=( ${(D)dirs} ) + + compstate[pattern_match]='*' + _wanted directories expl 'current directory from other shell' \ + compadd -Q -M "r:|/=* r:|=*" -f -a dirs +} + +zle -C term_list menu-complete _generic +bindkey "^v" term_list +zstyle ':completion:term_list::::' completer _term_list diff --git a/plugins/terraform/_terraform b/plugins/terraform/_terraform index e4298f2ab..a19e50670 100644 --- a/plugins/terraform/_terraform +++ b/plugins/terraform/_terraform @@ -6,14 +6,16 @@ _terraform_cmds=( 'console:Interactive console for Terraform interpolations' 'destroy:Destroy Terraform-managed infrastructure' 'fmt:Rewrites config files to canonical format' + 'force-unlock:Manually unlock the terraform state' 'get:Download and install modules for the configuration' 'graph:Create a visual graph of Terraform resources' 'import:Import existing infrastructure into Terraform' 'init:Initialize a Terraform working directory' + 'login:Obtain and save credentials for a remote host' + 'logout:Remove locally-stored credentials for a remote host' 'output:Read an output from a state file' 'plan:Generate and show an execution plan' 'providers:Prints a tree of the providers used in the configuration' - 'push:Upload this Terraform module to Atlas to run' 'refresh:Update local state file against real resources' 'show:Inspect Terraform state or plan' 'state:Advanced state management' @@ -23,6 +25,7 @@ _terraform_cmds=( 'version:Prints the Terraform version' 'workspace:Workspace management' '0.12upgrade:Rewrites pre-0.12 module source code for v0.12' + '0.13upgrade:Rewrites pre-0.13 module source code for v0.13' ) __012upgrade() { @@ -31,45 +34,51 @@ __012upgrade() { '-force[ Override the heuristic that attempts to detect if a configuration is already written for v0.12 or later. Some of the transformations made by this command are not idempotent, so re-running against the same module may change the meanings expressions in the module.]' } +__013upgrade() { + _arguments \ + '-yes[Skip the initial introduction messages and interactive confirmation. This can be used to run this command in batch from a script.]' +} + __apply() { _arguments \ - '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \ '-auto-approve[Skip interactive approval of plan before applying.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]:backupfile:_files -g "*.backup"' \ + '-compact-warnings[If Terraform produces any warnings that are not accompanied by errors, show them in a more compact form that includes only the summary messages.]' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ '-input=[(true) Ask for input for variables if not directly set.]' \ '-no-color[If specified, output wil be colorless.]' \ '-parallelism=[(10) Limit the number of parallel resource operations.]' \ '-refresh=[(true) Update state prior to checking for differences. This has no effect if a plan file is given to apply.]' \ - '-state=[(terraform.tfstate) Path to read and save state (unless state-out is specified).]' \ - '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]' \ - '-target=[(resource) Resource to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ - '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ - '-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]' + '-state=[(terraform.tfstate) Path to read and save state (unless state-out is specified).]:statefile:_files -g "*.tfstate"' \ + '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]:statefile:_files -g "*.tfstate"' \ + '*-target=[(resource) Resource to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ + '*-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ + '*-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]:file:_files -g "*.tfvars{,.json}"' } __console() { _arguments \ '-state=[(terraform.tfstate) Path to read state.]' \ - '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ - '-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]' + '*-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ + '*-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]:file:_files -g "*.tfvars{,.json}"' } __destroy() { _arguments \ - '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \ + '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]:backupfile:_files -g "*.backup"' \ '-auto-approve[Skip interactive approval before destroying.]' \ '-force[Deprecated: same as auto-approve.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ '-no-color[If specified, output will contain no color.]' \ '-parallelism=[(10) Limit the number of concurrent operations.]' \ '-refresh=[(true) Update state prior to checking for differences. This has no effect if a plan file is given to apply.]' \ - '-state=[(terraform.tfstate) Path to read and save state (unless state-out is specified).]' \ - '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]' \ - '-target=[(resource) Resource to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ - '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ - '-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]' + '-state=[(terraform.tfstate) Path to read and save state (unless state-out is specified).]:statefile:_files -g "*.tfstate"' \ + '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]:statefile:_files -g "*.tfstate"' \ + '*-target=[(resource) Resource to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ + '*-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ + '*-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]:file:_files -g "*.tfvars{,.json}"' } __fmt() { @@ -81,33 +90,36 @@ __fmt() { '-recursive=[(false) Also process files in subdirectories. By default, only the given directory (or current directory) is processed.]' } +__force_unlock() { + _arguments \ + "-force[Don't ask for input for unlock confirmation.]" +} + __get() { _arguments \ '-update=[(false) If true, modules already downloaded will be checked for updates and updated if necessary.]' \ - '-no-color[If specified, output will contain no color.]' + '-no-color[Disable text coloring in the output.]' } __graph() { _arguments \ '-draw-cycles[Highlight any cycles in the graph with colored edges. This helps when diagnosing cycle errors.]' \ - '-no-color[If specified, output will contain no color.]' \ '-type=[(plan) Type of graph to output. Can be: plan, plan-destroy, apply, validate, input, refresh.]' } __import() { _arguments \ - '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \ + '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]:backupfile:_files -g "*.backup"' \ '-config=[(path) Path to a directory of Terraform configuration files to use to configure the provider. Defaults to pwd. If no config files are present, they must be provided via the input prompts or env vars.]' \ '-allow-missing-config[Allow import when no resource configuration block exists.]' \ '-input=[(true) Ask for input for variables if not directly set.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ '-no-color[If specified, output will contain no color.]' \ - '-provider=[(provider) Specific provider to use for import. This is used for specifying aliases, such as "aws.eu". Defaults to the normal provider prefix of the resource being imported.]' \ - '-state=[(PATH) Path to the source state file. Defaults to the configured backend, or "terraform.tfstate"]' \ - '-state-out=[(PATH) Path to the destination state file to write to. If this is not specified, the source state file will be used. This can be a new or existing path.]' \ - '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times. This is only useful with the "-config" flag.]' \ - '-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]' + '-state=[(PATH) Path to the source state file. Defaults to the configured backend, or "terraform.tfstate"]:statefile:_files -g "*.tfstate"' \ + '-state-out=[(PATH) Path to the destination state file to write to. If this is not specified, the source state file will be used. This can be a new or existing path.]:statefile:_files -g "*.tfstate"' \ + '*-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times. This is only useful with the "-config" flag.]' \ + '*-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]:file:_files -g "*.tfvars{,.json}"' } __init() { @@ -115,80 +127,94 @@ __init() { '-backend=[(true) Configure the backend for this configuration.]' \ '-backend-config=[This can be either a path to an HCL file with key/value assignments (same format as terraform.tfvars) or a 'key=value' format. This is merged with what is in the configuration file. This can be specified multiple times. The backend type must be in the configuration itself.]' \ '-force-copy[Suppress prompts about copying state data. This is equivalent to providing a "yes" to all confirmation prompts.]' \ - '-from-module=[Copy the contents of the given module into the target directory before initialization.]' \ + '-from-module=[(SOURCE) Copy the contents of the given module into the target directory before initialization.]' \ '-get=[(true) Download any modules for this configuration.]' \ '-get-plugins=[(true) Download any missing plugins for this configuration.]' \ '-input=[(true) Ask for input if necessary. If false, will error if input was required.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ '-no-color[If specified, output will contain no color.]' \ - '-plugin-dir[Directory containing plugin binaries. This overrides all default search paths for plugins, and prevents the automatic installation of plugins. This flag can be used multiple times.]' \ + '-plugin-dir[Directory containing plugin binaries. This overrides all default search paths for plugins, and prevents the automatic installation of plugins. This flag can be used multiple times.]:plugin_dir:_files -/' \ '-reconfigure[Reconfigure the backend, ignoring any saved configuration.]' \ '-upgrade=[(false) If installing modules (-get) or plugins (-get-plugins), ignore previously-downloaded objects and install the latest version allowed within configured constraints.]' \ '-verify-plugins=[(true) Verify the authenticity and integrity of automatically downloaded plugins.]' } +__login() { + _arguments \ + +} + +__logout() { + _arguments \ + +} + __output() { _arguments \ - '-state=[(path) Path to the state file to read. Defaults to "terraform.tfstate".]' \ - '-no-color[ If specified, output will contain no color.]' \ - '-module=[(name) If specified, returns the outputs for a specific module]' \ + '-state=[(path) Path to the state file to read. Defaults to "terraform.tfstate".]:statefile:_files -g "*.tfstate"' \ + '-no-color[If specified, output will contain no color.]' \ '-json[If specified, machine readable output will be printed in JSON format]' } __plan() { _arguments \ - '-destroy[() If set, a plan will be generated to destroy all resources managed by the given configuration and state.]' \ + '-compact-warnings[If Terraform produces any warnings that are not accompanied by errors, show them in a more compact form that includes only the summary messages.]' \ + '-destroy[If set, a plan will be generated to destroy all resources managed by the given configuration and state.]' \ '-detailed-exitcode[() Return detailed exit codes when the command exits. This will change the meaning of exit codes to: 0 - Succeeded, diff is empty (no changes); 1 - Errored, 2 - Succeeded; there is a diff]' \ '-input=[(true) Ask for input for variables if not directly set.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ - '-module-depth=[(n) Specifies the depth of modules to show in the output. This does not affect the plan itself, only the output shown. By default, this is -1, which will expand all.]' \ '-no-color[() If specified, output will contain no color.]' \ '-out=[(path) Write a plan file to the given path. This can be used as input to the "apply" command.]' \ '-parallelism=[(10) Limit the number of concurrent operations.]' \ '-refresh=[(true) Update state prior to checking for differences.]' \ - '-state=[(statefile) Path to a Terraform state file to use to look up Terraform-managed resources. By default it will use the state "terraform.tfstate" if it exists.]' \ - '-target=[(resource) Resource to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ - '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ - '-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]' \ + '-state=[(statefile) Path to a Terraform state file to use to look up Terraform-managed resources. By default it will use the state "terraform.tfstate" if it exists.]:statefile:_files -g "*.tfstate"' \ + '*-target=[(resource) Resource to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ + '*-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ + '*-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]:file:_files -g "*.tfvars{,.json}"' } __providers() { - _arguments \ + local -a __providers_cmds + __providers_cmds=( + 'mirror:Mirrors the provider plugins needed for the current configuration' + 'schema:Prints the schemas of the providers used in the configuration' + ) + _describe -t providers "providers commands" __providers_cmds } -__push() { +__providers_mirror() { _arguments \ - '-atlas-address=[(url) An alternate address to an Atlas instance. Defaults to https://atlas.hashicorp.com.]' \ - '-upload-modules=[(true) If true (default), then the modules being used are all locked at their current checkout and uploaded completely to Atlas. This prevents Atlas from running terraform get for you.]' \ - '-name=[(name) Name of the infrastructure configuration in Atlas. The format of this is: "username/name" so that you can upload configurations not just to your account but to other accounts and organizations. This setting can also be set in the configuration in the Atlas section.]' \ - '-no-color[Disables output with coloring]' \ - '-overwrite=[(foo) Marks a specific variable to be updated on Atlas. Normally, if a variable is already set in Atlas, Terraform will not send the local value (even if it is different). This forces it to send the local value to Atlas. This flag can be repeated multiple times.]' \ - '-token=[(token) Atlas API token to use to authorize the upload. If blank or unspecified, the ATLAS_TOKEN environmental variable will be used.]' \ - '-var=[("foo=bar") Set the value of a variable for the Terraform configuration.]' \ - '-var-file=[(foo) Set the value of variables using a variable file.]' \ - '-vcs=[(true) If true (default), then Terraform will detect if a VCS is in use, such as Git, and will only upload files that are committed to version control. If no version control system is detected, Terraform will upload all files in path (parameter to the command).]' + '-platform=[(os_arch) Choose which target platform to build a mirror for.]' \ + "*:target_dir:_files -/" +} + +__providers_schema() { + _arguments \ + '-json[]' \ + '::' } __refresh() { _arguments \ - '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \ + '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]::backupfile:_files -g "*.backup"' \ + '-compact-warnings[If Terraform produces any warnings that are not accompanied by errors, show them in a more compact form that includes only the summary messages.]' \ '-input=[(true) Ask for input for variables if not directly set.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ '-no-color[If specified, output will not contain any color.]' \ - '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]' \ - '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]' \ - '-target=[(resource) A Resource Address to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ - '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ - '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]' + '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]:statefile:_files -g "*.tfstate"' \ + '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]:statefile:_files -g "*.tfstate"' \ + '*-target=[(resource) A Resource Address to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]:target:__statelist' \ + '*-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ + '*-var-file=[(foo) Set variables in the Terraform configuration from a file. If "terraform.tfvars" or any ".auto.tfvars" files are present, they will be automatically loaded.]:file:_files -g "*.tfvars{,.json}"' } __show() { _arguments \ - '-module-depth=[(n) The maximum depth to expand modules. By default this is zero, which will not expand modules at all.]' \ + '-json[If specified, output the Terraform plan or state in a machine-readable form.]' \ '-no-color[If specified, output will not contain any color.]' } @@ -199,6 +225,7 @@ __state() { 'mv:Move an item in the state' 'pull:Pull current state and output to stdout' 'push:Update remote state from a local state file' + 'replace-provider:Replace provider for resources in the Terraform state' 'rm:Remove instances from the state' 'show:Show a resource in the state' ) @@ -207,7 +234,7 @@ __state() { __state_list() { _arguments \ - '-state=[(path) Path to a Terraform state file to use to look up Terraform-managed resources. By default it will use the state "terraform.tfstate" if it exists.]' \ + '-state=[(statefile) Path to a Terraform state file to use to look up Terraform-managed resources. By default, Terraform will consult the state of the currently-selected workspace.]' \ '-id=[(id) Filters the results to include only instances whose resource types have an attribute named id whose value equals the given id string.]' \ "*:address:__statelist" } @@ -215,12 +242,12 @@ __state_list() { __state_mv() { _arguments \ "-dry-run[If set, prints out what would've been moved but doesn't actually move anything.]" \ - "-backup=[(path) Path where Terraform should write the backup for the original state. This can't be disabled. If not set, Terraform will write it to the same path as the statefile with a \".backup\" extension.]:file:_files" \ - "-backup-out=[(path) Path where Terraform should write the backup for the destination state. This can't be disabled. If not set, Terraform will write it to the same path as the destination state file with a backup extension. This only needs to be specified if -state-out is set to a different path than -state.]:file:_files" \ - "-lock=[(true|false) Lock the state files when locking is supported.]:lock:(true false)" \ - "-lock-timeout=[(seconds) Duration to retry a state lock.]" \ - '-state=[(path) Path to the source state file. Defaults to the configured backend, or "terraform.tfstate"]:file:_files' \ - "-state-out=[(path) Path to the destination state file to write to. If this isn't specified, the source state file will be used. This can be a new or existing path.]:file:_files" \ + '-backup=[(PATH) Path where Terraform should write the backup for the original state. This can"t be disabled. If not set, Terraform will write it to the same path as the statefile with a ".backup" extension.]:backupfile:_files -g "*.backup"' \ + '-backup-out=[(PATH) Path where Terraform should write the backup for the destination state. This can"t be disabled. If not set, Terraform will write it to the same path as the destination state file with a backup extension. This only needs to be specified if -state-out is set to a different path than -state.]:backupfile:_files -g "*.backup"' \ + "-lock=[(true) Lock the state files when locking is supported.]:lock:(true false)" \ + "-lock-timeout=[(0s) Duration to retry a state lock.]" \ + '-state=[(path) Path to the source state file. Defaults to the configured backend, or "terraform.tfstate"]:statefile:_files -g "*.tfstate"' \ + '-state-out=[(path) Path to the destination state file to write to. If this isn"t specified, the source state file will be used. This can be a new or existing path.]:statefile:_files -g "*.tfstate"' \ "::" \ ":source:__statelist" \ ":destination: " @@ -229,26 +256,37 @@ __state_mv() { __state_push() { _arguments \ "-force[Write the state even if lineages don't match or the remote serial is higher.]" \ - '-lock=[(true|false) Lock the state file when locking is supported.]:lock:(true false)' \ - "-lock-timeout=[(seconds) Duration to retry a state lock.]" \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ + "-lock-timeout=[(0s) Duration to retry a state lock.]" \ "::" \ ":destination:_files" } +__state_replace_provider() { + _arguments \ + '-auto-approve[Skip interactive approval.]' \ + '-backup=[(PATH) Path where Terraform should write the backup for the state file. This can"t be disabled. If not set, Terraform will write it to the same path as the state file with a ".backup" extension.]:backupfile:_files -g "*.backup"' \ + "-lock=[(true) Lock the state files when locking is supported.]:lock:(true false)" \ + "-lock-timeout=[(0s) Duration to retry a state lock.]" \ + '-state=[(PATH) Path to the source state file. Defaults to the configured backend, or "terraform.tfstate"]:statefile:_files -g "*.tfstate"' \ + ":from_provider_fqn:" \ + ":to_provider_fqn:" +} + __state_rm() { _arguments \ "-dry-run[If set, prints out what would've been removed but doesn't actually remove anything.]" \ - "-backup=[(path) Path where Terraform should write the backup for the original state.]:file:_files" \ - "-lock=[(true|false) Lock the state files when locking is supported.]:lock:(true false)" \ - "-lock-timeout=[(seconds) Duration to retry a state lock.]" \ - '-state=[(path) Path to the state file to update. Defaults to the current workspace state.]:file:_files' \ + '-backup=[(PATH) Path where Terraform should write the backup for the original state.]::backupfile:_files -g "*.backup"' \ + "-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)" \ + "-lock-timeout=[(0s) Duration to retry a state lock.]" \ + '-state=[(PATH) Path to the state file to update. Defaults to the current workspace state.]:statefile:_files -g "*.tfstate"' \ "*:address:__statelist" } __state_show() { _arguments \ - '-state=[(path) Path to a Terraform state file to use to look up Terraform-managed resources. By default it will use the state "terraform.tfstate" if it exists.]' \ + '-state=[(statefile) Path to a Terraform state file to use to look up Terraform-managed resources. By default it will use the state "terraform.tfstate" if it exists.]:statefile:_files -g "*.tfstate"' \ "*:address:__statelist" } @@ -259,34 +297,36 @@ __statelist() { __taint() { _arguments \ '-allow-missing[If specified, the command will succeed (exit code 0) even if the resource is missing.]' \ - '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]:backupfile:_files -g "*.backup"' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ '-module=[(path) The module path where the resource lives. By default this will be root. Child modules can be specified by names. Ex. "consul" or "consul.vpc" (nested modules).]' \ - '-no-color[If specified, output will not contain any color.]' \ - '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]' \ - '-state-out=[(path) Path to write updated state file. By default, the "-state" path will be used.]' \ + '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]:statefile:_files -g "*.tfstate"' \ + '-state-out=[(path) Path to write updated state file. By default, the "-state" path will be used.]:statefile:_files -g "*.tfstate"' \ "*:address:__statelist" } __untaint() { _arguments \ '-allow-missing[If specified, the command will succeed (exit code 0) even if the resource is missing.]' \ - '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \ - '-lock=[(true) Lock the state file when locking is supported.]' \ + '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]:backupfile:_files -g "*.backup"' \ + '-lock=[(true) Lock the state file when locking is supported.]:lock:(true false)' \ '-lock-timeout=[(0s) Duration to retry a state lock.]' \ '-module=[(path) The module path where the resource lives. By default this will be root. Child modules can be specified by names. Ex. "consul" or "consul.vpc" (nested modules).]' \ - '-no-color[If specified, output will not contain any color.]' \ - '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]' \ - '-state-out=[(path) Path to write updated state file. By default, the "-state" path will be used.]' + '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]:statefile:_files -g "*.tfstate"' \ + '-state-out=[(path) Path to write updated state file. By default, the "-state" path will be used.]:statefile:_files -g "*.tfstate"' } __validate() { _arguments \ - '-check-variables=[(true) If set to true (default), the command will check whether all required variables have been specified.]' \ '-no-color[If specified, output will not contain any color.]' \ - '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \ - '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]' + '-json[Produce output in a machine-readable JSON format, suitable for use in text editor integrations and other automated systems.]' \ + ':dir:_files -/' +} + +__version() { + _arguments \ + '-json[Output the version information as a JSON object.]' } __workspace() { @@ -312,6 +352,8 @@ local -a _command_args case "$words[1]" in 0.12upgrade) __012upgrade ;; + 0.13upgrade) + __013upgrade ;; apply) __apply ;; console) @@ -320,6 +362,8 @@ case "$words[1]" in __destroy ;; fmt) __fmt;; + force-unlock) + __force_unlock;; get) __get ;; graph) @@ -328,14 +372,19 @@ case "$words[1]" in __import;; init) __init ;; + login) + __login ;; + logout) + __logout ;; output) __output ;; plan) __plan ;; providers) - __providers ;; - push) - __push ;; + test $CURRENT -lt 3 && __providers + [[ $words[2] = "mirror" ]] && __providers_mirror + [[ $words[2] = "schema" ]] && __providers_schema + ;; refresh) __refresh ;; show) @@ -345,6 +394,7 @@ case "$words[1]" in [[ $words[2] = "list" ]] && __state_list [[ $words[2] = "mv" ]] && __state_mv [[ $words[2] = "push" ]] && __state_push + [[ $words[2] = "replace-provider" ]] && __state_replace_provider [[ $words[2] = "rm" ]] && __state_rm [[ $words[2] = "show" ]] && __state_show ;; @@ -354,6 +404,8 @@ case "$words[1]" in __untaint ;; validate) __validate ;; + version) + __version ;; workspace) test $CURRENT -lt 3 && __workspace ;; esac diff --git a/plugins/terraform/terraform.plugin.zsh b/plugins/terraform/terraform.plugin.zsh index 2c42d394d..997241c9a 100644 --- a/plugins/terraform/terraform.plugin.zsh +++ b/plugins/terraform/terraform.plugin.zsh @@ -2,8 +2,8 @@ function tf_prompt_info() { # dont show 'default' workspace in home dir [[ "$PWD" == ~ ]] && return # check if in terraform dir - if [ -d .terraform ]; then - workspace=$(terraform workspace show 2> /dev/null) || return + if [[ -d .terraform && -r .terraform/environment ]]; then + workspace=$(cat .terraform/environment) || return echo "[${workspace}]" fi } diff --git a/plugins/universalarchive/README.md b/plugins/universalarchive/README.md new file mode 100644 index 000000000..93a1bd9fc --- /dev/null +++ b/plugins/universalarchive/README.md @@ -0,0 +1,46 @@ +# universalarchive plugin + +Lets you compress files by a command `ua `, supporting various +compression formats (e.g. 7z, tar.gz, lzma, ...). + +To enable it, add `universalarchive` to the plugins array in your zshrc file: + +```zsh +plugins=(... universalarchive) +``` + +## Usage + +Run `ua ` to compress `` into an archive file using ``. +For example: + +```sh +ua xz *.html +``` + +this command will compress all `.html` files in directory `folder` into `folder.xz`. + +This plugin saves you from having to remember which command line arguments compress a file. + +## Supported compression formats + +| 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 | + +See [list of archive formats](https://en.wikipedia.org/wiki/List_of_archive_formats) for more information regarding the archive formats. diff --git a/plugins/universalarchive/_universalarchive b/plugins/universalarchive/_universalarchive new file mode 100644 index 000000000..17cfd782e --- /dev/null +++ b/plugins/universalarchive/_universalarchive @@ -0,0 +1,6 @@ +#compdef ua + +_arguments \ + "1:archive format:(7z bz2 gz lzma lzo rar tar tar.bz2 tar.gz tar.lzma tar.xz tar.Z tbz tgz tlz txz tZ xz Z zip zst)" \ + "*:input files:_files" \ +&& return 0 diff --git a/plugins/universalarchive/universalarchive.plugin.zsh b/plugins/universalarchive/universalarchive.plugin.zsh new file mode 100644 index 000000000..b287c22b2 --- /dev/null +++ b/plugins/universalarchive/universalarchive.plugin.zsh @@ -0,0 +1,70 @@ +function ua() { + local usage=\ +"Archive files and directories using a given compression algorithm. + +Usage: $0 +Example: $0 tbz PKGBUILD + +Supported archive formats are: +7z, bz2, gz, lzma, lzo, rar, tar, tbz (tar.bz2), tgz (tar.gz), +tlz (tar.lzma), txz (tar.xz), tZ (tar.Z), xz, Z, zip, and zst." + + if [[ $# -lt 2 ]]; then + print -u2 -- "$usage" + return 1 + fi + + local ext="$1" + local input="${2:a}" + + shift + + if [[ ! -e "$input" ]]; then + print -u2 -- "$input not found" + return 1 + fi + + # generate output file name + local output + if [[ $# -gt 1 ]]; then + output="${input:h:t}" + elif [[ -f "$input" ]]; then + output="${input:r:t}" + elif [[ -d "$input" ]]; then + output="${input:t}" + fi + + # if output file exists, generate a random name + if [[ -f "${output}.${ext}" ]]; then + output=$(mktemp "${output}_XXX") && rm "$output" || return 1 + fi + + # add extension + output="${output}.${ext}" + + # safety check + if [[ -f "$output" ]]; then + print -u2 -- "output file '$output' already exists. Aborting" + return 1 + fi + + case "$ext" in + 7z) 7z u "${output}" "${@}" ;; + bz2) bzip2 -vcf "${@}" > "${output}" ;; + gz) gzip -vcf "${@}" > "${output}" ;; + lzma) lzma -vc -T0 "${@}" > "${output}" ;; + lzo) lzop -vc "${@}" > "${output}" ;; + rar) rar a "${output}" "${@}" ;; + tar) tar -cvf "${output}" "${@}" ;; + tbz|tar.bz2) tar -cvjf "${output}" "${@}" ;; + tgz|tar.gz) tar -cvzf "${output}" "${@}" ;; + tlz|tar.lzma) XZ_OPT=-T0 tar --lzma -cvf "${output}" "${@}" ;; + txz|tar.xz) XZ_OPT=-T0 tar -cvJf "${output}" "${@}" ;; + tZ|tar.Z) tar -cvZf "${output}" "${@}" ;; + xz) xz -vc -T0 "${@}" > "${output}" ;; + Z) compress -vcf "${@}" > "${output}" ;; + zip) zip -rull "${output}" "${@}" ;; + zst) zstd -c -T0 "${@}" > "${output}" ;; + *) print -u2 -- "$usage"; return 1 ;; + esac +} diff --git a/plugins/vi-mode/README.md b/plugins/vi-mode/README.md index 8519a5592..b59d5f279 100644 --- a/plugins/vi-mode/README.md +++ b/plugins/vi-mode/README.md @@ -1,34 +1,72 @@ -vi-mode -======= +# vi-mode plugin + This plugin increase `vi-like` zsh functionality. +To use it, add `vi-mode` to the plugins array in your zshrc file: + +```zsh +plugins=(... vi-mode) +``` + +## Settings + +- `VI_MODE_RESET_PROMPT_ON_MODE_CHANGE`: controls whether the prompt is redrawn when + switching to a different input mode. If this is unset, the mode indicator will not + be updated when changing to a different mode. + Set it to `true` to enable it. For example: + + ```zsh + VI_MODE_RESET_PROMPT_ON_MODE_CHANGE=true + ``` + + The default value is unset, unless `vi_mode_prompt_info` is used, in which case it'll + automatically be set to `true`. + +- `VI_MODE_SET_CURSOR`: controls whether the cursor style is changed when switching + to a different input mode. Set it to `true` to enable it (default: unset): + + ```zsh + VI_MODE_SET_CURSOR=true + ``` + +- `MODE_INDICATOR`: controls the string displayed when the shell is in normal mode. + See [Mode indicator](#mode-indicator) for details. + +## Mode indicator + +*Normal mode* is indicated with a red `<<<` mark at the right prompt, when it +hasn't been defined by theme. + +You can change this indicator by setting the `MODE_INDICATOR` variable. This setting +supports Prompt Expansion sequences. For example: + +```zsh +MODE_INDICATOR="%F{yellow}+%f" +``` + +You can also use the `vi_mode_prompt_info` function in your prompt, which will display +this mode indicator. + +## Key bindings + Use `ESC` or `CTRL-[` to enter `Normal mode`. +NOTE: some of these key bindings are set by zsh by default when using a vi-mode keymap. -History -------- +### History - `ctrl-p` : Previous command in history - `ctrl-n` : Next command in history - `/` : Search backward in history - `n` : Repeat the last `/` +### Vim edition -Mode indicators ---------------- +- `vv` : Edit current command line in Vim -*Normal mode* is indicated with red `<<<` mark at the right prompt, when it -wasn't defined by theme. +NOTE: this used to be bound to `v`. That is now the default (`visual-mode`) - -Vim edition ------------ - -- `v` : Edit current command line in Vim - - -Movement --------- +### Movement - `$` : To the end of the line - `^` : To the first non-blank character of the line @@ -46,9 +84,7 @@ Movement - `;` : Repeat latest f, t, F or T [count] times - `,` : Repeat latest f, t, F or T in opposite direction - -Insertion ---------- +### Insertion - `i` : Insert text before the cursor - `I` : Insert text before the first character in the line @@ -57,9 +93,7 @@ Insertion - `o` : Insert new command line below the current one - `O` : Insert new command line above the current one - -Delete and Insert ------------------ +### Delete and Insert - `ctrl-h` : While in *Insert mode*: delete character before the cursor - `ctrl-w` : While in *Insert mode*: delete word before the cursor @@ -71,5 +105,5 @@ Delete and Insert - `C` : Delete to the end of the line and start insert - `r{char}` : Replace the character under the cursor with {char} - `R` : Enter replace mode: Each character replaces existing one -- `x` : Delete [count] characters under and after the cursor -- `X` : Delete [count] characters before the cursor +- `x` : Delete `count` characters under and after the cursor +- `X` : Delete `count` characters before the cursor diff --git a/plugins/vi-mode/vi-mode.plugin.zsh b/plugins/vi-mode/vi-mode.plugin.zsh index c91ba05ba..dd4afdd8b 100644 --- a/plugins/vi-mode/vi-mode.plugin.zsh +++ b/plugins/vi-mode/vi-mode.plugin.zsh @@ -1,32 +1,77 @@ +# Control whether to force a redraw on each mode change. +# +# Resetting the prompt on every mode change can cause lag when switching modes. +# This is especially true if the prompt does things like checking git status. +# +# Set to "true" to force the prompt to reset on each mode change. +# Unset or set to any other value to do the opposite. +# +# The default is not to reset, unless we're showing the mode in RPS1. +typeset -g VI_MODE_RESET_PROMPT_ON_MODE_CHANGE +# Control whether to change the cursor style on mode change. +# +# Set to "true" to change the cursor on each mode change. +# Unset or set to any other value to do the opposite. +typeset -g VI_MODE_SET_CURSOR + +typeset -g VI_KEYMAP=main + +function _vi-mode-set-cursor-shape-for-keymap() { + [[ "$VI_MODE_SET_CURSOR" = true ]] || return + + # https://vt100.net/docs/vt510-rm/DECSCUSR + local _shape=0 + case "${1:-${VI_KEYMAP:-main}}" in + main) _shape=6 ;; # vi insert: line + viins) _shape=6 ;; # vi insert: line + isearch) _shape=6 ;; # inc search: line + command) _shape=6 ;; # read a command name + vicmd) _shape=2 ;; # vi cmd: block + visual) _shape=2 ;; # vi visual mode: block + viopp) _shape=0 ;; # vi operation pending: blinking block + *) _shape=0 ;; + esac + printf $'\e[%d q' "${_shape}" +} + # Updates editor information when the keymap changes. function zle-keymap-select() { # update keymap variable for the prompt - VI_KEYMAP=$KEYMAP + typeset -g VI_KEYMAP=$KEYMAP - zle reset-prompt - zle -R + if [[ "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:-}" = true ]]; then + zle reset-prompt + zle -R + fi + _vi-mode-set-cursor-shape-for-keymap "${VI_KEYMAP}" } - zle -N zle-keymap-select -function vi-accept-line() { - VI_KEYMAP=main - zle accept-line +# These "echoti" statements were originally set in lib/key-bindings.zsh +# Not sure the best way to extend without overriding. +function zle-line-init() { + local prev_vi_keymap + prev_vi_keymap="${VI_KEYMAP:-}" + typeset -g VI_KEYMAP=main + [[ "$prev_vi_keymap" != 'main' ]] && [[ "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:-}" = true ]] && zle reset-prompt + (( ! ${+terminfo[smkx]} )) || echoti smkx + _vi-mode-set-cursor-shape-for-keymap "${VI_KEYMAP}" } +zle -N zle-line-init -zle -N vi-accept-line - +function zle-line-finish() { + typeset -g VI_KEYMAP=main + (( ! ${+terminfo[rmkx]} )) || echoti rmkx + _vi-mode-set-cursor-shape-for-keymap default +} +zle -N zle-line-finish bindkey -v -# use custom accept-line widget to update $VI_KEYMAP -bindkey -M vicmd '^J' vi-accept-line -bindkey -M vicmd '^M' vi-accept-line - -# allow v to edit the command line (standard behaviour) +# allow vv to edit the command line (standard behaviour) autoload -Uz edit-command-line zle -N edit-command-line -bindkey -M vicmd 'v' edit-command-line +bindkey -M vicmd 'vv' edit-command-line # allow ctrl-p, ctrl-n for navigate history (standard behaviour) bindkey '^P' up-history @@ -45,16 +90,56 @@ bindkey '^s' history-incremental-search-forward bindkey '^a' beginning-of-line bindkey '^e' end-of-line +function wrap_clipboard_widgets() { + # NB: Assume we are the first wrapper and that we only wrap native widgets + # See zsh-autosuggestions.zsh for a more generic and more robust wrapper + local verb="$1" + shift + + local widget + local wrapped_name + for widget in "$@"; do + wrapped_name="_zsh-vi-${verb}-${widget}" + if [ "${verb}" = copy ]; then + eval " + function ${wrapped_name}() { + zle .${widget} + printf %s \"\${CUTBUFFER}\" | clipcopy 2>/dev/null || true + } + " + else + eval " + function ${wrapped_name}() { + CUTBUFFER=\"\$(clippaste 2>/dev/null || echo \$CUTBUFFER)\" + zle .${widget} + } + " + fi + zle -N "${widget}" "${wrapped_name}" + done +} + +wrap_clipboard_widgets copy vi-yank vi-yank-eol vi-backward-kill-word vi-change-whole-line vi-delete +wrap_clipboard_widgets paste vi-put-{before,after} +unfunction wrap_clipboard_widgets + # if mode indicator wasn't setup by theme, define default -if [[ "$MODE_INDICATOR" == "" ]]; then - MODE_INDICATOR="%{$fg_bold[red]%}<%{$fg[red]%}<<%{$reset_color%}" +if [[ -z "$MODE_INDICATOR" ]]; then + MODE_INDICATOR='%B%F{red}<%b<<%f' fi function vi_mode_prompt_info() { + # If we're using the prompt to display mode info, and we haven't explicitly + # disabled "reset prompt on mode change", then set it here. + # + # We do that here instead of the `if` statement below because the user may + # set RPS1/RPROMPT to something else in their custom config. + : "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:=true}" + echo "${${VI_KEYMAP/vicmd/$MODE_INDICATOR}/(main|viins)/}" } # define right prompt, if it wasn't defined by a theme -if [[ "$RPS1" == "" && "$RPROMPT" == "" ]]; then +if [[ -z "$RPS1" && -z "$RPROMPT" ]]; then RPS1='$(vi_mode_prompt_info)' fi diff --git a/plugins/virtualenv/virtualenv.plugin.zsh b/plugins/virtualenv/virtualenv.plugin.zsh index e250eb63e..3041475ed 100644 --- a/plugins/virtualenv/virtualenv.plugin.zsh +++ b/plugins/virtualenv/virtualenv.plugin.zsh @@ -1,6 +1,6 @@ function virtualenv_prompt_info(){ [[ -n ${VIRTUAL_ENV} ]] || return - echo "${ZSH_THEME_VIRTUALENV_PREFIX:=[}${VIRTUAL_ENV:t}${ZSH_THEME_VIRTUALENV_SUFFIX:=]}" + echo "${ZSH_THEME_VIRTUALENV_PREFIX=[}${VIRTUAL_ENV:t}${ZSH_THEME_VIRTUALENV_SUFFIX=]}" } # disables prompt mangling in virtual_env/bin/activate diff --git a/plugins/wp-cli/README.md b/plugins/wp-cli/README.md index 43c41eb53..c4993ab4c 100644 --- a/plugins/wp-cli/README.md +++ b/plugins/wp-cli/README.md @@ -1,107 +1,109 @@ # WP-CLI +The [WordPress CLI](https://wp-cli.org/) is a command-line tool for managing WordPress installations. You can update plugins, set up multisite installs and much more, without using a web browser. + +This plugin adds [tab completion](https://wp-cli.org/#tab-completions) for `wp-cli` as well as several aliases for commonly used commands. + +To use it, add `wp-cli` to the plugins array in your zshrc file: + +```zsh +plugins=(... wp-cli) +``` + **Maintainer:** [joshmedeski](https://github.com/joshmedeski) -WordPress Command Line Interface (https://wp-cli.org/) +## Aliases -WP-CLI is a set of command-line tools for managing WordPress installations. You can update plugins, set up multisite installs and much more, without using a web browser. - -This plugin adds [tab completion](https://wp-cli.org/#tab-completions) for `wp-cli` as well as several aliases. - -## List of Aliases - -### Core -- wpcc='wp core config' -- wpcd='wp core download' -- wpci='wp core install' -- wpcii='wp core is-installed' -- wpcmc='wp core multisite-convert' -- wpcmi='wp core multisite-install' -- wpcu='wp core update' -- wpcudb='wp core update-db' -- wpcvc='wp core verify-checksums' - -### Cron -- wpcre='wp cron event' -- wpcrs='wp cron schedule' -- wpcrt='wp cron test' - -### Menu -- wpmc='wp menu create' -- wpmd='wp menu delete' -- wpmi='wp menu item' -- wpml='wp menu list' -- wpmlo='wp menu location' - -### Plugin -- wppa='activate' -- wppda='deactivate' -- wppd='delete' -- wppg='get' -- wppi='install' -- wppis='is-installed' -- wppl='list' -- wppp='path' -- wpps='search' -- wppst='status' -- wppt='toggle' -- wppun='uninstall' -- wppu='update' - -### Post -- wppoc='wp post create' -- wppod='wp post delete' -- wppoe='wp post edit' -- wppogen='wp post generate' -- wppog='wp post get' -- wppol='wp post list' -- wppom='wp post meta' -- wppou='wp post update' -- wppourl='wp post url' - -### Sidebar -- wpsbl='wp sidebar list' - -### Theme -- wpta='wp theme activate' -- wptd='wp theme delete' -- wptdis='wp theme disable' -- wpte='wp theme enable' -- wptg='wp theme get' -- wpti='wp theme install' -- wptis='wp theme is-installed' -- wptl='wp theme list' -- wptm='wp theme mod' -- wptp='wp theme path' -- wpts='wp theme search' -- wptst='wp theme status' -- wptu='wp theme update' - -### User -- wpuac='wp user add-cap' -- wpuar='wp user add-role' -- wpuc='wp user create' -- wpud='wp user delete' -- wpugen='wp user generate' -- wpug='wp user get' -- wpui='wp user import-csv' -- wpul='wp user list' -- wpulc='wp user list-caps' -- wpum='wp user meta' -- wpurc='wp user remove-cap' -- wpurr='wp user remove-role' -- wpusr='wp user set-role' -- wpuu='wp user update' - -### Widget -- wpwa='wp widget add' -- wpwda='wp widget deactivate' -- wpwd='wp widget delete' -- wpwl='wp widget list' -- wpwm='wp widget move' -- wpwu='wp widget update' - -The entire list of wp-cli commands can be found here: https://wp-cli.org/commands/ - -I only included the commands that are most used. Please feel free to contribute to this project if you want more commands. +The entire list of `wp-cli` commands can be found here: https://developer.wordpress.org/cli/commands/ +| Alias | Command | +|-----------|-----------------------------| +| **Core** | +| `wpcc` | `wp core config` | +| `wpcd` | `wp core download` | +| `wpci` | `wp core install` | +| `wpcii` | `wp core is-installed` | +| `wpcmc` | `wp core multisite-convert` | +| `wpcmi` | `wp core multisite-install` | +| `wpcu` | `wp core update` | +| `wpcudb` | `wp core update-db` | +| `wpcvc` | `wp core verify-checksums` | +| **Cron** | +| `wpcre` | `wp cron event` | +| `wpcrs` | `wp cron schedule` | +| `wpcrt` | `wp cron test` | +| **Database** | +| `wpdbe` | `wp db export` | +| `wpdbi` | `wp db import` | +| `wpdbcr` | `wp db create` | +| `wpdbs` | `wp db search` | +| `wpdbch` | `wp db check` | +| `wpdbr` | `wp db repair` | +| **Menu** | +| `wpmc` | `wp menu create` | +| `wpmd` | `wp menu delete` | +| `wpmi` | `wp menu item` | +| `wpml` | `wp menu list` | +| `wpmlo` | `wp menu location` | +| **Plugin** | +| `wppa` | `wp plugin activate` | +| `wppda` | `wp plugin deactivate` | +| `wppd` | `wp plugin delete` | +| `wppg` | `wp plugin get` | +| `wppi` | `wp plugin install` | +| `wppis` | `wp plugin is-installed` | +| `wppl` | `wp plugin list` | +| `wppp` | `wp plugin path` | +| `wpps` | `wp plugin search` | +| `wppst` | `wp plugin status` | +| `wppt` | `wp plugin toggle` | +| `wppun` | `wp plugin uninstall` | +| `wppu` | `wp plugin update` | +| **Post** | +| `wppoc` | `wp post create` | +| `wppod` | `wp post delete` | +| `wppoe` | `wp post edit` | +| `wppogen` | `wp post generate` | +| `wppog` | `wp post get` | +| `wppol` | `wp post list` | +| `wppom` | `wp post meta` | +| `wppou` | `wp post update` | +| `wppourl` | `wp post url` | +| **Sidebar** | +| `wpsbl` | `wp sidebar list` | +| **Theme** | +| `wpta` | `wp theme activate` | +| `wptd` | `wp theme delete` | +| `wptdis` | `wp theme disable` | +| `wpte` | `wp theme enable` | +| `wptg` | `wp theme get` | +| `wpti` | `wp theme install` | +| `wptis` | `wp theme is-installed` | +| `wptl` | `wp theme list` | +| `wptm` | `wp theme mod` | +| `wptp` | `wp theme path` | +| `wpts` | `wp theme search` | +| `wptst` | `wp theme status` | +| `wptu` | `wp theme update` | +| **User** | +| `wpuac` | `wp user add-cap` | +| `wpuar` | `wp user add-role` | +| `wpuc` | `wp user create` | +| `wpud` | `wp user delete` | +| `wpugen` | `wp user generate` | +| `wpug` | `wp user get` | +| `wpui` | `wp user import-csv` | +| `wpul` | `wp user list` | +| `wpulc` | `wp user list-caps` | +| `wpum` | `wp user meta` | +| `wpurc` | `wp user remove-cap` | +| `wpurr` | `wp user remove-role` | +| `wpusr` | `wp user set-role` | +| `wpuu` | `wp user update` | +| **Widget** | +| `wpwa` | `wp widget add` | +| `wpwda` | `wp widget deactivate` | +| `wpwd` | `wp widget delete` | +| `wpwl` | `wp widget list` | +| `wpwm` | `wp widget move` | +| `wpwu` | `wp widget update` | diff --git a/plugins/wp-cli/wp-cli.plugin.zsh b/plugins/wp-cli/wp-cli.plugin.zsh index 97bed406e..09bdf3260 100644 --- a/plugins/wp-cli/wp-cli.plugin.zsh +++ b/plugins/wp-cli/wp-cli.plugin.zsh @@ -2,14 +2,6 @@ # A command line interface for WordPress # https://wp-cli.org/ -# Cache - -# Cap - -# CLI - -# Comment - # Core alias wpcc='wp core config' alias wpcd='wp core download' @@ -27,18 +19,12 @@ alias wpcrs='wp cron schedule' alias wpcrt='wp cron test' # Db - -# Eval - -# Eval-File - -# Export - -# Help - -# Import - -# Media +alias wpdbe='wp db export' +alias wpdbi='wp db import' +alias wpdbcr='wp db create' +alias wpdbs='wp db search' +alias wpdbch='wp db check' +alias wpdbr='wp db repair' # Menu alias wpmc='wp menu create' @@ -47,10 +33,6 @@ alias wpmi='wp menu item' alias wpml='wp menu list' alias wpmlo='wp menu location' -# Network - -# Option - # Plugin alias wppa='wp plugin activate' alias wppda='wp plugin deactivate' @@ -77,25 +59,9 @@ alias wppom='wp post meta' alias wppou='wp post update' alias wppourl='wp post url' -# Rewrite - -# Role - -# Scaffold - -# Search-Replace - -# Shell - # Sidebar alias wpsbl='wp sidebar list' -# Site - -# Super-Admin - -# Term - # Theme alias wpta='wp theme activate' alias wptd='wp theme delete' @@ -111,8 +77,6 @@ alias wpts='wp theme search' alias wptst='wp theme status' alias wptu='wp theme update' -# Transient - # User alias wpuac='wp user add-cap' alias wpuar='wp user add-role' @@ -138,9 +102,8 @@ alias wpwm='wp widget move' alias wpwu='wp widget update' +# Completion for wp autoload -U +X bashcompinit && bashcompinit -# bash completion for the `wp` command - _wp_complete() { local cur=${COMP_WORDS[COMP_CWORD]} diff --git a/plugins/zbell/README.md b/plugins/zbell/README.md new file mode 100644 index 000000000..1c1c13546 --- /dev/null +++ b/plugins/zbell/README.md @@ -0,0 +1,30 @@ +# zbell plugin + +This plugin prints a bell character when a command finishes if it has been +running for longer than a specified duration. + +To use it, add `zbell` to the plugins array in your zshrc file: + +```zsh +plugins=(... zbell) +``` + +## Settings + +These settings need to be set in your zshrc file, before Oh My Zsh is sourced. + +- `zbell_duration`: duration in seconds after which to consider notifying + the end of a command. Default: 15 seconds. + +- `zbell_ignore`: if there are programs that you know run long that you + don't want to bell after, then add them to the `zbell_ignore` array. + By default, `$EDITOR` and `$PAGER` are ignored: + + ```zsh + zbell_ignore=($EDITOR $PAGER) + ``` + +## Author + +Adapted from an original version by [Jean-Philippe Ouellet](https://github.com/jpouellet). +Made available under the ISC license. diff --git a/plugins/zbell/zbell.plugin.zsh b/plugins/zbell/zbell.plugin.zsh new file mode 100644 index 000000000..6d0416502 --- /dev/null +++ b/plugins/zbell/zbell.plugin.zsh @@ -0,0 +1,83 @@ +#!/usr/bin/env zsh + +# This script prints a bell character when a command finishes +# if it has been running for longer than $zbell_duration seconds. +# If there are programs that you know run long that you don't +# want to bell after, then add them to $zbell_ignore. +# +# This script uses only zsh builtins so its fast, there's no needless +# forking, and its only dependency is zsh and its standard modules +# +# Written by Jean-Philippe Ouellet +# Made available under the ISC license. + +# only do this if we're in an interactive shell +[[ -o interactive ]] || return + +# get $EPOCHSECONDS. builtins are faster than date(1) +zmodload zsh/datetime || return + +# make sure we can register hooks +autoload -Uz add-zsh-hook || return + +# make sure we can do regexp replace +autoload -Uz regexp-replace || return + +# initialize zbell_duration if not set +(( ${+zbell_duration} )) || zbell_duration=15 + +# initialize zbell_ignore if not set +(( ${+zbell_ignore} )) || zbell_ignore=($EDITOR $PAGER) + +# initialize it because otherwise we compare a date and an empty string +# the first time we see the prompt. it's fine to have lastcmd empty on the +# initial run because it evaluates to an empty string, and splitting an +# empty string just results in an empty array. +zbell_timestamp=$EPOCHSECONDS + +# default notification function +# $1: command +# $2: duration in seconds +zbell_notify() { + type notify-send > /dev/null && \ + notify-send -i terminal "Command completed in ${2}s:" $1 + print -n "\a" +} + +# right before we begin to execute something, store the time it started at +zbell_begin() { + zbell_timestamp=$EPOCHSECONDS + zbell_lastcmd=$1 +} + +# when it finishes, if it's been running longer than $zbell_duration, +# and we dont have an ignored command in the line, then print a bell. +zbell_end() { + local cmd_duration=$(( $EPOCHSECONDS - $zbell_timestamp )) + local ran_long=$(( $cmd_duration >= $zbell_duration )) + + local zbell_lastcmd_tmp="$zbell_lastcmd" + regexp-replace zbell_lastcmd_tmp '^sudo ' '' + + [[ $zbell_last_timestamp == $zbell_timestamp ]] && return + + [[ $zbell_lastcmd_tmp == "" ]] && return + + zbell_last_timestamp=$zbell_timestamp + + local has_ignored_cmd=0 + for cmd in ${(s:;:)zbell_lastcmd_tmp//|/;}; do + words=(${(z)cmd}) + util=${words[1]} + if (( ${zbell_ignore[(i)$util]} <= ${#zbell_ignore} )); then + has_ignored_cmd=1 + break + fi + done + + (( ! $has_ignored_cmd && ran_long )) && zbell_notify $zbell_lastcmd $cmd_duration +} + +# register the functions as hooks +add-zsh-hook preexec zbell_begin +add-zsh-hook precmd zbell_end diff --git a/templates/zshrc.zsh-template b/templates/zshrc.zsh-template index 307618104..65d5ea65b 100644 --- a/templates/zshrc.zsh-template +++ b/templates/zshrc.zsh-template @@ -45,6 +45,8 @@ ZSH_THEME="robbyrussell" # ENABLE_CORRECTION="true" # Uncomment the following line to display red dots whilst waiting for completion. +# Caution: this setting can cause issues with multiline prompts (zsh 5.7.1 and newer seem to work) +# See https://github.com/ohmyzsh/ohmyzsh/issues/5765 # COMPLETION_WAITING_DOTS="true" # Uncomment the following line if you want to disable marking untracked files diff --git a/themes/adben.zsh-theme b/themes/adben.zsh-theme index b9ac77d00..ebdec7c82 100644 --- a/themes/adben.zsh-theme +++ b/themes/adben.zsh-theme @@ -29,11 +29,13 @@ # # This theme's look and feel is based on the Aaron Toponce's zsh theme, more info: # # https://pthree.org/2008/11/23/727/ # # enjoy! + ########## COLOR ########### for COLOR in CYAN WHITE YELLOW MAGENTA BLACK BLUE RED DEFAULT GREEN GREY; do - eval PR_$COLOR='%{$fg[${(L)COLOR}]%}' - eval PR_BRIGHT_$COLOR='%{$fg_bold[${(L)COLOR}]%}' + eval PR_$COLOR='%{$fg[${(L)COLOR}]%}' + eval PR_BRIGHT_$COLOR='%{$fg_bold[${(L)COLOR}]%}' done + PR_RESET="%{$reset_color%}" RED_START="${PR_RESET}${PR_GREY}<${PR_RESET}${PR_RED}<${PR_BRIGHT_RED}<${PR_RESET} " RED_END="${PR_RESET}${PR_BRIGHT_RED}>${PR_RESET}${PR_RED}>${PR_GREY}>${PR_RESET} " @@ -44,14 +46,14 @@ DIVISION="${PR_RESET}${PR_RED} < ${PR_RESET}" VCS_DIRTY_COLOR="${PR_RESET}${PR_YELLOW}" VCS_CLEAN_COLOR="${PR_RESET}${PR_GREEN}" VCS_SUFIX_COLOR="${PR_RESET}${PR_RED}› ${PR_RESET}" -# ########## COLOR ########### -# ########## SVN ########### + +########## SVN ########### ZSH_THEME_SVN_PROMPT_PREFIX="${PR_RESET}${PR_RED}‹svn:" ZSH_THEME_SVN_PROMPT_SUFFIX="" ZSH_THEME_SVN_PROMPT_DIRTY="${VCS_DIRTY_COLOR} ✘${VCS_SUFIX_COLOR}" ZSH_THEME_SVN_PROMPT_CLEAN="${VCS_CLEAN_COLOR} ✔${VCS_SUFIX_COLOR}" -# ########## SVN ########### -# ########## GIT ########### + +########## GIT ########### ZSH_THEME_GIT_PROMPT_PREFIX="${PR_RESET}${PR_RED}‹git:" ZSH_THEME_GIT_PROMPT_SUFFIX="" ZSH_THEME_GIT_PROMPT_DIRTY="${VCS_DIRTY_COLOR} ✘${VCS_SUFIX_COLOR}" @@ -62,53 +64,63 @@ ZSH_THEME_GIT_PROMPT_DELETED="${PR_RESET}${PR_YELLOW} ✖${PR_RESET}" ZSH_THEME_GIT_PROMPT_RENAMED="${PR_RESET}${PR_YELLOW} ➜${PR_RESET}" ZSH_THEME_GIT_PROMPT_UNMERGED="${PR_RESET}${PR_YELLOW} ═${PR_RESET}" ZSH_THEME_GIT_PROMPT_UNTRACKED="${PR_RESET}${PR_YELLOW} ✭${PR_RESET}" -# ########## GIT ########### -function precmd { - #gets the fortune - ps1_fortune () { - #Choose from all databases, regardless of whether they are considered "offensive" - fortune -a - } - #obtains the tip - ps1_command_tip () { - wget -qO - http://www.commandlinefu.com/commands/random/plaintext | sed 1d | sed '/^$/d' - } - prompt_header () { - if [[ "true" == "$ENABLE_COMMAND_TIP" ]]; then - ps1_command_tip - else - ps1_fortune - fi - } - PROMPT_HEAD="${RED_START}${PR_YELLOW}$(prompt_header)${PR_RESET}" - # set a simple variable to show when in screen - if [[ -n "${WINDOW}" ]]; then - SCREEN="" + +# Get a fortune quote +ps1_fortune() { + (( ${+commands[fortune]} )) && fortune +} + +# Obtain a command tip +ps1_command_tip() { + { + if (( ${+commands[wget]} )); then + command wget -qO- https://www.commandlinefu.com/commands/random/plaintext + elif (( ${+commands[curl]} )); then + command curl -fsL https://www.commandlinefu.com/commands/random/plaintext fi + } | sed 1d | sed '/^$/d' +} + +function precmd_adben { + prompt_header() { + if [[ "$ENABLE_COMMAND_TIP" = true ]]; then + ps1_command_tip + else + ps1_fortune + fi + } + + PROMPT_HEAD="${RED_START}${PR_YELLOW}$(prompt_header)${PR_RESET}" + + # set a simple variable to show when in screen + if [[ -n "${WINDOW}" ]]; then + SCREEN="" + fi } # Context: user@directory or just directory -prompt_context () { - if [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then - echo -n "${PR_RESET}${PR_RED}$USER@%m${PR_RESET}${PR_BRIGHT_YELLOW}%~%<<${PR_RESET}" - else - echo -n "${PR_RESET}${PR_BRIGHT_YELLOW}%~%<<${PR_RESET}" - fi +prompt_context() { + if [[ "$USERNAME" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then + echo -n "${PR_RESET}${PR_RED}$USERNAME@%m${PR_RESET}${PR_BRIGHT_YELLOW}%~%<<${PR_RESET}" + else + echo -n "${PR_RESET}${PR_BRIGHT_YELLOW}%~%<<${PR_RESET}" + fi } -set_prompt () { - # required for the prompt - setopt prompt_subst - autoload zsh/terminfo +########## SETUP ########### - # ######### PROMPT ######### - PROMPT='${PROMPT_HEAD} +# Required for the prompt +setopt prompt_subst +autoload zsh/terminfo + +# Prompt +PROMPT='${PROMPT_HEAD} ${RED_START}$(prompt_context) ${GREEN_START_P1}' - RPROMPT='${PR_RESET}$(git_prompt_info)$(svn_prompt_info)${PR_YELLOW}%D{%R.%S %a %b %d %Y} ${GREEN_END}${PR_RESET}' - # Matching continuation prompt - PROMPT2='${GREEN_BASE_START}${PR_RESET} %_ ${GREEN_BASE_START}${PR_RESET} ' - # ######### PROMPT ######### -} +RPROMPT='${PR_RESET}$(git_prompt_info)$(svn_prompt_info)${PR_YELLOW}%D{%R.%S %a %b %d %Y} ${GREEN_END}${PR_RESET}' +# Matching continuation prompt +PROMPT2='${GREEN_BASE_START}${PR_RESET} %_ ${GREEN_BASE_START}${PR_RESET} ' -set_prompt +# Prompt head +autoload -Uz add-zsh-hook +add-zsh-hook precmd precmd_adben diff --git a/themes/agnoster.zsh-theme b/themes/agnoster.zsh-theme index 99707f684..fe7ddbac6 100644 --- a/themes/agnoster.zsh-theme +++ b/themes/agnoster.zsh-theme @@ -88,7 +88,7 @@ prompt_end() { # Context: user@hostname (who am I and where am I) prompt_context() { - if [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then + if [[ "$USERNAME" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then prompt_segment black default "%(!.%{%F{yellow}%}.)%n@%m" fi } diff --git a/themes/avit.zsh-theme b/themes/avit.zsh-theme index 921ed99d3..1e20d8f9f 100644 --- a/themes/avit.zsh-theme +++ b/themes/avit.zsh-theme @@ -17,7 +17,7 @@ function _user_host() { local me if [[ -n $SSH_CONNECTION ]]; then me="%n@%m" - elif [[ $LOGNAME != $USER ]]; then + elif [[ $LOGNAME != $USERNAME ]]; then me="%n" fi if [[ -n $me ]]; then diff --git a/themes/essembeh.zsh-theme b/themes/essembeh.zsh-theme index 939bb7a4c..f34f36f8a 100644 --- a/themes/essembeh.zsh-theme +++ b/themes/essembeh.zsh-theme @@ -1,24 +1,14 @@ -# Theme with full path names and hostname -# Handy if you work on different servers all the time; - -local return_code="%(?..%{$fg_bold[red]%}%? ↵%{$reset_color%})" - -function my_git_prompt_info() { - ref=$(git symbolic-ref HEAD 2> /dev/null) || return - GIT_STATUS=$(git_prompt_status) - [[ -n $GIT_STATUS ]] && GIT_STATUS=" $GIT_STATUS" - echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$GIT_STATUS$ZSH_THEME_GIT_PROMPT_SUFFIX" -} - -# Colored prompt -ZSH_THEME_COLOR_USER="green" -ZSH_THEME_COLOR_HOST="green" -ZSH_THEME_COLOR_PWD="yellow" -test -n "$SSH_CONNECTION" && ZSH_THEME_COLOR_USER="red" && ZSH_THEME_COLOR_HOST="red" -test `id -u` = 0 && ZSH_THEME_COLOR_USER="magenta" && ZSH_THEME_COLOR_HOST="magenta" -PROMPT='%{$fg_bold[$ZSH_THEME_COLOR_USER]%}%n@%{$fg_bold[$ZSH_THEME_COLOR_HOST]%}%M%{$reset_color%}:%{$fg_bold[$ZSH_THEME_COLOR_PWD]%}%~%{$reset_color%} $(my_git_prompt_info)%(!.#.$) ' -RPS1="${return_code}" +# My custom theme: +# - single line +# - quite simple by default: user@host:$PWD +# - green for local shell as non root +# - red for ssh shell as non root +# - magenta for root sessions +# - prefix with remote address for ssh shells +# - prefix to detect docker containers or chroot +# - git plugin to display current branch and status +# git plugin ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg[cyan]%}(" ZSH_THEME_GIT_PROMPT_SUFFIX=") %{$reset_color%}" ZSH_THEME_GIT_PROMPT_UNTRACKED="%%" @@ -28,3 +18,33 @@ ZSH_THEME_GIT_PROMPT_RENAMED="~" ZSH_THEME_GIT_PROMPT_DELETED="!" ZSH_THEME_GIT_PROMPT_UNMERGED="?" +function zsh_essembeh_gitstatus { + ref=$(git symbolic-ref HEAD 2> /dev/null) || return + GIT_STATUS=$(git_prompt_status) + if [[ -n $GIT_STATUS ]]; then + GIT_STATUS=" $GIT_STATUS" + fi + echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$GIT_STATUS$ZSH_THEME_GIT_PROMPT_SUFFIX" +} + +# by default, use green for user@host and no prefix +local ZSH_ESSEMBEH_COLOR="green" +local ZSH_ESSEMBEH_PREFIX="" +if [[ -n "$SSH_CONNECTION" ]]; then + # display the source address if connected via ssh + ZSH_ESSEMBEH_PREFIX="%{$fg[yellow]%}[$(echo $SSH_CONNECTION | awk '{print $1}')]%{$reset_color%} " + # use red color to highlight a remote connection + ZSH_ESSEMBEH_COLOR="red" +elif [[ -r /etc/debian_chroot ]]; then + # prefix prompt in case of chroot + ZSH_ESSEMBEH_PREFIX="%{$fg[yellow]%}[chroot:$(cat /etc/debian_chroot)]%{$reset_color%} " +elif [[ -r /.dockerenv ]]; then + # also prefix prompt inside a docker contrainer + ZSH_ESSEMBEH_PREFIX="%{$fg[yellow]%}[docker]%{$reset_color%} " +fi +if [[ $UID = 0 ]]; then + # always use magenta for root sessions, even in ssh + ZSH_ESSEMBEH_COLOR="magenta" +fi +PROMPT='${ZSH_ESSEMBEH_PREFIX}%{$fg[$ZSH_ESSEMBEH_COLOR]%}%n@%M%{$reset_color%}:%{%B$fg[yellow]%}%~%{$reset_color%b%} $(zsh_essembeh_gitstatus)%(!.#.$) ' +RPROMPT="%(?..%{$fg[red]%}%?%{$reset_color%})" diff --git a/themes/flazz.zsh-theme b/themes/flazz.zsh-theme index c0a7fb5d0..e21b52ef5 100644 --- a/themes/flazz.zsh-theme +++ b/themes/flazz.zsh-theme @@ -1,4 +1,4 @@ -if [ "$USER" = "root" ] +if [ "$USERNAME" = "root" ] then CARETCOLOR="red" else CARETCOLOR="blue" fi diff --git a/themes/gallois.zsh-theme b/themes/gallois.zsh-theme index e6c2d8142..bb97bfb17 100644 --- a/themes/gallois.zsh-theme +++ b/themes/gallois.zsh-theme @@ -1,16 +1,18 @@ # Depends on the git plugin for work_in_progress() +(( $+functions[work_in_progress] )) || work_in_progress() {} ZSH_THEME_GIT_PROMPT_PREFIX="%{$reset_color%}%{$fg[green]%}[" ZSH_THEME_GIT_PROMPT_SUFFIX="]%{$reset_color%}" ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[red]%}*%{$reset_color%}" ZSH_THEME_GIT_PROMPT_CLEAN="" -#Customized git status, oh-my-zsh currently does not allow render dirty status before branch +# Customized git status, oh-my-zsh currently does not allow render dirty status before branch git_custom_status() { - local cb=$(git_current_branch) - if [ -n "$cb" ]; then - echo "$(parse_git_dirty)%{$fg_bold[yellow]%}$(work_in_progress)%{$reset_color%}$ZSH_THEME_GIT_PROMPT_PREFIX$(git_current_branch)$ZSH_THEME_GIT_PROMPT_SUFFIX" - fi + local branch=$(git_current_branch) + [[ -n "$branch" ]] || return 0 + echo "$(parse_git_dirty)\ +%{${fg_bold[yellow]}%}$(work_in_progress)%{$reset_color%}\ +${ZSH_THEME_GIT_PROMPT_PREFIX}${branch}${ZSH_THEME_GIT_PROMPT_SUFFIX}" } # RVM component of prompt @@ -18,6 +20,5 @@ ZSH_THEME_RUBY_PROMPT_PREFIX="%{$fg[red]%}[" ZSH_THEME_RUBY_PROMPT_SUFFIX="]%{$reset_color%}" # Combine it all into a final right-side prompt -RPS1='$(git_custom_status)$(ruby_prompt_info) $EPS1' - +RPS1="\$(git_custom_status)\$(ruby_prompt_info)${RPS1:+ $RPS1}" PROMPT='%{$fg[cyan]%}[%~% ]%(?.%{$fg[green]%}.%{$fg[red]%})%B$%b ' diff --git a/themes/gentoo.zsh-theme b/themes/gentoo.zsh-theme index 5f2427c7a..e18bce890 100644 --- a/themes/gentoo.zsh-theme +++ b/themes/gentoo.zsh-theme @@ -1,8 +1,28 @@ -function prompt_char { - if [ $UID -eq 0 ]; then echo "#"; else echo $; fi +autoload -Uz colors && colors + +autoload -Uz vcs_info +zstyle ':vcs_info:*' check-for-changes true +zstyle ':vcs_info:*' unstagedstr '%F{red}*' # display this when there are unstaged changes +zstyle ':vcs_info:*' stagedstr '%F{yellow}+' # display this when there are staged changes +zstyle ':vcs_info:*' actionformats '%F{5}(%F{2}%b%F{3}|%F{1}%a%c%u%m%F{5})%f ' +zstyle ':vcs_info:*' formats '%F{5}(%F{2}%b%c%u%m%F{5})%f ' +zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat '%b%F{1}:%F{3}%r' +zstyle ':vcs_info:*' enable git cvs svn +zstyle ':vcs_info:git*+set-message:*' hooks untracked-git + ++vi-untracked-git() { + if command git status --porcelain 2>/dev/null | command grep -q '??'; then + hook_com[misc]='%F{red}?' + else + hook_com[misc]='' + fi } -PROMPT='%(!.%{$fg_bold[red]%}.%{$fg_bold[green]%}%n@)%m %{$fg_bold[blue]%}%(!.%1~.%~) $(git_prompt_info)$(prompt_char)%{$reset_color%} ' +gentoo_precmd() { + vcs_info +} -ZSH_THEME_GIT_PROMPT_PREFIX="(" -ZSH_THEME_GIT_PROMPT_SUFFIX=") " +autoload -U add-zsh-hook +add-zsh-hook precmd gentoo_precmd + +PROMPT='%(!.%B%F{red}.%B%F{green}%n@)%m %F{blue}%(!.%1~.%~) ${vcs_info_msg_0_}%(!.#.$)%k%b%f ' diff --git a/themes/obraun.zsh-theme b/themes/obraun.zsh-theme index 7af44056f..cc2769e4b 100644 --- a/themes/obraun.zsh-theme +++ b/themes/obraun.zsh-theme @@ -1,4 +1,4 @@ -if [ "$USER" = "root" ]; then CARETCOLOR="red"; else CARETCOLOR="blue"; fi +if [ "$USERNAME" = "root" ]; then CARETCOLOR="red"; else CARETCOLOR="blue"; fi local return_code="%(?..%{$fg[red]%}%? ↵%{$reset_color%})" diff --git a/themes/re5et.zsh-theme b/themes/re5et.zsh-theme index 95af1e2ee..bdf342f49 100644 --- a/themes/re5et.zsh-theme +++ b/themes/re5et.zsh-theme @@ -1,4 +1,4 @@ -if [ "$USER" = "root" ]; then CARETCOLOR="red"; else CARETCOLOR="magenta"; fi +if [ "$USERNAME" = "root" ]; then CARETCOLOR="red"; else CARETCOLOR="magenta"; fi local return_code="%(?..%{$fg_bold[red]%}:( %?%{$reset_color%})" diff --git a/themes/sunrise.zsh-theme b/themes/sunrise.zsh-theme index 2111576c3..11f6af127 100644 --- a/themes/sunrise.zsh-theme +++ b/themes/sunrise.zsh-theme @@ -9,7 +9,7 @@ Y=$fg_no_bold[yellow] B=$fg_no_bold[blue] RESET=$reset_color -if [ "$USER" = "root" ]; then +if [ "$USERNAME" = "root" ]; then PROMPTCOLOR="%{$R%}" PROMPTPREFIX="-!-"; else PROMPTCOLOR="" PROMPTPREFIX="---"; diff --git a/themes/ys.zsh-theme b/themes/ys.zsh-theme index 89d5355dc..303c898b4 100644 --- a/themes/ys.zsh-theme +++ b/themes/ys.zsh-theme @@ -26,15 +26,26 @@ ys_hg_prompt_info() { if [ -d '.hg' ]; then echo -n "${YS_VCS_PROMPT_PREFIX1}hg${YS_VCS_PROMPT_PREFIX2}" echo -n $(hg branch 2>/dev/null) - if [ -n "$(hg status 2>/dev/null)" ]; then - echo -n "$YS_VCS_PROMPT_DIRTY" - else - echo -n "$YS_VCS_PROMPT_CLEAN" + if [[ "$(hg config oh-my-zsh.hide-dirty 2>/dev/null)" != "1" ]]; then + if [ -n "$(hg status 2>/dev/null)" ]; then + echo -n "$YS_VCS_PROMPT_DIRTY" + else + echo -n "$YS_VCS_PROMPT_CLEAN" + fi fi echo -n "$YS_VCS_PROMPT_SUFFIX" fi } +# Virtualenv +local venv_info='$(virtenv_prompt)' +YS_THEME_VIRTUALENV_PROMPT_PREFIX=" %{$fg[green]%}" +YS_THEME_VIRTUALENV_PROMPT_SUFFIX=" %{$reset_color%}%" +virtenv_prompt() { + [[ -n ${VIRTUAL_ENV} ]] || return + echo "${YS_THEME_VIRTUALENV_PROMPT_PREFIX}${VIRTUAL_ENV:t}${YS_THEME_VIRTUALENV_PROMPT_SUFFIX}" +} + local exit_code="%(?,,C:%{$fg[red]%}%?%{$reset_color%})" # Prompt format: @@ -55,6 +66,7 @@ PROMPT=" %{$terminfo[bold]$fg[yellow]%}%~%{$reset_color%}\ ${hg_info}\ ${git_info}\ +${venv_info}\ \ %{$fg[white]%}[%*] $exit_code %{$terminfo[bold]$fg[red]%}$ %{$reset_color%}" diff --git a/tools/changelog.sh b/tools/changelog.sh new file mode 100755 index 000000000..836afef14 --- /dev/null +++ b/tools/changelog.sh @@ -0,0 +1,431 @@ +#!/usr/bin/env zsh + +############################## +# CHANGELOG SCRIPT CONSTANTS # +############################## + +#* Holds the list of valid types recognized in a commit subject +#* and the display string of such type +local -A TYPES +TYPES=( + build "Build system" + chore "Chore" + ci "CI" + docs "Documentation" + feat "Features" + fix "Bug fixes" + perf "Performance" + refactor "Refactor" + style "Style" + test "Testing" +) + +#* Types that will be displayed in their own section, +#* in the order specified here. +local -a MAIN_TYPES +MAIN_TYPES=(feat fix perf docs) + +#* Types that will be displayed under the category of other changes +local -a OTHER_TYPES +OTHER_TYPES=(refactor style other) + +#* Commit types that don't appear in $MAIN_TYPES nor $OTHER_TYPES +#* will not be displayed and will simply be ignored. + + +############################ +# COMMIT PARSING UTILITIES # +############################ + +function parse-commit { + + # This function uses the following globals as output: commits (A), + # subjects (A), scopes (A) and breaking (A). All associative arrays (A) + # have $hash as the key. + # - commits holds the commit type + # - subjects holds the commit subject + # - scopes holds the scope of a commit + # - breaking holds the breaking change warning if a commit does + # make a breaking change + + function commit:type { + local type="$(sed -E 's/^([a-zA-Z_\-]+)(\(.+\))?!?: .+$/\1/' <<< "$1")" + + # If $type doesn't appear in $TYPES array mark it as 'other' + if [[ -n "${(k)TYPES[(i)$type]}" ]]; then + echo $type + else + echo other + fi + } + + function commit:scope { + local scope + + # Try to find scope in "type():" format + scope=$(sed -nE 's/^[a-zA-Z_\-]+\((.+)\)!?: .+$/\1/p' <<< "$1") + if [[ -n "$scope" ]]; then + echo "$scope" + return + fi + + # If no scope found, try to find it in ":" format + # Make sure it's not a type before printing it + scope=$(sed -nE 's/^([a-zA-Z_\-]+): .+$/\1/p' <<< "$1") + if [[ -z "${(k)TYPES[(i)$scope]}" ]]; then + echo "$scope" + fi + } + + function commit:subject { + # Only display the relevant part of the commit, i.e. if it has the format + # type[(scope)!]: subject, where the part between [] is optional, only + # displays subject. If it doesn't match the format, returns the whole string. + sed -E 's/^[a-zA-Z_\-]+(\(.+\))?!?: (.+)$/\2/' <<< "$1" + } + + # Return subject if the body or subject match the breaking change format + function commit:is-breaking { + local subject="$1" body="$2" message + + if [[ "$body" =~ "BREAKING CHANGE: (.*)" || \ + "$subject" =~ '^[^ :\)]+\)?!: (.*)$' ]]; then + message="${match[1]}" + # remove CR characters (might be inserted in GitHub UI commit description form) + message="${message//$'\r'/}" + # skip next paragraphs (separated by two newlines or more) + message="${message%%$'\n\n'*}" + # ... and replace newlines with spaces + echo "${message//$'\n'/ }" + else + return 1 + fi + } + + # Return truncated hash of the reverted commit + function commit:is-revert { + local subject="$1" body="$2" + + if [[ "$subject" = Revert* && \ + "$body" =~ "This reverts commit ([^.]+)\." ]]; then + echo "${match[1]:0:7}" + else + return 1 + fi + } + + # Parse commit with hash $1 + local hash="$1" subject body warning rhash + subject="$(command git show -s --format=%s $hash)" + body="$(command git show -s --format=%b $hash)" + + # Commits following Conventional Commits (https://www.conventionalcommits.org/) + # have the following format, where parts between [] are optional: + # + # type[(scope)][!]: subject + # + # commit body + # [BREAKING CHANGE: warning] + + # commits holds the commit type + commits[$hash]="$(commit:type "$subject")" + # scopes holds the commit scope + scopes[$hash]="$(commit:scope "$subject")" + # subjects holds the commit subject + subjects[$hash]="$(commit:subject "$subject")" + + # breaking holds whether a commit has breaking changes + # and its warning message if it does + if warning=$(commit:is-breaking "$subject" "$body"); then + breaking[$hash]="$warning" + fi + + # reverts holds commits reverted in the same release + if rhash=$(commit:is-revert "$subject" "$body"); then + reverts[$hash]=$rhash + fi +} + +############################# +# RELEASE CHANGELOG DISPLAY # +############################# + +function display-release { + + # This function uses the following globals: output, version, + # commits (A), subjects (A), scopes (A), breaking (A) and reverts (A). + # + # - output is the output format to use when formatting (raw|text|md) + # - version is the version in which the commits are made + # - commits, subjects, scopes, breaking, and reverts are associative arrays + # with commit hashes as keys + + # Remove commits that were reverted + local hash rhash + for hash rhash in ${(kv)reverts}; do + if (( ${+commits[$rhash]} )); then + # Remove revert commit + unset "commits[$hash]" "subjects[$hash]" "scopes[$hash]" "breaking[$hash]" + # Remove reverted commit + unset "commits[$rhash]" "subjects[$rhash]" "scopes[$rhash]" "breaking[$rhash]" + fi + done + + # If no commits left skip displaying the release + if (( $#commits == 0 )); then + return + fi + + ##* Formatting functions + + # Format the hash according to output format + # If no parameter is passed, assume it comes from `$hash` + function fmt:hash { + #* Uses $hash from outer scope + local hash="${1:-$hash}" + case "$output" in + raw) printf "$hash" ;; + text) printf "\e[33m$hash\e[0m" ;; # red + md) printf "[\`$hash\`](https://github.com/ohmyzsh/ohmyzsh/commit/$hash)" ;; + esac + } + + # Format headers according to output format + # Levels 1 to 2 are considered special, the rest are formatted + # the same, except in md output format. + function fmt:header { + local header="$1" level="$2" + case "$output" in + raw) + case "$level" in + 1) printf "$header\n$(printf '%.0s=' {1..${#header}})\n\n" ;; + 2) printf "$header\n$(printf '%.0s-' {1..${#header}})\n\n" ;; + *) printf "$header:\n\n" ;; + esac ;; + text) + case "$level" in + 1|2) printf "\e[1;4m$header\e[0m\n\n" ;; # bold, underlined + *) printf "\e[1m$header:\e[0m\n\n" ;; # bold + esac ;; + md) printf "$(printf '%.0s#' {1..${level}}) $header\n\n" ;; + esac + } + + function fmt:scope { + #* Uses $scopes (A) and $hash from outer scope + local scope="${1:-${scopes[$hash]}}" + + # Get length of longest scope for padding + local max_scope=0 padding=0 + for hash in ${(k)scopes}; do + max_scope=$(( max_scope < ${#scopes[$hash]} ? ${#scopes[$hash]} : max_scope )) + done + + # If no scopes, exit the function + if [[ $max_scope -eq 0 ]]; then + return + fi + + # Get how much padding is required for this scope + padding=$(( max_scope < ${#scope} ? 0 : max_scope - ${#scope} )) + padding="${(r:$padding:: :):-}" + + # If no scope, print padding and 3 spaces (equivalent to "[] ") + if [[ -z "$scope" ]]; then + printf "${padding} " + return + fi + + # Print [scope] + case "$output" in + raw|md) printf "[$scope]${padding} " ;; + text) printf "[\e[38;5;9m$scope\e[0m]${padding} " ;; # red 9 + esac + } + + # If no parameter is passed, assume it comes from `$subjects[$hash]` + function fmt:subject { + #* Uses $subjects (A) and $hash from outer scope + local subject="${1:-${subjects[$hash]}}" + + # Capitalize first letter of the subject + subject="${(U)subject:0:1}${subject:1}" + + case "$output" in + raw) printf "$subject" ;; + # In text mode, highlight (#) and dim text between `backticks` + text) sed -E $'s|#([0-9]+)|\e[32m#\\1\e[0m|g;s|`([^`]+)`|`\e[2m\\1\e[0m`|g' <<< "$subject" ;; + # In markdown mode, link to (#) issues + md) sed -E 's|#([0-9]+)|[#\1](https://github.com/ohmyzsh/ohmyzsh/issues/\1)|g' <<< "$subject" ;; + esac + } + + function fmt:type { + #* Uses $type from outer scope + local type="${1:-${TYPES[$type]:-${(C)type}}}" + [[ -z "$type" ]] && return 0 + case "$output" in + raw|md) printf "$type: " ;; + text) printf "\e[4m$type\e[24m: " ;; # underlined + esac + } + + ##* Section functions + + function display:version { + fmt:header "$version" 2 + } + + function display:breaking { + (( $#breaking != 0 )) || return 0 + + case "$output" in + raw) fmt:header "BREAKING CHANGES" 3 ;; + text|md) fmt:header "⚠ BREAKING CHANGES" 3 ;; + esac + + local hash subject + for hash message in ${(kv)breaking}; do + echo " - $(fmt:hash) $(fmt:scope)$(fmt:subject "${message}")" + done | sort + echo + } + + function display:type { + local hash type="$1" + + local -a hashes + hashes=(${(k)commits[(R)$type]}) + + # If no commits found of type $type, go to next type + (( $#hashes != 0 )) || return 0 + + fmt:header "${TYPES[$type]}" 3 + for hash in $hashes; do + echo " - $(fmt:hash) $(fmt:scope)$(fmt:subject)" + done | sort -k3 # sort by scope + echo + } + + function display:others { + local hash type + + # Commits made under types considered other changes + local -A changes + changes=(${(kv)commits[(R)${(j:|:)OTHER_TYPES}]}) + + # If no commits found under "other" types, don't display anything + (( $#changes != 0 )) || return 0 + + fmt:header "Other changes" 3 + for hash type in ${(kv)changes}; do + case "$type" in + other) echo " - $(fmt:hash) $(fmt:scope)$(fmt:subject)" ;; + *) echo " - $(fmt:hash) $(fmt:scope)$(fmt:type)$(fmt:subject)" ;; + esac + done | sort -k3 # sort by scope + echo + } + + ##* Release sections order + + # Display version header + display:version + + # Display breaking changes first + display:breaking + + # Display changes for commit types in the order specified + for type in $MAIN_TYPES; do + display:type "$type" + done + + # Display other changes + display:others +} + +function main { + # $1 = until commit, $2 = since commit + local until="$1" since="$2" + + # $3 = output format (--text|--raw|--md) + # --md: uses markdown formatting + # --raw: outputs without style + # --text: uses ANSI escape codes to style the output + local output=${${3:-"--text"}#--*} + + if [[ -z "$until" ]]; then + until=HEAD + fi + + if [[ -z "$since" ]]; then + # If $since is not specified: + # 1) try to find the version used before updating + # 2) try to find the first version tag before $until + since=$(command git config --get oh-my-zsh.lastVersion 2>/dev/null) || \ + since=$(command git describe --abbrev=0 --tags "$until^" 2>/dev/null) || \ + unset since + elif [[ "$since" = --all ]]; then + unset since + fi + + # Commit classification arrays + local -A commits subjects scopes breaking reverts + local truncate=0 read_commits=0 + local hash version tag + + # Get the first version name: + # 1) try tag-like version, or + # 2) try name-rev, or + # 3) try branch name, or + # 4) try short hash + version=$(command git describe --tags $until 2>/dev/null) \ + || version=$(command git name-rev --no-undefined --name-only --exclude="remotes/*" $until 2>/dev/null) \ + || version=$(command git symbolic-ref --quiet --short $until 2>/dev/null) \ + || version=$(command git rev-parse --short $until 2>/dev/null) + + # Get commit list from $until commit until $since commit, or until root + # commit if $since is unset, in short hash form. + # --first-parent is used when dealing with merges: it only prints the + # merge commit, not the commits of the merged branch. + command git rev-list --first-parent --abbrev-commit --abbrev=7 ${since:+$since..}$until | while read hash; do + # Truncate list on versions with a lot of commits + if [[ -z "$since" ]] && (( ++read_commits > 35 )); then + truncate=1 + break + fi + + # If we find a new release (exact tag) + if tag=$(command git describe --exact-match --tags $hash 2>/dev/null); then + # Output previous release + display-release + # Reinitialize commit storage + commits=() + subjects=() + scopes=() + breaking=() + reverts=() + # Start work on next release + version="$tag" + read_commits=1 + fi + + parse-commit "$hash" + done + + display-release + + if (( truncate )); then + echo " ...more commits omitted" + echo + fi +} + +cd "$ZSH" + +# Use raw output if stdout is not a tty +if [[ ! -t 1 && -z "$3" ]]; then + main "$1" "$2" --raw +else + main "$@" +fi diff --git a/tools/check_for_upgrade.sh b/tools/check_for_upgrade.sh index cadd5fe49..29a48b880 100644 --- a/tools/check_for_upgrade.sh +++ b/tools/check_for_upgrade.sh @@ -1,6 +1,6 @@ # Migrate .zsh-update file to $ZSH_CACHE_DIR if [[ -f ~/.zsh-update && ! -f "${ZSH_CACHE_DIR}/.zsh-update" ]]; then - mv ~/.zsh-update "${ZSH_CACHE_DIR}/.zsh-update" + mv ~/.zsh-update "${ZSH_CACHE_DIR}/.zsh-update" fi # Cancel update if: @@ -10,79 +10,82 @@ fi if [[ "$DISABLE_AUTO_UPDATE" = true ]] \ || [[ ! -w "$ZSH" || ! -O "$ZSH" ]] \ || ! command -v git &>/dev/null; then - return + return fi function current_epoch() { - zmodload zsh/datetime - echo $(( EPOCHSECONDS / 60 / 60 / 24 )) + zmodload zsh/datetime + echo $(( EPOCHSECONDS / 60 / 60 / 24 )) } function update_last_updated_file() { - echo "LAST_EPOCH=$(current_epoch)" >! "${ZSH_CACHE_DIR}/.zsh-update" + echo "LAST_EPOCH=$(current_epoch)" >! "${ZSH_CACHE_DIR}/.zsh-update" } function update_ohmyzsh() { - ZSH="$ZSH" sh "$ZSH/tools/upgrade.sh" + if ZSH="$ZSH" zsh -f "$ZSH/tools/upgrade.sh" --interactive; then update_last_updated_file + fi } () { - emulate -L zsh + emulate -L zsh - local epoch_target mtime option LAST_EPOCH + local epoch_target mtime option LAST_EPOCH - # Remove lock directory if older than a day - zmodload zsh/datetime - zmodload -F zsh/stat b:zstat - if mtime=$(zstat +mtime "$ZSH/log/update.lock" 2>/dev/null); then - if (( (mtime + 3600 * 24) < EPOCHSECONDS )); then - command rm -rf "$ZSH/log/update.lock" - fi + # Remove lock directory if older than a day + zmodload zsh/datetime + zmodload -F zsh/stat b:zstat + if mtime=$(zstat +mtime "$ZSH/log/update.lock" 2>/dev/null); then + if (( (mtime + 3600 * 24) < EPOCHSECONDS )); then + command rm -rf "$ZSH/log/update.lock" fi + fi - # Check for lock directory - if ! command mkdir "$ZSH/log/update.lock" 2>/dev/null; then - return - fi + # Check for lock directory + if ! command mkdir "$ZSH/log/update.lock" 2>/dev/null; then + return + fi - # Remove lock directory on exit. `return 1` is important for when trapping a SIGINT: - # The return status from the function is handled specially. If it is zero, the signal is - # assumed to have been handled, and execution continues normally. Otherwise, the shell - # will behave as interrupted except that the return status of the trap is retained. - trap "command rm -rf '$ZSH/log/update.lock'; return 1" EXIT INT QUIT + # Remove lock directory on exit. `return 1` is important for when trapping a SIGINT: + # The return status from the function is handled specially. If it is zero, the signal is + # assumed to have been handled, and execution continues normally. Otherwise, the shell + # will behave as interrupted except that the return status of the trap is retained. + trap " + unset -f current_epoch update_last_updated_file update_ohmyzsh + command rm -rf '$ZSH/log/update.lock' + return 1 + " EXIT INT QUIT - # Create or update .zsh-update file if missing or malformed - if ! source "${ZSH_CACHE_DIR}/.zsh-update" 2>/dev/null || [[ -z "$LAST_EPOCH" ]]; then - update_last_updated_file - return - fi + # Create or update .zsh-update file if missing or malformed + if ! source "${ZSH_CACHE_DIR}/.zsh-update" 2>/dev/null || [[ -z "$LAST_EPOCH" ]]; then + update_last_updated_file + return + fi - # Number of days before trying to update again - epoch_target=${UPDATE_ZSH_DAYS:-13} - # Test if enough time has passed until the next update - if (( ( $(current_epoch) - $LAST_EPOCH ) < $epoch_target )); then - return - fi + # Number of days before trying to update again + epoch_target=${UPDATE_ZSH_DAYS:-13} + # Test if enough time has passed until the next update + if (( ( $(current_epoch) - $LAST_EPOCH ) < $epoch_target )); then + return + fi - # Ask for confirmation before updating unless disabled - if [[ "$DISABLE_UPDATE_PROMPT" = true ]]; then - update_ohmyzsh - else - # input sink to swallow all characters typed before the prompt - # and add a newline if there wasn't one after characters typed - while read -t -k 1 option; do true; done - [[ "$option" != ($'\n'|"") ]] && echo + # Ask for confirmation before updating unless disabled + if [[ "$DISABLE_UPDATE_PROMPT" = true ]]; then + update_ohmyzsh + else + # input sink to swallow all characters typed before the prompt + # and add a newline if there wasn't one after characters typed + while read -t -k 1 option; do true; done + [[ "$option" != ($'\n'|"") ]] && echo - echo -n "[oh-my-zsh] Would you like to update? [Y/n] " - read -r -k 1 option - [[ "$option" != $'\n' ]] && echo - case "$option" in - [yY$'\n']) update_ohmyzsh ;; - [nN]) update_last_updated_file ;; - esac - fi + echo -n "[oh-my-zsh] Would you like to update? [Y/n] " + read -r -k 1 option + [[ "$option" != $'\n' ]] && echo + case "$option" in + [yY$'\n']) update_ohmyzsh ;; + [nN]) update_last_updated_file ;; + esac + fi } - -unset -f current_epoch update_last_updated_file update_ohmyzsh diff --git a/tools/install.sh b/tools/install.sh index 953c68baf..cfc2808fe 100755 --- a/tools/install.sh +++ b/tools/install.sh @@ -57,15 +57,16 @@ command_exists() { } fmt_error() { - echo ${RED}"Error: $@"${RESET} >&2 + printf '%sError: %s%s\n' "$BOLD$RED" "$*" "$RESET" >&2 } fmt_underline() { - echo "$(printf '\033[4m')$@$(printf '\033[24m')" + printf '\033[4m%s\033[24m\n' "$*" } fmt_code() { - echo "\`$(printf '\033[38;5;247m')$@${RESET}\`" + # shellcheck disable=SC2016 # backtic in single-quote + printf '`\033[38;5;247m%s%s`\n' "$*" "$RESET" } setup_color() { @@ -102,7 +103,8 @@ setup_ohmyzsh() { exit 1 } - if [ "$OSTYPE" = cygwin ] && git --version | grep -q msysgit; then + ostype=$(uname) + if [ -z "${ostype%CYGWIN*}" ] && git --version | grep -q msysgit; then fmt_error "Windows/MSYS Git is not supported on Cygwin" fmt_error "Make sure the Cygwin git package is installed and is first on the \$PATH" exit 1 @@ -130,7 +132,7 @@ setup_zshrc() { OLD_ZSHRC=~/.zshrc.pre-oh-my-zsh if [ -f ~/.zshrc ] || [ -h ~/.zshrc ]; then # Skip this if the user doesn't want to replace an existing .zshrc - if [ $KEEP_ZSHRC = yes ]; then + if [ "$KEEP_ZSHRC" = yes ]; then echo "${YELLOW}Found ~/.zshrc.${RESET} ${GREEN}Keeping...${RESET}" return fi @@ -162,7 +164,7 @@ export ZSH=\"$ZSH\" setup_shell() { # Skip setup if the user wants or stdin is closed (not running interactively). - if [ $CHSH = no ]; then + if [ "$CHSH" = no ]; then return fi @@ -183,8 +185,9 @@ EOF echo "${BLUE}Time to change your default shell to zsh:${RESET}" # Prompt for user choice on changing the default login shell - printf "${YELLOW}Do you want to change your default shell to zsh? [Y/n]${RESET} " - read opt + printf '%sDo you want to change your default shell to zsh? [Y/n]%s ' \ + "$YELLOW" "$RESET" + read -r opt case $opt in y*|Y*|"") echo "Changing the shell..." ;; n*|N*) echo "Shell change skipped."; return ;; @@ -211,7 +214,7 @@ EOF # Get the path to the right zsh binary # 1. Use the most preceding one based on $PATH, then check that it's in the shells file # 2. If that fails, get a zsh path from the shells file, then check it actually exists - if ! zsh=$(which zsh) || ! grep -qx "$zsh" "$shells_file"; then + if ! zsh=$(command -v zsh) || ! grep -qx "$zsh" "$shells_file"; then if ! zsh=$(grep '^/.*/zsh$' "$shells_file" | tail -1) || [ ! -f "$zsh" ]; then fmt_error "no zsh binary found or not present in '$shells_file'" fmt_error "change your default shell manually." @@ -222,9 +225,9 @@ EOF # We're going to change the default shell, so back up the current one if [ -n "$SHELL" ]; then - echo $SHELL > ~/.shell.pre-oh-my-zsh + echo "$SHELL" > ~/.shell.pre-oh-my-zsh else - grep "^$USER:" /etc/passwd | awk -F: '{print $7}' > ~/.shell.pre-oh-my-zsh + grep "^$USERNAME:" /etc/passwd | awk -F: '{print $7}' > ~/.shell.pre-oh-my-zsh fi # Actually change the default shell to zsh @@ -288,7 +291,7 @@ EOF setup_zshrc setup_shell - printf "$GREEN" + printf %s "$GREEN" cat <<'EOF' __ __ ____ / /_ ____ ___ __ __ ____ _____/ /_ @@ -307,7 +310,7 @@ Before you scream Oh My Zsh! please look over the ~/.zshrc file to select plugin • Get stickers, shirts, coffee mugs and other swag: $(fmt_underline https://shop.planetargon.com/collections/oh-my-zsh) EOF - printf "$RESET" + printf %s "$RESET" if [ $RUNZSH = no ]; then echo "${YELLOW}Run zsh to try it out.${RESET}" diff --git a/tools/theme_chooser.sh b/tools/theme_chooser.sh index 82ae5857c..3883f1d37 100755 --- a/tools/theme_chooser.sh +++ b/tools/theme_chooser.sh @@ -25,6 +25,7 @@ function theme_preview() { print "$fg[blue]${(l.((${COLUMNS}-${#THEME_NAME}-5))..─.)}$reset_color $THEME_NAME $fg[blue]───$reset_color" source "$THEMES_DIR/$THEME" cols=$(tput cols) + (exit 1) print -P "$PROMPT $RPROMPT" } diff --git a/tools/uninstall.sh b/tools/uninstall.sh index b327a0163..6a0e7b4c7 100644 --- a/tools/uninstall.sh +++ b/tools/uninstall.sh @@ -9,20 +9,20 @@ if [ -d ~/.oh-my-zsh ]; then rm -rf ~/.oh-my-zsh fi +if [ -e ~/.zshrc ]; then + ZSHRC_SAVE=~/.zshrc.omz-uninstalled-$(date +%Y-%m-%d_%H-%M-%S) + echo "Found ~/.zshrc -- Renaming to ${ZSHRC_SAVE}" + mv ~/.zshrc "${ZSHRC_SAVE}" +fi + echo "Looking for original zsh config..." ZSHRC_ORIG=~/.zshrc.pre-oh-my-zsh if [ -e "$ZSHRC_ORIG" ]; then echo "Found $ZSHRC_ORIG -- Restoring to ~/.zshrc" - - if [ -e ~/.zshrc ]; then - ZSHRC_SAVE=~/.zshrc.omz-uninstalled-$(date +%Y-%m-%d_%H-%M-%S) - echo "Found ~/.zshrc -- Renaming to ${ZSHRC_SAVE}" - mv ~/.zshrc "${ZSHRC_SAVE}" - fi - mv "$ZSHRC_ORIG" ~/.zshrc - echo "Your original zsh config was restored." +else + echo "No original zsh config found" fi if hash chsh >/dev/null 2>&1 && [ -f ~/.shell.pre-oh-my-zsh ]; then diff --git a/tools/upgrade.sh b/tools/upgrade.sh old mode 100644 new mode 100755 index e005519d6..417e06fe8 --- a/tools/upgrade.sh +++ b/tools/upgrade.sh @@ -1,40 +1,49 @@ -# Use colors, but only if connected to a terminal, and that terminal -# supports them. +#!/usr/bin/env zsh + +if [ -z "$ZSH_VERSION" ]; then + exec zsh "$0" "$@" +fi + +cd "$ZSH" + +# Use colors, but only if connected to a terminal +# and that terminal supports them. + +local -a RAINBOW +local RED GREEN YELLOW BLUE BOLD DIM UNDER RESET + if [ -t 1 ]; then - RB_RED=$(printf '\033[38;5;196m') - RB_ORANGE=$(printf '\033[38;5;202m') - RB_YELLOW=$(printf '\033[38;5;226m') - RB_GREEN=$(printf '\033[38;5;082m') - RB_BLUE=$(printf '\033[38;5;021m') - RB_INDIGO=$(printf '\033[38;5;093m') - RB_VIOLET=$(printf '\033[38;5;163m') + RAINBOW=( + "$(printf '\033[38;5;196m')" + "$(printf '\033[38;5;202m')" + "$(printf '\033[38;5;226m')" + "$(printf '\033[38;5;082m')" + "$(printf '\033[38;5;021m')" + "$(printf '\033[38;5;093m')" + "$(printf '\033[38;5;163m')" + ) RED=$(printf '\033[31m') GREEN=$(printf '\033[32m') YELLOW=$(printf '\033[33m') BLUE=$(printf '\033[34m') BOLD=$(printf '\033[1m') + DIM=$(printf '\033[2m') UNDER=$(printf '\033[4m') RESET=$(printf '\033[m') -else - RB_RED="" - RB_ORANGE="" - RB_YELLOW="" - RB_GREEN="" - RB_BLUE="" - RB_INDIGO="" - RB_VIOLET="" - - RED="" - GREEN="" - YELLOW="" - BLUE="" - UNDER="" - BOLD="" - RESET="" fi -cd "$ZSH" +# Update upstream remote to ohmyzsh org +git remote -v | while read remote url extra; do + case "$url" in + https://github.com/robbyrussell/oh-my-zsh(|.git)) + git remote set-url "$remote" "https://github.com/ohmyzsh/ohmyzsh.git" + break ;; + git@github.com:robbyrussell/oh-my-zsh(|.git)) + git remote set-url "$remote" "git@github.com:ohmyzsh/ohmyzsh.git" + break ;; + esac +done # Set git-config values known to fix git errors # Line endings (#4069) @@ -45,30 +54,45 @@ git config fsck.zeroPaddedFilemode ignore git config fetch.fsck.zeroPaddedFilemode ignore git config receive.fsck.zeroPaddedFilemode ignore # autostash on rebase (#7172) -resetAutoStash=$(git config --bool rebase.autoStash 2>&1) +resetAutoStash=$(git config --bool rebase.autoStash 2>/dev/null) git config rebase.autoStash true -# Update upstream remote to ohmyzsh org -remote=$(git remote -v | awk '/https:\/\/github\.com\/robbyrussell\/oh-my-zsh\.git/{ print $1; exit }') -if [ -n "$remote" ]; then - git remote set-url "$remote" "https://github.com/ohmyzsh/ohmyzsh.git" -fi +local ret=0 +# Update Oh My Zsh printf "${BLUE}%s${RESET}\n" "Updating Oh My Zsh" -if git pull --rebase --stat origin master -then - printf '%s %s__ %s %s %s %s %s__ %s\n' $RB_RED $RB_ORANGE $RB_YELLOW $RB_GREEN $RB_BLUE $RB_INDIGO $RB_VIOLET $RB_RESET - printf '%s ____ %s/ /_ %s ____ ___ %s__ __ %s ____ %s_____%s/ /_ %s\n' $RB_RED $RB_ORANGE $RB_YELLOW $RB_GREEN $RB_BLUE $RB_INDIGO $RB_VIOLET $RB_RESET - printf '%s / __ \%s/ __ \ %s / __ `__ \%s/ / / / %s /_ / %s/ ___/%s __ \ %s\n' $RB_RED $RB_ORANGE $RB_YELLOW $RB_GREEN $RB_BLUE $RB_INDIGO $RB_VIOLET $RB_RESET - printf '%s/ /_/ /%s / / / %s / / / / / /%s /_/ / %s / /_%s(__ )%s / / / %s\n' $RB_RED $RB_ORANGE $RB_YELLOW $RB_GREEN $RB_BLUE $RB_INDIGO $RB_VIOLET $RB_RESET - printf '%s\____/%s_/ /_/ %s /_/ /_/ /_/%s\__, / %s /___/%s____/%s_/ /_/ %s\n' $RB_RED $RB_ORANGE $RB_YELLOW $RB_GREEN $RB_BLUE $RB_INDIGO $RB_VIOLET $RB_RESET - printf '%s %s %s %s /____/ %s %s %s %s\n' $RB_RED $RB_ORANGE $RB_YELLOW $RB_GREEN $RB_BLUE $RB_INDIGO $RB_VIOLET $RB_RESET - printf "${BLUE}%s\n" "Hooray! Oh My Zsh has been updated and/or is at the current version." - printf "${BLUE}${BOLD}%s ${UNDER}%s${RESET}\n" "To keep up on the latest news and updates, follow us on Twitter:" "https://twitter.com/ohmyzsh" +last_commit=$(git rev-parse HEAD) +if git pull --rebase --stat origin master; then + # Check if it was really updated or not + if [[ "$(git rev-parse HEAD)" = "$last_commit" ]]; then + message="Oh My Zsh is already at the latest version." + else + message="Hooray! Oh My Zsh has been updated!" + + # Save the commit prior to updating + git config oh-my-zsh.lastVersion "$last_commit" + + # Display changelog with less if available, otherwise just print it to the terminal + if [[ "$1" = --interactive ]]; then + "$ZSH/tools/changelog.sh" HEAD "$last_commit" + fi + + printf "${BLUE}%s \`${BOLD}%s${RESET}${BLUE}\`${RESET}\n" "You can see the changelog with" "omz changelog" + fi + + printf '%s %s__ %s %s %s %s %s__ %s\n' $RAINBOW $RESET + printf '%s ____ %s/ /_ %s ____ ___ %s__ __ %s ____ %s_____%s/ /_ %s\n' $RAINBOW $RESET + printf '%s / __ \%s/ __ \ %s / __ `__ \%s/ / / / %s /_ / %s/ ___/%s __ \ %s\n' $RAINBOW $RESET + printf '%s/ /_/ /%s / / / %s / / / / / /%s /_/ / %s / /_%s(__ )%s / / / %s\n' $RAINBOW $RESET + printf '%s\____/%s_/ /_/ %s /_/ /_/ /_/%s\__, / %s /___/%s____/%s_/ /_/ %s\n' $RAINBOW $RESET + printf '%s %s %s %s /____/ %s %s %s %s\n' $RAINBOW $RESET + printf '\n' + printf "${BLUE}%s${RESET}\n" "$message" + printf "${BLUE}${BOLD}%s ${UNDER}%s${RESET}\n" "To keep up with the latest news and updates, follow us on Twitter:" "https://twitter.com/ohmyzsh" printf "${BLUE}${BOLD}%s ${UNDER}%s${RESET}\n" "Want to get involved in the community? Join our Discord:" "https://discord.gg/ohmyzsh" printf "${BLUE}${BOLD}%s ${UNDER}%s${RESET}\n" "Get your Oh My Zsh swag at:" "https://shop.planetargon.com/collections/oh-my-zsh" else - status=$? + ret=$? printf "${RED}%s${RESET}\n" 'There was an error updating. Try again later?' fi @@ -79,4 +103,4 @@ case "$resetAutoStash" in esac # Exit with `1` if the update failed -exit $status +exit $ret