xmonadの設定の基本は、xmonad関数の引数となるXConfig l型のデータを定義することです。 そして、その際には、XConfig l型データを一から定義するのではなく、 XMonad.Configモジュールで定義されたデフォルトデータであるdefをベースとし、 レコード構文を使って必要な部分のみをカスタマイズする形を取るのが一般的です。
このようなカスタマイズの方法に従ったxmonad.hsの雛形は、以下のようなものになります。
ここでは、この雛型を基にしてxmonadのレイアウトを司るlayoutHookフィールドの定義を行います。
layoutHookフィールド
xmonadにおける「レイアウト」の設定は、 xmonad関数に渡すxconfig l型データのlayoutHookフィールドで行うことになります。 まずは、xmonadのレイアウトはどんな風に設定されているのかについて、 xmonadのデフォルトで定義されていて、皆さんにも既に馴染みのある3つのレイアウト、 「Tall」、「Mirror」、「Full」に関する実際の設定を見ながら親しんでいきましょう。
雛形設定の中のdefのレコード構文で、
layoutHookフィールドはmylayouthook
と定義されており、
このmylayouthook
自体は、後ろの「レイアウト」の項目で定義されています。
mylayouthook
の定義を見てみると以下の様になっています。
mylayouthook =
avoidStruts mytall ||| avoidStruts mymirror ||| myfull
where mytall = Tall 1 0.03 0.5
mymirror = Mirror mytall
myfull = Full
haskellでは、where構文を使うと、式の中でローカル変数を定義するように使えます。
上記の式では、where以降の部分で、ローカル変数mytall
、mymirror
、myfull
が定義され、
whereの前で、それら変数名が使われています。
つまり、whereを使わなければ次のようになります。
mylayouthook = avoidStruts (Tall 1 0.03 0.5)
||| avoidStruts (Mirror (Tall 1 0.03 0.5))
||| Full
レイアウトをつなぐための演算子
さて、上述のコードは折り返していますが、
(|||)
という縦棒三本の記号の集まりは演算子です。
演算子は、馴染みの(+)
(プラス)や(-)
(マイナス)と同じで、
その両側にあるものに作用します。
そしてこの(|||)
という演算子は、「レイアウトを繋げる」作用を持っています。
xmonadを既に触っているならば、レイアウトが「Mod + Space」で切り替わる事を知っていると思います。
xmonadでは、(|||)
演算子でレイアウトを繋ぐように設定しておき、
実際にxomonadを使用している時にそれら繋がれたレイアウトを「Mod + Space」で切り替えて利用することが出来るようになっています。
ですから、例えば、layoutA、layoutB、layoutCという3つのレイアウトを切り替えて使うには、
(|||)
演算子を使って、layoutHookに以下の様に書けば良いことになります。
layoutHook = layoutA ||| layoutB ||| layoutC
レイアウト
上述の実例で示されたコードの中で「layoutA」や「layoutB」に相当する部分、 即ち、式の中の「レイアウト」を表している部分は、 haskell初心者にとって少し複雑な形をしているように見えるかもしれません。 ですから、まずは、一つ目を丁寧に見て行きましょう。
avoidStruts (Tall 1 0.03 0.5)
もし、あなたがhaskellについて、なんの予備知識も持っていないならば、 「haskellの関数をおしゃれに把握する」を参照してみて下さい。 haskellの書式では、関数に渡す引数を囲むカッコがありません。 単語の並びの先頭が関数名になり、それに、続く単語が引数になります。 後は、記号演算子と、それらの結合の優先順位で、どの部分がかたまりになっているのかを把握することになります。
ここで上記の例は、avoidStruts
という関数に、
(Tall 1 0.03 0.5)
の結果が引数として渡されるという構成になっています。
ここで使われている括弧は、avoidStruts()
という他の言語でよく見る関数の形では無いことに注意が必要です。
この括弧は、Tall関数とその引数をひとまとまりにするための括弧です。
次に括弧の中のTall 1 0.03 0.5
の部分は、
Tall
という関数に、「1」、「0.03」、「0.5」という3つの引数が渡されているという構成になっています。
そして、この式の中の「レイアウト」の本体は、
このTall 1 0.03 0.5
の部分になります。
Tallレイアウト
改めて、xmonadを立ち上げた状態のデフォルトのレイアウトであるTallレイアウトを表すのがこの式です。
avoidStruts (Tall 1 0.03 0.5)
avoidStrutsについては、後で触れるので、今は無視しておきます。
さて、このTall
は、関数の一種であり、これにある引数を渡して得られる結果が「Tallレイアウト」となっています。
Tallレイアウトは、
左側にマスターペインが1つあり、右側には、それ以外のペインが縦に並べられていきます。
このTallレイアウトでは、
Tall
に渡す引数を変えることで幾つかの事を設定できます。
引数位置 | フィールド名 | 意味 |
---|---|---|
第1引数 | tallNMaster | マスターペイン側に配置するウィンドウの数 |
第2引数 | tallRatioIncrement | 左右区切りを増減させるときの1回の大きさを表す比率 |
第3引数 | tallRatio | マスターペイン側の大きさの比率 |
つまり、例示のTallレイアウトの設定では、マスターペインは1つのウインドで、 「Mod+h」や「Mod+l」を使った真ん中の区切りを左右に動かす際の移動の大きさは3%、 更に、マスターペインの大きさは左右同じ配分の50%という意味になります。 これを、マスターペインに2つのウィンド、その領域を66%程度に大きくしたいなら、 Tallに渡す引数を以下の様に調整することになります。
avoidStruts (Tall 2 0.03 0.66)
FullレイアウトとavoidStruts
三つ目のレイアウトに設定されているFull
は、
Fullレイアウトを表しています。
Fullレイアウトは画面に、フォーカスのあるウィンドウ1つだけを表示させるレイアウトです。
その式はとてもシンプルで、Fullレイアウトを設定するための関数Full
には引数がありません。
さて、先の二つのレイアウトに付いているavoidStruts
関数が、このFullレイアウトの設定式には書かれていません。
avoidStruts
関数が何をするモノかを確かめるために、Fullレイアウトの式にもつけてみましょう。
avoidStruts Full
気が付きましたか?avoidStruts
関数を使うことで、
xmobar等のステータスバーをウィンドウが避けて、いつでもステータスバーが見えるようにしてくれます。
実は、xmonadでは、デフォルトでレイアウトは画面の全領域を使います。
ですから、せっかくxmobarの様なステータスバーを付けても、
いつでもウィンドウがステータスバーに重なって、ステータスバーが見えなくなってしまうのです。
そこでステータスバーを利用する場合に必要となるのが、
このavoidStruts
関数の機能なのです。
一方で、Fullレイアウトのように全画面表示をしたい場合には、
ステータスバーの部分も含めて全体画面を使いたいので、
逆に、このavoidStruts
関数の機能を使わないように外してあるのです。
もし、どちらも使いたければ、(|||)演算子で追加すればOKです。
avoidStruts Full ||| Full
レイアウトとレイアウトを加工するもの
ここまで、「Tallレイアウト」というものは、Tall 1 0.03 0.5
で作成され、
「Fullレイアウトは」Full
で作成されることを紹介しました。
そして、次に紹介した、avoidStruts
関数は、
これら「レイアウト」本体を引数として渡す事で、
ステータスバーを見えるようにしたウィンドウ配置をしてくれるようになる事を紹介しました。
つまり、TallやFullは、レイアウト本体を作成するための関数であり、
avoidStrutsは、それらレイアウト本体を引数にとって、
それを加工したレイアウトを結果として返す関数になっています。
このようなことから、まず、xmonadのレイアウト設定では、 「レイアウト本体を作る関数」と「あるレイアウトを加工する関数」の二つのものがあると区別しておくことで、レイアウト設定の式の意味を把握しやすくなります。 そして、次に、「レイアウトを加工する関数」の結果は「レイアウト」であるため、 これをまた「レイアウトを加工する関数」の引数とすることも可能だという事を把握することで、 更にレイアウトの設定の式の意味が良く分かるようになります(実際によく見られる形なのです)。
Mirrorレイアウト
Mirrorレイアウトは、二つ目に設定しているレイアウトです。 ミラーレイアウトは、Tallレイアウトを時計回りに90度回転させた、ウィンドウ配置になるレイアウトです。
設定部分のコードは以下の通り。
avoidStruts (Mirror (Tall 1 0.03 0.5))
avoidStruts
関数の引数として渡されているのが、
Mirrorレイアウト本体ですが、その式は、関数Mirror
に、Tallレイアウト本体を渡しています。
じつは、Mirrorレイアウトというのは、「Tallレイアウトを時計回りに90度回転させた」レイアウトだけではないのです。
たまたま、Tallレイアウトを与えているから、「Tallレイアウトを時計回りに90度回転させた」レイアウトになっているだけで、
実際には、「与えられたレイアウトを時計回りに90度回転させた」レイアウトであり、
与えたレイアウトをなんでも回転させることが出来るのです。
そして、この事をよく考えてみると実は、Mirrorレイアウト自身は、Mirrorレイアウト単独でレイアウト本体を作成できません。 ですから、どちらかと言えば、avoidStrutsの様に、レイアウトを加工するモノに分類して考えることができます。
TallレイアウトがMirrorによって加工された結果もレイアウトであり、 そのレイアウトを更にavoidStrut関数に渡した結果もまたレイアウトになっています。 このように、実際のレイアウトの設定では、レイアウトを引数にとってレイアウトを返す関数を順次適用することで自分の好きなレイアウトを作るのです。
レイアウト本体を作成してくれるもの
「Tallレイアウト」、「Mirrorレイアウト」、「Fullレイアウト」は、 xmonadの初期設定でも設定されている基本的なレイアウトですが、 xmonadでは、この他にも色々な「レイアウト本体」を提供しています。 ここでは、分かり易いものを行くつか簡単に紹介します。
新しいレイアウトを取り入れる際にし注目しなければならないことは、次の2つです。
- 関連するレイアウトが定義されているモジュールのインポート
- レイアウトを作成する関数やその引数の把握
各レイアウトに関する型や関数は、それぞれhaskellのモジュールといものにまとめて定義されています。 ですから、これらを利用する場合、忘れずにそのモジュールを「インポート」する必要があります。 そして、実際に、レイアウト本体を定義するには、ここまでで見てきたとおり、 関数(正確には、関数であったり値コンストラクタというものであったりします。)を使ってレイアウト本体を作成するので、 その「関数名」とそれが取る「引数」(引数は取らないものもあります)を把握する必要があります。
Circleレイアウト
「Circleレイアウト」は、マスタペインが真ん中、その他サブはその後ろで円状に配置されます。
-- モジュールの読み込み
import XMonad.Layout.Circle
-- layoutHook部分の設定
layoutHook = Circle
Circleレイアウトは、関数Circle
で作成できます。この関数はFull
と同じで引数を取りません。
Roledexレイアウト
「Roledexレイアウト」は、斜めに綺麗に並べられます。
-- モジュールの読み込み
import XMonad.Layout.Roledex
-- layoutHook部分の設定
layoutHook = Roledex
Roledexレイアウトは、関数Roledex
で作成できます。この関数もFull
と同じで引数を取りません。
OneBigレイアウト
「OneBigレイアウト」は、左上に大きなマスターペインが一つ配置され、 その右側と下側にその他のサブウインドウが配置されます。
-- モジュールの読み込み
import XMonad.Layout.OneBig
-- layoutHook部分の設定
layoutHook = OneBig (3/4) (3/4)
OneBigレイアウトは、関数OneBig
で作成できます。そして、この関数は2つの引数を取ります。
第一引数には、画面全体幅に対するマスターペインの幅の割合を、
第二引数には、画面全体高さに対するマスターペインの高さの画面高さの割合をそれぞれ与えます。
レイアウトを加工するもの
次は、関数avoidStruts
や関数Mirror
の様に、
レイアウトを引数にとって加工してくれるものの中から、
よく使うもので比較的簡単に利用できるものを幾つか紹介します。
この場合も、注意すべき点は、それらの機能を持つ関数を定義しているモジュールをインポートすることと、
関数がどの様な引数を取るのかを把握することになります。
Spacing
Spacingモジュールの関数等を使うと、ウィンドウの周りに隙間を作ってデスクトップの見栄えを良くしてくれます。
-- モジュールの読み込み
import XMonad.Layout.Spacing
-- layoutHook部分の設定
layoutHook =
spacingRaw
True
(Border 10 10 10 10)
True
(Border 5 5 5 5)
True
(Tall 1 0.03 0.5)
spacingRaw
関数は、6つの引数を取ります。
引数位置 | 意味 |
---|---|
第1引数 | ウィンドウが1つの時、レイアウトの周りにスペースを作るかどうかの切り替え |
第2引数 | レイアウトの周りの隙間の設定 |
第3引数 | レイアウトの周りに隙間を作るかどうかの切り替え |
第4引数 | 各ウィンドウの周りの隙間の設定 |
第5引数 | 各ウィンドウの周りに隙間を作るかどうかの切り替え/td> |
第6引数 | レイアウト本体 |
隙間の設定に関しては、関数Border
を用いて設定用データを作成します。
関数Border
は、4つの引数を取り、順に、ウィンドウの上、下、右、左の隙間を整数で指定します。
つまり、設定例では、ベースとなるTallレイアウトについて、 ウィンドウが一つの場合には、レイアウトの周りに隙間を作らないけれども、 ウィンドウが2つ以上の場合、レイアウトの周りに上下左右に10ドットづゝの隙間を作り、 更に、ウィンドウの周りにそれぞれ上下左右に5ドットづゝの隙間を作る設定になります。
NoBorders
ウィンドウにはフォーカスの有無を示すボーダーラインが有りますが、
全画面表示や画面にウィンドウが一つの場合にはボーダーが必要ない場合があります。
NoBordersモジュールにある関数smartBorders
を利用することで、
ウィンドウが一つの場合にはボーダーラインが表示されないレイアウトを作ることが出来ます。
ウィンドウの周辺をよく見ると見慣れたボーダーがありません。
-- モジュールの読み込み
import XMonad.Layout.NoBorders
-- layoutHook部分の設定
layoutHook = avoidStruts (smartBorders (Tall 1 0.03 0.5))
関数smartBorders
の引数は、レイアウト本体を渡すだけでOKです。
実際のレイアウトの書き方
さて、最初の方で紹介した、レイアウトを繋ぐ(|||)
演算子ですが、
実は、これもレイアウトを加工する関数の1種であり、
この演算子は、2つのレイアウトを引数にとって、
その「2つのレイアウトから一つを選択できるという性質の新しい一つのレイアウト」を作るという関数なのです。
ですから、layoutA ||| layoutB
というのは、選択的な一つのレイアウトを表していると言えます。
1件ややこしそうな話をしているかに思われるかもしれませんが、
レイアウトを加工する関数は、レイアウトを引数に取ることを思い出して下さい。
そうです。ということは、このlayoutA ||| layoutB
という式自体も、実は、レイアウトを加工する関数の引数になることが出来るのです。
ここまでで、レイアウト本体とそれを作るための関数や引数、更に、それらレイアウトを加工する関数について順に紹介しました。
更に、(|||)
演算子の結果もまたレイアウトであることを知りました。
これらの知識を得た上で、次は、それらレイアウトを実際にxmonad.hsの中で書く時の幾つかのパターンを紹介します。
where構文を使う
もとの雛形で使われているように、haskellのwhere構文を使って、 レイアウト本体を作成する式を纏めてしまうのはよく使われるパターンです。 特に、レイアウトを作成する際に引数がある場合等、一箇所で設定して、それをあちこちで使い回すことができます。
mylayouthook =
avoidStruts myspace ||| avoidStruts mymirror ||| myfull
where mytall = Tall 1 0.03 0.5
mymirror = Mirror myspace
myfull = Full
myspace = spacingRaw
True
(Border 10 10 10 10)
True
(Border 5 5 5 5)
True
mytall
|||演算子の結果を関数に与える
先に紹介したとおり、(|||)
演算子の結果もまたレイアウトであるという事を利用して、
関数avoidStruts
に渡す引数に(|||)
演算子の結果であるレイアウトを渡すと言う書き方をすれば、
次のような書き方が出来るようになります。
mylayouthook =
(avoidStruts (myspace ||| mymirror)) ||| myfull
where mytall = Tall 1 0.03 0.5
mymirror = Mirror myspace
myfull = Full
myspace = spacingRaw
True
(Border 10 10 10 10)
True
(Border 5 5 5 5)
True
mytall
全体も一つのレイアウト
結局、上記で設定したものは全てで一つのレイアウトを表しているわけですから、
全体を関数smartBorder
の引数として与えると、
全てのレイアウトにスマートボーダーの効果が付くことになります。
mylayouthook =
smartBorders ((avoidStruts (myspace ||| mymirror)) ||| myfull)
where mytall = Tall 1 0.03 0.5
mymirror = Mirror myspace
myfull = Full
myspace = spacingRaw
True
(Border 10 10 10 10)
True
(Border 5 5 5 5)
True
mytall
ここで更に、関数の部分適用等をまだ知らない、haskell初心者の人には難しく感じるかもしれませんが、
巷のxmonad.hsではよく見られるパターンとして関数合成された式も紹介しておきます。
where構文の定義に置いて、関数spacingRaw
は、
レイアウトを引数に取る関数なので、部分適用を利用した定義を行うことが出来ます。
そこで、関数spacingRaw
について、自分の好きなパラメータを与えて、
レイアウトだけを受けるとように部分適用して再定義した関数と関数avoidStruts
とを関数合成して、
tallレイアウトとミラーレイアウトの選択レイアウトをそこに渡すことも出来ます。
mylayouthook =
smartBorders $ (avoidStruts . myspace) (mytall ||| mymirror) ||| myfull
where mytall = Tall 1 0.03 0.5
mymirror = Mirror mytall
myfull = Full
myspace = spacingRaw
True
(Border 10 10 10 10)
True
(Border 5 5 5 5)
True
巷でみられるxmonad.hsでも、レイアウトの定義の部分が複雑な式になりがちです。 haskellの式は、引数を表す括弧が無いので、式がどのように纏まっているのか、初めのうちは分かりづらいこともあります。 これらを見分けるコツは、記号演算子とそれがない部分の結合の強さの順番に慣れること。 特に$記号演算子の結合が他の記号演算子よりも弱いということをきちんと把握すること。 そして、関数合成がある場合には、「関数結合演算子の引数は関数である」ことを意識すること。 長く複雑な場合は、適宜括弧を使って、まとまりの見通しを良くすること。 などなどを意識して、色々なxmonad.hsをみていると、割とすぐに慣れて来ると思います。
0 件のコメント:
コメントを投稿