1
0

improve command and completions

This commit is contained in:
2026-04-08 20:54:51 +02:00
parent 8a7f922b52
commit 7ca3e42cd3
3 changed files with 142 additions and 63 deletions

View File

@@ -6,14 +6,14 @@
readonly __GOTO_ROOT_DIR=~/.goto
# goto configuration file that contains the directory mappings
readonly __GOTO_FILE=${__GOTO_ROOT_DIR}/goto.yaml
# path to yq executable
# path to yq executable used by goto
readonly __GOTO_YQ=/usr/local/bin/yq
__goto_exists() {
[[ -f ${__GOTO_FILE} ]]
}
__goto_load() {
__goto_load_entries() {
# load the directory mappings from the configuration file into the variable reference passed as parameter
# $1: name of the result associative array to create
@@ -24,7 +24,8 @@ __goto_load() {
return
fi
local entries entry key value
local -a entries
local entry key value
mapfile entries < <(${__GOTO_YQ} 'explode(.) | to_entries[] | "\(.key) \(.value)"' ${__GOTO_FILE})
@@ -43,13 +44,27 @@ __goto_load() {
done
}
__goto_load_keys() {
# load the directory keys from the configuration file into the variable reference passed as parameter
# $1: name of the result array to create
local -n data_ref=$1
data_ref=()
if ! __goto_exists; then
return
fi
mapfile data_ref < <(${__GOTO_YQ} 'keys[]' ${__GOTO_FILE})
}
__goto_comp_keys() {
# loads and initializes directory aliases completions for the goto command
local -A data
__goto_load data
local -a data
__goto_load_keys data
_comp_compgen -- -W '"${!data[@]}"'
_comp_compgen -- -W '"${data[@]}"'
}
__goto_resolve_path() {
@@ -63,7 +78,7 @@ __goto_prompt() {
# prompt string for the terminal
local -A data
__goto_load data
__goto_load_entries data
local entry_key entry_value best_match="" best_key=""
@@ -71,7 +86,7 @@ __goto_prompt() {
entry_value=$(__goto_resolve_path "${data[${entry_key}]}")
# select the closest ancestor of the current working directory
if [[ "${PWD}" == "${entry_value}"* ]] && [[ ${#entry_value} -gt ${#best_match} ]]; then
if [[ "${PWD}" == "${entry_value}"?(/*) ]] && [[ ${#entry_value} -gt ${#best_match} ]]; then
best_match="${entry_value}"
best_key="${entry_key}"
fi
@@ -91,7 +106,7 @@ __goto_test() {
# command: goto -t
local -A data
__goto_load data
__goto_load_entries data
local entry_key entry_value
local -i ret_code=0
@@ -119,7 +134,7 @@ __goto_edit() {
# edits the goto configuration file
# command: goto -e
nano ${__GOTO_FILE}
${EDITOR:-nano} ${__GOTO_FILE}
}
__goto_list() {
@@ -127,7 +142,7 @@ __goto_list() {
# command: goto -l
local -A data
__goto_load data
__goto_load_entries data
local -a sorted_keys
mapfile -d '' sorted_keys < <(printf '%s\0' "${!data[@]}" | sort -z)
@@ -146,16 +161,17 @@ __goto_add() {
# $1: directory alias and optional path
local dir_alias dir_path
IFS=':' read dir_alias dir_path <<< "$1"
if [[ -n "${dir_path}" ]]; then
dir_path=$(__goto_resolve_path "${dir_path}")
dir_path="$(__goto_resolve_path "${dir_path}")"
else
dir_path="${PWD}"
fi
if __goto_exists; then
dir_alias="${dir_alias}" dir_path="${dir_path}" ${__GOTO_YQ} -i '. | (.[env(dir_alias)] = env(dir_path))' ${__GOTO_FILE}
dir_alias="${dir_alias}" dir_path="${dir_path}" ${__GOTO_YQ} -i '.[env(dir_alias)] |= env(dir_path)' ${__GOTO_FILE}
else
dir_alias="${dir_alias}" dir_path="${dir_path}" ${__GOTO_YQ} '.[env(dir_alias)] = env(dir_path)' ${__GOTO_FILE}
fi
@@ -179,32 +195,35 @@ __goto_get() {
# $1: directory alias
if ! __goto_exists; then
echo "goto: $1: configuration file not found" >&2
return 10
fi
local dir_path=$(dir_alias="$1" ${__GOTO_YQ} 'explode(.)[env(dir_alias)] // ""' ${__GOTO_FILE})
if [[ -z "${dir_path}" ]]; then
echo "goto: $1: no such entry" >&2
return 11
fi
local dir_path="$(dir_alias="$1" ${__GOTO_YQ} '.[env(dir_alias)] // ""' ${__GOTO_FILE})"
if [[ -z "${dir_path}" ]]; then
return 10
fi
__goto_resolve_path "${dir_path}"
}
goto() {
# the goto command
local OPTIND OPT
local can_run_main=true
local OPTIND OPT OPTARG
while getopts 'a:r:g:elt' OPT; do
while getopts ':a:r:g:elt' OPT; do
case "${OPT}" in
a)
__goto_add "${OPTARG}"
return
can_run_main=false
;;
r)
__goto_remove "${OPTARG}"
return
can_run_main=false
;;
g)
__goto_get "${OPTARG}"
@@ -222,8 +241,12 @@ goto() {
__goto_test
return
;;
:)
echo "goto: missing argument for option '${OPTARG}'" >&2
return 1
;;
*)
echo "goto: invalid option ${OPTARG}" >&2
echo "goto: invalid option '${OPTARG}'" >&2
return 1
;;
esac
@@ -236,25 +259,29 @@ goto() {
return 1
fi
if (( $# == 0 )); then
cd
if ! ${can_run_main}; then
if (( $# > 0 )); then
echo 'goto: too many arguments' >&2
return 1
fi
return
fi
if ! __goto_exists; then
echo "goto: $1: configuration file not found" >&2
return 3
if (( $# == 0 )); then
echo 'goto: not enough arguments' >&2
return
fi
local dir_path="$(dir_alias="$1" ${__GOTO_YQ} '.[env(dir_alias)] // ""' ${__GOTO_FILE})"
local dir_path
dir_path=$(__goto_get "$1")
local -i ret_code=$?
if [[ -z "${dir_path}" ]]; then
echo "goto: $1: no such entry" >&2
return 2
if (( ret_code != 0 )); then
return ${ret_code}
fi
cd $(__goto_resolve_path "${dir_path}")
cd ${dir_path}
}
# complete -F __goto_completions goto
source ${__GOTO_ROOT_DIR}/completion.bash
. ${__GOTO_ROOT_DIR}/completion.bash