#!/usr/bin/env zsh # ------------------------------------------------------------------------------ # UTILS # Utils for common used actions # This file is used as a API for sections developers # ------------------------------------------------------------------------------ # Check if command exists in $PATH # USAGE: # spaceship::exists spaceship::exists() { command -v $1 > /dev/null 2>&1 } # Check if function is defined # USAGE: # spaceship::defined spaceship::defined() { typeset -f + "$1" &> /dev/null } # Precompile zsh file to ZWC (zsh word code) # USAGE: # spaceship::precomile spaceship::precompile() { spaceship::exists zcompile || return 1 local file="$1" if [[ ! $file.zwc -nt $file && -w "$(dirname $1)" ]]; then zcompile -R -- $file.zwc $file fi } # Check if the current directory is in a Git repository. # USAGE: # spaceship::is_git spaceship::is_git() { # See https://git.io/fp8Pa for related discussion [[ $(command git rev-parse --is-inside-work-tree 2>/dev/null) == true ]] } # Check if the current directory is in a Mercurial repository. # USAGE: # spaceship::is_hg spaceship::is_hg() { local hg_root="$(spaceship::upsearch .hg)" [[ -n "$hg_root" ]] &>/dev/null } # Checks if the section is async or not # USAGE: # spaceship::is_section_async
spaceship::is_section_async() { local section="$1" local sync_sections=( user dir host exec_time async line_sep jobs exit_code char ) # Some sections must be always sync if (( $sync_sections[(Ie)$section] )); then return 1 fi # If user disabled async rendering for whole prompt if [[ "$SPACESHIP_PROMPT_ASYNC" != true ]]; then return 1 fi local async_option="SPACESHIP_${(U)section}_ASYNC" [[ "${(P)async_option}" == true ]] } # Check if async is available and there is an async section # USAGE: # spaceship::is_prompt_async spaceship::is_prompt_async() { [[ "$SPACESHIP_PROMPT_ASYNC" == true ]] && (( ASYNC_INIT_DONE )) } # Print message backward compatibility warning # USAGE: # spaceship::deprecated [message] spaceship::deprecated() { [[ -n $1 ]] || return local deprecated=$1 message=$2 local deprecated_value=${(P)deprecated} # the value of variable name $deprecated [[ -n $deprecated_value ]] || return print -P "%B$deprecated%b is deprecated. $message" } # Display seconds in human readable format # For that use `strftime` and convert the duration (float) to seconds (integer). # USAGE: # spaceship::displaytime [precision] spaceship::displaytime() { local duration="$1" precision="$2" [[ -z "$precision" ]] && precision=1 integer D=$((duration/60/60/24)) integer H=$((duration/60/60%24)) integer M=$((duration/60%60)) local S=$((duration%60)) [[ $D > 0 ]] && printf '%dd ' $D [[ $H > 0 ]] && printf '%dh ' $H [[ $M > 0 ]] && printf '%dm ' $M printf %.${precision}f%s $S s } # Union of two or more arrays # USAGE: # spaceship::union [arr1[ arr2[ ...]]] # EXAMPLE: # $ arr1=('a' 'b' 'c') # $ arr2=('b' 'c' 'd') # $ arr3=('c' 'd' 'e') # $ spaceship::union $arr1 $arr2 $arr3 # > a b c d e spaceship::union() { typeset -U sections=("$@") echo $sections } # Upsearch for specific file or directory # Returns the path to the first found file or fails # USAGE: # spaceship::upsearch # EXAMPLE: # $ spaceship::upsearch package.json node_modules # > /home/username/path/to/project/node_modules spaceship::upsearch() { # Parse CLI options zparseopts -E -D \ s=silent -silent=silent local files=("$@") local root="$(pwd -P)" # Go up to the root while [ "$root" ]; do # For every file as an argument for file in "${files[@]}"; do local filepath="$(find $root -maxdepth 1 -name $file -print -quit 2>/dev/null)" if [[ -n "$filepath" ]]; then [[ -z "$silent" ]] && echo "$filepath" return 0 fi done if [[ -d "$root/.git" || -d "$root/.hg" ]]; then # If we reached the root of repo, return non-zero return 1 fi # Go one level up root="${root%/*}" done # If we reached the root, return non-zero return 1 } # Read data file with dot notation (JSON, YAML, TOML, XML) # USAGE: # spaceship::datafile -- [key] # EXAMPLE: # $ spaceship::datafile --json package.json "author.name" # > "John Doe" spaceship::datafile() { # Parse CLI options zparseopts -E -D \ -json=json \ -yaml=yaml \ -toml=toml \ -xml=xml local file="$1" key="$2" if [[ -n "$yaml" ]]; then if spaceship::exists yq; then yq -r ".$key" "$file" elif spaceship::exists ruby; then ruby -r yaml -e "puts '$key'.split('.').reduce(YAML::load_file('$file')) { |obj, key| obj[key] }" 2>/dev/null elif spaceship::exists python3; then python3 -c "import yaml, functools; print(functools.reduce(lambda obj, key: obj[key] if key else obj, '$key'.split('.'), yaml.safe_load(open('$file'))))" 2>/dev/null else return 1 fi fi if [[ -n "$json" ]]; then if spaceship::exists jq; then jq -r ".$key" "$file" 2>/dev/null elif spaceship::exists yq; then yq -r ".$key" "$file" 2>/dev/null elif spaceship::exists ruby; then ruby -r json -e "puts '$key'.split('.').reduce(JSON::load(File.read('$file'))){ |obj, key| obj[key] }" 2>/dev/null elif spaceship::exists python3; then python3 -c "import json, functools; print(functools.reduce(lambda obj, key: obj[key] if key else obj, '$key'.split('.'), json.load(open('$file'))))" 2>/dev/null elif spaceship::exists node; then node -p "require('./$file').$key" 2>/dev/null else return 1 fi fi if [[ -n "$toml" ]]; then if spaceship::exists tomlq; then tomlq -r ".$key" "$file" else return 1 fi fi if [[ -n "$xml" ]]; then if spaceship::exists xq; then xq -r ".$key" "$file" else return 1 fi fi # todo: grep by regexp? return 1 } # grep with --color=never or not # USAGE: # spaceship::grep [options] [pattern] [file ...] spaceship::grep() { local GREP_OPTIONS="" if command grep --color=never "" &>/dev/null <<< ""; then GREP_OPTIONS="--color=never" fi command grep $GREP_OPTIONS "$@" }