248 lines
6.2 KiB
Bash
Executable File
248 lines
6.2 KiB
Bash
Executable File
#!/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 <command>
|
|
spaceship::exists() {
|
|
command -v $1 > /dev/null 2>&1
|
|
}
|
|
|
|
# Check if function is defined
|
|
# USAGE:
|
|
# spaceship::defined <function>
|
|
spaceship::defined() {
|
|
typeset -f + "$1" &> /dev/null
|
|
}
|
|
|
|
# Precompile zsh file to ZWC (zsh word code)
|
|
# USAGE:
|
|
# spaceship::precomile <file>
|
|
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 <section>
|
|
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 <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 <seconds> [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 <paths...>
|
|
# 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 --<type> <file> [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 "$@"
|
|
}
|