Bash expand cd with shortcuts like zsh

Is it possible in bash to deploy something like

cd /u/lo/b <hit tab>

to

cd /usr/local/bin

?

+6
source share
1 answer

Sorry I couldn't post it before, I was kept at work, and the bind function was more error prone than I thought.

Here is what I came up with:

Bind the following script:

 #!/bin/bash #$HOME/.bashrc.d/autocomplete.sh autocomplete_wrapper() { BASE="${READLINE_LINE% *} " #we save the line except for the last argument [[ "$BASE" == "$READLINE_LINE " ]] && BASE=""; #if the line has only 1 argument, we set the BASE to blank EXPANSION=($(autocomplete "${READLINE_LINE##* }")) [[ ${#EXPANSION[@]} -gt 1 ]] && echo "${EXPANSION[@]:1}" #if there is more than 1 match, we echo them READLINE_LINE="$BASE${EXPANSION[0]}" #the current line is now the base + the 1st element READLINE_POINT=${#READLINE_LINE} #we move our cursor at the end of the current line } autocomplete() { LAST_CMD="$1" #Special starting character expansion for '~', './' and '/' [[ "${LAST_CMD:0:1}" == "~" ]] && LAST_CMD="$HOME${LAST_CMD:1}" S=1; [[ "${LAST_CMD:0:1}" == "/" || "${LAST_CMD:0:2}" == "./" ]] && S=2; #we don't expand those #we do the path expansion of the last argument here by adding a * before each / EXPANSION=($(echo "$LAST_CMD*" | sed s:/:*/:"$S"g)) if [[ ! -e "${EXPANSION[0]}" ]];then #if the path cannot be expanded, we don't change the output echo "$LAST_CMD" elif [[ "${#EXPANSION[@]}" -eq 1 ]];then #else if there is only one match, we output it echo "${EXPANSION[0]}" else #else we expand the path as much as possible and return all the possible results while [[ $l -le "${#EXPANSION[0]}" ]]; do for i in "${EXPANSION[@]}"; do if [[ "${EXPANSION[0]:$l:1}" != "${i:$l:1}" ]]; then CTRL_LOOP=1 break fi done [[ $CTRL_LOOP -eq 1 ]] && break ((l++)) done #we add the partial solution at the beggining of the array of solutions echo "${EXPANSION[0]:0:$l} ${EXPANSION[@]}" fi } 

with the following command:

  source "$HOME/.bashrc.d/autocomplete.sh" bind -x '"\t" : autocomplete_wrapper' 

Output:

 >$ cd /u/lo/b<TAB> >$ cd /usr/local/bin >$ cd /u/l<TAB> /usr/local /usr/lib >$ cd /usr/l 

A binding string can be added to your ~/.bashrc , doing something like this:

 if [[ -s "$HOME/.bashrc.d/autocomplete.sh" ]]; then source "$HOME/.bashrc.d/autocomplete.sh" bind -x '"\t" : autocomplete_wrapper' fi 

(taken from this answer )

In addition, I highly recommend not binding this command to your Tab key, as it will override the default autocomplete.

Note: In some cases this will not be true, since isntance if you try to autocomplete "/path/with spaces/something" , since the last argument to complete is determined by ${READLINE_LINE##* } . If this is a problem in your case, you should encode a function that returns the last argument of the string when considering quotes

Feel free to ask for further clarification, and I welcome any suggestion to improve this script.

+6
source

Source: https://habr.com/ru/post/973212/


All Articles