When answering this question I used a very messy bind
function to modify the current line according to the result of my automplete.sh
script.
As I ended up using this script for my personal use, I tried to simplify the bind
and try to do all the reading and modification directly inside the script.
So far, I can access $READLINE_LINE
and $READLINE_POINT
and extract the informations I need, but I can't replace the current value. Quotting bind
mand page, this should work though :
When shell-command is executed, the shell sets the READLINE_LINE variable to the contents of the readline line buffer and the READLINE_POINT variable to the current location of the insertion point. If the executed command changes the value of READLINE_LINE or READLINE_POINT, those new values will be reflected in the editing state
I bound my scipt with bind -x '"\t":autocomplete.sh'
, and did something like this :
#!/bin/bash
#autocomplete.sh
BASE="${READLINE_LINE% *} "
LAST_CMD="${READLINE_LINE##* }"
EXPANSION=($(magical_autocomplete $LAST_CMD))
#we store the desired value for the line in ${EXPANSION[0]}
[[ ${#EXPANSION[@]} -gt 1 ]] && echo ${EXPANSION[@]:1} #we echo the match if there are more than 1
#Doesn't work, even with simple values like READLINE_LINE="test" or READLINE_POINT=0
READLINE_LINE=${EXPANSION[0]}
READLINE_POINT=${#READLINE_LINE}
#echo READLINE_LINE READLINE_POINT echoes the correct value here
After execution of the script, the correct matches are displayed, but the current line feed is not updated. As I am echo-ing some informations, I can't just redirect the ouptut of my script in the bind
part. Why can I read from the variables but not write into it ?
Just by the same reason why this won’t work:
$ export a=1
$ bash -c 'echo $a; let a++'
1
$ echo $a
1
Environment variables are heritable, not shareable. Since autocomplete.sh
is executed as a new child process, it can read all parent’s variables, but can‘t push new values back.
To modify READLINE_LINE
and READLINE_POINT
you have to execute your autocomplete in the same process – source
and functions will help you.
# autocomplete.sh
# should be sourced from ~/.bashrc or something
autocomplete() {
echo $READLINE_LINE $READLINE_POINT
EXPANSION=($(magical_autocomplete $READLINE_LINE))
#we store the desired value for the line in ${EXPANSION[0]}
[[ ${#EXPANSION[@]} -gt 1 ]] && echo ${EXPANSION[@]:1}
READLINE_LINE=${EXPANSION[0]}
READLINE_POINT=${#READLINE_LINE}
}
Binding:
if [[ -s "$HOME/.bashrc.d/autocomplete.sh" ]]; then
source "$HOME/.bashrc.d/autocomplete.sh"
bind -x '"\t" : autocomplete'
fi
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With