X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=bin%2Faxzshctl;h=efc8a982f3d939f00ef8c13dc632c9067728046a;hb=HEAD;hp=c051bfd64458eb095bc50f00b014e80b356f3e2b;hpb=148426f26c55bc45be0ec767b3c2686a01a795aa;p=ax-zsh.git diff --git a/bin/axzshctl b/bin/axzshctl index c051bfd..943e464 100755 --- a/bin/axzshctl +++ b/bin/axzshctl @@ -1,25 +1,48 @@ #!/usr/bin/env zsh # # AX-ZSH: Alex' Modular ZSH Configuration -# Copyright (c) 2015-2017 Alexander Barton +# Copyright (c) 2015-2023 Alexander Barton # -# Include "ax-common.sh", if available: -for dir ("$HOME/lib" "$HOME/.ax" /usr/local /opt/ax /usr); do - [[ -z "$ax_common_sourced" ]] || break - ax_common="${dir}/lib/ax/ax-common.sh" - [[ -r "$ax_common" ]] && source "$ax_common" -done -if [[ -z "$ax_common_sourced" ]]; then - function ax_msg { - shift - echo "$@" - } - function ax_error { - ax_msg 2 "$@" >&2 - } -fi -unset dir ax_common ax_common_sourced +# Embedded ax-common compatibility functions ... +function ax_msg { + case "$1" in + "0") c="32"; ;; + "1") c="33"; ;; + "2") c="31"; ;; + "-") c="1"; ;; + *) c="0"; ;; + esac + shift + printf "\e[${c}m%s\e[0m\n" "$@" +} +function ax_error { + ax_msg 2 "$@" >&2 +} + +function Version { + echo "ax-zsh -- Modular configuration system for the Z shell (ZSH)" + echo "Copyright (c) 2015-2023 Alexander Barton ." + echo "Licensed under the terms of the MIT license, see LICENSE.md for details." + echo "Homepage: " + echo + echo "Installation prefix: $AXZSH" + echo -n "Version: " + if [[ -d "$AXZSH/.git" && -n "$commands[git]" ]]; then + echo -n "Git Commit-ID " + ( cd "$AXZSH" && git describe --always ) + else + echo "unknown" + fi + echo -n "Active theme: " + if [[ -n "$AXZSH_THEME" ]]; then + echo "${AXZSH_THEME:A:t:r}" + else + echo "unknown" + fi + echo + exit 0 +} function Usage { echo "Usage: $NAME [...]" @@ -35,6 +58,8 @@ function Usage { echo " Disable plugin(s)." echo " list-enabled" echo " List enabled plugins." + echo " plugin-help" + echo " Show help text for a plugin (when provided by the plugin)." echo echo " reset-plugins" echo " Reset active plugins to the default set." @@ -43,7 +68,7 @@ function Usage { echo " check-plugins" echo " Detect plugins which are \"useful\" on this system." echo - echo " set-theme |-" + echo " set-theme {|-}" echo " Set active theme to , or to the default." echo echo " upgrade" @@ -51,25 +76,41 @@ function Usage { echo " update-caches" echo " Force rebuild of all cache files." echo + echo " help" + echo " Show this help text." + echo " version" + echo " Show version and setup information." + echo exit 0 } function UpdatePluginCache { [[ -r "$AXZSH/cache" ]] || return 0 - ax_msg - "Updating plugin cache ..." + [[ "$1" = "-v" ]] && ax_msg - "Invalidating & updating caches ..." + + if [[ -d "$ZSH_CACHE_DIR" ]]; then + [[ "$1" = "-v" ]] && echo "Removing ZSH cache folder ..." + rm -fr "$ZSH_CACHE_DIR" + fi + + [[ "$1" = "-v" ]] && echo "Removing AX-ZSH cache files ..." rm -rf \ + $AXZSH/cache/ax-io.cache \ $AXZSH/cache/zlogin.cache \ $AXZSH/cache/zlogout.cache \ $AXZSH/cache/zprofile.cache \ $AXZSH/cache/zshrc.cache \ || return 1 - echo "Regenerating cache files ..." - zsh -ilc '' >/dev/null + + echo "Regenerating AX-ZSH cache ..." + [[ -z "$AXZSH_DEBUG" ]] \ + && AXZSH_PLUGIN_CHECK=1 zsh -ilc '' >/dev/null \ + || AXZSH_PLUGIN_CHECK=1 zsh -ilc '' } function NormalizedPluginName { - if [[ "$1" =~ "^[[:alnum:]-]+/[[:alnum:]_-]+$" ]]; then + if [[ "$1" =~ "^@?[[:alnum:]-]+/[[:alnum:]_.-]+$" ]]; then echo "${1:gs/\//#}" elif [[ "$1" =~ "/" ]]; then echo "${1:t}" @@ -80,16 +121,20 @@ function NormalizedPluginName { function EnableAXZSH { for f (~/.zlogin ~/.zlogout ~/.zprofile ~/.zshrc); do - ln -sv "$AXZSH/ax.zsh" "$f" \ + ln -s "$AXZSH/ax.zsh" "$f" \ || ax_error "Failed to create symbolic link for \"$f\"!" done + if [[ -z "$AXZSH_FPATH" ]]; then + echo "AX-ZSH was enabled. Now you should restart your shell, for example like this:" + echo "$ exec -l \"\$SHELL\"" + fi } function DisableAXZSH { for f (~/.zlogin ~/.zlogout ~/.zprofile ~/.zshrc); do - if [ -h "$f" ]; then - rm -v "$f" || ax_msg 2 "Failed to remove \"$f\"!" - elif [ -e "$f" ]; then + if [[ -h "$f" ]]; then + rm "$f" || ax_msg 2 "Failed to remove \"$f\"!" + elif [[ -e "$f" ]]; then ax_error "Error: Not removing \"$f\", it is not a symbolic link!" else ax_msg 1 "Warning: \"$f\" already does not exist. Ok." @@ -100,13 +145,27 @@ function DisableAXZSH { function EnablePlugin { local plugin=$(NormalizedPluginName "$1") local dir="$AXZSH/active_plugins" + local name="$plugin" if [[ -h "$dir/$plugin" ]]; then ax_msg 1 "Plugin \"$1\" already active!" return 1 fi - if [[ "$1" =~ "^[[:alnum:]-]+/[[:alnum:]_-]+$" ]]; then + if [[ "$1" =~ "^@[[:alnum:]-]+/[[:alnum:]_.+-]+$" ]]; then + # GitHub plugin repository (like OhMyZsh) + local repo="${1##@}" + repo="${repo%/*}" + mkdir -p "$AXZSH/repos/@$repo" + if [[ ! -d "$AXZSH/repos/@$repo/plugins" ]]; then + ax_msg - "Cloning \"$repo\" from GitHub ..." + git clone --depth=1 "https://github.com/$repo/$repo.git" \ + "$AXZSH/repos/@$repo" \ + || ax_error "Failed to clone \"$repo\" repository!" + fi + plugin="@$repo/plugins/${1#*/}" + echo "Trying to enable \"$1\" ..." + elif [[ "$1" =~ "^[[:alnum:]-]+/[[:alnum:]_.-]+$" ]]; then # GitHub plugin mkdir -p "$AXZSH/repos" if [[ ! -e "$AXZSH/repos/$plugin" ]]; then @@ -118,13 +177,16 @@ function EnablePlugin { # Try to enable a theme in this "foreign module", but ignore # errors: we don't know if this module provides a theme or is # a "regular" plugin ... - if SetTheme "${plugin#*#}" 2>/dev/null; then + if SetTheme "$plugin" 2>/dev/null; then ax_msg 0 "Module \"$1\" was enabled as theme \"${plugin#*#}\"." # A theme was enabled: So assume that this is a theme # and don't enable it as plugin. return 0 fi echo "Trying to enable \"$1\" as plugin ..." + elif ! [[ "$1" =~ "^[[:alnum:]_.-]+$" ]]; then + ax_error "Invalid plugin name!" + return 1 fi for dname ( @@ -141,12 +203,12 @@ function EnablePlugin { mkdir -p "$dir" if ! ( cd "$dir" || exit 9 - ln -s "$dname" "$PWD" + ln -s "$dname" "$PWD/$name" ); then ax_error "Failed to create link!" return 1 fi - ax_msg 0 "Plugin \"$plugin\" enabled." + ax_msg 0 "Plugin \"$1\" enabled." return 0 done @@ -190,6 +252,35 @@ function ListEnabledPlugins { return 0 } +function PluginHelp { + local plugin=$(NormalizedPluginName "$1") + local repo_plugin=$(echo "$plugin" | sed -e 's|#|/plugins/|') + local plugin_found= + + for plugin_d ( + "$plugin:A" + "$AXZSH/active_plugins/$plugin" + "$AXZSH/active_plugins/$repo_plugin" + "$AXZSH_PLUGIN_D/$plugin" + "$ZSH_CUSTOM/$plugin" + "$AXZSH/custom_plugins/$plugin" + "$AXZSH/repos/$plugin" + "$AXZSH/repos/$repo_plugin" + "$AXZSH/plugins/$plugin" + "$AXZSH/default_plugins/$plugin" + "$AXZSH/core/$plugin" + ); do + [[ -e "$plugin_d" ]] && plugin_found=1 + [[ -r "$plugin_d/README.md" ]] || continue + less "$plugin_d/README.md" + return 0 + done + [[ -n "$plugin_found" ]] \ + && echo "Plugin \"$1\" found, but no help available!" >&2 \ + || echo "Plugin \"$1\" not found!" >&2 + return 1 +} + function ResetPlugins { local dir="$AXZSH/active_plugins" local r1=0, r2=0 @@ -208,11 +299,11 @@ function ResetPlugins { function EnableDefaultPlugins { local dir="$AXZSH/active_plugins" - ax_msg - "Activating (linking) default plugins ..." + ax_msg - "Activating default plugins ..." mkdir -p "$dir" ( cd "$dir" || exit 9 - ln -sfv "$AXZSH/default_plugins/"* "$PWD" + ln -sf "$AXZSH/default_plugins/"* "$PWD" ) return $? } @@ -220,19 +311,34 @@ function EnableDefaultPlugins { function SetTheme { local link_name="$AXZSH/active_theme" - if [ "$1" = "-" ]; then + # --- Powerlevel10k --- + # Remove "instant prompt" configuration, if any ... + rm -f "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" + + if [[ "$1" = "-" ]]; then rm -f "$link_name" || return 1 ax_msg 0 "Theme settings have been reset." return 0 fi - if [ -r "$1" ]; then + if [[ -r "$1" ]]; then theme="$1" - elif [ -r "$AXZSH/custom_themes/$1.axzshtheme" ]; then + elif [[ -r "$AXZSH/custom_themes/$1.axzshtheme" ]]; then theme="$AXZSH/custom_themes/$1.axzshtheme" - elif [ -r "$AXZSH/themes/$1.axzshtheme" ]; then + elif [[ -r "$AXZSH/themes/$1.axzshtheme" ]]; then theme="$AXZSH/themes/$1.axzshtheme" else + # Look for theme in specific remote module: + for f ( + "$AXZSH/repos/$1/"*.axzshtheme(N[1]) + "$AXZSH/repos/$1/"*.zsh-theme(N[1]) + ); do + if [[ -r "$f" ]]; then + theme="$f" + break + fi + done + # Look for theme inside of installed plugins: for dname ( "$AXZSH/custom_themes" @@ -247,12 +353,13 @@ function SetTheme { break fi done + if [[ -z "$theme" ]]; then ax_error "Theme \"$1\" not found!" return 1 fi fi - ln -fsv "$theme" "$link_name" || return 1 + ln -fs "$theme" "$link_name" || return 1 return $? } @@ -267,7 +374,12 @@ function UpgradeAXZSH { fi ax_msg - "Upgrading AX-ZSH in \"$AXZSH\" using git(1) ..." - ( cd "$AXZSH" && git pull --ff-only ) + ( + set -e + cd "$AXZSH" + git pull --ff-only || ax_error "Git pull failed!" + git log --pretty=format:"%C(yellow)%h %C(blue)%ar %C(green)%an %Creset%s" ORIG_HEAD.. + ) } function UpgradeForeignPlugins { @@ -278,11 +390,13 @@ function UpgradeForeignPlugins { for dir ($AXZSH/repos/*(N)); do name=${dir:t:s/#/\//} - if [ -d "$dir/.git" ]; then + if [[ -d "$dir/.git" ]]; then ax_msg - "Upgrading \"$name\" [git] ..." ( + set -e cd "$dir" - git pull --ff-only || ax_error "Pull failed!" + git pull --ff-only || ax_error "Git pull failed!" + git log --pretty=format:"%C(yellow)%h %C(blue)%ar %C(green)%an %Creset%s" ORIG_HEAD.. ) else ax_error "Unknown repository type!" @@ -294,25 +408,43 @@ function CheckPlugins { missing_plugins=() invalid_plugins=() + # Building cache file for all zshrc core files: + if ! T=$(mktemp); then + ax_error "Failed to create temporary file!" + return 1 + fi + for p in $AXZSH/core/*/*.zshrc; do + [[ "$(basename "$p")" == "01_zprofile.zshrc" ]] && continue + printf "# BEGIN: %s\naxzsh_plugin_init()\n{\n" "$p" >>"$T" + cat "$p" >>"$T" + printf "}\naxzsh_plugin_init\n# END: %s\n\n" "$p" >>"$T" + done + ax_msg - "Checking plugins ..." - for dir ($AXZSH/plugins/*(N)); do + for dir ($AXZSH/plugins/[a-z0-9]*(N)); do plugin=${dir:t} # Test if plugin is already enabled - [[ -e "$AXZSH/active_plugins/$plugin" ]] \ - && enabled=" (enabled)" \ - || unset enabled + if [[ -e "$AXZSH/active_plugins/$plugin" ]]; then + printf ' \e[1;32m+\e[m "\e[1m%s\e[m" ... ' "${plugin}" + enabled=1 + else + printf ' \e[1;31m-\e[m "%s" ... ' "${plugin}" + unset enabled + fi # Test plugin ... - printf " - \"%s\"%s ... " "$plugin" "$enabled" new_plugin="" - for script ($AXZSH/plugins/$plugin/$plugin.{zshrc,zprofile}); do + for script ($AXZSH/plugins/$plugin/$plugin.{zshrc,zprofile,ax-io}); do [[ -r "$script" ]] || continue - AXZSH_PLUGIN_CHECK=1 zsh -i -c "source $script"; r=$? - if [[ $r -eq 0 ]]; then - new_plugin=$plugin - break - fi + ( + AXZSH_PLUGIN_CHECK=1 + source "$T" + axzsh_plugin_fnc() { source "$script" } + axzsh_plugin_fnc + ); r=$? + [[ $r -eq 0 ]] && new_plugin=$plugin + break done if [[ -n "$new_plugin" ]]; then detected_plugins+=($new_plugin) @@ -324,9 +456,10 @@ function CheckPlugins { ax_msg 1 "optional." else [[ -n "$enabled" ]] && invalid_plugins+=($plugin) - ax_msg 2 "failed." + ax_msg 2 "failed ($r)." fi done + rm -f "$T" echo result=0 @@ -393,6 +526,10 @@ case "$cmd" in [[ $# -eq 0 ]] || Usage ListEnabledPlugins ;; + "plugin-help") + [[ $# -eq 1 ]] || Usage + PluginHelp "$1" + ;; "reset-plugins") [[ $# -eq 0 ]] || Usage ResetPlugins @@ -419,10 +556,13 @@ case "$cmd" in ;; "update-caches") [[ $# -eq 0 ]] || Usage - UpdatePluginCache + UpdatePluginCache -v + ;; + "--version"|"version") + Version >&2 ;; - "--help") - Usage + "--help"|"help") + Usage >&2 ;; *) ax_error "Invalid command \"$cmd\"!"