Text doesn't clear after modifying terminal prompt - terminal

Note: I am running Mac OS X Sierra but this problem occurs on Ubuntu also.
I have customised the terminal prompt as such:
export PS1="\n\[\033[1;31m\]\u 🖖 \[\033[1;32m\]# \[\033[1;32m\]\h \[\033[0;35m\]in \[\033[0;36m\]\w\n\[\033[0;34m\]> \[\033[1;37m\] \e[0m"
Note that I have put a newline at the end, so I start typing commands on a new line after the >. I have done this on a number of machines, and I've noticed that whenever I add the newline, the terminal behaves weirdly.
By weirdly, the exact behaviour I refer to is this (this includes the steps to replicate the error if you use the PS1 value I have mentioned):
Access older commands by pressing the up arrow key.
When I encounter a command in the history which consists of more than 1 word, and the first word is is more than 4 characters long, then the first 4 characters of the word 'stick' to the initial part of the prompt.
This 'sticky part' cannot be deleted by me, and does not even go when I press the up arrow key several more times.
For instance, if the last 4 commands I entered were (from least recent to most recent): clear, man man, this that and help.
Then, when I look at previous commands by pressing the up key incrementally:
help is visible properly.
this that is visible properly.
Note how this is appended at the start. I cannot delete it if I try.
Continues to stay as I press the up key.
How can I resolve this issue?

Each of the escape-sequences in your prompt has to be bracketed with \[ and \] to tell bash that those characters should be ignored for the purpose of counting columns. The last one in your example is not bracketed:
export PS1="\n\[\033[1;31m\]\u 🖖 \[\033[1;32m\]# \[\033[1;32m\]\h \[\033[0;35m\]in \[\033[0;36m\]\w\n\[\033[0;34m\]> \[\033[1;37m\] \e[0m"
i.e., \e[0m
If you fix the error, bash is likely to give better results. This shows the suggested correction;
export PS1="\n\[\033[1;31m\]\u 🖖 \[\033[1;32m\]# \[\033[1;32m\]\h \[\033[0;35m\]in \[\033[0;36m\]\w\n\[\033[0;34m\]> \[\033[1;37m\] \[\e[0m\]"

Related

Disable delete key in terminal prompt

I modified my prompt in my .bashrc file using the following command:
PS1='\[$(tput bold)\e[1;34m\w\e[m$ '
Now my prompt shows the current directory in bold blue color followed by the $ sign. On a new prompt, if no other text has been entered, I press the delete key nothing happens.
However, if I enter any text, say cd, delete that and then press the delete key once more, it will delete my prompt. How can I change my .bashrc file so my prompt can never be deleted?
Bash is confused about how long your prompt actually is. You can tell bash by enclosing non-printable parts of the prompt with backslash-brackets: \[....\].
Your prompt, however only contains the opening bracket, making bash believe that the prompt is very short, so it happily removes almost all of it in some situations. A proper use of the bracketing would look like this:
PS1='\[$(tput bold)\e[1;34m\]\w\[\e[m\]$ '
That is, everything is in backslash-bracket except the working directory and the dollar sign, because those are the only parts that actually consume space on the terminal screen.

Cygwin wraps text back on to the same line, causing text to be overwritten

I have cygwin installed on my Windows 7 box and I have been running into a problem where when I type a command it will occasionally be wrapped back onto the same line, deleting the bash prompt. Here is an example:
The command in question is command "201" (4 lines from the bottom). I included the others for context.
The text of the command I was typing was
git commit -m "Forced LF line endings."
(Note: I am posting this with mostly git commands, but the problem occurs with any command. I have not noticed a pattern yet.)
It jumped to the start of the line and started to overwrite my prompt.
When I push the up arrow (to view the history) the result is even weirder:
(Note the cursor is many characters past the end of the command.)
When I try to backspace the cursor from that position, I can only go back this far:
Then when I go up into the history from that backspaced line, I get this:
The command starts from the end of the text that is displayed. (This is consistent for the entire history) But when I go up in the history to the faulty git commit ... it displays as it did before with the overwritten text but when I go past it, it deletes a line of the prompt and displays the previous entry in the history the same way it was doing it before (a la image 2).
When I was creating my PS1 variable I has odd output like this, but I have since closed my brackets and things and don't think that is causing the issue. However if you would like to see my .bash_profile (that sets the PS1) feel free to see it on GitHub. It is really short.
I have tried searching for the issue and can only find a few cygwin email archives about the line wrapping in xterm, but no solutions.
PS: As I was pushing the latest .bash_profile, in order to link it, I ran into the problem again when I typed git add .bash_profile and hit enter, it ran the command but returned the cursor to the start of the same command instead of printing a new prompt.
Then when I as writing another commit line, it did the same as the first image, but it blacked out the rest of the line (It wrapped the line, but overwrote the entire line and not just the first few chars.)
See http://manpages.ubuntu.com/manpages/lucid/man1/bash.1.html#contenttoc26:
\[
begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
\]
end a sequence of non-printing characters
If you don't enclose non-printing characters (e.g. color sequences) in your prompt with these their length is counted as part of the prompt's length, eventually resulting in the symptoms that you describe.
It doesn't occur frequently to me. When it does, I just type in 'kill -WINCH $$' into the cygwin terminal and it fixes the problem. link to source

How can I add a vertical space in 'Terminal' after each command?

I've just started using Terminal (the CLI for Mac OS X).
When I run a command, get some information back, run another command, get more info etc., it is hard (on the eyes) to find a certain point on the screen (e.g. the output for the command before last).
Is there a way of adding a vertical empty space to the end of each output/ after each command is run that has no output?
Each new command that you enter is preceded by a "prompt", and these can be customized (though the exact way to customize depends on the shell). Since you mention Mac OS X I'm assuming you are using the default bash shell, in which case the absolute simplest way to add a blank line is like this: PROMPT_COMMAND=echo. You can run that command to try it out, or add it to a startup file (like .profile in your home folder) to have it done automatically each time.
If you use Bash 4.4 and you want a blank line after your prompt, you could set the PS0 prompt to a newline:
PS0="\n"
Now, this will be inserted every time you run a command:
$ echo "Hello"
Hello
Wondering this too, I've looked at the menu options in Terminal & most of the control characters one can type in and nothing does this on a keystroke. You can however enter an echo command, it alone to leave a single blank line below it before the next prompt. echo \n will add an extra blank line to that, echo \n\n to do 2 extra, ie. 3 blank lines, etc. (you can also do echo;echo;echo getting the same effect)
You can create a shell alias like alias b='echo;echo' (i couldn't seem to get the \n notation to work in a alias), then entering b on a prompt will leave a double-blank line, not bad. Then you gotta figure out how to save aliases in your .profile script.
I tried making an alias for the command ' ' ie. space character, which I though you could type like \ (hmm, stack overflow not formatting this well, that's backslash followed by a space, then return to execute it), but the bash shell doesn't seem to allow an alias with that name. It probably wouldn't allow a function named that either (similar to alias), though I didn't check.
I often use the fish shell, and I found that it does allow a function with that name! Created with function ' '; echo \n; end and indeed it works; at the shell prompt, typing the command \ (again backslash space) leaves a double blank line.
Cool, but.. I tried saving this function using funcsave ' ' (how you save functions in fish, no messing with startup scripts!) and afterwards the function no longer works :^( This is probably a bug in the fish shell. It's in active development right now though, I think I'll report this as a bug since I would kind of like this to work myself.
One could also send Apple a feature request through their bug reporter for an Insert Blank Line menu/keyboard command in Terminal. If someone pays attention to your request it might be implemented in a year maybe.
I wanted to solve exactly the same, and for anyone interested in doing the same, I used what tripleee said in his comment here - I created a .bash_profile (see details here) with the line export PS1="\n\n$ ".
Hopefully that helps someone else too!

How do I select the line in bash terminal

Is it possible to select part of a string in the bash terminal and delete it at once, rather than navigating to a point in the command and backspacing it all??
thanks!
I'm not 100% sure I understand your question.
If you are at the interactive command line:
ctrl-u: Deletes everything to the left of your cursor
ctrl-k: Deletes everything to the right of your cursor
I'm using emacs bindings and my favourite command line shortcuts, which were not included in the previously linked tutorial, are the following:
^W - delete last word
meta-b - move cursor back one word
^R - find a previously used command
!$ - last attribute of the last command
!! - last command
You can also manipulate the history with regexps, although that could quickly get quite messy. See "man zshexpn" for reference, mostly the same regexp syntax works for bash also.
Example:
1) If you execute the following command:
echo first second third fourth fifth
2) Then you could execute the same command and remove "first" by:
!!:s/first//
If this was not what you were after, please clarify on your question! :)
See this. Alternatively, set -o vi to have vim-like key bindings.
Note that the list given in the link is not full. You might read man bash for a good reference. Usually, ALT-x might be replaced by ESC, x if you run bash inside a terminal that uses Alt-letter shortcuts for windowing system.

Going backwards in a bash prompt

I'd like to have a blank line after my bash prompt and before the output on my Mac. It should look like this would:
echo; ls
Can I add a newline to my bash prompt and then go back up one line to wait for user input? Is there something obvious I'm missing?
I know this is old but for someone like me who came across this while googling for it. This is how you do this...
It's actually pretty simple!
Check out this link --> Cursor Movement
Basically to move up N number of lines:
echo -e "\033[<N>A HELLO WORLD\n"
Just change the "< N >" to however many lines you want to go back...
For instance, to move up 5 lines it would be "/033[5A"
To my knowledge this is not possible unless you delve into more low-level stuff like full-screen emulators like curses.
This is a bit of a stab in the dark, but you may be able to use VT102 terminal codes to control the cursor without having to use Curses. The relevant VT102 commands that you'd be interested in all consist of sending ESC, then [, then the specific command parameters.
For instance, to move the cursor up one line, one needs to output:
ESC [ 1 A
0x1B 0x5B 0x31 0x41
Be warned that the VT102 documentation generally uses octal, so keep an ascii table handy if you're using hex.
All of this advice is given without having tested it -- I don't know if VT102 commands can be embedded into your bash prompt, but I thought it might be worth a shot.
Edit: Yeah -- looks like a lot of people use VT102 formatting codes in their bash prompts. To translate my above example into something Bash would recognize, putting:
\e[1A
into your prompt should move the cursor up one line.
This is very possible. If your bash has C-v set as the readline quoted-insert command, you can simply add the following to your ~/.inputrc:
RETURN: "\C-e\C-v\n\C-v\n\n"
This wil make bash (readline, actually) insert two verbatim newlines before a regular interpreted newline. By default, only one is inserted, which is what causes output to start on the line after the prompt.
You can test if C-v is set to quoted-insert by typing it in bash (that's Ctrl+V) followed by e.g. an up arrow. This should print ^[[A or something similar. If it doesn't, you can bind it in ~/.inputrc too:
C-v: quoted-insert
RETURN: "\C-e\C-v\n\C-v\n\n"
~/.inputrc can be created if it doesn't exist. The changes will not take effect in running bashes unless you issue a readline re-read-init-file command (by default on C-x C-r). Be careful though. If you do something wrong, enter will no longer issue commands, and fixing your mistake could prove to be difficult. If you should do something wrong, C-o will by default also accept the line.
Adding a newline followed by moving the cursor back to the regular prompt (like you described) is possible, but will not have the effect you intend. The newline you inserted would simply be overwritten by the application output, since you moved the cursor back in front of it.
This works:
trap echo DEBUG
It doesn't add an extra newline if you hit return at an empty prompt.
The command above will cause a newline to be output for every member of a pipeline or multi-command line such as:
$ echo foo; echo bar
\n
foo
\n
bar
To prevent that so that only one extra newline is output before all command output:
PROMPT_COMMAND='_nl=true'; trap -- '$_nl && [[ $BASH_COMMAND != $PROMPT_COMMAND ]] && echo; _nl=false' DEBUG
The DEBUG trap is performed before each command so before the first command it checks to see if the flag is true and, if so, outputs a newline. Then it sets the flag to false so each command afterwards on the line doesn't trigger an extra newline.
The contents of $PROMPT_COMMAND are executed before the prompt is output so the flag is set to true - ready for the next cycle.
Because pressing enter on an empty command line still triggers the execution of the contents of $PROMPT_COMMAND the test in the trap also checks for those contents as the current command and doesn't perform the echo if they match.
I believe (but haven't tried) if you put '\n\b' in the prompt string it would do that.
In general, if you want to find out the codes to do anything a terminal can do, read the terminfo man page.
In this case, the cursor up one line code can be determined by:
tput cuu1
If you redirect the tput output to a file, you can see what control characters are used.
Bash also supports the PROMPT_COMMAND variable, allowing you to run arbitrary commands before each prompt is issued.

Resources