xmonad-contrib を使って xmonad をもっと使いこなそう

# xmonad-contrib を使って xmonad をもっと使いこなそう

どうも、ぼくです。
最近、`gnome3` から `xmonad` に出戻りました。
`awesome` を使い込んだりもしてる時期もあったのですが、マルチディスプレイ対応を考えると `xmonad` の方が良いだろうとと思い、`xmonad` にしました。
そこそこ使い込んで便利だった機能（生き残った機能）を紹介していきたいと思います。
当たり前ですが `xmonad-contrib` はインストールしている前提です。

`Qiita` の `xmonad` のタグを見ても `xmonad-contrib` を使ってる例があまりないようです。
`xmonad` を使いこなすともっと生産性があげることができるのでもっと設定を真面目にした方がいいです。

## NamedScratchpad

`NamedScratchpad` はその名の通り、名前をつけられる `Scratchpad` です。
そもそも `Scratchpad` って何？という人もいるかも知れません。
`Scratchpad` は指定したプログラムをどの `Workspace` からもショートカットキー一発で呼び出す、隠す機能です。
`Scratchpad` で起動されたプログラムのプロセスは基本的にずっと起動しています。
そのため、別の `Workspace` で呼び出した `Scratchpad` のブラウザは別の `Workspace` で呼び出しても状態は保持されており作業を継続して行うことができます。
これでよくある `Alt + Tab` で切り替え、みたいなダサい事しなくて済みますね。
もちろん `Scratchpad` でもいいのですが、複数まとめて設定し、わかりやすく名前をつけれる `NamedScratchpad` の方がよいと思います。

まず使うには `import` します。

```haskell
import XMonad.Util.NamedScratchpad
```

以下設定例です。これは実際に私が使用している設定です。
名前をキーに呼び出し、プログラムや呼び出し時にレイアウトなどの設定を記述します。

```haskell
myScratchpads :: [NamedScratchpad]
myScratchpads = [
    NS "qurxvt"  "urxvtc -name qurxvt" (appName =? "qurxvt")
        (customFloating $ W.RationalRect 0 0.02 1 0.48)
  , NS "qurxvt2"  "urxvtc -name qurxvt2" (appName =? "qurxvt2")
        (customFloating $ W.RationalRect 0 0.5 1 0.48)
  , NS "htop"   "urxvtc -e htop" (title =? "htop")
        (customFloating $ W.RationalRect 0 0.02 1 0.4)
  , NS "ranger"   "urxvtc -e ranger" (title =? "ranger")
        (customFloating $ W.RationalRect 0 0.02 1 0.6)
  , NS "chrome" "google-chrome-stable" (className =? "google-chrome")
        (customFloating $ W.RationalRect 0 0.02 1 0.98)
  , NS "firefox" "firefox" (className =? "Firefox")
        (customFloating $ W.RationalRect 0 0.02 1 0.98)
 ]
```

詳細はショートカットキーと合わせて説明します。
以下ショートカットの設定です。
`NamedScratchpad` なのでその名の通り名前を指定します。

```haskell
  , ((0                     , xK_F12),   namedScratchpadAction myScratchpads "qurxvt")
  , ((0                     , xK_F11),   namedScratchpadAction myScratchpads "qurxvt2")
  , ((modm                  , xK_h),     namedScratchpadAction myScratchpads "htop")
  , ((modm .|. shiftMask    , xK_f),     namedScratchpadAction myScratchpads "firefox")
  , ((modm .|. shiftMask    , xK_r),     namedScratchpadAction myScratchpads "ranger")
  , ((modm                  , xK_g),     namedScratchpadAction myScratchpads "chrome")
  , ((modm                  , xK_b),     namedScratchpadAction myScratchpads "chrome")
```

私の場合、`NamedScratchpad` にはターミナルとブラウザをメインで設定しています。
`F11`, `F12` には `urxvtc` を割り当てています。
これで `gnome3` などで使う `guake` と同じような機能を実現できます。
どこでも `F12` でターミナルを呼び出せます。もちろん状態も保持されています。
`F11`, `F12` と 2 つ割り当てているのには理由があります。
`NamedScratchpad` はその名の通り名前をキーに設定をすることができます。

今回の場合、`F12` には `qurxvt` `F11` には `qurxvt2` を割り当てています。
`qurxvt` の設定を見るとわかりますが、呼び出し時のレイアウトが記述されています。
上部 2 % の位置に高さ 48% で配置しています。つまり画面上部半分にターミナルが表示されます。
（上部 2 % 空けているのは `xmobar` と重ならないようにするため）

```haskell
    NS "qurxvt"  "urxvtc -name qurxvt" (appName =? "qurxvt")
        (customFloating $ W.RationalRect 0 0.02 1 0.48)

```

一方 `qurxvt2` の設定を見る以下のようになっています。
上部 50 % の位置に高さ 48% で配置しています。つまり画面下部半分にターミナルが表示されます。

```haskell
  , NS "qurxvt2"  "urxvtc -name qurxvt2" (appName =? "qurxvt2")
        (customFloating $ W.RationalRect 0 0.5 1 0.48)
```

`F11`, `F12` を押すときれいに上下ターミナルが並ぶといった形になります。
私の場合、ローカルとリモートで作業することが多いので画面上部をローカル、画面下部をリモートに割り当てて仕事をしています。
根本的にターミナルの位置が変わるため、作業ミスを格段に減らすことできます。

では `ManageHook` に設定を追加しましょう。
`namedScratchpadManageHook` で設定します。

```haskell
       , manageHook         = myManageHookShift
                              <+> myManageHookFloat
                              <+> namedScratchpadManageHook myScratchpads
                              <+> manageDocks

```

設定すると以下のようなイメージになります。

![001.jpg](https://qiita-image-store.s3.amazonaws.com/0/2526/928f66f2-d0b0-f089-636a-66ea24cad702.jpeg)

`NamedScratchpad` を使うと特殊な `Workspace` "NSP" ができるのですが何も設定しないとこの `Workspace` にも移動できてしまい、非常に煩わしいことになります。
(`CycleWS` ではそのまま "NSP" に移動できる）

そのため移動時に "NSP" を無視するようフィルタ設定をする必要があります。
以下のような移動用の関数を用意すると簡単に "NSP" へ移動しなくすることができます。

```haskell
notSP :: X (WindowSpace -> Bool)
notSP = return $ ("NSP" /=) . W.tag

nextWS' :: X ()
nextWS' = moveTo Next (WSIs notSP)
prevWS' :: X ()
prevWS' = moveTo Prev (WSIs notSP)
```

その他、`LogHook` や、 Workspace 一覧にフィルタをかける関数が用意されているので適時設定しましょう。
(`namedScratchpadFilterOutWorkspacePP` や `namedScratchpadFilterOutWorkspace`)


## RunOrRise

次は `RunOrRaise` です。
これはその名の通り、存在しなければ起動し、存在していればそのアプリケーションを再表示します。
再表示時は現在の `Workspace` に表示されます。
もちろん閉じてない場合には何も起こりません。

これは間違って落としたくないアプリケーションを起動させる際に使います。
メッセンジャー、チャットツール系などで重宝します。
私の場合は `skype`, `slack`、`pavcontrol` その他もろもろ起動するランチャーに使用しています。

まず使うには `import` します。

```haskell
import XMonad.Prompt.RunOrRaise (runOrRaisePrompt)
```

最低限必要な `runOrRaisePrompt` だけでいいと思います。
使い方は簡単で以下のようにショートカットキーを割り当てるだけです。

```haskell
  , ((modm                  , xK_r    ), runOrRaisePrompt myXPConfig)
```

`XPConfig` ですが、ランチャー代わりに使うことになるので自動補完は効いた方が楽だと思います。
`autoComplete` を設定しておきましょう。

```haskell
myXPConfig :: XPConfig
myXPConfig = defaultXPConfig
                { font              = "xft:Ricty:size=12:antialias=true"
                , fgColor           = colorfg
                , bgColor           = colorNormalbg
                , borderColor       = colorNormalbg
                , height            = 20
                , promptBorderWidth = 1
                , autoComplete      = Just 100000
                , bgHLight          = colorWhite
                , fgHLight          = colorNormalbg
                , position          = Bottom
                }
```

これで絞り込み、自動補完が効きます。
よくランチャーに `dmenu` などを使う例がありますが自動補完が効くので十分実用的になります。

## Search

次は `Search` です。
`Search` はその名の通り、様々なサイトで検索を行う機能です。
一時期 `google` 検索をプロンプトで仕込んでいたのですが、`xmonad` のプロンプトは日本語が打てないのでやめました。
現状残しているのは `selectSearchBrowser` の機能です。

```haskell
import XMonad.Actions.Search (selectSearchBrowser, google)
```

`X` 上で選択している単語を google 検索する機能を使います。
検索できるサイトはそれなりにあるので以下を参考にするといいでしょう。

http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Actions-Search.html

では設定します。
`selectSearchBrowse` に ブラウザと `searchEngine` を指定するだけです。
簡単ですね。

```haskell
  , ((modm .|. shiftMask    , xK_g    ), selectSearchBrowser "/usr/bin/google-chrome-stable" google)
```

これで `X` で選択している単語の検索結果が指定ブラウザに表示されます。
選択した単語なので日本語でも問題なく検索できます。

## GridSelect

次は `GridSelect` です。
正直、`NamedScratchpad` があるのでそんなに使ってないのですが見た目がいいので使いましょう。
一時期、ランチャーの代わりに `runOrRise` をひっかけて使ってたのですが、やはり使わなくなったので生き残ってるは `goToSelected` ぐらいです。

import は以下です。

```haskell
import XMonad.Actions.GridSelect (goToSelected, defaultGSConfig)
```

設定はほぼデフォルトのもので問題ないです。

```haskell
  , ((modm                , xK_Tab), goToSelected defaultGSConfig)
```

イメージは以下のページの下部にあるので参考にしてみて下さい。

http://xmonad.org/xmonad-docs/xmonad-contrib/XMonad-Actions-GridSelect.html

## まとめ

とざっくり私の使い込んでいる `xmonad` の機能を紹介しました。
`xmonad-contrib` にはその他にも便利な機能が多数存在するので覗いてみると良いかも知れません。