Files
dotfiles/dot/.bashrc.d/function.bash

216 lines
5.4 KiB
Bash

generate-bash-completion() {
local file="$1"
local command="$2"
if [[ -z "$file" || -z "$command" ]]; then
echo "usage: generate-bash-completion <file> <command>" >&2
echo "example: generate-bash-completion mycmd '_mycmd_completion'" >&2
return 1
fi
local completion_dir="${HOME}/.local/share/bash-completion/completions"
local completion_file="${completion_dir}/${file}"
if [[ -d "$completion_dir" && ! -w "$completion_dir" ]]; then
echo "ERROR: has no permission to write to directory '${completion_dir}'" >&2
return 1
fi
if [[ ! -f "$completion_file" ]]; then
if ! mkdir -p "$completion_dir"; then
echo "ERROR: cannot create directory '$completion_dir'" >&2
return 1
fi
if ! bash -c "$command" > "$completion_file"; then
echo "ERROR: failed to execute command '$command'" >&2
rm -f "$completion_file"
return 1
fi
fi
}
load-bash-completion() {
local silence=false
local -a files=()
while [[ $# -gt 0 ]]; do
case "$1" in
-s)
silence=true
shift
;;
--)
shift
files+=("$@")
break
;;
*)
files+=("$1")
shift
;;
esac
done
if [[ ${#files[@]} -eq 0 ]]; then
echo "usage: load-bash-completion [-s] <path1> [path2 ...]" >&2
echo "" >&2
echo " -s: if some completion file not exist, just skip it silently" >&2
echo "" >&2
echo "example: load-bash-completion pnpm npm" >&2
return 1
fi
local completion_dir="${HOME}/.local/share/bash-completion/completions"
for file in "${files[@]}"; do
local completion_file="${completion_dir}/${file}"
if [[ ! -e "$completion_file" ]]; then
if [[ "$silence" == false ]]; then
echo "WARNING: cannot found completion file '${file}'" >&2
fi
continue
fi
if [[ ! -r "$completion_file" ]]; then
if [[ "$silence" == false ]]; then
echo "WARNING: cannot read completion file '$file'" >&2
fi
continue
fi
source "$completion_file"
done
}
add-to-path() {
local silence=false
local -a dirs=()
while [[ $# -gt 0 ]]; do
case "$1" in
-s)
silence=true
shift
;;
--)
shift
dirs+=("$@")
break
;;
*)
dirs+=("$1")
shift
;;
esac
done
if [[ ${#dirs[@]} -eq 0 ]]; then
echo "usage: add-to-path [-s] <path1> [path2 ...]" >&2
echo "" >&2
echo " -s: if some path not exist, just skip it silently" >&2
echo "" >&2
echo "example: add-to-path /usr/local/bin /tmp/my-dir" >&2
return 1
fi
local dir
local dir_normalized
local new_path="$PATH"
for dir in "${dirs[@]}"; do
[[ -z "$dir" ]] && continue
dir_normalized="${dir%/}"
if [[ ! -d "$dir_normalized" ]]; then
if [[ "$silence" == false ]]; then
echo "WARNING: '${dir}' is not a valid directory, skipped." >&2
fi
continue
fi
case ":${new_path}:" in
*":${dir_normalized}:"*) ;;
*)
new_path="${dir_normalized}${new_path:+:}${new_path}"
;;
esac
done
if [[ "$new_path" != "$PATH" ]]; then
export PATH="$new_path"
fi
}
remove-from-path() {
if [[ $# -eq 0 ]]; then
echo "usage: remove-from-path <path1> [path2 ...]" >&2
echo "example: remove-from-path /usr/local/bin /tmp/my-dir" >&2
return 1
fi
local original_ifs="$IFS"
local -a remove_paths=("$@")
local new_path=""
local path
local remove_path
local path_normalized
local remove_path_normalized
local -i keep_path=1 # 1=keep, 0=remove
IFS=':'
for path in $PATH; do
[[ -z "$path" ]] && continue
path_normalized="${path%/}" # remove / at tail
keep_path=1
for remove_path in "${remove_paths[@]}"; do
remove_path_normalized="${remove_path%/}"
if [[ "$path_normalized" == "$remove_path_normalized" ]]; then
keep_path=0
break
fi
done
if [[ $keep_path -eq 1 ]]; then
new_path="${new_path}${new_path:+:}${path}"
fi
done
IFS="$original_ifs"
export PATH="${new_path}"
}
show-path() {
echo "$PATH" | tr ':' '\n' | nl -w2 -s'. '
}
unhash-command-in-dirs() {
if [[ $# -eq 0 ]]; then
echo "usage: unhash-command-in-dir <dir1> [dir2 ...]" >&2
echo "example: unhash-command-in-dir ~/.local/bin/ ~/.volta/bin/" >&2
return 1
fi
local -a dirs=("$1")
local dir
local dir_normalized
local file_path
local filename
for dir in "${dirs[@]}"; do
[[ -z "$dir" || ! -d "$dir" ]] && continue
dir_normalized="${dir%/}"
for file_path in "$dir_normalized"/*; do
[[ ! -f "$file_path" || ! -x "$file_path" ]] && continue
filename="$(basename "$file_path")"
hash -d "$filename" 2>/dev/null
done
done
}