Edited at

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

More than 1 year has passed since last update.

この前に投稿した記事で今年変えてみたことを書きましたが、今度は今年に限らず自分で使っていて地味に便利だと思うことをまとめておこうと思います。


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

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


  1. tmuxは基本的に1つのセッションのみを使うので、もし既存のセッションがあればそれをアタッチする

  2. sshしてからtmux起動と2ステップかかるのが面倒なのでssh接続したら即座にtmuxの環境になるようにする

  3. ただし、たまにtmuxなしで接続することもあるので使い分けられるようにする


    • tmux.confを間違ってtmuxが起動しなくなることもあるので...



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

まず、要件1を満たすためssh接続先の環境で、以下のようなコマンド(function)を用意します。

このtmコマンドはtmuxを起動するためのコマンドです。既にtmuxのセッションがあればそれにattachし、なければ新規作成します。


.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コマンドの実行方法で使い分けています。

# tmuxなしで通常のssh接続する場合

$ ssh serv

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

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

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


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と記述することで、この動作を範囲全体に対して1回のみ実行されるにできます。

その上で、a:firstlinea:lastlineで範囲に対して操作を行うコマンド文字列を作成し、execコマンドで実行しています。

functionをExコマンドで実行する方法は、command! -rangeの行の通りです。


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

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

これは何かの研究用途で作成されたツールのようですが、汎用的に使うことができます。

内容については上記の公式説明を見ていただくのでも十分だとは思いますが、ざっと紹介します。

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


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"


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

これを普通のrakeで実行するとout_filesに入っているタスクを順番に実行することになります。

ここで、rakeと同じ要領でpwrakeでタスクを実行するとout_files部分を並列に実行することができます。

# 順番に1ファイルずつ処理

$ rake log

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

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

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

ただ、今回記事を書くにあたってあらためてrake(v11.2.2)コマンドを調べると、multitaskというタスク生成機能とrake-jオブションでそこまで遜色なく同じことができそうです。

私がpwrakeを使い始めたころは、rakeでは並列数の上限を指定できなかったんですが、今は変わっているようです。


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

私はUSキーボード配列をメインで使っているのですが、いま会社で支給されているMacBookがJISキーボードです。

JISキーボードでは操作に色々と困るので KarabinerSeilというツールで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キーのキーコード)を入力する

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

追記: 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