rxvt-unicode の設定 (と、わりと微妙な自作カラースキームの紹介)
設定ファイル
#define FGCOLOR #f7fcfe
#define BGCOLOR #203744
#define BLACK #0d0015
#define B_BLACK #2b2b2b
#define RED #a25768
#define B_RED #ee827c
#define GREEN #82ae46
#define B_GREEN #93ca76
#define YELLOW #f08300
#define B_YELLOW #f7c114
#define BLUE #455765
#define B_BLUE #53727d
#define MAGENTA #68699b
#define B_MAGENTA #a59aca
#define CYAN #008899
#define B_CYAN #59b9c6
#define WHITE #9fa0a0
#define B_WHITE FGCOLOR
URxvt.termName: rxvt
URxvt.font: xft:Ricty:size=10:antialias=true
URxvt.letterSpace: 0
URxvt.transparent: true
URxvt.shading: 100
URxvt.saveLines: 2048
URxvt.scrollBar_right: true
URxvt.scrollstyle: plain
URxvt.fading: 40
URxvt.foreground: FGCOLOR
URxvt.background: BGCOLOR
URxvt.cursorColor: FGCOLOR
URxvt.cursorColor2: BGCOLOR
URxvt.highlightColor: FGCOLOR
URxvt.highlightTextColor: BGCOLOR
! 基本 8 色
URxvt.color0: BLACK
URxvt.color1: RED
URxvt.color2: GREEN
URxvt.color3: YELLOW
URxvt.color4: BLUE
URxvt.color5: MAGENTA
URxvt.color6: CYAN
URxvt.color7: WHITE
! 基本 8 色の Bright 色
URxvt.color8: B_BLACK
URxvt.color9: B_RED
URxvt.color10: B_GREEN
URxvt.color11: B_YELLOW
URxvt.color12: B_BLUE
URxvt.color13: B_MAGENTA
URxvt.color14: B_CYAN
URxvt.color15: B_WHITE
% xrdb -merge ~/.Xresources
このとき C 言語のプリプロセッサを通るらしいので、#define による定数の定義や #ifdef による条件分岐などを書くことができます。
ここでは color0 ~ color15 の説明はあと回しにして、先に 20 ~ 34 行目を説明します。詳細は urxvt(1) と urxvt(7) のマニュアルを参照してください。
termName
ここで設定した値が環境変数 TERM にセットされます。その意味についてはよくわかりませんが、これをセットしないといろいろ挙動がおかしいです。
font
使用するフォントを指定します。
letterSpace
文字と文字の間隔をピクセル単位で指定します。デフォルト値は 0 で、負の値を指定すれば間隔が詰まり、正の値を指定すれば開きます。
transparent
true のとき背景が疑似透過されます。疑似透過では、デスクトップの背景は透過しているように見えますが、ウィンドウの重なりなどは表現できません。そこまでするには完全透過の設定が必要ですが、ここでは触れません。
shading
疑似透過の透過率と思われます。0 に近づくほど透けなくなります。
saveLines
スクロールバックしたときにたどれる行数。
True のときスクロールバーを右に表示します。scrollBar_right
scrollstyle
スクロールバーのスタイル。plain にすると最近流行りのフラットな感じになります。
fading
urxvt のウィンドウがフォーカスから外れたときにグレーアウトしたように見せます。単位は % で、100 に近づくほど暗くなります。
foreground
文字色を RGB で指定します。
background
背景色を RGB で指定します。
cursorColor
カーソル色を RGB で指定します。
cursorColor2
カーソル上にある文字の色を RGB で指定します。デフォルトで background に指定した色が使われます。
highlightColor
強調表示された文字 (マウスで選択された範囲など) の背景色を RGB で指定します。
highlightTextColor
強調表示された文字の文字色を RGB で指定します。
カラースキームの検討
リソース名 | インデックス | 色名 | ANSI (文字色) | ANSI (背景色) | 備考 |
---|---|---|---|---|---|
foreground | ― | ― | 39m | ― | ― |
background | ― | ― | ― | 49m | ― |
color0 | 0 | Black | 30m | 40m | ― |
color1 | 1 | Red | 31m | 41m | ― |
color2 | 2 | Green | 32m | 42m | ― |
color3 | 3 | Yellow | 33m | 43m | ― |
color4 | 4 | Blue | 34m | 44m | ― |
color5 | 5 | Magenta | 35m | 45m | ― |
color6 | 6 | Cyan | 36m | 46m | ― |
color7 | 7 | White | 37m | 47m | ― |
color8 | 8 | Bright Black | 1;30m / 90m | 1;40m / 100m | (*) |
color9 | 9 | Bright Red | 1;31m / 91m | 1;41m / 101m | (*) |
color10 | 10 | Bright Green | 1;32m / 92m | 1;42m / 102m | (*) |
color11 | 11 | Bright Yellow | 1;33m / 93m | 1;43m / 103m | (*) |
color12 | 12 | Bright Blue | 1;34m / 94m | 1;44m / 104m | (*) |
color13 | 13 | Bright Magenta | 1;35m / 95m | 1;45m / 105m | (*) |
color14 | 14 | Bright Cyan | 1;36m / 96m | 1;46m / 106m | (*) |
color15 | 15 | Bright White | 1;37m / 97m | 1;47m / 107m | (*) |
(*) | 私の試したかぎり、Bright な色を ANSI で「1;30m」のように指定しても、urxvt では「30m」と同じ色になってしまいました。Bright 色を指定したければ、文字色なら 90m ~、背景色なら 100m ~ の系列で指定する必要がありそうです。 |
カラースキームを (半) 自作してみた
Tig で気になった点を調整してみた
#color main-head color11 default # なぜか背景色が変わる
color main-head color3 default bold # 色は期待どおりだがフォントウェイトが…
#define DISORDER
...
#ifdef DISORDER
! 1 軍色
URxvt.color0: YELLOW
URxvt.color1: B_RED
URxvt.color2: GREEN
URxvt.color3: B_YELLOW
URxvt.color4: B_BLUE
URxvt.color5: B_MAGENTA
URxvt.color6: BLUE
URxvt.color7: WHITE
! 2 軍色
URxvt.color8: B_BLACK
URxvt.color9: RED
URxvt.color10: B_GREEN
URxvt.color11: BLACK
URxvt.color12: CYAN
URxvt.color13: MAGENTA
URxvt.color14: B_CYAN
URxvt.color15: B_WHITE
#else
! 基本 8 色
URxvt.color0: BLACK
URxvt.color1: RED
URxvt.color2: GREEN
URxvt.color3: YELLOW
URxvt.color4: BLUE
URxvt.color5: MAGENTA
URxvt.color6: CYAN
URxvt.color7: WHITE
! 基本 8 色の Bright 色
URxvt.color8: B_BLACK
URxvt.color9: B_RED
URxvt.color10: B_GREEN
URxvt.color11: B_YELLOW
URxvt.color12: B_BLUE
URxvt.color13: B_MAGENTA
URxvt.color14: B_CYAN
URxvt.color15: B_WHITE
#endif
おまけ: カラースキームの検討に使った・使い損ねた自作ツール
コントラスト比表示ツール
図 1 のような表示を行う Python スクリプトです。参考にしたシェルスクリプトが下記のリンク先にあります。
import subprocess
import re
LV_2A = 4.5 # 最低限のコントラスト >= LV_2A
LV_3A = 7.0 # より十分なコントラスト >= LV_3A
# SGR パラメータの表示用文字列
FG_STR = (' 0m', ' 1m', \
' 30m', ' 90m', ' 31m', ' 91m', ' 32m', ' 92m', ' 33m', ' 93m', \
' 34m', ' 94m', ' 35m', ' 95m', ' 36m', ' 96m', ' 37m', ' 97m')
BG_STR = (' 40m ', ' 41m ', ' 42m ', ' 43m ', ' 44m ', ' 45m ', ' 46m ', ' 47m ')
BB_STR = (' 100m ', ' 101m ', ' 102m ', ' 103m ', ' 104m ', ' 105m ', ' 106m ', ' 107m ')
# RGB 値をとる X リソースを選別するための正規表現
PAT_XRCOLOR = re.compile(r'\w+\.(\w+):\s*(#\w{6})')
# SGR パラメータから RGB 値を得るためのハッシュテーブル
RgbTab = {}
#
# メイン関数
#
def main():
init()
print('')
colours(0); print('')
colours(1); print('')
#
# 初期化
# urxvt の X リソースを読み出して RgbTab を完成させる
#
def init():
query = f'xrdb -query | grep URxvt'
proc = subprocess.Popen(query, shell = True,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
sout, serr = proc.communicate()
lines = sout.decode('utf-8').split('\n')
for line in lines:
m = PAT_XRCOLOR.match(line)
if not m:
continue
name = m.group(1)
rgb = m.group(2)
if (name == 'foreground'):
RgbTab['fg'] = rgb
RgbTab['0m'] = rgb
RgbTab['1m'] = rgb
elif (name == 'background'):
RgbTab['bg'] = rgb
elif name[0:5] == 'color':
colno = int(name.replace('color', ''))
if (colno >= 0) and (colno <= 7):
RgbTab[f'3{colno}m'] = rgb
RgbTab[f'4{colno}m'] = rgb
elif (colno >= 8) and (colno <= 15):
colno -= 8
RgbTab[f'9{colno}m'] = rgb
RgbTab[f'10{colno}m'] = rgb
else:
continue
else:
continue
#
# カラースキームを表示する
#
def colours(bright = 0):
bgstrs = BG_STR if bright == 0 else BB_STR
header = " "
for b in bgstrs:
header += f' {b}'
print(header)
bgrgb = RgbTab['bg']
for fgs in FG_STR:
f = fgs.strip()
cr = contrast_ratio(RgbTab[f], bgrgb)
crstr = make_crstring(cr)
j = judge(cr, ('!', ' ', ' '))
print(f' {fgs} \033[{f}{crstr}\033[0m{j}', end = '')
for bgs in bgstrs:
b = bgs.strip()
cr = contrast_ratio(RgbTab[f], RgbTab[b])
crstr = make_crstring(cr)
j = judge(cr, ('!', ' ', ' '))
print(f'\033[{f}\033[${b}{crstr}\033[0m{j}', end = '')
print('')
#
# RGB で指定された 2 色のコントラスト比を返す
# https://waic.jp/docs/WCAG20/Overview.html
#
def contrast_ratio(rgb1, rgb2):
rl = (relative_luminance(rgb1), relative_luminance(rgb2))
rl1 = max(rl)
rl2 = min(rl)
return (rl1 + 0.05) / (rl2 + 0.05)
#
# RGB で指定された色の相対輝度を返す
#
def relative_luminance(rgb):
rgb = rgb.replace('#', '')
rgb = [int(rgb[0:2], 16), int(rgb[2:4], 16), int(rgb[4:6], 16)]
for i in range(0, len(rgb)):
c = rgb[i]
c /= 255
if c <= 0.03928:
c /= 12.92
else:
c = ((c + 0.055) / 1.055) ** 2.4
rgb[i] = c
return (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2])
#
# コントラスト比の出力文字列を作って返す
#
def make_crstring(cr):
return f'{cr:6.2f} '
#
# コントラスト比を判定する
# ダメなら '!'、まあまあなら '?'、十分なら ' ' を返す
#
def judge(cr, retstr = ('!', '?', ' ')):
if cr < LV_2A: return retstr[0]
elif cr < LV_3A: return retstr[1]
else: return retstr[2]
if __name__ == '__main__':
main()
HSV 表示ツール
使うかもと思って作ってはみたものの、まったく使わずに終わった HSV 表示ツールです。xrdb -query コマンドで urxvt の色リソースの RGB 値を取得して HSV に変換し、表示します。色の勉強と Python の勉強には役立ったと思います。
No Name RGB R/255 G/255 B/255 H S V
0 Black #0d0015 0.0510 0.0000 0.0824 277.1429 1.0000 0.0824
8 B.Black #2b2b2b 0.1686 0.1686 0.1686 359.0000 0.0000 0.1686
1 Red #a25768 0.6353 0.3412 0.4078 346.4000 0.4630 0.6353
9 B.Red #ee827c 0.9333 0.5098 0.4863 3.1579 0.4790 0.9333
2 Green #82ae46 0.5098 0.6824 0.2745 85.3846 0.5977 0.6824
10 B.Green #93ca76 0.5765 0.7922 0.4627 99.2857 0.4158 0.7922
3 Yellow #f08300 0.9412 0.5137 0.0000 32.7500 1.0000 0.9412
11 B.Yellow #f7c114 0.9686 0.7569 0.0784 45.7269 0.9190 0.9686
4 Blue #455765 0.2706 0.3412 0.3961 206.2500 0.3168 0.3961
12 B.Blue #53727d 0.3255 0.4471 0.4902 195.7143 0.3360 0.4902
5 Magenta #68699b 0.4078 0.4118 0.6078 238.8235 0.3290 0.6078
13 B.Magenta #a59aca 0.6471 0.6039 0.7922 253.7500 0.2376 0.7922
6 Cyan #008899 0.0000 0.5333 0.6000 186.6667 1.0000 0.6000
14 B.Cyan #59b9c6 0.3490 0.7255 0.7765 187.1560 0.5505 0.7765
7 White #9fa0a0 0.6235 0.6275 0.6275 180.0000 0.0062 0.6275
15 B.White #f7fcfe 0.9686 0.9882 0.9961 197.1429 0.0276 0.9961
-- foreground #f7fcfe 0.9686 0.9882 0.9961 197.1429 0.0276 0.9961
-- background #203744 0.1255 0.2157 0.2667 201.6667 0.5294 0.2667
import subprocess
import re
# RGB 値をとる X リソースを選別するための正規表現
PAT_XRCOLOR = re.compile(r'\w+\.(\w+):\s*(#\w{6})')
#
# メイン関数
#
def main():
xr = readxr()
printtable(xr)
#
# urxvt の色関係の X リソースを読み出してリストにして返す
#
def readxr():
xr = [[None, None]] * 18 # [0..15]: color0..15, [16]: foreground, [17]: background
query = f'xrdb -query | grep URxvt'
proc = subprocess.Popen(query, shell = True,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
sout, serr = proc.communicate()
lines = sout.decode('utf-8').split('\n')
for line in lines:
m = PAT_XRCOLOR.match(line)
if not m:
continue
name = m.group(1)
if name == 'foreground':
i = -2
elif name == 'background':
i = -1
elif name[0:5] == 'color':
i = int(name.replace('color', ''))
if (i < 0) or (i > 15):
continue
else:
continue
rgb = m.group(2)
xr[i] = [name, rgb]
return xr
#
# urxvt の色リソース一覧を表示する
#
def printtable(xr):
name = ('Black', 'Red', 'Green', 'Yellow', 'Blue', 'Magenta', 'Cyan', 'White', \
'B.Black', 'B.Red', 'B.Green', 'B.Yellow', 'B.Blue', 'B.Magenta', 'B.Cyan', 'B.White')
w = ('2', '10', '7', '6', '6', '6', '8', '6', '6')
sp = ' '
header = f'{"No":>{w[0]}}{sp}' + \
f'{"Name":<{w[1]}}{sp}' + \
f'{"RGB":^{w[2]}}{sp}' + \
f'{"R/255":^{w[3]}}{sp}' + \
f'{"G/255":^{w[4]}}{sp}' + \
f'{"B/255":^{w[5]}}{sp}' + \
f'{"H":^{w[6]}}{sp}' + \
f'{"S":^{w[7]}}{sp}' + \
f'{"V":^{w[8]}}{sp}'
print('\n' + header)
for i in range(0, len(xr)):
x = xr[i]
if (i >= 0) and (i <= 7):
xbright = xr[i + 8]
printline(i, name[i], x[1], srgb(x[1]), rgb2hsv(x[1], True), sp, '.4f', w)
printline(i + 8, name[i + 8], xbright[1], srgb(xbright[1]), rgb2hsv(xbright[1], True), sp, '.4f', w)
elif (i >= 8) and (i <= 15):
pass
else:
printline('--', x[0], x[1], srgb(x[1]), rgb2hsv(x[1], True), sp, '.4f', w)
print('')
#
# 1 行出力
#
def printline(i, name, rgb, srgb, hsv, sp = ' ', f = '.4f',
w = ('2', '10', '7', '6', '6', '6', '8', '6', '6')):
line = f'{i:>{w[0]}}{sp}' + \
f'{name:<{w[1]}}{sp}' + \
f'{rgb:<{w[2]}}{sp}' + \
f'{srgb[0]:>{w[3]}{f}}{sp}' + \
f'{srgb[1]:>{w[4]}{f}}{sp}' + \
f'{srgb[2]:>{w[5]}{f}}{sp}' + \
(f'{hsv[0]:>{w[6]}{f}}{sp}' if hsv[0] >= 0 else f'{"undef":>{w[6]}}{sp}') + \
(f'{hsv[1]:>{w[7]}{f}}{sp}' if hsv[1] >= 0 else f'{"undef":>{w[7]}}{sp}') + \
f'{hsv[2]:>{w[8]}{f}}'
print(line)
#
# RGB → HSV 変換
# https://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93
#
def rgb2hsv(rgb, cyl = False):
r, g, b = srgb(rgb)
rgbmax = max([r, g, b])
rgbmin = min([r, g, b])
h = rgbmax - rgbmin
s = h # 円錐モデル
if cyl and (rgbmax != 0.0): # 円柱モデル
s /= rgbmax
else:
s = -1
if h <= 0.0:
h = -1
elif rgbmin == b:
h = (60 * ((g - r) / h)) + 60
elif rgbmin == r:
h = (60 * ((b - g) / h)) + 180
else: # rgbmin == g
h = (60 * ((r - b) / h)) + 300
if h:
h %= 360
v = rgbmax
return [h, s, v]
#
# RGB 値 (#rrggbb) を 0.0..1.0 の範囲に正規化して返す
#
def srgb(rgb):
rgb = rgb.replace('#', '')
r = int(rgb[0:2], 16)
g = int(rgb[2:4], 16)
b = int(rgb[4:6], 16)
return [r / 255, g / 255, b / 255]
if __name__ == '__main__':
main()