zshのViモードをインターフェイスとして利用してみる


##ViとEmacs

zshでは、`Vi`と`Emacs`のキーバインドを利用できます。

私は普段、Emacsのキーバインドを使っています｡

確かに､Viのノーマルモードは、非常に有効です｡

その理由は､コーディングにおいては､繰り返し処理、一括処理をする場面が多く､複雑な処理をコマンド一発で実行することが多いからです｡

しかし、僅か1行の短文などを編集する場合は､ノーマルモードの利点を上手く生かせないと考えています｡

このような場合までノーマルモードに移行するのは、面倒です｡

そんなこともあり､私は､基本 Emacs のキーバインドを使っています｡

しかし、せっかく Vi のノーマルモードが用意されているのだから、よく使う外部ツールを操作するためのインターフェイスとして利用してみてはどうかと考えました｡

ということで、今回は､zshのViモードを外部アプリのインターフェイスとして利用する方法を提案をしてみたいと思います｡

##Vi modeをプロンプトに表示する

まず、現在はノーマルモードかインサートモードかを判断できるようプロンプトに表示してみます｡

```zsh:~/.zshrc
function zle-line-init zle-keymap-select {
    VIM_NORMAL="%K{208}%F{black}⮀%k%f%K{208}%F{white} % NORMAL %k%f%K{black}%F{208}⮀%k%f"
    VIM_INSERT="%K{075}%F{black}⮀%k%f%K{075}%F{white} % INSERT %k%f%K{black}%F{075}⮀%k%f"
    RPS1="${${KEYMAP/vicmd/$VIM_NORMAL}/(main|viins)/$VIM_INSERT}"
    RPS2=$RPS1
    zle reset-prompt
}
zle -N zle-line-init
zle -N zle-keymap-select
```

参考:
[http://hamberg.no/erlend/posts/2010-10-17-show-current-vi-mode-in-zsh-prompt.html](http://hamberg.no/erlend/posts/2010-10-17-show-current-vi-mode-in-zsh-prompt.html)

これを設定ファイルに書くと、現在の Vi mode がプロンプトに表示されます。




ちなみに、カラーは､256色で指定しています｡カラーを確認したい場合は､以下のコマンドを実行してください｡


```bash:
for c in {000..255}; do echo -n "\e[38;5;${c}m $c" ; [ $(($c%16)) -eq 15 ] && echo;done;echo
```


参考:
[http://qiita.com/k_ui/items/b02b93e3af13023c0bfd](http://qiita.com/k_ui/items/b02b93e3af13023c0bfd)

##ノーマルモードに移行するキーを変更する

通常は､`Esc`または、`C-]`かと思いますが､`jj`で移行できるようにしてみます。ちなみに、インサートモードに戻るには､`i`です。

これにより、ノーマルモードに移行しやすくなります。

```zsh:~/.zshrc
bindkey -M viins 'jj' vi-cmd-mode
```

##Chromeを操作するインターフェイスとして利用してみる

私は､ターミナルの次に、ブラウザをよく使いますので、`vi-mode`をChromeを操作するインターフェイスとして使ってみることにしました｡


ノーマルモードのキーバインドを定義するには､`bindkey -a`を使います｡

例えば､「bindkey -a 'a' [vi-forward-word](http://www.cs.elte.hu/zsh-manual/zsh_14.html)」みたいな感じです｡

`GitHub`に上げましたので、試したい方は､ダウンロードしてください。

ただし、例のごとく`Apple script`を利用していますので、利用者出来る人はかなり限定されています｡`iTerm2`と`Chrome`が必要です｡

[https://github.com/syui/airchrome.zsh](https://github.com/syui/airchrome.zsh)


```bash:
$ sudo port install gauche

$ git clone https://github.com/syui/airchrome.zsh

$ cd !$:t

$ echo "source $PWD/!$:t" >> ~/.zshrc
```

テーマ`-theme`を`all`に変更し、`-chrome on`を使います｡

|キー|効果|
|---|---|
|j|下にスクロール|
|k|上にスクロール|
|h|戻る|
|l|進む|
|t|タブを閉じる|
|f|f{2文字}|
|b|続けてキー{Enter,Esc,Delete,Shift}を押す|

`j,k`でスクロール。`h,l`で前と次へ。

[ViChrome](https://github.com/k2nr/ViChrome)入れている人などは､`f`を押すと､`f-mode`が起動します。`f-mode`は、続けて二文字を入力することでコマンドが完了するように設定しました。



二文字判定の処理は､[こちら](http://qiita.com/PSP_T/items/c502eff16c174260ae4b)の記事で紹介したスクリプトを利用しています。

```bash:
$ sudo port install gauche
```

`Enter`や`Esc`などの一部キーは､`b`に続いて押すことで､実行されます。例えば､`b{Enter}`などです。

ただし、パソコンによっては､キーコードが異なることが予想されるため､この部分は、個人環境によって書き直す必要があります｡ここでは、`A`の部分です｡

```bash:chrome_button.sh
case "$button" in

    "A")
echo "
tell application \"Google Chrome\"
    activate
    tell application \"System Events\"
        delay 0.1
        keystroke return
        tell application \"iterm\"
            activate
        end tell
    end tell
end tell
" | osascript -
;;
```

それぞれのキーを判別するには､`cscroll.zsh`に入っているスクリプトを使い以下のコマンドを実行しましょう｡

```bash:
$ gosh read-single-char.gosh |col -bx| tr -d ''
```

ちなみに、`iTerm2`のウィンドウの透過度を設定するには､以下の様な`Shell script`を使います｡引数で透過度を指定します｡

```bash:iterm2_transparency.sh
#!/bin/sh
echo "
tell application \"iTerm\"
    activate
    tell current session of current terminal
      set transparency to $1
    end tell
end tell
" | osascript -
```

```bash:
$ chmod +x iterm2_transparency.sh

$ ./iterm2_transparency.sh 0.3
```

あと、クリップボードにある文字列を送るキーや入力モードを追加すると、便利な気がしています｡


##追記

だいぶ変更されました。


[http://qiita.com/syui/items/ff4205a00a6b46c8f21e](http://qiita.com/syui/items/ff4205a00a6b46c8f21e)