Issue
I have a Bash script which asks a user to input text. It displays the question and answer within a line-drawing character menu 'panel', like so:
#!/bin/bash
function menu_display {
clear
tput cup 0 0; tput sgr0; echo " ┌───────────────────────────────────────────────────────────┐"
tput cup 1 0; tput sgr0; echo " │ │"
tput cup 2 0; tput sgr0; echo " │ │"
tput cup 3 0; tput sgr0; echo " │ │"
tput cup 4 0; tput sgr0; echo " │ │"
tput cup 5 0; tput sgr0; echo " │ │"
tput cup 6 0; tput sgr0; echo " │ │"
tput cup 7 0; tput sgr0; echo " ╘═══════════════════════════════════════════════════════════╛"
}
function ask_question {
menu_display
tput cup 3 3; tput sgr0; echo "Type some text here: "
tput cup 3 24; read -e -r INPUT_TEXT;
}
ask_question
exit 0
Everything looks and works fine to start with -until the user types some text and then hits the backspace key to delete/edit/correct it. Backspacing works correctly to start with, as characters from the end to the second character typed are erased. But if the backspace key is pressed to delete the first character typed at the prompt, the cursor jumps back to the beginning of the line and the vertical line-drawing characters and the question prompt is lost entirely. (At least, it does on current Manjaro using KDE with either Konsole or Xterm). The user is left attempting to type a correct answer to a question that is no longer displayed (and quite possibly not remembered!)
Is there a way to either:
- Detect when a user backspaces on the first character and thus re-draw and re-display the menu_display and question prompt when it can be presumed that the originals have vanished; or
- Totally prevent the user backspacing on the first character typed by way of response, thus preserving the question prompt from "backspace erasure", whilst still giving the user the ability to correct the first character typed in some way; or
- Allowing the user to backspace erase the first typed character, but preventing the cursor at that point from jumping to the beginning of the line, thus preserving the original question prompt; or
- A better way of doing this entirely? (I don't want to use ncurses or dialog, however, as this would be the only point in a long bash script where such tools would be used, and I'm trying to keep external dependencies down to a minimum)
Note that there is no limit to the length of user input expected, so a user's answers could well wrap onto a second line, if that was going to affect any suggested solutions.
Would appreciate any pointers, if they exist!
Solution
So, I continue my comments in a proper answer, since it might be acceptable to you. As I was saying, this is a readline behaviour, not a bash behaviour. Readline is the librarie used by almost all commandline tools (such as interactive interpreter, like python, node, bash, ...)
A way around it may be to loose the -e
flag you pass to read. Which precisely means "use readline to read".
Of course, it has a drawback: no more completion or history, or any perk like that that readline offers
Answered By - chrslg Answer Checked By - Terry (WPSolving Volunteer)