1

Bash provides facilities to modify an entire line and change the position of the cursor with commands bound to bind -x through READLINE_LINE and READLINE_POINT variables:

$ cat test.sh
#!/bin/bash

autocompletefunc()
{
    echo $READLINE_LINE >> test.out
    READLINE_LINE='completely rewritten line & cursor is right here ->X<-'
    READLINE_POINT=51
}
$ source test.sh
$ bind -x '"\t" : autocompletefunc'
$ smth<TAB>  <== gets transformed into the below:
$ completely rewritten line & cursor is right here ->|X<-

(with | denoting the position of the cursor)

I did not find a way to modify the entire line (rather than just the currently-entered word) in an autocompletion function (registered with complete -F). Escape codes seem to just be printed (if only a single element is provided to COMPREPLY):

$ smth word<TAB>
$ smth ^[[2Kotherwisetheargumentcanentirelybereplaced

All the autocompletion variables are available "only in shell functions invoked by the programmable completion facilities". Is it possible to somehow combine the two (callback registered through complete -F and the one through bind -X) to simultaneously modify the line and list some suggestions, preferrably on <TAB><TAB>? Like this:

$ smth<TAB>
$ modified line=| further modified line
possiblevalue1
possiblevalue2
possiblevalue3
2
  • 1
    I am not sure to understand your target use case, may you elaborate? Do you expect "possiblevalueX" list is computed from "smth" so the original line before completion? Commented Aug 25, 2024 at 14:37
  • My use case is to "correct" the rest of the user's command (syntactically) when they ask for autocompletion for a particular parameter. Thus, I still want to present a list of suggestions, while slightly altering the surrounding parameters and perhaps the command itself. Commented Aug 26, 2024 at 15:58

1 Answer 1

1

According to my understanding, it looks like you try to divert completion as a "command line template". The main concern with your initial proposal is to keep standard completion working when binding TAB to a function instead of standard readline command. And it seems like the builtin complete logic does not allow to replace line itself.

A work-around would be to bind TAB with a sequence of keystrokes to invoke first a function that generates line templates (here Alt-H) before standard completion (kept as Ctrl-H)

#!/usr/bin/env bash

myecho() {
    echo $*
}

_templatelines() {
    if [[ "$READLINE_LINE" == "smth" ]]; then
        READLINE_LINE='myecho  " with other parameters"'
        READLINE_POINT=7
    fi
}

_myecho_completions() {
  COMPREPLY+=("possiblevalue1")
  COMPREPLY+=("possiblevalue2")
  COMPREPLY+=("possiblevalue3")
}

complete -o nosort -F _myecho_completions myecho
bind -x '"\eH": _templatelines'
bind '"\C-H": complete'
bind '"\t":"\eH\C-H"'

Inspired from Complex keybinding in bash

Anyway, I would recommend to use a custom function and completion the standard way.

  • Define a smth function which runs the expected command line(s) according to some parameters when invoked
  • Define completion for smth function to generate expected arguments

I agree you have no option to edit template live then, but it reduce risk to impact other Bash behaviors.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your answer! I was not able to trigger bash to list the possible completion values with your script (such as those that appear if the last three lines are commented out): ` $ myecho possiblevalue <NEWLINE> possiblevalue1 possiblevalue2 possiblevalue3 ` If "possiblevalue[1-3]" suggestion is changed to something without a common prefix, no completion is done. AFAIU, all that this script accomplishes can be done with READLINE facilities, without any autocompletion. I think it might be impossible to achieve both suggestion lists and line modification
In my opinion, intercepting TAB prevents the double TAB sequence to display completions. I am sorry for missing the bounty

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.