23

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?

Carl B
  • 6,660

5 Answers5

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));
    }
    ()
}
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.

regnarg
  • 201
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.

amonakov
  • 205
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

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".

rich
  • 1