Escape sequence for arrow keys - terminal

I am trying to recognize the arrow keys from stdin and I have found many resources online suggesting to look for this escape sequence: ESC-[-D
However, on my terminal the arrow keys are actually printing the following: ESC-O-D
Here is what I get if I run cat and press the left arrow:
$ cat
^[OD
Could you please help me understand why this is happening? Are both escape sequences considered valid?
Additional information:
The $TERM environment variable is set to screen.
I am running zsh inside tmux.
I use Putty to SSH to the server.
Thanks!!

Related

Text doesn't clear after modifying terminal prompt

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\]"

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!

In bash, how do I bind a function key to a command?

Example: I want to bind the F12 key to the command echo "foobar" such that every time I hit F12 the message "foobar" will be printed to screen. Ideally it could be any arbitrary shell command, not just builtins. How does one go about this?
You can determine the character sequence emitted by a key by pressing Ctrl-v at the command line, then pressing the key you're interested in. On my system for F12, I get ^[[24~. The ^[ represents Esc. Different types of terminals or terminal emulators can emit different codes for the same key.
At a Bash prompt you can enter a command like this to enable the key macro so you can try it out.
bind '"\e[24~":"foobar"'
Now, when you press F12, you'll get "foobar" on the command line ready for further editing. If you wanted a keystroke to enter a command immediately, you can add a newline:
bind '"\e[24~":"pwd\n"'
Now when you press F12, you'll get the current directory displayed without having to press Enter. What if you've already typed something on the line and you use this which automatically executes? It could get messy. However, you could clear the line as part of your macro:
bind '"\e[24~":"\C-k \C-upwd\n"'
The space makes sure that the Ctrl-u has something to delete to keep the bell from ringing.
Once you've gotten the macro working the way you want, you can make it persistent by adding it to your ~/.inputrc file. There's no need for the bind command or the outer set of single quotes:
"\e[24~":"\C-k \C-upwd\n"
Edit:
You can also create a key binding that will execute something without disturbing the current command line.
bind -x '"\eW":"who"'
Then while you're typing a command that requires a username, for example, and you need to know the names of user who are logged in, you can press Alt-Shift-W and the output of who will be displayed and the prompt will be re-issued with your partial command intact and the cursor in the same position in the line.
Unfortunately, this doesn't work properly for keys such as F12 which output more than two characters. In some cases this can be worked around.
The command (who in this case) could be any executable - a program, script or function.
You can define bash key bindings in ~/.inputrc (configuration file for the GNU Readline library). The syntax is
<keysym or key name>: macro
for example:
Control-o: "> output"
will create a macro which inserts "> output" when you press ControlO
"\e[11~": "echo foobar"
will create a macro which inserts "echo foobar" when you press F1... I don't know what the keysym for F11 is off hand.
Edit:
.inputrc understands the \n escape sequence for linefeed, so you can use
"\e[11~": "echo foobar\n"
Which will effectively 'press enter' after the command is issued.
This solution is specific to X11 environments and has nothing to do with bash, but adding the following to your .Xmodmaps
% loadkeys
keycode 88 = F12
string F12 = "foobar"
%
will send the string "foobar" to the terminal upon hitting F12.
I wanted to bind Ctrl+B to a command. Inspired by an answer above, I tried to use bind but could not figure out what series of cryptic squiggles (\e[24~ ?) translate to Ctrl+B.
On a Mac, go to Settings of the Terminal app, Profiles -> Keyboard -> + then press the keyboard shortcut you're after and it comes out. For me Ctrl+B resulted in \002 which i successfully bound to command
bind '"\002":"echo command"'
Also, if you want the command to be executed right-away (not just inserted in to the prompt), you can add the Enter to the end of your command, like so:
bind '"\002":"echo command\015"'

Shell Prompt Line Wrapping Issue

I've done something to break my Bash Shell Prompt in OS X (10.5.7) Terminal.
This is the PS1 that I had configured:
PS1='\[\e[1;32m\]\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]\$ '
As far as I can tell I have the color commands escaping correctly. However when I scroll up and down in my command history I often get line wrapping issues if the historic commands wrap onto multiple lines.
I simplified my prompts to the following:
PS1='\[\e[1m\]\h:\w\$ \[\e[0m\]'
PS2='> '
And I still see something like:
localhost:~/Library/Application Support/Firefox/Profiles/knpmxpup.Defau
lt/extensions/{1A2D0EC4-75F5-4c91-89C4-3656F6E44B68}$ expocd \{1A2D0EC4-7
5F5-4c91-89C4-3656F6E export PS1="\[
\e[1;32m\]\h\[\e[0m\]: cd Library/Appl
ication\ Support/
I've also tried \033 instead of \e. I just included PS2 up there for information, I haven't changed that from the install default. If I completely remove the color codes then everything works fine, any ideas?
I am now using this PS1 with good effect:
green=$(tput setaf 2)
blue=$(tput setaf 4)
bold=$(tput bold)
reset=$(tput sgr0)
PS1="\[$green$bold\]\h\[$reset\]:\[$blue$bold\]\w\[$reset\]\$ "
Scrolling through my command history appears to handle line wraps now. However in the meantime since this question was asked I have also updated my OS X to 10.6.3
This stackoverflow thread seems relevant. As someone noted in that thread, the Bash FAQ at mywiki.wooledge.org discusses how to properly quote color codes in Bash prompts (FAQ 53), and the proper invocation of terminal colors (FAQ 37).
Line wrapping issues in Bash are nothing new. Your PS1 should work as is but there is a bug in Bash 3.2.49. Consult the mailing list, there's yet another bug regarding this which was confirmed to be fixed in 4.0.
You can't do much more than tagging unprintable characters with \[ and \], the rest must be done by the prompting code.
It seems that you have correctly escaped and enclosed sequences.
A workaround I use anyway it it to add a '\n' at the end. I find it clearer and lessen any problem with wrapping issues. The exact end of my PS1 is :
'\n\[\033[0;30m\]$\[\033[0m\]
An excellent howto you probably know :
Bash prompt howto
I noticed that there are some issues with the prompt cursor positioning even if there are no special character in the PS1 or PROMPT environment variable.
If we output a file that does not have a end-of-line char at the end. It will confuse the prompt.
You can reproduce this by doing:
curl https://gist.githubusercontent.com/martinos/d4aa0a7d4d752b0d0d9f/raw/3198c39f84a080c44227a084a19fb3a0bb661ee5/wrapping_issue.txt
and pressing the up key multiple times and you will see that the prompt get confused.
You can see an example of this in action:
https://asciinema.org/a/9mtjhi9dib6md4ocsbw210cca
When this occurs, just press <CTRL-C> and the prompt will come back to normal.
Note that ZShell does not have this issue.
For future reference, this is what I use:
export PS1="\[\033[0;31m\][\u#Project:\w]$\[\033[0m\] "
This would display my shell prompt as:
[ec2-user#Project:~]$
Helps me distinguish between live and dev sites.
Here's mine: it's the best one I've found, but the site where I originally found it was missing an escape character, leading to the line wrapping issue. I tinkered with it and finally got it working. It shows your user, path, and branch info with good contrast, color-wise.
export PS1='\[\e[1;37m\]\[\e[1;32m\]\u\[\e[0;39m\]:\[\e[1;33m\]\w\[\e[0;39m\]\[\e[1;35m\]$(__git_ps1 " (%s)")\[\e[0;39m\] \[\e[1;37m\]|\[\e[0;39m\]\$'
Also, add
GIT_PS1_SHOWDIRTYSTATE=true
To show a marker when a branch is "dirty" (changes to be committed exist)
export HISTCONTROL=ignoredups
Is also useful to ignore duplicates when scrolling up through bash history.
bind "set completion-ignore-case on"
Helps too.
Lastly,
shopt -s checkwinsize
May be helpful on OSX if issues persist.
'shopt -s checkwinsize' also works for Cygwin wrap problems also
If you're using the title bar trick "\e]2;titlebar\a", make sure to escape that too: "\[\e]2;titlebar\a\]"

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