端末設定にも欠かせない X resources の設定や応用例について
X 環境にはユーザの要望に応じて X クライアントアプリケーションを容易にカスタマイズできるよう、リソースの値を合理的に設定・格納する機能があり、 X resources とかリソースデータベースなどと呼ばれる。
主に端末エミュレータの配色や書体、カーソルテーマの設定などに利用され、これに触らず CLI の恩恵にあずかることはないと言えなくはないものである。
ネットには多くの設定例が掲げられており、私はよくそれらの記述例をコピペして自分の環境に適用している。それは世にも多く行われていることかと思う。
しかしこれの書き方や応用はどうなるかと思い man ページを眺めようとしたら、どこを読めばいいやらわからない。ちょっとググってみてもしっくりくる説明に出会えず、頼みの Arch Wiki も私には少々難しい記述がある。
そうなものだからこれはもっときちんと調べようと思い、やりはじめたら嵌った。意外に捉えどころがないような、なんというか複雑で曖昧なところがあると感じた。
そもそも X resources は X 環境を構築する一部なのだから、掘り下げれば X 全般に話が及んでしまう。また、歴史的経緯のうちに当初のコンベンションが変遷していったというようなこともあったのではなかろうか。そういったことが話を難しくしているのであろう。
ともかく、X resources ファイルの記述についてかようにまとめることにした。
目次
xrdb か ~/.Xdefaults か
X resources によるユーザーレベルの設定は通常、 ~/.Xresources
に書き込んだ設定内容を xrdb でリソースデータベースにロードしておくことによる。するとアプリが必要とする時にリソースデータベースからリソースが渡されるようになる。
~/.Xresources
というファイル名は規約上のもので、記述書式が同様ならばファイル名は問わないとされる(話をややこしくするようだが、xrdb でロードできるなら後述の ~/.Xdefaults
という名前であっても構わないわけだ)。
ただしフル装備のデスクトップ環境では X の起動時に ~/.Xresources
をロードするような xrdb コマンドの記述が X セッションのスタートアップスクリプトになっている(以下は ~/.xinitrc
の例)。
# ~/.xinitrc sysXresources=/etc/X11/xinit/.Xresources userXresources=$HOME/.Xresources if [ -f "$sysXresources" ]; then xrdb -merge "$sysXresources" fi if [ -f "$userXresources" ]; then xrdb -merge "$userXresources" fi
かようにシステムは xrdb が ~/.Xresources
をロードするよう構築されていることが多いようである。容易にインストール可能な充実したデスクトップ環境の利用が著しくなれば、この傾向は強まるものと思う。
そのことと別に、リソースマネージャが使われていない場合に、 ~/.Xdefaults
を要求の都度読み込むという「古い」方法へとフォールバックするというのがある。
この ~/.Xdefaults
に記述して都度読ませるという方法は今でも時々紹介される方法であり、ある条件下では思惑通りの結果をもたらしてくれるようである。
xrdb と違い、プログラム起動時(xlibが呼ばれるたび)に毎回ファイルを読み取るというのがミソで、これはつまり ~/.Xdefaults
に設定を書き込んで X アプリを起動すれば即反映されるということであり、一見扱いやすいように思えることだろう。しかし X クライアントを別のホストで実行する際には、リモートの ~/.Xdefaults
を読んでしまうから都合が悪いということがある。
また、繰り返すようだが ~/.Xdefaults
が読まれるのはリソースマネージャが使われていない場合である。そして前述のように多くのデスクトップ環境では xrdb が ~/.Xresources
をロードしてリソースマネージャを利用しているわけだから、これを無理に利用しないような策を講じない限りは ~/.Xdefaults
の出番はないはずである。
一方の xrdb を使う方法のメリットは、リソース設定の内容は xrdb が一度だけロードすれば十分でありかつ無駄がないということ、そしてローカルかリモートであるかに拘らずアプリが必要とすれば適切なリソースが常に渡されるということである。
このようなことから X resources の設定については、 ~/.Xdefaults
の利用法の確立や安定化を追究するよりは、 xrdb で設定をロードし、管理をリソースマネージャに任せたほうが良いと思われる。そして恒常的に反映させたい設定内容は ~/.Xresources
に記述しておき、スタートアップスクリプトでこれをロードする道を確立しておく。シンプルでわかりやすいだろうし、このことを前提とするプログラムが多いということでもある。
だからここでは基本的に ~/.Xresources
に記述したものを xrdb でロードしてリソースマネージャを使う方法として記す。
X resources の構文
リソースの基本書式
リソースは1行単位で記す。各行は、いくつかのワード ― ここではコンポーネントと呼ぶ ― を .
でつないで構成したリソース名と、そこへ格納したいリソース値を :
で区切って記す。
instance.resource: value class.resource: value
コンポーネントの大文字小文字は区別される。基本的には キャメルケース を用い、主にローワーキャメルケース(最初の文字は小文字)で表現する(例: xterm
、 geometry
、 scrollBar
)。
最初のコンポーネントは、リソースがどのアプリケーション設定かを示すための名前、つまりアプリケーション名である。アプリケーション名の表現はインスタンス(instance)か、あるいはクラス(class)で示すこととなる。
そしてドット区切りに続けてそのアプリケーションが持つリソース(resource)を記す。
リソースの持つ値、すなわちリソース値(value)として指定できるのは文字列、整数、ブーリアン( true
/ false
)である。
インスタンス
インスタンスは、ほとんどの場合プログラム名(実行ファイル名)をもとにしたアプリケーション名である。
以下の例はインスタンス emacs
というプログラムの cursorColor
に dark green
という値を適用したリソースを表している。Emacs のカーソル色をダークグリーンにするということだ。
emacs.cursorColor: dark green
インスタンスは前述のとおりプログラム名なので、これをリネームするならばインスタンスも同様に変わる。
このことを利用して以下のようなことができる。
例えば xterm の実行ファイル xterm
を xtermgreen
などと言う名前でコピーし、リソースには xtermgreen.background: #002540
と書いてロードしておき xtermgreen
を起動すると、背景が #002540
(緑色)になる、というような使い方ができる。
もっとも、 xterm の場合には -name
オプションでインスタンスを指定できるから、無駄にコピーなどせず xterm -name xtermgreen
というように起動すれば同じことである。 urxvt なども然り。
クラス
前述のとおりインスタンスは固定的とはいい難いが、クラスを用いた定義では意図せずインスタンスが変わってしまったとしても、確実にアプリケーションを指定できる。ネットでよく見かける設定例では、以下のようにクラスを用いた記述が多い。
Emacs.background: #002540 Emacs.foreground: azure3
このクラス名の表現に限っては、 Emacs
、 Xmessage
のようにアッパーキャメルケース(最初の文字も大文字)を用いるのが慣例とされている。が、歴史的経緯からちょっとややこしくなっている。
例えば XTerm
のように X 関連のクラス名は最初の2文字までを大文字にしていることが多く、他にも XClock
や XScreenSaver
といったものがあるが、 Xfd
などのように1文字目だけのものもある。また rxvt は Rxvt
だが rxvt-unicode は URxvt
である。さらに UXTerm
というのもある。
URxvt.visualBell: true URxvt.scrollBar: false
ともかく、クラスを使うには固有に決められているものを調べて正確に記述する配慮が必要だろう。
書式
リソースの表現はワイルドカード( ?
*
)での置き換えが可能で、 ?
は1つの、 *
は複数のリソースとみなすことができる。
例えば urxvt と xterm の背景色定義はそれぞれ URxvt.background
と XTerm.vt100.background
などと記すが、両方のアプリケーションプログラムが取りうる値とすべく、以下のように記述を1つにまとめることができる。
*background: #282828
Xresources では !
を記すと以降をコメントとみなす。よく開発言語ではスクリプトを書いた行内の後ろにコメントを付与できるが、 Xresources ではそういうのはうけつけないようなのでコメントは1行ずつにしておいた方がよさそうだ。
また行末に \
を置くことで行を分割できる。
!! ~/.Xresources ! Colors URxvt.colorIT: #8ec07c URxvt.colorBD: #fe8019 ! Fonts - DejaVu with IPAGothic URxvt.font: xft:DejaVuSansMono Nerd Font-9,\ xft:IPAGothic
プリプロセッサに命令を渡す
ドットファイルとか rc ファイルは柔軟に設定できるほどに行数も増える。だからコメントをつけたりエディタのフォールド機能を使うとかで解りやすいよう工夫する向きも多い。そこではまたファイルの分割も有効な手段となり得るだろう。例えば *shrc では .
コマンドでソースしたり、 ssh/config でも OpenSSH 7.3 あたりからは Include
が使えるようになって、すっきりと見通しよく整理できる。
だから X resources ファイルの記述でもこのようなことができるとありがたいと思うのだが、残念ながらそんな仕様ではないのだ。
ところが、 xrdb コマンドはファイルをロードして読み取る前にプリプロセッサを通す仕様となっているから、そのときに解釈させる命令が利用できるのだ。
デフォルトで利用されるのはCプリプロセッサ(CPP)だが、多くのシステムでこれが標準利用できるだろう。条件分岐や外部ファイルの読み込みができるのは柔軟な記述につながるはずだという、そういう目論見が持てる。
ここでは CPP の #include
、 #define
、 #ifdef
について簡単に記す。
#include
#include
で外部ファイルを差し込むことができる。例えばカラー定義だけを別のファイルにしたりできるから、テーマ切り替えを容易にする工夫ができそうだ。
#include "FILE"
パスはダブルクォーテーションで括って記すとカレントを基準にする。例えば以下のように ~/.Xresources
に書いた場合、 ~/.Xresources.d
ディレクトリの下にある theme_file
というファイルを読み込むということになる。
#include ".Xresources.d/theme_file"
#define
#define
はマクロ置き換え機能だが、シンボルの定義が便利で、よく使われることだろう。
#define IDENTIFIER [REPLACEMENT]
ワイルドカードによるプロパティ指定ができても、結局色や書体の指定を何度となく行うこともあるだろう。そういったものを #define
でまとめておくと改変が楽になるかもしれない。
#ifdef / #ifndef
#if 〜 #endif
で条件式が扱える。Cの式をまんま書くことができるが、 defined
(否定は !defined
)で定義の有無を判断できるのが便利である。この #if defined
、 #if !defined
は #ifdef
、 #ifndef
という簡略文に置き換えられる。
#ifdef | #ifndef 〜 #elif 〜 #else 〜 #endif
xrdb
コマンドは -D
オプションでシンボル定義をプリプロセッサに渡せる(値も渡せる)ので、 #ifdef
と組み合わせることでロード時に独自の値を渡して条件分岐させることも可能になる(記述例の項を参照)。
X resources のロード( xrdb コマンド)
リソースデータベースへの反映は xrdb で設定ファイルをロードすることによる。
既述のとおり xrdb コマンドがスタートアップスクリプトに書き込まれてあることが多いが、ユーザが設定内容の記述を書き換えた場合には明示的にロードする必要がある(でなければシステムを再起動するか)。
以下のようにファイル名を与えると、リソースデータベースをそのファイルの内容で書き換える。それまでの値は残らない( -load
オプションと同じ)。なお、繰り返しになるがファイル名は ~/.Xresources
である必要はない。
xrdb ~/.Xresources
前のリソースを残しつつ、一部のリソース値を刷新したり、新しいリソースを追加したりするには -merge
オプションを用いる。スタートアップスクリプトではこの -merge
オプションを記述してあることが多く、それまでにリソースデータベースへ登録されたものが失われないようにするためである。
xrdb -merge ~/.Xresources
また、 xrdb コマンドはパイプでテキストを渡すとリソースとして登録してくれる。 -merge
オプションと組み合わせると一時的な改変などに便利である。
echo "URxvt.scrollBar: false" | xrdb -merge
-query
オプションで設定した内容を一覧できる。
xrdb -query
様子をみながら設定調整することも多いかと思うが、多少なりとも見やすければ勘違いも減るかもしれない。 column コマンドは結構便利である。
xrdb -query | sort | column -t -s $'\t'
X resources ファイルの記述例
xterm と urxvt のリソースの共有
以下は xterm と urxvt でリソース名が同じで、よく使われるものを区切り子 *
で指定したもの。ほかに termName
や、色定義の color0
などもある。
urxvt が xterm よりも後の実装で同じリソース名を使っているのはこういう事を企図したものと思う。
!! ~/.Xresources *geometry: 96x36 *saveLines: 1000 *visualBell: true *scrollBar: true *cursorBlink: true *cursorUnderLine: true *background: #FBF1C7 *foreground: #282828
外部ファイル
以下の例は色定義を別のファイル ~/.Xresources.d/theme_file
にしたうえで、定数 DARK_THEME
が定義されてあれば背景を黒にしてそうでなければ白にするもの。
!! ~/.Xresources #include ".Xresources.d/theme_file" *background: BG *foreground: FG
!! ~/.Xresources.d/theme_file #define colBlack #282828 #define colWhite #ebdbb2 #ifdef DARK_THEME #define BG colBlack #define FG colWhite #else #define BG colWhite #define FG colBlack #endif
上記2ファイルの構成で、以下のようにロードすると白っぽい背景になる。
$ xrdb ~/.Xresources
そして -D
オプションで DARK_THEME
を定義した場合には黒っぽい背景となる。
$ xrdb -DDARK_THEME ~/.Xresources
#include〜
より前のとこに #define DARK_THEME
と書き込んどいて、都度コメントアウトしたりアンコメントするっていうやりかたもありだろう。
システムによって設定を変える
GitHub や Dropbox などを介し、複数ホストでドットファイルを使い回す工夫はよく行われていることだろう。するとPCシステムの違いなどによってパラメータを変える工夫をしなければならないことも多いが、 X resources でもプリプロセッサの解釈を利用することでそれが可能である。
シンボルには #define
や xrdb -Dsymbol[=value]
などで自前定義するものだけでなく、PC環境に則った内容が標準的に渡されるものもある( xrdb -symbols
で一覧表示できる。詳細は XRDB(1) )。 hostname を格納した定数( HOST
, SERVERHOST
)もあるが、ここで至便なのは SRVR_ホスト名
で、これは hostname から生成されるシンボルである。
以下はシステムによってインストールされているフォントが違うことを条件分岐で補うもの。ホスト alicia では DejaVu と IPAゴシックの9ポを 、ホスト abigail.foo-bar.com では Inconsolata と Nasuフォント の11ポを、そしてそれ以外では monospace の9ポを使うというように、 xterm と urxvt の両方に設定してある。
!! ~/.Xresources #ifdef SRVR_alicia #define FONT DejaVu Sans Mono #define FONTW IPAGothic #define FONT_SIZE 9 #elif defined SRVR_abigail_foo_bar_com #define FONT Inconsolata #define FONTW NasuM #define FONT_SIZE 11 #else #define FONT monospace:lang=en #define FONTW monospace:lang=ja #define FONT_SIZE 9 #endif XTerm*faceName: FONT XTerm*faceNameDoublesize: FONTW XTerm*faceSize: FONT_SIZE URxvt.font: xft:FONT-FONT_SIZE, xft:FONTW
GDMやLightDMあるいはUbuntuの~/.Xresources
X resources で #define などを記述する向きは少なくないように思うのだが、これは前述の通り xrdb がデフォルトで CPP を通すことを前提としている。
が、最近たまたま Ubuntu を使った機会に妙なエラー(urxvtが起動しない)に遭遇し 、 xrdb -query
の結果をみるとどうも CPP を通していないようである。
Ubuntu 18.04 のディスプレイマネージャは GDM だが、これの /etc/gdm3/Xsession
を覗いてみると以下のような -nocpp
の記述が数箇所見受けられる。 xrdb の -nocpp
オプションは CPP を通さずにロードさせる指示である。
# Ubuntu 18.04 - /etc/gdm3/Xsession から抜粋 ... userresources="$HOME/.Xresources" ... if [ -f "$userresources" ]; then xrdb -nocpp -merge "$userresources" fi ...
CPP が必要なのはレアなケースと捉え、パフォーマンスを重視してこうなったのだろうか。
ネットで調べると5年以上前から話題になっていたようで、それも GDM でなく LightDM 環境で同様の記述がされていた、という話である。
このことは Arch Wiki 日本語版( LightDM – ArchWiki ) にも反映されている。
私の普段使いは Arch Linux + i3wm を LightDM でラフにまとめたものだが、特に気付いたことがないのは改善された後で私が CPP 記述を使い始めたからとか、そんなところかもしれない。
いずれにしろ、少なくとも GDM3 あるいは最近の Ubuntu に上記の設定は存在するので、そこで CPP を通さなければならない事情があるなら Xsession
スクリプトから -nocpp
オプションを取り去らなければならないだろう。
あるいは、 Xsession
の実行よりも後のどこかで、 xrdb ~/.Xresources
というようにマージせずにロードを実行する手もあるかもしれないが、システムがリソースデータを書き込んでいた場合、それを消してしまうことになるのであまりおすすめできない。
Sources and Revisions
Sources
- x resources – “Xterm” or “xterm” in configuration file – Unix & Linux Stack Exchange
- Sharing Xresources between systems — JNRowe
- x resources – Can I use environment variables when #including another Xresources file – Unix & Linux Stack Exchange
- Resources – GNU Emacs Manual
- Bug #1084885 “lightdm-session loads Xresources with “-nocpp” opt…” : Bugs : Light Display Manager
Revision
- GDM などの No CPP について追記
Photo credit: ·júbilo·haku· on VisualHunt.com / CC BY-NC-ND