16

I would like to setup the prompt colors in .bashrc depending on the colors it is using for foreground and background.

For example, blue prompt if background is light and beige if it is dark.

Is there a way to find out the current settings in a script?

Robotnik
  • 2,390
  • 3
  • 23
  • 41
Miserable Variable
  • 942
  • 2
  • 12
  • 30

2 Answers2

27

The email back from Thomas Dickey (xterm's maintainer) has this. Note in particular the part about ?. The Ps = 4 refers to OSC Ps ; Pt ST where OSC (the "Operating System Control" prefix) is ESC ] and ST (the "String Terminator" suffix) is \ (backslash). The 4 is one of the possible subcommands to OSC.

For the whole palette, that can be set/retrieved using the 88/256 color extension. In ctlseqs.txt, it's summarized here:

  Ps = 4 ; c ; spec -> Change Color Number c to the color
specified by spec.  This can be a name or RGB specification as
per XParseColor.  Any number of c/spec pairs may be given.
The color numbers correspond to the ANSI colors 0-7, their
bright versions 8-15, and if supported, the remainder of the
88-color or 256-color table.

If a "?" is given rather than a name or RGB specification,
xterm replies with a control sequence of the same form which
can be used to set the corresponding color.  Because more than
one pair of color number and specification can be given in one
control sequence, xterm can make more than one reply.

A bit later in the docs are more OSC subcommands, Ps = 10 and Ps = 11, and others.

Ps = 1 0  -> Change VT100 text foreground color to Pt.
Ps = 1 1  -> Change VT100 text background color to Pt.

Example - this queries the background using Ps = "11" (from just above) and Pt = "?", plugged into the OSC Ps ; Pt ST. In the echo, \033 is being used for escape, and \\ for the final backslash.

echo -en "\033]11;?\033\\"

Output:

^[]11;rgb:0000/0000/0000^[\ 

Warning: The returned color does not reflect whether reverse video, like -rv, is enabled, and crawling through the ~260 colors available via OSC 4 ; c ; ? ST doesn't show any that both follow the background AND change with reverse video. Since many users set a dark background by using just xterm -rv, this complicates determining whether the background is actually dark or not. Most colors don't adjust to -rv, either.

A script to do the full query and actually capture the reply from xterm:

#!/bin/bash
success=false
exec < /dev/tty
oldstty=$(stty -g)
stty raw -echo min 0
col=11      # background
#          OSC   Ps  ;Pt ST
echo -en "\033]${col};?\033\\" >/dev/tty  # echo opts differ w/ OSes
result=
if IFS=';' read -r -d '\' color ; then
    result=$(echo $color | sed 's/^.*\;//;s/[^rgb:0-9a-f/]//g')
    success=true
fi
stty $oldstty
echo $result
$success
wjandrea
  • 595
  • 8
  • 19
Alex North-Keys
  • 271
  • 3
  • 4
  • 1
    Wow...a response after two years...thank you. I didn't quite understand the explanation but the example does nothing for me...echoes nothing. – Miserable Variable Mar 29 '12 at 17:08
  • Heh. I'm re-running it in a pretty recent xterm - an actual xterm - this time with all my X resources stripped out (which means it yields all "f"s for the colors instead of all "0"s). Using either /bin/echo or bash's builtin echo works fine. The example I tried was copy/pasted directly from the post above. My environment is Ubuntu 11.10 (a Linux/Debian derivative). I don't have a different OS handy to test. – Alex North-Keys Mar 29 '12 at 18:23
  • Depending on how your prompt is configured, there's a chance that it's landing on top of xterm's attempt to stuff input into your terminal in response to your query. From your shell's perspective, xterm's reply just looks like you, typing. – Alex North-Keys Mar 29 '12 at 18:45
  • Previously I had set `PS1` to `\$> ` when I did not see any output. Now I tried `$> /bin/echo -en "\033]11;?\033\\" | od -cx` and exactly the same string on my terminal: `0000000 033 ] 1 1 ; ? 033 \` – Miserable Variable Mar 29 '12 at 20:27
  • 1
    Hmm, gnome terminal in Ubuntu 12.04 claims to be xterm-compatible, but doesn't print anything back. Why is that? – Nik Reiman Sep 21 '12 at 13:03
  • 1
    Now *this* is pure terminal voodoo. Excellent answer. – Qix - MONICA WAS MISTREATED Oct 31 '14 at 05:48
  • Here is a program that makes this easy: https://github.com/JessThrysoee/xtermcontrol/tree/master/doc – Tim Siegel Jun 13 '18 at 02:27
  • `echo -en "\033]11;?\033\\"` works in my terminal, but the bash script given at the end just hangs for me (macos, iTerm2) – Anentropic Jan 30 '22 at 16:32
1

kind of

put the settings into your ~/.Xdefaults file:

xterm*foreground: blue
xterm*background: white

in your shell you just grep the values:

awk '/xterm\*foreground:(.*)/ { print $2 }' < .Xdefaults

otherwise it's pretty hard to get some internal values of the xterm.

akira
  • 61,009
  • 17
  • 135
  • 165
  • I am not even using X :) I am using an rxvt from cygwin that runs without an X server. Besides I would like to be able to use different colors on different hosts and for different tasks, which requires that I query the termincal for settings. – Miserable Variable Jun 28 '10 at 06:56
  • well, you didnt specify your OS :) – akira Jun 28 '10 at 07:14
  • sorry about that. The reason I did not specify is because I had expected the solution to be based on echoing some magic strings and get some info back on stdout. – Miserable Variable Jun 28 '10 at 07:20
  • well, what you "echo" normally stays inside the shell (bash, zsh), it does not go to xterm (except in the final step when it comes to displaying the output of the commands). – akira Jun 28 '10 at 08:13
  • -1 awk is the wrong tool for the job. –  Aug 20 '11 at 09:36
  • @Noah: it is not. you have to process `xrdb -query` as well. the "wrong" part of my answer is that i parse .Xdefault instead of the globally merged settings. – akira Aug 20 '11 at 10:32
  • From the xrdb manpage: "FILES Generalizes ~/.Xdefaults files." That's what we're doing here. Awk might work for this, just as duct tape might hold together a sink. But there is a tool created for the specific purpose of manipulating these X resource files, and its name is xrdb. –  Aug 20 '11 at 13:36
  • since OP does not want to manipulate xresources your argument is nil... the question is about getting the current value of the forground of xterm and you have to use some regexp tool to get to that resource, `xrdb -query` is not enough (neither is awking .Xdefaults, but i admitted that alredy). – akira Aug 20 '11 at 14:52
  • My "argument"? Honestly I don't think it's necessary to put it in such adversarial terms, and I'm more than a bit put off by your claim that you know what "the question is about". Do you really have some unique insight into OP's state of mind? Well, even if you do, and it's true that all OP wants to do *right now* is "get the current value", consider what would happen if he changes his mind. Then he would have to ... throw out your awk solution and re-write it using ... xrdb. Which is precisely why xrdb is the right tool for the job. –  Aug 20 '11 at 15:23
  • @Noah: then 'get the current value for the foreground of xterm' with a commandline based upon xrdb only. – akira Aug 20 '11 at 15:26
  • @Noah let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/1127/discussion-between-akira-and-noah) – akira Aug 20 '11 at 15:27
  • I can do it in a single command -- if that's what you mean by "a commandline ... only" -- using 10 different programming langues. But I'm not going to for the same reason I'm not going to use Awk to do it. –  Aug 20 '11 at 19:11
  • @Noah: reread the question until you get it. OP does NOT want to change xterm's foreground / background. OP wants to change the color of shell prompt, depending on how xterm currently looks. `xrdb -merge` is "the wrong tool for the job, and for `xrdb -query` you have to use a companion like awk to actually get _the_ _one_ _value_. – akira Aug 22 '11 at 07:53