Debian .bashrc: prompt PS1 - bash

Let's say I'm on a fresh install of Debian, Jessie (or Wheezy). As a regular user, I've got the prompt defined in the /etc/bash.bashrc file, eventually override by the one in my /home/foobar/.bashrc
Ok, cool, so I've got something like that: foobar#myserver:~$
Now, I'm trying to understand the code below:
# If this is an xterm set the title to user#host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u#\h: \w\a\]$PS1"
;;
*)
;;
esac
As you can see, the PS1 variable (= the prompt) seems to be overrided again (cause yeah I'm in a xterm). But I can't get why we have another $PS1 on the end of the line!
In order to get this, I've put 3 letters a b c in this line :
PS1="a\[\e]0;${debian_chroot:+($debian_chroot)}\u#\h: \w\a\]b$PS1 c"
And now, I have the strange prompt below:
abfoobar#myserver:~$ c
So it seems that the almost entire line is not use, everything between the brakets.
Is that a sort of conditional statement?
What is really the purpose of this line?
Why the comment talk about the title of the xterm windows but seems
to only override the PS1? I'm running this xterm through PuTTY ; in ubuntu, this line is quite different
PROMPT_COMMAND='echo -ne "\033]0;${USER}#${HOSTNAME}: ${PWD}\007"'

the part between \[ \] seems to be an escape sequence which is handled by terminal : ESC ] which is named OSC for Operating System Commands in following link xterm escape sequence
OSC Ps ; Pt ST
Set Text Parameters. For colors and font, if Pt is a "?", the
control sequence elicits a response which consists of the con-
trol sequence which would set the corresponding value. The
dtterm control sequences allow you to determine the icon name
and window title.
Ps = 0 -> Change Icon Name and Window Title to Pt.
It is to change xterm window title.
As the window title contains the current working directory setting the prompt allows to update the title when changing directory after cd command.

Related

How can I add a character before every capital letter in a terminal emulator's output (for a Braille display)?

TL;DR?
How can I change every instance of one character (e.g. 'E') in a terminal window to another string of characters (e.g. '~E'), moving all other characters along in the window in the process? So:
abcdEfghij
becomes:
abcd~Efghij
This should work in the gnome-terminal and work with whatever output is on that terminal, from whatever program. Ideally it will be a script or other program I can run within that terminal emulator.
The context
I am using a Braille display (the Canute 360) with a Braille screen-reader (brltty), which at present does not support capital letters. They show up in Braille the same as lower-case letters. Until this is developed for BRLTTY I sometimes need to be able to force showing which letters are capitalised in order for me to, for example, write code.
The proposed solution
N.B. The below proposed solution is not intended to be elegant; it is a quick and dirty way of letting me and other Braille-using developers continue to program with this display for our work until the proper solution is forthcoming in the screen-reader proper.
I am trying to essentially 'wrap' the output of the terminal emulator (in this case gnome-terminal to force a certain character in front of every capital letter so on the Braille display it can be identified. I am going to assume that character is tilde (~). I am not concerned about this breaking vertical alignment, or forcing the line off the edge of the display. I am assuming a 40 character wide terminal (width of the Canute).
So this normal output:
$ echo ${string}
A Quick Brown Fox
Jumps over the lazy
Dog. Etc.
$
Becomes this:
$ echo ${string}
~A ~Quick ~Brown ~Fox
~Jumps over the lazy
~Dog. ~Etc.
$
That would then be viewable on the Canute (in US Computer Braille) as this:
$ echo ${string}
~a ~quick ~brown ~fox
~jumps over the lazy
~dog. ~etc.
$
It is fine for this to be a command that has to be called first, like screen. So:
$ caps-hack
$ nano
[doing my thing, then quit nano]
$
[ctrl-x to quit caps-hack]
$
Or alternatively it could launch a new terminal window, or it could be tied to specific TUI applications (like nano). I will primarily be using it for working inside vi, nano, micro and other editors, so if it cannot capture all terminal output the solution is still valuable.
Example use case: Micro/nano text editor
When I need to see capitals whilst editing text using micro or nano I would first launch caps-hack, then I could use the TUI editor, exit it, be back on the terminal, then cancel caps-hack if I wanted to revert to usual behaviour.
This is what nano normally looks like:
GNU nano 4.8 New Buffer Modified
This is a nonsense file for
Stackoverflow.
^G Get Hel^O Write O^W Where I^K Cut Tex
^X Exit ^R Read Fi^\ Replace^U Paste T
I'm looking for a solution that would then make it look like this:
~G~N~U nano 4.8 ~New ~Buffer ~Modi
~This is a nonsense file for
~Stackoverflow.
^~G Get ~Hel^~O ~Write ~O^~W ~Where ~I^~
^~X ~Exit ^~R ~Read ~Fi^\ ~Replace^~U
(Note that I have cut it off at 40 characters.)
The effect would be the same (inserting tildes, cutting off at 40 characters) whether I was in the terminal itself, in mc, or watching a ping stream.
This active use case means that so far as I can see I cannot simply pipe the output of programs to a bash script (like the one below), as that wouldn't work with a TUI. So I cannot do: $ nano myfile.txt | caps-hack
What I have tried so far
I have not worked out how to essentially capture the output, modify it and write it back to the terminal window. However I have the following shell snippet which I believe could be used for it, if I know where to put it.
# Repeat for all visible lines in the terminal
moddedline1=$( echo ${originalLine1} | sed -E -e 's/\([A-Z]\)/~\1/g' )
moddedline1="${moddedline1:0:40}"
tput cup 1 0 && printf "${moddedline1}"

Terminal escape sequences not working on OS X Mavericks 10.9DP7

When i try to set my terminal window title:
$ echo -n "\033]0;foo\007"
\033]0;foo\007
It just print plain text, the terminal title had no change. How to fix it?
You're missing the -e to echo which tells it to interpret backslash escape sequences. Try this:
$ echo -en "\033]0;foo\007"
Although #chris-page is correct about -n being non-standard, the bash builtin echo and the system /bin/echo both support -n. However, the system echo does not support -e which is the real import feature when trying to send those escape codes to the terminal.
Also be aware that the system wide /etc/bashrc sets PROMPT_COMMAND to the function update_terminal_cwd, which is defined as:
update_terminal_cwd() {
# Identify the directory using a "file:" scheme URL,
# including the host name to disambiguate local vs.
# remote connections. Percent-escape spaces.
local SEARCH=' '
local REPLACE='%20'
local PWD_URL="file://$HOSTNAME${PWD//$SEARCH/$REPLACE}"
printf '\e]7;%s\a' "$PWD_URL"
}
And apparently the operating system code 7 for Apple's Terminal.app sets a special icon link to the current working directory. You can right click on the folder icon in the title bar to open Finder at that location. This code also modifies the title bar title a bit by prepending the last component of the current working directory.
I've been investigating how Terminal.app's tab titles vs title bar title are set. And apparently they follow along with xterm's pretty well, where 'icon name' is the tab title, and 'window title' is the title bar title.
The title bar title is whatever you set with osc-2 (or osc-0). If the extra path component is set by osc-7 it will be prepended to the title bar title. And if any components are checked in Preferences->Settings->Window, they will be appended to the title bar title.
The tab title is whatever you set with osc-1 (or osc-0). If that is unset, it will be the contents of the Title box of Preferences->Settings->Window with the active process name appended. If the title is exactly Terminal (whether set by the text box in preferences or by osc-1) the tab title will just be the active process name.
Bash’s built-in echo command no longer† supports the -n option, because it’s not a POSIX option. Instead, use the printf command to send control characters: printf '\033]0;foo\007’.
In general, it’s better practice to use printf for consistent results instead of echo for anything more complicated than printing strings with ASCII graphic characters, because POSIX echo is fairly simple and any extended behaviors may vary between shells.
† I don’t recall exactly which OS version it changed, but it’s unsupported in 10.8.

"CLS" Equivalent in BASH?

How do you clear the entire terminal in BASH, like the command prompt's cls command?
clear doesn't work because it doesn't actually clear anything, it just scrolls down.
As far as I know, there isn't a way to do this any better than what clear does with bash.
I think it's a feature that could be built into the terminal you're using though. I know the Mac Terminal app has a 'Clear Scrollback' menu option (command + k) that does what you're asking for.
Why don't you try Ctrl+l (control, lowercase "L"). This works in most shells (err terminals)...
In OSX terminal -
Command ⌘+l (command, l) leads to removing last typed command from display.
Command ⌘+k (command, k) leads to removing/clearing all display buffer.
reset (type this in terminal) leads to reset of terminal in case display becomes garbled.
not sure of equivalent in other unix flavors.
You're probably looking for the reset command.
However, the scroll-back buffer is not a feature of bash but of the terminal program. You didn't say what terminal program you were using.
xterm will allow the escape sequence ESC [3J to clear the scroll back, so you could do:
alias cls="clear; printf '\033[3J'"
Short Answer
clear && clear
or
tput reset
Other Ways
Here are all the ways you can clear the terminal screen in Unix:
clear # only clear visible screen
clear && clear # clear buffer as well
tput clear # same as clear but by sending escape seq
reset # clear + reset internal terminal state + 1sec delay
tput reset # same as reset but without 1sec delay
stty sane # don't clear screen but reset some terminal options
echo -e "\033c" # same as tput reset but hardcoded escape seq
printf "\033c" # same as tput reset but hardcoded escape seq
setterm -reset # same as tput reset, setterm has friendlier commands
Long Answer
The clear command only clears the visible screen but not the buffer so you can do Shift+PageUp to scroll up in the terminal and still view previous outputs. If you want to get same result as cls then do clear twice like clear && clear.
Another related command is reset which (I believe) resets the internal state of the terminal program. Unfortunately, this command includes 1 second of delay to support really old terminals. So if you are not ok with that kind of delay then use tput reset which seems to do same thing as reset minus the delay.
But what does tput do? In Unix, you can send terminal all kinds of ASCII character sequences which are interpreted as commands by the terminal. This allows you to do funky things like blink or color the text or turn off echo (during password typing) or set terminal options or do clear or reset. This you can send by tput clear or tput reset. The clear and reset command are equivalent but they run from the binaries that comes with your distro and may do additional stuff. The setterm -reset is similar to tput reset. Setting terminal using setterm is usually better because unlike tput it has more readable options in general case however we here use tput because it's smaller in length :).
You might have also seen people using things like echo -e "\033c" or printf "\033c" which is equivalent to tput reset but the escape sequence is now hard coded. The tput looks up terminal properties and uses the right escape sequence.
Another related command is stty sane which actually doesn't do any screen clearing but it sets many of the terminal options to defaults so if your terminal looks garbled or if terminal stays blank when you type (for example, because you printed binary file to terminal with escape sequence to turn off echo) then this command might help. For extreme garbled terminal cases, you can use all of the available resetting techniques in the sequence. I've alias like this for such occasions:
alias cls='tput reset'
alias clshard='reset; stty sane; tput rs1; setterm -reset; tput reset'
Related
What's the equivalent of the “cls” command from Windows/DOS?
What commands can I use to reset and clear my terminal?
Use ⌘+K. It removes the entries so I can't scroll up anymore.
So ⌘+K to clear everything including scrolling.
Ctrl+L to clear terminal window but still be able to see everything when scrolling up.
In ~/.bashrc, the perfect cls is:
cls () {
printf -- '%b' '\033c'
return $?
}
The clear command works for me.
But I personally find it impractical, because, for me, it clears the scrollback permanently and irreversibly. However, often I want just to insert some "marker"/"separator" into the scrollback, in order to be able to visually distinguish the "recent scrollback" from the "too old scrollback" (but sometimes ability to see the "too old scrollback" would be still useful). So I use something like:
yes '' | head -n100
That inserts 100 empty lines into the scrollback. (Inspired by this answer. You can vary the number of lines, of course.)

What's an easy way to have terminal use a different color based on ssh host name?

Using putty in windows, you can save sessions that connect to a certain host and use a certain text color...this was super useful for me since I work with a bunch of remote hosts and I'm wondering if there is (there must be) a way to get Terminal (in Snow Leopard) to emulate this behavior.
I'm wondering how I would
1. Save a connection (e.g. username#hostname.com) and have that connection always open with a certain text color (e.g. #00ff00)
2. Ideally, have any terminal window detect what host it was in and change its color accordingly. So if I was in my regular Terminal environment and issued a successful ssh username#hostname.com, it would automatically change the text color of that terminal window (or tab) to #00ff00
Let me know, thanks!
OK, if you insist on invoking ssh from the command line, here's something that should do the trick: write a shell script and save it somewhere as colorssh.sh. When it runs, it looks at its arguments for a matching host and sets the active terminal window's colors appropriately. Then it invokes the real ssh, passing along those arguments. When ssh returns execution to the script, it sets the colors back to normal.
Since you probably want to keep typing ssh instead of colorssh.sh, you can set an alias in your .profile.
As for the script itself? Here is teh codez:
#!/bin/bash
function setTerminalColors {
osascript \
-e "tell application \"Terminal\"" \
-e "tell selected tab of front window" \
-e "set normal text color to $1" \
-e "set background color to $2" \
-e "end tell" \
-e "end tell"
}
for ARG in $*
do
case "$ARG" in
host.example.com)
username#host.example.com)
setTerminalColors "{0,65535,65535}" "{65535,0,0}"
;;
username#otherhost.example.com)
setTerminalColors "{65535,65535,0}" "{0,65535,0}"
;;
esac
done
ssh $*
# back to normal
setTerminalColors "{0,0,0}" "{65535,65535,65535}"
You'll have to edit the script to add new host/color combinations.
Note that colors must be specified as an RGB triplet of integers in the range 0-65535. I know, weird, right?
Technically, the AppleScript portion changing deprecated properties. You're supposed to change a window's colors via its "settings set" property, but I suspect that would change all windows using that settings set, not just the current one.
Also, this script assumes that black on white is your "normal" setting. If that's not the case you could change the script to save the current values before running or use the colors from the default settings set.
In terminal you can define profiles with different window background color, opacity, etc. Also in profiles you can specify a startup command. You could set up a different profile for each host you use with a startup command of "ssh me#thathost", but this would only work for new windows. Profiles are easy to get to via Shell -> New Window.

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