From d24e84255be2828df3c3892a2f19274441740aa3 Mon Sep 17 00:00:00 2001 From: Andrew Janke Date: Sat, 14 Feb 2015 21:28:50 -0500 Subject: [PATCH] Themes: Fold themes plugin in to core oh-my-zsh Rewrite theme() and lstheme() to remove side effects, add debugging, and fix `local` inside theme definitions. Add `theme next` for stepping through theme list, and "blacklist" support. Modify tools/theme_chooser to use new theme functions. --- .gitignore | 1 + completions/_theme | 3 + lib/misc.zsh | 4 +- lib/theme-and-appearance.zsh | 391 +++++++++++++++++++++++++++++-- oh-my-zsh.sh | 29 +-- plugins/themes/_theme | 3 - plugins/themes/themes.plugin.zsh | 24 -- tools/theme_chooser.sh | 92 +++++--- 8 files changed, 452 insertions(+), 95 deletions(-) create mode 100644 completions/_theme delete mode 100644 plugins/themes/_theme delete mode 100644 plugins/themes/themes.plugin.zsh diff --git a/.gitignore b/.gitignore index b2022081a..0ed3fb094 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ custom/ # temp files directories cache/ log/ +.AppleDouble diff --git a/completions/_theme b/completions/_theme new file mode 100644 index 000000000..3186943ea --- /dev/null +++ b/completions/_theme @@ -0,0 +1,3 @@ +#compdef theme + +_arguments "1: :($(lstheme))" diff --git a/lib/misc.zsh b/lib/misc.zsh index 3052b7710..a13491182 100644 --- a/lib/misc.zsh +++ b/lib/misc.zsh @@ -38,5 +38,7 @@ if [[ -z "$LC_CTYPE" && -z "$LC_ALL" ]]; then export LC_CTYPE=${LANG%%:*} # pick the first entry from LANG fi -# recognize comments setopt interactivecomments +setopt auto_cd +setopt multios +setopt cdablevars diff --git a/lib/theme-and-appearance.zsh b/lib/theme-and-appearance.zsh index 96f34aa81..2fa1368bf 100644 --- a/lib/theme-and-appearance.zsh +++ b/lib/theme-and-appearance.zsh @@ -1,13 +1,13 @@ -# ls colors +# Configure and enable ls colors + autoload -U colors && colors -# Enable ls colors export LSCOLORS="Gxfxcxdxbxegedabagacad" # TODO organise this chaotic logic -if [[ "$DISABLE_LS_COLORS" != "true" ]]; then - # Find the option for using colors in ls, depending on the version +if [[ $DISABLE_LS_COLORS != "true" ]]; then + # Find the option for using colors in ls, depending on the version: Linux or BSD if [[ "$OSTYPE" == netbsd* ]]; then # On NetBSD, test if "gls" (GNU ls) is installed (this one supports colors); # otherwise, leave ls as is, because NetBSD's ls doesn't support -G @@ -39,17 +39,380 @@ if [[ "$DISABLE_LS_COLORS" != "true" ]]; then fi fi -setopt auto_cd -setopt multios +if [[ -n $WINDOW ]]; then + SCREEN_NO="%B$WINDOW%b " +else + SCREEN_NO="" +fi + +# OMZ themes use promptsubst, so make sure it's on setopt prompt_subst -[[ -n "$WINDOW" ]] && SCREEN_NO="%B$WINDOW%b " || SCREEN_NO="" +# Set to true to enable debugging output for theme functions +# Note that this can cause unstable behavior, especially with these themes: +# agnoster dstufft +ZSH_THEME_DEBUG=${ZSH_THEME_DEBUG:-false} +# These themes are known to interact badly with our debugging support +_OMZ_DEBUG_BLACKLISTED_THEMES=(agnoster dstufft dogenpunk fino fino-time half-life \ + kolo peepcode smt steeef suvash zhann) -# Apply theming defaults -PS1="%n@%m:%~%# " -# git theming default: Variables for theming the git info prompt -ZSH_THEME_GIT_PROMPT_PREFIX="git:(" # Prefix at the very beginning of the prompt, before the branch name -ZSH_THEME_GIT_PROMPT_SUFFIX=")" # At the very end of the prompt -ZSH_THEME_GIT_PROMPT_DIRTY="*" # Text to display if the branch is dirty -ZSH_THEME_GIT_PROMPT_CLEAN="" # Text to display if the branch is clean +# Loads a theme +# +# Usage: +# theme - load named theme +# theme random - load a random theme +# theme - load a theme by index (where is an integer) +# theme next - load the next theme in the list of defined themes +# +# If no argument is given, `theme random` is the default behavior. +# +# Return value: +# 0 on success +# Nonzero on failure, such as requested theme not being found or theme index +# out of range. +# +# The "random" and "next" forms will skip over themes in the ZSH_BLACKLISTED_THEMES +# variable. +# +# As a consequence of this argument syntax, themes may not be named "random", "next", +# or an integer number. +function theme() { + local themes n_themes random_theme blacklist + if [[ -z $1 || $1 == "random" ]]; then + # Special case: random theme + blacklist=($(_omz_theme_blacklist)) + themes=($(lstheme)) + #themes=(${themes:|blacklist}) + _omz_array_setdiff themes themes blacklist + n_themes=${#themes[@]} + ((n=(RANDOM%n_themes)+1)) + random_theme=${themes[$n]} + echo "[oh-my-zsh] Loading random theme '$random_theme'..." + theme $random_theme + elif [[ $1 == "next" ]]; then + # Auto-advance to next theme + _omz_theme_n next + elif [[ $1 =~ '^[0-9]+$' ]]; then + # Select theme by index + _omz_theme_n $1 + else + # Main case: load named theme + _omz_load_theme $1 + fi +} + +function _omz_load_theme() { + local name=$1 + local theme_dir found + found=false + for theme_dir ($ZSH_CUSTOM $ZSH_CUSTOM/themes $ZSH/themes); do + if [[ -f "$theme_dir/$name.zsh-theme" ]]; then + found=true + _omz_load_theme_from_file $name "$theme_dir/$name.zsh-theme" + break + fi + done + if [[ $found == false ]]; then + echo "[oh-my-zsh] Theme not found: '$name'" + return 1 + fi +} + +# Loads a theme by index +# +# Usage: +# themen - advance to the next theme +# themen next - advance to the next theme +# themen - load theme number +# +# Loads a theme selected by index into list of defined themes, instead of by +# name. This is to make it easy to cycle through all the themes for debugging +# or browsing purposes. +# +# If called without an argument, it just advances to the next theme in the list +# +# `themen next` will ignore themes in the ZSH_BLACKLISTED_THEMES variable. +function _omz_theme_n() { + # Numeric index argument: select theme by index + local themes n name n_themes blacklist + themes=($(lstheme)) + n_themes=${#themes[@]} + if [[ -z $1 || $1 == "next" ]]; then + # Auto-advance to next theme + # Find index of currently loaded theme + local last_n=${themes[(i)$ZSH_THEME]} + (( n = (last_n % n_themes) + 1 )) + # Advance past blacklisted themes. Do it this way instead of removing blacklist + # from themes list to keep indexes stable + blacklist=($(_omz_theme_blacklist)) + while [[ ${blacklist[(i)${themes[n]}]} -le ${#blacklist} ]]; do + (( n = n % n_themes + 1 )) + done + else + n=$1 + if [[ $n -gt $n_themes ]]; then + printf "[oh-my-zsh]: Theme index %s is out of range (max is %s)\n" $n $n_themes + return 1 + fi + fi + name=${themes[$n]} + echo "Loading theme #$n/$n_themes: '$name'" + theme $name +} + +# Computes the set difference between two arrays using only ZSH 4.x features +# +# _omz_array_setdiff(c, a, b) +# +# Determines all the items in $a that are not in $b, and outputs them. +# This is the same functionality as ZSH 5.x's "c=(${a:|b})" expansion operation, +# but is re-implemented here for compatibility with ZSH 4.x. +# +# This operates by "reference", so caller should pass in names of the input +# parameters, not their values. +# +# Implementation note: the input variables may not be named "omz_asd_a", "omz_asd_b", +# or "omz_asd_out_name". +# due to dynamic scoping conflicts. And you cannot use the numeric parameters ($1, $2, etc) +# as inputs. +# +# Example: +# +# a=(foo bar baz) +# b=(bar qux) +# _omz_array_setdiff c a b +# +# After the function call, $c will contain (foo baz). +# +function _omz_array_setdiff() { + local omz_asd_a omz_asd_b omz_asd_out_name + omz_asd_out_name=$1 + omz_asd_a=(${(P)2}) + omz_asd_b=(${(P)3}) + local my_out item + my_out=() + for item (${omz_asd_a}); do + if [[ ${omz_asd_b[(i)$item]} -gt ${#omz_asd_b} ]]; then + my_out+=($item) + fi + done + set -A $omz_asd_out_name $my_out +} + + +# Variables to track hook functions installed by themes +_OMZ_THEME_CHPWD_FUNCTIONS=() +_OMZ_THEME_PRECMD_FUNCTIONS=() +_OMZ_THEME_PREEXEC_FUNCTIONS=() + +# Outputs the effective theme blacklist +function _omz_theme_blacklist() { + local blacklist=$ZSH_BLACKLISTED_THEMES + if [[ $ZSH_THEME_DEBUG == true ]]; then + blacklist+=($_OMZ_DEBUG_BLACKLISTED_THEMES) + fi + echo ${(F)blacklist} +} + +# Implementation of loading a theme +# Most of the code in here is for tracking hooks and debugging support +function _omz_load_theme_from_file() { + local name=$1 file=$2 params_before exclude_params + local -A values_before + + # Reset so theme is loaded into a clean slate + _omz_reset_theme + + # Set up tracking and debugging + local chpwd_fcns_0 precmd_fcns_0 preexec_fcns_0 chpwd_0 precmd_0 preexec_0 + local params_after params_added param ignore_params + chpwd_0=$(which chpwd) + precmd_0=$(which precmd) + preexec_0=$(which preexec) + chpwd_fcns_0=($chpwd_functions) + precmd_fcns_0=($precmd_functions) + preexec_fcns_0=($preexec_functions) + if [[ $ZSH_THEME_DEBUG == true ]]; then + params_before=($(set +)) + fi + for param ($params_before); do + values_before[$param]=${(P)param} + done + + # Actually load the theme, using an indirection function + _omz_source_theme_file $file + + # Debugging stuff + if [[ $ZSH_THEME_DEBUG == true ]]; then + params_after=($(set +)) + #params_added=(${params_after:|params_before}) + _omz_array_setdiff params_added params_after params_before + ignore_params=(LINENO RANDOM _ parameters prompt values_before modules \ + params_added ignore_params params_before params_after params_changed \ + SECONDS TTYIDLE PS1 PS2 PS3 PS4 RPS1 RPS2) + #params_before=(${params_before:|ignore_params}) + _omz_array_setdiff params_before params_before ignore_params + local params_changed + params_changed=() + for param ($params_before); do + if [[ "${(P)param}" != "${values_before[$param]}" ]]; then + params_changed+=($param) + fi + done + fi + + # Record which theme was loaded + ZSH_THEME=$name + + # Track changes to hooks + #_OMZ_THEME_CHPWD_FUNCTIONS=(${chpwd_functions:|chpwd_fcns_0}) + _omz_array_setdiff _OMZ_THEME_CHPWD_FUNCTIONS chpwd_functions chpwd_fcns_0 + #_OMZ_THEME_PRECMD_FUNCTIONS=(${precmd_functions:|precmd_fcns_0}) + _omz_array_setdiff _OMZ_THEME_PRECMD_FUNCTIONS precmd_functions precmd_fcns_0 + #_OMZ_THEME_PREEXEC_FUNCTIONS=(${preexec_functions:|preexec_fcns_0}) + _omz_array_setdiff _OMZ_THEME_PREEXEC_FUNCTIONS preexec_functions preexec_fcns_0 + + # Post-loading debugging + if [[ $ZSH_THEME_DEBUG == true ]]; then + echo "Loaded theme '$name' from file $file" + if [[ -n $params_added ]]; then + printf '=== %s ===\n%s\n' "Theme added parameters:" ${(F)params_added} + fi + if [[ -n $params_changed ]]; then + printf '=== %s ===\n%s\n' "Theme changed parameters:" ${(F)params_changed} + fi + if [[ -n "${_OMZ_THEME_CHPWD_FUNCTIONS}${_OMZ_THEME_PRECMD_FUNCTIONS}${_OMZ_THEME_PREEXEC_FUNCTIONS}" ]]; then + printf '=== %s ===\n' "Theme added hooks:" + if [[ -n $_OMZ_THEME_CHPWD_FUNCTIONS ]]; then + echo "Theme added chpwd hooks: $_OMZ_THEME_CHPWD_FUNCTIONS" + fi + if [[ -n $_OMZ_THEME_PRECMD_FUNCTIONS ]]; then + echo "Theme added precmd hooks: $_OMZ_THEME_PRECMD_FUNCTIONS" + fi + if [[ -n $_OMZ_THEME_PREEXEC_FUNCTIONS ]]; then + echo "Theme added preexec hooks: $_OMZ_THEME_PREEXEC_FUNCTIONS" + fi + fi + if [[ $(which chpwd) != $chpwd_0 ]]; then + echo "WARNING: Theme changed chpwd()" + fi + if [[ $(which preexec) != $preexec_0 ]]; then + echo "WARNING: Theme changed preexec()" + fi + if [[ $(which precmd) != $precmd_0 ]]; then + echo "WARNING: Theme changed precmd()" + fi + fi +} + +# Sources the given file +# The only reason this function exists is to provide a layer of +# indirection so that the theme file runs in its own function call stack frame +# and "local" statements in the theme definitions work as intended. +function _omz_source_theme_file() { + source $1 +} + +# Resets all theme settings to their default state +# (To the extent that we know what themes do, that is.) +# This will reset all variables used by the core OMZ *_prompt_info functions. +# It will also remove any hook functions installed by the current theme, if it +# was loaded by the theme() function +function _omz_reset_theme() { + # Prompts + PROMPT="%n@%m:%~%# " + PROMPT2='%_> ' + PROMPT3='?# ' + PROMPT4='+%N:%i> ' + unset RPROMPT RPROMPT2 + + # This assumes that all ZSH_THEME__* variables are owned by + # OMZ theming, and can be reset en masse + # All the commented-out variables are there to serve as a list of things + # that are used by theme support and could be given default values + + # git_prompt_info variables + unset -m 'ZSH_THEME_GIT_PROMPT_*' + ZSH_THEME_GIT_PROMPT_PREFIX="git:(" # Prefix at the very beginning of the prompt, before the branch name + ZSH_THEME_GIT_PROMPT_SUFFIX=")" # At the very end of the prompt + #ZSH_THEME_GIT_PROMPT_PREFIX= + #ZSH_THEME_GIT_PROMPT_SUFFIX= + #ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX= + #ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX= + ZSH_THEME_GIT_PROMPT_DIRTY="*" # Text to display if the branch is dirty + ZSH_THEME_GIT_PROMPT_CLEAN="" # Text to display if the branch is clean + #ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE= + #ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE= + #ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE= + #ZSH_THEME_GIT_PROMPT_AHEAD= + #ZSH_THEME_GIT_PROMPT_BEHIND= + #ZSH_THEME_GIT_PROMPT_SHA_BEFORE= + #ZSH_THEME_GIT_PROMPT_SHA_AFTER= + #ZSH_THEME_GIT_PROMPT_ADDED= + #ZSH_THEME_GIT_PROMPT_MODIFIED= + #ZSH_THEME_GIT_PROMPT_RENAMED= + #ZSH_THEME_GIT_PROMPT_DELETED= + #ZSH_THEME_GIT_PROMPT_STASHED= + #ZSH_THEME_GIT_PROMPT_UNMERGED= + #ZSH_THEME_GIT_PROMPT_DIVERGED= + #ZSH_THEME_GIT_PROMPT_UNTRACKED= + # nvm_prompt_info variables + unset -m 'ZSH_THEME_NVM_PROMPT_*' + #ZSH_THEME_NVM_PROMPT_PREFIX= + #ZSH_THEME_NVM_PROMPT_SUFFIX= + # rvm_prompt_info variables + unset -m 'ZSH_THEME_RVM_PROMPT_*' + #ZSH_THEME_RVM_PROMPT_PREFIX= + #ZSH_THEME_RVM_PROMPT_SUFFIX= + #ZSH_THEME_RVM_PROMPT_OPTIONS= + # svn_prompt_info variables + unset -m 'ZSH_THEME_SVN_PROMPT_*' + #ZSH_THEME_SVN_PROMPT_CLEAN + #ZSH_THEME_SVN_PROMPT_DIRTY + #ZSH_THEME_SVN_PROMPT_PREFIX + #ZSH_THEME_SVN_PROMPT_SUFFIX + + # Hook functions + if [[ -n $_OMZ_THEME_CHPWD_FUNCTIONS ]]; then + #echo Removing chpwd hooks: $_OMZ_THEME_CHPWD_FUNCTIONS + #chpwd_functions=(${chpwd_functions:|_OMZ_THEME_CHPWD_FUNCTIONS}) + _omz_array_setdiff chpwd_functions chpwd_functions _OMZ_THEME_CHPWD_FUNCTIONS + fi + if [[ -n $_OMZ_THEME_PRECMD_FUNCTIONS ]]; then + #echo Removing precmd hooks: $_OMZ_THEME_PRECMD_FUNCTIONS + #precmd_functions=(${precmd_functions:|_OMZ_THEME_PRECMD_FUNCTIONS}) + _omz_array_setdiff precmd_functions precmd_functions _OMZ_THEME_PRECMD_FUNCTIONS + fi + if [[ -n $_OMZ_THEME_PREEXEC_FUNCTIONS ]]; then + #echo Removing preexec hooks: $_OMZ_THEME_PREEXEC_FUNCTIONS + #preexec_functions=(${preexec_functions:|_OMZ_THEME_PREEXEC_FUNCTIONS}) + _omz_array_setdiff preexec_functions preexec_functions _OMZ_THEME_PREEXEC_FUNCTIONS + fi + +} + + +# List available themes by name +# +# The list will always be in sorted order, so you can index in to it. +# Themes in the "blacklist" are still included in lstheme, because they're +# still eligible for direct reference by explicit name or index, and that +# keeps the order stable. +function lstheme() { + local themes x theme_dir + themes=() + for theme_dir ($ZSH_CUSTOM $ZSH_CUSTOM/themes $ZSH/themes); do + if [[ -d $theme_dir ]]; then + themes+=($(_omz_lstheme_dir $theme_dir)) + fi + done + themes=(${(ou)themes}) + echo ${(F)themes} +} + +# List themes defined in a given dir +function _omz_lstheme_dir() { + ls $1 | grep '.zsh-theme$' | sed 's,\.zsh-theme$,,' +} + diff --git a/oh-my-zsh.sh b/oh-my-zsh.sh index a7de646f2..64023d1f4 100644 --- a/oh-my-zsh.sh +++ b/oh-my-zsh.sh @@ -1,5 +1,5 @@ # Check for updates on initial load... -if [ "$DISABLE_AUTO_UPDATE" != "true" ]; then +if [[ "$DISABLE_AUTO_UPDATE" != "true" ]]; then env ZSH=$ZSH DISABLE_UPDATE_PROMPT=$DISABLE_UPDATE_PROMPT zsh -f $ZSH/tools/check_for_upgrade.sh fi @@ -30,7 +30,7 @@ fi # TIP: Add files you don't want in git to .gitignore for config_file ($ZSH/lib/*.zsh); do custom_config_file="${ZSH_CUSTOM}/lib/${config_file:t}" - [ -f "${custom_config_file}" ] && config_file=${custom_config_file} + [[ -f "${custom_config_file}" ]] && config_file=${custom_config_file} source $config_file done @@ -60,7 +60,7 @@ else fi # Save the location of the current completion dump file. -if [ -z "$ZSH_COMPDUMP" ]; then +if [[ -z "$ZSH_COMPDUMP" ]]; then ZSH_COMPDUMP="${ZDOTDIR:-${HOME}}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}" fi @@ -79,9 +79,9 @@ fi # Load all of the plugins that were defined in ~/.zshrc for plugin ($plugins); do - if [ -f $ZSH_CUSTOM/plugins/$plugin/$plugin.plugin.zsh ]; then + if [[ -f $ZSH_CUSTOM/plugins/$plugin/$plugin.plugin.zsh ]]; then source $ZSH_CUSTOM/plugins/$plugin/$plugin.plugin.zsh - elif [ -f $ZSH/plugins/$plugin/$plugin.plugin.zsh ]; then + elif [[ -f $ZSH/plugins/$plugin/$plugin.plugin.zsh ]]; then source $ZSH/plugins/$plugin/$plugin.plugin.zsh fi done @@ -93,21 +93,6 @@ done unset config_file # Load the theme -if [ "$ZSH_THEME" = "random" ]; then - themes=($ZSH/themes/*zsh-theme) - N=${#themes[@]} - ((N=(RANDOM%N)+1)) - RANDOM_THEME=${themes[$N]} - source "$RANDOM_THEME" - echo "[oh-my-zsh] Random theme '$RANDOM_THEME' loaded..." -else - if [ ! "$ZSH_THEME" = "" ]; then - if [ -f "$ZSH_CUSTOM/$ZSH_THEME.zsh-theme" ]; then - source "$ZSH_CUSTOM/$ZSH_THEME.zsh-theme" - elif [ -f "$ZSH_CUSTOM/themes/$ZSH_THEME.zsh-theme" ]; then - source "$ZSH_CUSTOM/themes/$ZSH_THEME.zsh-theme" - else - source "$ZSH/themes/$ZSH_THEME.zsh-theme" - fi - fi +if [[ $ZSH_THEME != "" ]]; then + theme $ZSH_THEME fi diff --git a/plugins/themes/_theme b/plugins/themes/_theme deleted file mode 100644 index 8214ddb0d..000000000 --- a/plugins/themes/_theme +++ /dev/null @@ -1,3 +0,0 @@ -#compdef theme - -_arguments "1: :($(lstheme | tr "\n" " "))" diff --git a/plugins/themes/themes.plugin.zsh b/plugins/themes/themes.plugin.zsh deleted file mode 100644 index 7519b0253..000000000 --- a/plugins/themes/themes.plugin.zsh +++ /dev/null @@ -1,24 +0,0 @@ -function theme -{ - if [ -z "$1" ] || [ "$1" = "random" ]; then - themes=($ZSH/themes/*zsh-theme) - N=${#themes[@]} - ((N=(RANDOM%N)+1)) - RANDOM_THEME=${themes[$N]} - source "$RANDOM_THEME" - echo "[oh-my-zsh] Random theme '$RANDOM_THEME' loaded..." - else - if [ -f "$ZSH_CUSTOM/$1.zsh-theme" ] - then - source "$ZSH_CUSTOM/$1.zsh-theme" - else - source "$ZSH/themes/$1.zsh-theme" - fi - fi -} - -function lstheme -{ - cd $ZSH/themes - ls *zsh-theme | sed 's,\.zsh-theme$,,' -} diff --git a/tools/theme_chooser.sh b/tools/theme_chooser.sh index 2c2a379ba..bbb784799 100755 --- a/tools/theme_chooser.sh +++ b/tools/theme_chooser.sh @@ -1,17 +1,27 @@ #!/bin/zsh # Zsh Theme Chooser by fox (fox91 at anche dot no) +# # This program is free software. It comes without any warranty, to # the extent permitted by applicable law. You can redistribute it # and/or modify it under the terms of the Do What The Fuck You Want # To Public License, Version 2, as published by Sam Hocevar. See # http://sam.zoy.org/wtfpl/COPYING for more details. -THEMES_DIR="$ZSH/themes" +# This is intended to be run in its own shell process, as a command +# To get it to work properly, you should set ZSH and ZSH_CUSTOM in its +# environment before running. +# +# Note that themes with both multi-line prompts and RPROMPTs may not display +# properly. + +ZSH=${ZSH:-$HOME/.oh-my-zsh} FAVLIST="${HOME}/.zsh_favlist" source $ZSH/oh-my-zsh.sh + function noyes() { + local a read "a?$1 [y/N] " if [[ $a == "N" || $a == "n" || $a = "" ]]; then return 0 @@ -20,11 +30,11 @@ function noyes() { } function theme_preview() { - THEME=$1 - THEME_NAME=`echo $THEME | sed s/\.zsh-theme$//` - print "$fg[blue]${(l.((${COLUMNS}-${#THEME_NAME}-5))..─.)}$reset_color $THEME_NAME $fg[blue]───$reset_color" - source "$THEMES_DIR/$THEME" + local THEME=$1 + print "$fg[blue]${(l.((${COLUMNS}-${#THEME}-5))..─.)}$reset_color $THEME $fg[blue]───$reset_color" + theme $THEME cols=$(tput cols) + #TODO: Figure out how to display RPROMPT correctly print -P "$PROMPT $RPROMPT" } @@ -37,61 +47,81 @@ function banner() { } function usage() { - echo "Usage: $0 [options] [theme]" - echo - echo "Options" - echo " -l List available themes" - echo " -s Show all themes" - echo " -h Get this help message" - exit 1 + local EXIT_STATUS=$1 + echo \ +"Usage: $TOOL_NAME [options] [theme] +Options: + -s Show (preview) all themes + -l List available themes + -a List current favourite list contents + -h Display this help message + +If [theme] is supplied, previews that single theme. +If no option and no argument is given, previews all themes in turn, giving user +the option to add each to their favourites list. +If you have a custom ZSH or ZSH_CUSTOM directory defined, you should pass that in +via environment variables. For example: + ZSH=\$ZSH ZSH_CUSTOM=\$ZSH_CUSTOM $TOOL_NAME" + + exit $EXIT_STATUS } function list_themes() { - for THEME in $(ls $THEMES_DIR); do - THEME_NAME=`echo $THEME | sed s/\.zsh-theme$//` - echo $THEME_NAME - done + lstheme } function insert_favlist() { - if grep -q "$THEME_NAME" $FAVLIST 2> /dev/null ; then - echo "Already in favlist" + local THEME=$1 + #TODO: This simple grep will match substrings of theme names, not just full names + if grep -q $THEME $FAVLIST 2> /dev/null ; then + echo "Already in favlist: $THEME" else - echo $THEME_NAME >> $FAVLIST - echo "Saved to favlist" + echo $THEME >> $FAVLIST + echo "Added to favlist: $THEME" fi - } function theme_chooser() { - for THEME in $(ls $THEMES_DIR); do + local THEME + if [[ -z $1 ]]; then + echo "Updating favourite list at $FAVLIST" + fi + for THEME in $(lstheme); do echo theme_preview $THEME echo if [[ -z $1 ]]; then - noyes "Do you want to add it to your favourite list ($FAVLIST)?" || \ - insert_favlist $THEME_NAME + noyes "Do you want to add it to your favourite list" || \ + insert_favlist $THEME echo fi done } -while getopts ":lhs" Option -do - case $Option in +function list_favlist() { + if [[ -f $FAVLIST ]]; then + cat $FAVLIST + fi + return 0; +} + +TOOL_NAME=${0##*/} +while getopts ":lhas" OPTION; do + case $OPTION in l ) list_themes ;; s ) theme_chooser 0 ;; - h ) usage ;; - * ) usage ;; # Default. + a ) list_favlist ;; + h ) usage 0 ;; + * ) echo "Unrecognized option" >&2; usage 1 ;; esac done -if [[ -z $Option ]]; then +if [[ -z $OPTION ]]; then if [[ -z $1 ]]; then banner echo theme_chooser else - theme_preview $1".zsh-theme" + theme_preview $1 fi fi