9

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]\$ '
  • This should be moved to superuser. – ℝaphink Dec 27 '09 at 17:42
  • I like your version! You used $() in one place and backticks in another. You can use $() in both. – Dennis Williamson Dec 29 '09 at 2:08
  • I know. But for me it's easier to read that way – GetFree Dec 29 '09 at 3:26
  • I wouldn't use tput cols because it just outputs the value of the COLUMNS variable anyway, and it's slower because it's not a shell builtin. You'll also want to include \e[K (equivalent to tput el) to delete the inserted whitespace so that you don't get a bunch of trailing whitespace when copying and pasting in the default case. Finally, you need to enclose all this magic between \[ and \] or else bash will try to second-guess your cursor position and it'll mess up when you edit your command/history. – dlitz Jun 14 at 6:35
  • The whole thing can be done as just: PS1='\[\e[7m%\e[m$( printf "%*s" "$((COLUMNS-1))" "" )\r\e[K\]\u@\h [\w]\$ ' – dlitz Jun 14 at 6:35
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.

  • I wonder why someone downvoted each answer. Hmmm... no explanation. How helpful. – Dennis Williamson Dec 28 '09 at 0:21
  • Here's another way, without using a loop, to create the pad string: printf -v PROMPT_SP '%*s' $((COLUMNS + 52)) '' – Dennis Williamson Apr 28 '12 at 0:28
  • What is a "reverse video percent sign"? The word "video" has me confused, and I haven't been able to find the answer on Google. – davidchambers Nov 22 '13 at 23:29
  • 1
    @davidchambers: The background of the character is displayed in the foreground color and the character itself is displayed in the background color. See man 5 terminfo and search for "reverse video" to see some documentation that uses this terminology. – Dennis Williamson Nov 22 '13 at 23:56
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.

  • Good idea. The only problem is... is it possible to know the cursor position? – GetFree Dec 27 '09 at 3:28
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.