11

Most of the time the output of a command ends with the newline character. But sometimes it does not, so the next shell prompt is printed in the same line together with the output.

Example:

root@hostname [~] # echo -n hello
helloroot@hostname [~] #

I've always found that very annoying.
Now, I could just add a "\n" at the beginning of the the PS1 variable, but most of the time that will print one extra line I dont need.

Is it possible to know whether the last command's output ended with a newline or not?


Solution:
(Thanks to Dennis)

PS1='$(printf "%$((`tput cols`-1))s\r")\u@\h [\w]\$ '
GetFree
  • 1,582

4 Answers4

6

I've been experimenting with the following to emulate the feature from zsh in Bash:

$ unset PROMPT_SP; for ((i = 1; i <= $COLUMNS + 52; i++ )); do PROMPT_SP+=' '; done
$ PS1='\[\e[7m%\e[m\]${PROMPT_SP: -$COLUMNS+1}\015$ '

It issues a reverse video percent sign, followed by a bunch of spaces to make it wrap to the next line, then a carriage return, followed by a dollar sign and a space. You can add prompt escapes after the "\015" to customize your prompt.

Using this depends on how your terminal handles right margin line wrapping (automatic margins). The length of PROMPT_SP is arbitrary, but should be at least 80 or whatever your usual terminal width is. You may need to hard-code that value if $COLUMNS isn't set yet by the time the for loop is run in ~/.bashrc. You may want shopt -s checkwinsize if it's not already set.

1

I got this idea from @Teddy of detecting the horizontal cursor position and issuing a newline if it isn't at the first column.

In bash, we can detect the cursor position using this command: IFS=';' read -sdR -p $'\E[6n' ROW COL. More information in this answer: https://unix.stackexchange.com/a/183121/340297
The COL variable holds the current column where the cursor is. If $COL is not equal to 1, add a newline before setting the PS1 variable.

Here is my implementation:

_set_prompt() {
    IFS=';' read -sdR -p $'\E[6n' ROW COL # Get cursor position
    [ $COL -ne 1 ] && echo '' # Add newline if cursor is not at 1st column
    PS1="........." # Your PS1 variable
}

PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }'_set_prompt'

And here is the result (with different PS1):
enter image description here

echo -n doesn't include newline, but newline is issued before displaying the prompt. Whereas, there is no extra newline if newline is already printed by the normal echo command.

Puspam
  • 111
1

zsh tries to solve your problem. If the last output ends without a newline, you will get:

$ echo -n 'abc'
abc%
$ 

Where the % uses inverted background/foreground. Not sure if it's portable to bash in any way.

viraptor
  • 1,176
0

No it isn't possible. Bash itself does not process or see the output of the program it has started.

It just occured to me that it might be possible to write a program to set PROMPT_COMMAND to, which would check the current position of the cursor and issue a newline if the cursor was not at the left edge.

Teddy
  • 5,424