Consider you want to run this command in bash
:
echo -n "Command of a specific length will break at the second run attempt."
Here's the output for a 24x80 TTY:
ubuntu@ubuntu:~$ echo -n "Command of a specific length will break at the second
run attempt."
Command of a specific lenght will break at the second run attempt.ubuntu@ubuntu:
~$
Consider you want to run the same command again.
As soon as you hit ↑:
ubuntu@ubuntu:~$ echo -n "Command of a specific lenght will break at the second
run attempt."
Command of a specific lenght will break at the second run attempt.ubuntu@ubuntu:
run attempt."ommand of a specific lenght will break at the second r
This happens with commands of a certain size which don't print a newline at the end.
This is extremely annoying. So far I haven't found any solution to this, and I think everyone who's experiencing this issue would be really grateful to someone who has a solution for this.
Use a smarter shell, like
zsh
:Note how it added a
%
to indicate the lack of a newline and printed the prompt on a different line.Just hit CtrlL. That will redraw your terminal and make everything appear as it should:
This can be done with
bash
too. The trick is to use a customPROMPT_COMMAND
that queries the terminal for the position of the cursor (as per this question ).This solution can probably be extended to other shells, but I'm only familiar with
bash
. (See @muru 's answer for azsh
solution). And perhaps there is already an option inbash
to do this automatically.Put this in your
.bashrc
:The last line prepends a call to
new.line.if.not.on.left
to yourPROMPT_COMMAND
(as you may already have aPROMPT_COMMAND
defined).The bash function
new.line.if.not.on.left
works as follows:echo -n -e "\033[6n"
is a piece of magic that asks the terminal about the row and column of the cursor's current position. The terminal "responds" by sending fake keyboard input with the answer.read -s -d \[ garbage
. The first part of the response is some gibberish, some sort of escape code. Ignore it by storing it ingarbage
.read -s -d R foo
. Store the fake keyboard response in bash variablefoo
. The-s
is needed to stopread
from echoing the input to the screen again. And-d R
is the delimiter - the fake input is terminated by anR
, not by a newline as you might expect.column="$(echo "$foo" | cut -d';' -f2)"
extracts the column number from the response (i.e. skipping over the row number) and stores the result incolumn
test "$column" "!=" 1 && { tput smso; echo "%"; tput rmso; }
If the current column number is not 1, then print the percent sign (and a newline). Thetput
commands turn on "stand out mode" - which should make the%
stand out more - perhaps bold or perhaps by reversing the background and foreground colours.