Programmatic access to current xterm background color?

13

6

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?

Miserable Variable

Posted 2010-06-28T06:00:40.013

Reputation: 759

Answers

22

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

Alex North-Keys

Posted 2010-06-28T06:00:40.013

Reputation: 221

1Now this is pure terminal voodoo. Excellent answer. – Qix - MONICA WAS MISTREATED – 2014-10-31T05:48:58.790

Here is a program that makes this easy: https://github.com/JessThrysoee/xtermcontrol/tree/master/doc

– Tim Smith – 2018-06-13T02:27:30.550

1Wow...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 – 2012-03-29T17:08:17.943

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 – 2012-03-29T18:23:09.100

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 – 2012-03-29T18:45:39.023

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 – 2012-03-29T20:27:56.010

1Hmm, gnome terminal in Ubuntu 12.04 claims to be xterm-compatible, but doesn't print anything back. Why is that? – Nik Reiman – 2012-09-21T13:03:26.703

0

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

Posted 2010-06-28T06:00:40.013

Reputation: 52 754

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 – 2010-06-28T06:56:02.550

well, you didnt specify your OS :) – akira – 2010-06-28T07:14:59.470

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 – 2010-06-28T07:20:18.467

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 – 2010-06-28T08:13:06.210

-1 awk is the wrong tool for the job. – g33kz0r – 2011-08-20T09:36:08.637

@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 – 2011-08-20T10:32:08.213

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. – g33kz0r – 2011-08-20T13:36:03.457

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 – 2011-08-20T14:52:15.083

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. – g33kz0r – 2011-08-20T15:23:30.520

@Noah: then 'get the current value for the foreground of xterm' with a commandline based upon xrdb only. – akira – 2011-08-20T15:26:08.813

@Noah let us continue this discussion in chat

– akira – 2011-08-20T15:27:16.813

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. – g33kz0r – 2011-08-20T19:11:20.877

@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 – 2011-08-22T07:53:06.957

-1

Actually I think you want this:

% xrdb -query

That will list the settings for you. See also:

http://docstore.mik.ua/orelly/unix3/upt/ch06_08.htm

To modify the runtime, use:

% echo "some*setting: somevalue" | xrdb -merge

g33kz0r

Posted 2010-06-28T06:00:40.013

Reputation: 284

-query lists all resources. specifying a resource does not work on my ubuntu. – akira – 2011-08-20T10:46:02.927

echo "whatever" | xrdb -merge – g33kz0r – 2011-08-20T13:32:40.857

reread the question: OP wants to set the colors of the BASH PROMPT according to the settings of the xterm. OP does not want to change the xresources. – akira – 2011-08-20T14:47:20.547

See his comment to your answer. He wants to "query the termincal [sic]". Thus, he wants xrdb -query – g33kz0r – 2011-08-20T19:07:31.350

if you want to be that specific: he wants to query rxvt withtout a running xserver on windows (which is possible) and xrdb -query just gives you the list of all resources .. which you have to awk / grep again to get to the foreground. and thats what i admitted already. xrdb -merge is completely offtopic here coz OP does not want to modify the xresources but the appearance of the bashprompt. – akira – 2011-08-20T20:50:30.030