個人的には重宝していることまとめ

[この前に投稿した記事](http://qiita.com/namutaka/items/ea10263a272475f7a02f)で今年変えてみたことを書きましたが、今度は今年に限らず自分で使っていて地味に便利だと思うことをまとめておこうと思います。


## SSH接続先サーバーでtmuxを使いわける

SSH接続した先の環境でtmuxを使っているのですが、以下のようなことができるようにしています。

1. tmuxは基本的に１つのセッションのみを使うので、もし既存のセッションがあればそれをアタッチする
2. sshしてからtmux起動と２ステップかかるのが面倒なのでssh接続したら即座にtmuxの環境になるようにする
3. ただし、たまにtmuxなしで接続することもあるので使い分けられるようにする
    * tmux.confを間違ってtmuxが起動しなくなることもあるので... 

実現方法は以下のとおりです。

まず、要件1を満たすためssh接続先の環境で、以下のようなコマンド(function)を用意します。
この`tm`コマンドはtmuxを起動するためのコマンドです。既にtmuxのセッションがあればそれにattachし、なければ新規作成します。

```bash:.bashrc
function tm {
  tmux has -t main #2> /dev/null 
  if [ "$?" -eq 0 ]; then 
    exec tmux attach -t main 
  else 
    exec tmux new -s main 
  fi 
} 
```

その上で、要件2,3はsshコマンドの実行方法で使い分けています。

```bash
# tmuxなしで通常のssh接続する場合
$ ssh serv

# 必ず新規セッションのtmuxを起動
$ ssh -t serv tmux

# 既存のセッションにアタッチしつつ起動
$ ssh -t serv tm
```

単に`ssh`で`tmux`コマンドを実行してしまうとttyがないのでtmuxが起動できませんが、`-t`オプションをつけてttyがある状態にすることでtmuxを起動できます。


## Vimで選択範囲の変換処理をコマンド化する

Vimで決まった整形をするときに、複数の置換操作を一連で実行したいことがあります。
そういうときは以下のような感じでコマンド化できます。

```vim:formatter.vim
" タブ区切りやCSVをMarkdown table形式に変換する
function! MdTable(...) range
  let delim="\t"
  if a:0 >= 1
    let delim = a:1
  end
  let rng = a:firstline . "," . a:lastline
  exec rng . 's/^\|$\|' . delim . '/|/g'
  exec rng . 's/"//g'
  exec rng . 'EasyAlign *|'
endf

command! -range -nargs=? MdTable silent <line1>,<line2>call MdTable(<f-args>)


" SQLのin句に指定するような形式にする
function! SqlList() range
  let rng = a:firstline . "," . a:lastline
  exec rng . 's/"//g'
  exec rng . 's/^\|$/''/g'
  exec rng . 's/$/,/'
endf

command! -range SqlList silent <line1>,<line2>call SqlList()
```

functionを範囲に対してcallしたら1行ずつに個別にfunctionが実行されます。
functionの末尾に`range`と記述することで、この動作を範囲全体に対して１回のみ実行されるにできます。
その上で、`a:firstline`と`a:lastline`で範囲に対して操作を行うコマンド文字列を作成し、`exec`コマンドで実行しています。
functionをExコマンドで実行する方法は、`command! -range`の行の通りです。


## Rakeタスクを並列で実行する

私はログ分析をRakeで実装しているのですが、分析処理を手軽に並列実行するのに`pwrake`というコマンドを使わせていただいています。

* https://github.com/masa16/pwrake ( [Readmeの日本語版](https://github.com/masa16/pwrake/wiki/Pwrake%E3%81%A8%E3%81%AF) )

これは何かの研究用途で作成されたツールのようですが、汎用的に使うことができます。
内容については上記の公式説明を見ていただくのでも十分だとは思いますが、ざっと紹介します。

ログの分析をRakeで行うときに以下のような感じで`Rakefile`を作成します。

```ruby:Rakefile
# 出力先フォルダ
directory "out"

# "in"フォルダ内の入力となるログファイルをループ
out_files = Dir.glob('in/*.log').map { |filepath|
  out_file = File.join("out", filepath)

  # 出力ファイル生成タスクを動的に定義
  file out_file => ["out", filepath] do |t|
    # filepath のファイルから、out_file を生成する処理を実装する
    `cat #{filepath} | grep "GET" > #{out_file}` # 例
  end
}

file "result.log" => out_files do |t|
  # 複数の出力ファイルを一つにまとめる処理を実装する
  `cat #{out_files.join(' ')} > #{t.name}` # 例
end

desc "parse logs"
task :log => "result.log"
```

これは、入力となるログの１ファイルごとを加工するための`file`タスクを定義し、それらを最後に１つにまとめて`result.log`というファイルを生成するような処理になっています。

これを普通の`rake`で実行すると`out_files`に入っているタスクを順番に実行することになります。
ここで、`rake`と同じ要領で`pwrake`でタスクを実行すると`out_files`部分を並列に実行することができます。

```bash
# 順番に１ファイルずつ処理
$ rake log

# out_filesのタスクを並列実行
$ pwrake log

# 並列数の上限を決めて実行
$ pwrake -j 3 log # ３並列で実行
```

`pwrake`は普通の`rake`コマンドの代わりに使えて、Rakefileに特殊な記述をすることもなく、決まった並列数で並列処理を実行してくれます。


ただ、今回記事を書くにあたってあらためてrake(v11.2.2)コマンドを調べると、`multitask`というタスク生成機能と`rake`の`-j`オブションでそこまで遜色なく同じことができそうです。
私が`pwrake`を使い始めたころは、`rake`では並列数の上限を指定できなかったんですが、今は変わっているようです。

## MacのJISキーボードを仮想的にUSキーボード配列にする

私はUSキーボード配列をメインで使っているのですが、いま会社で支給されているMacBookがJISキーボードです。
JISキーボードでは操作に色々と困るので [Karabiner](https://pqrs.org/osx/karabiner/index.html.ja)と[Seil](https://pqrs.org/osx/karabiner/seil.html.ja)というツールでJISキーボードの配列をUSキーボードに近づけて対応しています。

Karabiner の設定において、以下にチェックをつけます。

  * [For Japanese]-[Change Keyboard Layout]-[Use Japanese Keyboard as US Keyboard]
  * [For Japanese]-[Change EISUU Key]-[EISUU to Command_L (+ When you type EISUU only, send EISUU)]
  * [For Japanese]-[Change KANA Key]-[KANA to Command_R (+ When you type KANA only, send KANA)]

次に、以下の手順でキーボードの左下の「caps」キーを「fn」キーに変えます。

  - OSXの[システム環境設定]->[キーボード]画面で、[修飾キー...]ボタンをクリックし、出てきたダイアログで[Caps Lockキー]欄を「アクションなし」に設定する
  - Seilを起動し、[Setting]画面で[Change the caps lock key]-[Change the caps lock key]にチェックをいれ、[keycode]欄に「63」(Fnキーのキーコード)を入力する

物理的な配置の問題で変えられないキーもありますが、実用的な状態にはできます。

  * 参考: MacでCapsキーをFnキーに変更する方法 - ttaka/tmp 
    * http://d.hatena.ne.jp/ttaka_tmp/20110414/1302770240

**追記: 2017/02/13**
Mac OSX Sierra 10.12 では、2017/02/13 現在では karabinerが動きませんので、上記の方法は実現できません。

次期版として https://github.com/tekezo/Karabiner-Elements を作成中のようです。
Karabiner-Elements でも設定ファイルを上手く作ると実現できるっぽいのですが、その設定ファイルの内容がよくわからず...
https://github.com/tekezo/Karabiner-Elements/issues/55