diff --git a/styler/.local/bin/styler b/styler/.local/bin/styler index ebc13a8..a48570f 100755 --- a/styler/.local/bin/styler +++ b/styler/.local/bin/styler @@ -1,11 +1,26 @@ #!/usr/bin/env bash readonly BASE_PATH="${STYLER_DATA_PATH:-${XDG_DATA_HOME:-$HOME/.local/share}/styler}" +readonly CACHE_PATH="${STYLER_CACHE_PATH:-${XDG_CACHE_HOME:-$HOME/.cache}/styler}" readonly PACKAGE_PATH="$BASE_PATH/packages" readonly PROCESSOR_PATH="$BASE_PATH/processors" -readonly VERSION="0.3.0" +readonly VERSION="0.4.1" + +# ensures that some grep-like program is available, prefers rg +setgrepper() { + if command -v rg 1>/dev/null 2>&1; then + GREPPER="rg" + elif command -v grep 1>/dev/null 2>&1; then + GREPPER="grep" + else + notify-send "grep missing" "styler needs grep, or preferably rg to work." + echo "grep missing!" "styler needs grep, or preferably rg to work." + exit 127 + fi +} +setgrepper main() { local cmd="" @@ -34,7 +49,7 @@ main() { esac shift - $cmd "$1" + $cmd "$@" ret=$((ret + $?)) exit $ret } @@ -56,6 +71,8 @@ usage() { " Same as 'theme' option, but changes will be made permanent." \ "" \ " list [processors|packages|themes] Print out all currently installed processors, templates, or themes from selection. " \ + " list themes Will print out themes which are available for all installed packages." \ + " list themes all Will print out every single installed theme, regardless of its universal availability." \ "" \ " download [username/repository] Download a base16 template into the package directory or download a processor16" \ " into the processor directory. Use user/repo format to automatically pull from github." \ @@ -99,7 +116,7 @@ get_processors() { for processor in "$package"/*; do [[ -e "$processor" ]] || break [[ -f "$processor" ]] || break - if grep -q -e '/theme_[[:alnum:]]\{1,\}$' <<<"$processor"; then + if ${GREPPER} -q -e '/theme_[[:alnum:]]\{1,\}$' <<<"$processor"; then printf "%s\n" "$(basename -- "$processor")" fi done @@ -107,11 +124,103 @@ get_processors() { done } -# retrieves all installed themes from all packages, appends applications they exist for +# retrieves all installed themes available to all packages +# can be called with `all` argument to return themes which only exist for some packages get_themes() { local themes themes=$(find "$PACKAGE_PATH" -type f -name 'base16-*') - echo "$themes" | sed "s/.*\\/base16-//" | sed "s/\\..*//" | sort | uniq + + local filtered + if [[ "$1" = "all" ]]; then + filtered="$(get_unique_themes "$themes")" + else + filtered="$(get_universal_themes "$themes")" + fi + + echo "$filtered" +} + +# filter down the list passed in to keep repeating base16 themes only once per name +# and remove surrounding path information (and file ending) +get_unique_themes() { + if _cache_invalid "$CACHED_UNIQUE_THEMES" "$PACKAGE_PATH"; then + notify-send "styler cache invalid" "rebuilding cache will take a moment..." + _cache_rebuild "$CACHED_UNIQUE_THEMES" _fetch_unique_themes "$@" + else + cat "$CACHED_UNIQUE_THEMES" + fi +} +readonly CACHED_UNIQUE_THEMES=${CACHE_PATH}/unique_themes + +# returns themes which are available in all installed packages +# returns cached version or rebuilds cache +get_universal_themes() { + if _cache_invalid "$CACHED_UNIVERSAL_THEMES" "$PACKAGE_PATH"; then + notify-send "styler cache invalid" "rebuilding cache will take a moment..." + _cache_rebuild "$CACHED_UNIVERSAL_THEMES" _fetch_universal_themes "$@" + else + cat "$CACHED_UNIVERSAL_THEMES" + fi +} +readonly CACHED_UNIVERSAL_THEMES=${CACHE_PATH}/universal_themes + +_fetch_unique_themes() { + echo "$1" | sed "s/.*\\/base16-//;s/\\..*//" | sort | uniq +} + +# only keep themes which are available in every installed package +_fetch_universal_themes() { + local themes="$1" + local unique + unique="$(get_unique_themes "$themes")" + + local packages + packages="$(get_packages)" + + local filtered + for t in $unique; do + for p in $packages; do + if ! echo "$themes" | ${GREPPER} -qe "^.*$p.*$t.*$" -; then + themes="$(echo "$themes" | sed "/$t/d")" + unique="$(echo "$unique" | sed "/$t/d")" + break + fi + done + done + echo "$unique" +} + +# returns true if changes to $2 are newer than $1 +# used to pass in cache file for $1, what it is caching for $2 +_cache_invalid() { + cache_upd="$(_last_update "$1")" + live_upd="$(_last_update "$2")" + if [ "${live_upd%.*}" -gt "${cache_upd%.*}" ]; then + true + else + false + fi +} + +# recreates target cache with output of function +# arguments: "target_cache_file" "function_name" "arguments_for_function" +_cache_rebuild() { + local target="$1" + shift + local fct="$1" + shift + local new + new="$($fct "$@")" + mkdir -p "$CACHE_PATH" + echo "$new" | tee "$target" +} + +# returns time of last update to argument passed in +# argument can be path to file or directory (searched recursively) +# if argument does not exist gives 0 +_last_update() { + [[ ! -e "$1" ]] && echo 0 && return + find "$1" -type f -printf "%T@\n" | sort -n | tail -n 1 } # temporarily switch theme, same thing as setting, only with permanence flag turned off for processors @@ -152,7 +261,7 @@ set_theme() { appext=$(sed -e 's|^[A-Za-z0-9-]\{1,\}/base16-||' <<<"$pkg") # Compares application extension with existing processors and runs the appropriate processor if found - processor=$(find "$PROCESSOR_PATH" -type f | grep -e "theme_$appext") + processor=$(find "$PROCESSOR_PATH" -type f | ${GREPPER} -e "theme_$appext") if [[ -f "$processor" ]]; then "$processor" "$PACKAGE_PATH" "$pkg" "$theme" "$permanent" else @@ -164,6 +273,7 @@ set_theme() { list() { local selected="$1" + shift case "$selected" in packages) @@ -173,7 +283,7 @@ list() { get_processors ;; themes) - get_themes + get_themes "$@" ;; *) echo "Please select one of packages | processors | themes to list." @@ -205,9 +315,9 @@ download() { # if package has patter name/base16-program, put it in packages; if name/process16-program put it in processors # if none of the above, assume it's a processor but warn the user - if grep -q -e '^[0-9A-Za-z-]\{1,\}/base16-[0-9A-Za-z-]\{1,\}$' <<<"$pkg"; then + if ${GREPPER} -q -e '^[0-9A-Za-z-]\{1,\}/base16-[0-9A-Za-z-]\{1,\}$' <<<"$pkg"; then git clone "$repo" "$PACKAGE_PATH/$pkg" - elif grep -q -e '^[0-9A-Za-z-]\{1,\}/process16-[0-9A-Za-z-]\{1,\}$' <<<"$pkg"; then + elif ${GREPPER} -q -e '^[0-9A-Za-z-]\{1,\}/process16-[0-9A-Za-z-]\{1,\}$' <<<"$pkg"; then git clone "$repo" "$PROCESSOR_PATH/$pkg" else echo "Package does not fit default naming scheme of packages/processors. Assuming it is a processor but please check manually."