Bash script: How to implement your own history engine?

I am implementing an interactive bash script, similar to the MySQL client /usr/bin/mysql. In this script, I need to issue various types of "commands". I also need to provide a history mechanism through which the user can use the up / down arrow keys to scroll through the entered commands.

The following is a snippet ( Example 15-6, Detecting the arrow keys ) does not do exactly what I want. I really want the following:

  • The up / down arrow keys should work in silent mode. So they should not repeat their character codes on the terminal.

  • However, other keys (which will be used to read the names of the commands and their arguments) should not work in silent mode.

The problem with read -s -n3is that it does not satisfy my simultaneously conflicting requirements of the tick mode and based solely on the character code. In addition, the value -n3will work for arrow keys, but for other / regular keys, it will not “return control” to the calling program until 3 characters are used.

Now I could try -n1and manually collect the input, one character at a time (yuck!). But the problem of switching quiet / echo signals based on a character code will still remain!

Has anyone tried to do this in bash? (Note: I cannot use C and other scripting languages ​​such as Perl, Python, etc.)

EDIT

Continuing Dennis's answer ... You also need to manually add the necessary entries to your story through history -s, for example ...

while read -e x; do
    history -s "$x"
    # ...
done
+5
source share
3 answers

You can use read -eto readuse readline. It will process your cursor keys and save a story for you.

+3
source

MySQL and Bash use the Readline library to implement this. Perhaps you could use something like rlwrap or rlfe ?

+2

rlwrap has a special "one shot" mode, which will act as a replacement for the "read" shell command. If you want, each occurrence of this command in your script can be provided with its own history list and completion list.

Use it as follows:

REPLY=$(rlwrap -o cat)

or by specifying a history file and a list of completion words:

REPLY=$(rlwrap -H my_history -f  my_completions -o cat)
+2
source

All Articles