e___e
e___e

Reputation: 159

Bash : read + completion

I'm new on bash and I'm trying to write a bash script that will save user's input (some tags), to help this user I would like to allow completion based on my personal list of predefined tags only and not on the common TAB files completion (files names in the folder).

predefinedtags=(one two three four five)
echo "enter tags (separate multiple values by space)"
read -e tags
echo $tags

I would like that during the read input the user can press TAB to complete is word with the list of predefined tags. I thought it was an common question and method but I do not find a good way to do it. I found some posts that are a bit too complex for me and they seem to explain that is a not a so simple question. I don't even know if it's possible or not.

Changing tab-completion for read builtin in bash

bash and readline: tab completion in a user input loop?

Do you have any ideas ? Or there is maybe a completely different way to do it ? Thank you for your help.

Upvotes: 5

Views: 1997

Answers (1)

Jay jargot
Jay jargot

Reputation: 2868

In the second part, there is a simple version.

Give this tested version a try:

#!/bin/bash --

reade () {
  tmpdir=$(date "+/tmp/%Y%m%d%H%M%S$$")
  mkdir "${tmpdir}"
  for ptag in "${predefinedtags[@]}" ; do
    touch "${tmpdir}"/"${ptag}"
  done
  readetags=$(cd "${tmpdir}" || printf "internal error" ; read -re usertags ; printf "%s" "${usertags}")
  rm -rf "${tmpdir}" 2>/dev/null >/dev/null
  eval "${1}"=\"\$\{readetags\}\"
}
predefinedtags=(one two three four five)
printf "enter tags (separate multiple values by space)\n"
reade tags
printf "%s\n" "${tags}"

It migth be seen as odd but it is fun ! (and checked with shellcheck)

It defines a new reade function which creates a temporary directory with a unique name, and one empty file for each elements in predefinedtags. It changes the current directory to the new temporary one and runs read -e .

The TAB key will work as expected.

Finally the tags entered by the user are all assigned to tags.

Beware to not insert tags with spaces or special chars like ', " (etc.) into predefinedtags.

----

second part

You might want to define a configuration directory that would already contain empty files (the predifined tags) instead of creating and removing a temporary directory.

Replace /path/to/configuration with real pathname of the configuration directory in the script below:

#!/bin/bash --

printf "enter tags (separate multiple values by space)\n"
tags=$(cd /path/to/configuration || printf "internal error" ; read -re usertags ; printf "%s" "${usertags}")
printf "%s\n" "${tags}"

The test (where TAB key press is written):

$ ls configuration/
five  four  one  three  two

$ ./script.sh
enter tags (separate multiple values by space)
TAB
five   four   one    three  two
five ten
five ten

$ touch configuration/cat
$ ls configuration/
cat  five  four  one  three  two

$ ./script.sh
enter tags (separate multiple values by space)
TAB
cat    five   four   one    three  two
cat hello
cat hello

Upvotes: 2

Related Questions