4

I am having issues with my known methods of generating user input prompts:

read -p "Input something: " variabile

This causes issues if attempting to use the arrow keys, it echoes the ANSI code for each arrow key stroke

read -e -p "Input something: " variable

This fixes the arrow keys issue but when reaching the width of the terminal, text input doesn't continue on a newline but on the same line, overwriting (visually) the existing input

echo -n "Input something: "; read -e variable

This apparently fixes both formerly described issues... until I found that typing something then hitting backspace overwrites the prompt and also when the input is longer, from the second newline of input the visual overwriting manifests again.

So is there a good way of producing prompts without the above issues?

UPDATE

After re-checking, I now know what's causing the input overwrite for read -e -p I am using these variables for highlighting text for the read prompt:

highlight=$(echo -e "\e[1;97m")
clear=$(echo -e "\e[0m")
read -e -p "Input$highlight something$clear: " variable

This is the only way I could make the highlighting work inside read prompt (assigning escape sequences to the variables doesn't work, I need to echo them like I did) but they also seem to cause the input overwrite issue.

3
  • 3
    Did you try precisely read -e -p "Input something: " variable? Or does the prompt include things like VT-100 console codes to change color, etc.? And is the cursor at the left margin when the prompt is displayed? The command as you show it in the question works perfectly for me. Commented Jan 14, 2016 at 19:25
  • 1
    What kind of terminal are you using? putty? Commented Jan 14, 2016 at 19:51
  • read -e -p "Input something: " variable works fine for me. Commented Jan 15, 2016 at 0:42

2 Answers 2

1

As dimo414 mentions, readline thinks the prompt is longer than it is. It counts every character in the terminal escape sequence in computing the length. You can see how long it thinks the escape sequence is as follows

echo ${#highlight}

In the bash PS1 prompt, surrounding such an escape sequence with "\[" and "\]" instructs readline to ignore everything between when calculating current line length, but these are not the right escapes for the bash read built-in.

The escapes for read are $'\001' and $'\002', as mentioned in BashFAQ, but in my experience, you need the -e option on read, as well. The brute force way to do what you want would be:

read -e -p "Input "$'\001'"${highlight}"$'\002'something$'\001'"${clear}"$'\002'": "

You should use tput rather than hard-coded escape sequences, for the sake of terminal independence. Read man 5 termcap.

See my dotfiles for elegant bash functions to do the begin/end quoting above for you.

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

Comments

1

The shell keeps track of how long it thinks the prompt is, in order to know where the user's input starts and stops. Unfortunately when you print color escape codes in a prompt you throw of Bash's counting, since it expects the escape characters to take up space in the terminal.

To avoid that, you just need to wrap all color sequences in \[ and \], which tells your shell the enclosed characters are non-printing, and should not be counted.

For example, your highlight variable should be:

highlight=$(echo -e "\[\e[1;97m\]")

Personally, I use the color and pcolor functions from my Prompt.gem project, which handles the proper escaping and would make your command much easier to read:

read -e -p "Input $(pcolor DEFAULT BOLD)something$(pcolor): " variable

10 Comments

I tried your wrapping but it didn't do anything to fix the described issues, furthermore the \[ and \] were displayed in the prompts so they don't have any effect. I even tried without \ , still no effect, other than just displaying the extra [ and ]. Tried both with echo + read and with read -e -p. BASH version: 4.1.2(1)
Are you perhaps using a custom PS1 prompt? What you're describing is exactly what happens when Bash isn't able to correctly figure out where the cursor should be, so it's possible the problem isn't specifically with this read command. Are you able to replicate your problem in a clean Bash environment? I haven't been able to replicate it from your examples, with a similarly modern version of Bash.
No custom PS1 prompt. Maybe it would be better to give me a concrete example on the prompt syntax content that worked for you.
When I run the command you have in your question, I do not replicate the problem you're describing.
If you execute the 3 lines in my UPDATE and your input reaches the end of the terminal (putty), the prompt is not overwritten by the input which should normally go to the 2nd line?
|

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.