Dealing with bash breaking commands of a certain length
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 custom PROMPT_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 a zsh
solution). And perhaps there is already an option in bash
to do this automatically.
Put this in your .bashrc
:
function new.line.if.not.on.left {
local foo
local garbage
local column
echo -n -e "\033[6n" # as the terminal for the position
read -s -d \[ garbage # ignore the first part of the response
read -s -d R foo # store the position in foo
column="$(echo "$foo" | cut -d';' -f2)" # skip over the row number
test "$column" "!=" 1 && { tput smso; echo "%"; tput rmso; }
}
PROMPT_COMMAND="new.line.if.not.on.left; $PROMPT_COMMAND"
The last line prepends a call to new.line.if.not.on.left
to your PROMPT_COMMAND
(as you may already have a PROMPT_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.