From 1028ad1120572403c733059b43d295454d810489 Mon Sep 17 00:00:00 2001 From: work Date: Tue, 9 Jan 2024 19:53:36 +0300 Subject: [PATCH] Cd : Make cdd find exact match first. --- .config/bash/module/Cd.sh | 55 +++++++++++++++++++++++------------- .config/bash/module/Parse.sh | 2 +- .config/bash/module/Util.sh | 19 +++++++++++++ .doc/Bash.md | 2 +- 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/.config/bash/module/Cd.sh b/.config/bash/module/Cd.sh index cae55ba..805afb4 100644 --- a/.config/bash/module/Cd.sh +++ b/.config/bash/module/Cd.sh @@ -1,26 +1,36 @@ -# CD (back) to directory. -# Finds first directory that matches the input (case-insensitive). +# CD (back to) directory. +# Goes to the exact-match dir first. If no exact match found, it finds first directory that contains the input (case-insensitive). # Usage: cdd function cdd() { local target="${1}" - local array + + if [[ "${target}" = "" ]]; then + help cdd + return 2 + fi + + local array=($(_cdd_directories)) local result - IFS='/' read -r -a array <<< "${PWD}" - array=("${array[@]:1}") - # Make search case-insensitive. - shopt -s nocasematch + # Check for exact match ELSE look for containing. + if _contains ${target} ${array[@]}; then + local current="${PWD%/*}" + result="${current%\/$target\/*}/${target}" + else + # Make search case-insensitive. + shopt -s nocasematch - # Find desired dir. - local found=1 - for (( idx=${#array[@]}-2 ; idx>=0 ; idx-- )); do - dir="${array[idx]}" - [[ "${dir}" =~ "${target}" ]] && found=0 - [[ ${found} = 0 ]] && result="/${dir}${result}" - done + # Find dir name that contains input. + local found=1 + for (( idx=${#array[@]}-1 ; idx>=0 ; idx-- )); do + dir="${array[idx]}" + [[ "${dir}" =~ "${target}" ]] && found=0 + [[ ${found} = 0 ]] && result="/${dir}${result}" + done - # Clean-up??? - shopt -u nocasematch + # Clean-up??? + shopt -u nocasematch + fi # Go there! if [[ "${result}" != "" ]]; then @@ -31,12 +41,19 @@ function cdd() { fi } -_cdd_directories() { +# Get list of all parent dirs. +function _cdd_directories() { local array IFS='/' read -r -a array <<< "${PWD}" array=("${array[@]:1}") unset array[-1] - _autocomplete_first "${array[@]}" + printf "%s\n" "${array[@]}" } -complete -o nosort -o filenames -F _cdd_directories cdd +function _comp_cdd() { + local IFS=$'\n' + local dirs=($(_cdd_directories)) + _autocomplete_first ${dirs[@]} +} + +complete -o nosort -o filenames -F _comp_cdd cdd diff --git a/.config/bash/module/Parse.sh b/.config/bash/module/Parse.sh index 8a42f43..3aecbd3 100644 --- a/.config/bash/module/Parse.sh +++ b/.config/bash/module/Parse.sh @@ -124,7 +124,7 @@ function parse_titlecase() { continue fi - if [[ "${minors[@]}" =~ $(echo ${part} | sed -e "s/[${_PARSE_SPLIT_CHARS}]//g") ]]; then + if _contains $(echo ${part} | sed -e "s/[${_PARSE_SPLIT_CHARS}]//g") ${minors[@]}; then echo -n "${part}" else echo -n "${part^}" diff --git a/.config/bash/module/Util.sh b/.config/bash/module/Util.sh index 6eac2cb..79bfa7b 100644 --- a/.config/bash/module/Util.sh +++ b/.config/bash/module/Util.sh @@ -97,3 +97,22 @@ function _debug() { function _info() { >&2 echo -e "${color_bwhite}${*}${color_default}" } + +# Check if array contains an element (strict). +# Usage: _contains +function _contains() { + local IFS=$'\n' + local target="${1}" + local array="${@:2}" + + if [[ "${target}" = "" ]] || [[ "${array}" = "" ]]; then + help _contains + return 2 + fi + + for item in ${array[@]}; do + [[ "${item}" = "${target}" ]] && return 0 + done + + return 1 +} diff --git a/.doc/Bash.md b/.doc/Bash.md index fe86d51..7a95463 100644 --- a/.doc/Bash.md +++ b/.doc/Bash.md @@ -51,7 +51,7 @@ Command|Description Command|Description ---|--- -`cdd `|CD (back) to directory. Finds first directory that matches the input (case-insensitive). +`cdd `|CD (back to) directory. Goes to the exact-match dir first. If no exact match found, it finds first directory that contains the input (case-insensitive). ## Checksum.