22

I have two urxvt color themes that I use, one for light background and one for dark, depending on how sunny the environment is.

It's easy enough to switch them by modifying ~/.Xresources and running xrdb ~/.Xresources again, but this doesn't affect terminals which are already running.

I use tmux so I can detach, restart the terminal, and reattach, but this gets very annoying very quickly when there are 8 of them already laid-out how I want on various work spaces.

The solution, it seems, is for urxvt to reload its settings somehow but I can't find any information on how to do this or if it's even possible. Does anyone know how?

Note: I don't run any of the major DE's and I'm not about to install all of kde or gnome libs just for a terminal.

Edit: man 7 urxvt shows some wizardly looking codes to do... well... something. I don't see how it applies to changing entire color sets. Any tips?

5 Answers 5

12

By chance, I happened to find the config wiki for mintty. It has a lot of great suggestions, one of which is how to set various options using escape sequences meant for xterm. So this works by not reading the config again but instead by interpreting escape sequences to override the existing color selections.

We can use this from URxvt by binding a key to a long chain of commands, each of which changes one of the 16 default colors.

For example, here I set alt+ctrl+l to change every color to C0C0C0:

# This stupidly changes every color to grey.
URxvt.keysym.M-C-l: command:\033]11;#C0C0C0\007\033]10;#C0C0C0\007\033]4;0;#C0C0C0\007\033]4;1;#C0C0C0\007\033]4;2;#C0C0C0\007\033]4;3;#C0C0C0\007\033]4;4;#C0C0C0\007\033]4;5;#C0C0C0\007\033]4;6;#C0C0C0\007\033]4;7;#C0C0C0\007\033]4;8;#C0C0C0\007\033]4;9;#C0C0C0\007\033]4;10;#C0C0C0\007\033]4;11;#C0C0C0\007\033]4;12;#C0C0C0\007\033]4;13;#C0C0C0\007\033]4;14;#C0C0C0\007\033]4;15;#C0C0C0\007

Perl Plugin

I have it "working" but not really, because it seems that there is a fundamental difference between resources defined as

URxvt.keysym.M-1: command:\033].......

and any attempt to do the same with $term->cmd_parse().

Is there anything that can be done about this? So far I have hardcoded entire light and dark color sets using (very long) escape sequences:

URxvt.keysym.M-C-l: command:\033]4;12;#72729F9FCFCF\007\033]4;1;#CCCC00000000\007\033]4;15;#EEEEEEEEECEC\007\033]4;14;#3434E2E2E2E2\007\033]4;5;#757550507B7B\007\033]4;3;#C4C4A0A00000\007\033]4;7;#D3D3D7D7CFCF\007\033]4;4;#34346565A4A4\007\033]4;10;#8A8AE2E23434\007\033]4;13;#ADAD7F7FA8A8\007\033]4;8;#555557575353\007\033]11;#FFFFFFFFFFFF\007\033]4;9;#EFEF29292929\007\033]4;2;#4E4E9A9A0606\007\033]4;0;#2E2E34343636\007\033]4;11;#FCFCE9E94F4F\007\033]10;#000000000000\007\033]4;6;#060698209A9A\007
URxvt.keysym.M-C-d: command:\033]4;12;#9090FF\007\033]4;1;#AA0000\007\033]4;15;#FFFFFF\007\033]4;14;#55FFFF\007\033]4;5;#AA00AA\007\033]4;3;#AA5500\007\033]4;7;#AAAAAA\007\033]4;10;#55FF55\007\033]4;13;#FF55FF\007\033]4;4;#0000AD\007\033]4;8;#555555\007\033]11;#000000\007\033]4;9;#FF5555\007\033]4;2;#00AA00\007\033]\007\033]4;0;#000000\007\033]4;11;#FFFF55\007\033]10;#00FF00\007\033]5;0;#00FF00\007\033]4;6;#00AAAA\007

This works exactly how I'd hoped it would and can be toggled at runtime so I'm marking this as answered, but why can't this be done dynamically from Perl? Here is what I have so far, I'm not a great Perl coder so please excuse the undoubtedly bad style.

Hopefully someone can chime in on what the issue is. This will be a nice plugin. Upstream is at github.

#! /usr/bin/env perl -w
# Author:  John Tyree
# Website: http://github.com/johntyree/urxvt-perls/blob/master/rotate-colors
# License: CCBYNC

# Use keyboard shortcuts to load colors of the form *.colorN:XXXXXX from a file
# This gives us "on demand" theme switching.

# Usage: put the following lines in your .Xdefaults/.Xresources:
#   URxvt.perl-ext-common: ...,rotate-colors
#   URxvt.colorFiles: ~/.Xresources,~/light.txt,~/dark.txt
#   URxvt.keysym.M-C-n:   perl:rotate-colors:forward
#   URxvt.keysym.M-C-p:   perl:rotate-colors:backward

use strict;


sub on_start {
    my ($self) = @_;
    $self->{current_index} = -1;
    my @arr = split(/,/, $self->x_resource('colorFiles') || '');
    $self->{color_files} = \@arr;
    ()
}

sub read_colors {
    my $fn = shift;
    open my $fin, $fn or print STDERR "Unable to open $fn for reading";
    my %colors;

    while (my $line = <$fin>) {
        if ($line =~ /(\w+)\s*:\s*(#[0-9a-fA-F]+)/) {
            $colors{$1} = $2;
        }
    }
    return %colors
}

sub escape_seq {
    my ($k, $v) = @_;
    my $cmd = "";
    if ($k =~ /^color(\d+)$/) {
        $cmd = "4;$1;$v";
    } elsif ($k =~ /^colorBD$/) {
        $cmd = "5;0;$v";
    } elsif ($k =~ /^colorUL$/) {
        $cmd = "5;1;$v";
    } elsif ($k =~ /^colorBL$/) {
        $cmd = "5;2;$v";
    } elsif ($k =~ /^colorRV$/) {
        $cmd = "5;3;$v";
    } elsif ($k =~ /^foreground$/) {
        $cmd = "10;$v";
    } elsif ($k =~ /^background$/) {
        $cmd = "11;$v";
    } elsif ($k =~ /^cursorColor$/) {
        $cmd = "12;$v";
    } elsif ($k =~ /^pointerColor$/) {
        $cmd = "13;$v";
    }
    return "\033]".$cmd."\007"
}

sub build_cmd {
    my $fn = shift;
    my %colors = read_colors($fn);
    my $s =  join("", map {escape_seq($_, $colors{$_})} keys %colors);
    return $s   # was implicit anyway
}

sub on_user_command {
    my ($self, $cmd) = @_;
    my @fs = @{$self->{color_files}};
    my $len = @fs;

    if ($cmd eq "rotate-colors:forward") {
        my $idx = $self->{current_index}++;
        my $fn = $fs[$idx % scalar(@fs)];
        $self->cmd_parse(build_cmd($fn));
    } elsif ($cmd eq "rotate-colors:backward") {
        my $idx = $self->{current_index}--;
        my $fn = $fs[$idx % scalar(@fs)];
        $self->cmd_parse(build_cmd($fn));
    }
    ()
}
3
  • build_cmd does not return the colors string and cmd_parse() is executed without parameters? Mar 14, 2013 at 2:28
  • Typo. I didn't notice because in perl's infinite wisdom, the return value is implicitly $s there.
    – John Tyree
    Mar 14, 2013 at 14:05
  • 1
    Please tell us when your plugin works.
    – erik
    Feb 5, 2014 at 22:57
7

I created a Perl extension that reloads urxvt configuration upon recieving SIGUSR1: https://github.com/regnarg/urxvt-config-reload

Currently it supports only reloading color configuration but other things (like fonts) can be added easily. Report bugs as github issues.

2
  • It now support font and geometry configuration too! :)
    – Powerman
    Mar 25, 2017 at 4:55
  • Nice! Reading the entire config again isn't really what I want but maybe you've figured out some things that I haven't. With our powers combined...?
    – John Tyree
    May 30, 2017 at 17:38
5

The following script can be used with URxvt (or any other terminal supporting XTerm OSC escape sequences) to change the color scheme on the fly. It accepts .Xresources-style definitions as input, and outputs the escape sequences. Simply running the script in the terminal and pasting a colorscheme into it will change the color palette — useful for quickly trying out different schemes.

#!/bin/sh
tr -d ' \t' | sed -n '
s/.*background:/\x1b]11;/p
s/.*foreground:/\x1b]10;/p
s/.*color\([0-9][^:]*\):/\x1b]4;\1;/p
' | tr \\n \\a

Shell redirection can be used as well: ~/bin/term-recolor < .Xdefaults.solarized.dark.

0

Configuration is read once in the lifetime of a urxvtd process or a standalone urxvt. It's not possible to reload the configuration and have the effects take place in an already running instance of the program. There are exceptions to this rule, when it comes to some font and locale settings.

You could scroll down to the appropriate section in your terminal. Here are a couple of relevant FAQs

Q Why doesn't rxvt-unicode read my resources?

A (shortened) It does, use xrdb. You have to re-login after every change (or run xrdb -merge $HOME/.Xresources).

That implies reloading the terminal binary to me.

Q I don't like the screen colours. How do I change them?

A You can change the screen colours at run-time using ~/.Xdefaults resources (or as long-options).

I think that means "when you start the application".


You could make certain text appear in a certain color, but the colors are defined in the x-resources files and have to be re-read (by restarting) every time they are changed. I may be wrong, but I don't think urxvt supports changing color definitions after its started. Perhaps there is a control sequence for that, I'm not sure.

E. G.

$ cat colors-in-bash
#!/bin/bash
for code in {0..255}; do
        if [[ code%8 -eq 0 ]];then echo ;fi
        printf "%5s" `echo -n -e "\e[38;05;${code}m $code: Test"`
done

more relevant info:

http://pod.tst.eu/http://cvs.schmorp.de/rxvt-unicode/doc/rxvt.7.pod#XTerm_Operating_System_Commands

http://www.xfree86.org/current/xterm.1.html#toc19

http://en.wikipedia.org/wiki/Control_Sequence_Introducer#Sequence_elements

http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

5
  • Right. And the special exceptions with respect to font and colors shown in man 7 urxvt are what I'm interested in. I just can't tell how it works.
    – John Tyree
    Mar 13, 2013 at 18:00
  • AFAIK, the color escape sequences are used to say "after here comes red" --red text-- "after here normal text" -- black on white-- and so on. But the definitions of red and white and black are read from the available x resources only when the binary starts. Mar 13, 2013 at 19:21
  • I found this as well looking at the wiki for mintty but SU doesn't let new people answer their own questions within 8 hours. I'm currently writing a urxvt perl plugin to do just this.
    – John Tyree
    Mar 13, 2013 at 19:52
  • It would be interesting to see your results. Mar 13, 2013 at 19:54
  • I solved the problem in an unsatisfying way. The beginnings of a nice plugin to dynamically load color files is included. Help appreciated.
    – John Tyree
    Mar 13, 2013 at 23:38
0

I know it's been a while, but I was looking at your perl code with an eye towards setting the default urxvt colors depending on which ssh host I was connected to.

Then I stumbled across the OSC escape sequence definitions at http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Control, and came up with the following:

printf '\x1b]10;%s\a\x1b]11;%s\a' yellow blue

Where in this case "yellow" is the foreground and "blue" is the background color. The color definitions can be any string acceptable to XParseColor e.g. LemonChiffon or #FF4455.

This permanently overrides the terminal's default colors, such that a terminal reset will use new colors. It is therefore sticky with respect to normal ANSI escape sequences, which is exactly what I needed. Works on rxvt and urxvt, probably other consoles as well (OSC is even mentioned in man console_codes).

There also appear to be codes to override individual ANSI colors, I haven't tried those but if they work I would think that's the best way to dynamically theme your console, you could literally just "cat dark" or "cat light".

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .