4

We all know this annoying issue:

$ printf "abc" > some-file
$ cat some-file
abc$ 

which tends to mess up the prompt if it is any more complex than $, throws off the current cursor position and looks just plain ugly. There are some solutions (e.g. here), but they have another drawback: Logging into a slow machine over ssh, you may start to type before the prompt appears. Normally, your input is then buffered and displayed nicely as soon as possible. However, with the linked solution, the input is discarded.

How do I

  • always start the prompt on a new line, esp. if the output of the last command did not end with a new line and
  • keep unconsumed input already entered during the execution of the previous command in the command line buffer?

1 Answer 1

2

This solution slightly combines the solution from the question with a small perl snippet:

The following code in .bashrc defines two new functions, inject and clear_newline. The latter is then called every time a prompt has to be printed. The former is called from within the latter (see inline commands for the details):

# injects the arguments into the terminal, from the second link
function inject() {
  perl -e 'ioctl(STDIN, 0x5412, $_) for split "", join " ", @ARGV' "$@"
}
# prints a newline if the cursor is not in position 1
clear_newline() {
  local curpos # local variable to hold the cursor position
  local input  # local variable to hold entered input
  stty -echo # disable echoing
inject '
' # inject a newline to terminate entered input, '\0' didn't work?
  IFS='\n' read -s input # read entered input
  echo -en '\033[6n'
  # ask the terminal driver to print the current cursor position
  IFS=';' read -d R -a curpos # read cursor position 
  stty echo # enable echoing
  (( curpos[1] > 1 )) && echo -e '\033[7m%\033[0m'
  # if cursor not in first column, print a % with inverted colours and a newline
  stty -echo # disable echoing of input to terminal again
  inject "${input}" # inject stored input
  stty echo # enable echo
}

PROMPT_COMMAND='clear_newline' # run clear_newline for every prompt

The second stty -echo/stty echo pair is necessary to hide the input injected; it will be printed by bash as soon as the prompt finishes.

1
  • This works as expected if I paste 2 commands into the terminal (both are executed), but if I paste more than 2 commands, the >2 commands will appear at the prompt one-by-one, but I have to manually hit enter one-by-one for them to execute. How would I fix that so commands >2 are automatically 'entered' like the 2nd command is?
    – proximous
    Commented Jul 4, 2020 at 19:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .