WindowsのVIMで開発しているスクリプトをリモートのLinuxで動作確認するために半自動でSCPする
というありがちなパターン。
WinSCPがインストールされている前提で、その keepuptodate コマンドでもいいんだけど、今回は反映タイミングは制御したかったので、初VIMスクリプトの練習として書いてみた。
といっても、パスセパレータのエスケープが面倒だったんで、この記事の隠れ主題として、VIMスクリプトの中でセパレータをどこで何個書けばよいかの備忘録というのがある。
下記スクリプト呼び出されている WinSCP スクリプト(sync.winscp)はリモートに接続して、syncしたりputしたりしてclose→exitするものであれば何でもよく、このVIMスクリプトと同じディレクトリに置いておくように記載している。
" Sync let s:winscp = 'C:\\Program Files (x86)\\WinSCP\\WinSCP.exe' let s:script_filepath = expand('%:h') . '\sync.winscp' function! Sync() let l:script_filepath = substitute(s:script_filepath, '\\', '\\\\', 'g') let l:command = \ printf('call system("\"%s\" /console /script=\"%s\"")', \ s:winscp, l:script_filepath) execute l:command endfunction command! Sync :call Sync()
んで、VIMを起動したときに最初にこのスクリプトを source しておくと、開発したスクリプトをリモートのLinuxに持っていきたいときに :Sync とするだけでそれができる。
(追記)
Windowsでも、Cygwinなどの scp.exe がインストールされていてパスが適切に設定されていれば、:edit scp://~ でリモートのファイルを透過的に編集できるらしい。まあいいや。VIMスクリプトのいい練習になったのでよしとする。
部分クイックソート
久しぶりに勉強。配列の一部だけをソートする部分ソート(partial sort)。
参考にしたのは、ぐぐって見つけた論文と、ロゼッタコードのページ。たぶんこれでいいと思うけど。
sortRecursively(array, 0, array.length - 1, lowerBound, upperBound); private static <T extends Compatible<T>> sortRecursively(T[] array, int leftEnd, int rightEnd, int lowerBound, int upperBound) { int pivotIdx = selectPivot(array, leftEnd, rightEnd); int[] lrIdx = splitArrayIntoLandU(array, leftEnd, rightEnd, pivotIdx); if (lowerBound < lrIdx[0]) { sortRecursively(array, leftEnd, lrIdx[0], lowerBound, upperBound); } if (lrIdx[1] < upperBound) { sortRecursively(array, lrIdx[1], rightEnd, lowerBound, upperBound); } } private static <T extends Comparable<T>> int[] splitArrayIntoLandU(T[] array, int leftEnd, int rightEnd, int pivotIndex) { T pivot = array[pivotIndex]; while(leftEnd<= rightEnd) { while (array[leftEnd].compareTo(pivot) < 0) { ++leftEnd; } while (pivot.compareTo(array[rightEnd]) < 0) { --rightEnd; } if (leftEnd <= rightEnd) { swap(array, leftEnd, rightEnd); ++leftEnd; --rightEnd; } } return new int[] {rightEnd, leftEnd}; }
これで lowerBound ~ upperBound の間だけがソートされる。メソッド selectPivot は leftEnd と rightEnd の間からピボットを取るようにする。
Rubyエンコーディング
Rubyを時々触るのだけれど、こんなプログラム:
# -*- coding: utf-8 -*- puts "あいうえお"
を組んで、実行すると
PS D:\home\iwsttty\> ruby .\puts_japanese.rb 縺ゅ>縺・∴縺
こうなる。で、あれ?と思って、ああ「-U」オプション忘れてたと気づく。国産言語なのに、こんな単純なプログラムでさえ、日本語をJavaみたいによろしくやってくれない。
くやしいので、なぜこうなるのかというところを理解するために、とりあえず図にする。
左側が書き込みのとき、右側が読み込みのとき。矢印は実線と破線の二種類があって、前者はそのままバイト列が渡されること、後者は何らかの変換がされることを表わしている。
書き込みのときは、外部エンコーディングが明示的に設定されているかどうかで挙動が異なる(内部エンコーディングは関係ない)。設定されていなければ、Stringオブジェクトのバイト列がそのまま出力される。設定されていれば、文字列エンコーディングからそのIOオブジェクトの外部エンコーディングに変換されて出力される。明示的と言ったのは、EncodingのメソッドにEncoding.default_externalというのがあって、外部エンコーディングが設定されていないとあたかもこちらの値が使われるようなイメージがあるからであるが、書き込み時はこの値は関係ない。
読み込みのときは、内部エンコーディングが設定されているかどうかで挙動が異なる。設定されていなければ、入力されたバイト列は外部エンコーディングを仮定して、Rubyプロセス内部に読み込まれる。設定されていれば、さらに内部エンコーディングに変換される。
先ほどのEncoding.default_externalは、読み込み時で、かつそのIOオブジェクトに外部エンコーディングが設定されていない場合に用いられる。ニッチだ。
冒頭のプログラムに戻ると、Rubyは何もしないと標準出力オブジェクトSTDOUTのエンコーディングは内部、外部ともに設定されないため、UTF-8文字列を外部に出力すると、そのままPowerShellの端末に出力される。PowerShellのエンコーディングはディフォルトでは「日本語 (シフト JIS)」なので、文字化けする。
PS D:\home\iwsttty> [console]::OutputEncoding.EncodingName 日本語 (シフト JIS)
結局、STDOUTの外部エンコーディングが初期状態でnilなのがダメなんだろうな。せっかくEncoding.default_externalが適切に設定されているのに。
PowerShellでプロクシ設定
ぐぐっても意外と情報がなかったのでメモ。
> Set-Item -path Env:http_proxy -value http://proxy.youroffice.co.jp:7777 > $Env:http_proxy http://proxy.youroffice.co.jp:7777 > gem install nokogiri Fetching: nokogiri-1.5.5-x86-mingw32.gem (100%) Successfully installed nokogiri-1.5.5-x86-mingw32 1 gem installed
ジョギング音楽
(2014/5/9) 新しく2014年バージョンを公開。→こちら。
私がジョギングのときにiPodで聴いている曲を紹介。BPM 160前後の洋楽が中心。
曲名 | アーティスト名 | BPM | リンク | |
---|---|---|---|---|
Crawling Back To You | Daughtry | 151 | iTunes / Youtube | |
Feelin' Way Too Damn Good | Nickelback | 156 | iTunes | |
Over You | Daughtry | 156 | iTunes / Youtube | |
Duca | Chara | 156 | ||
変わらないもの | 奥華子 | 157 | iTunes | |
Blurry | Puddle of Mudd | 157 | iTunes / Youtube | |
Holding On to Heaven | Nickelback | 158 | iTunes | |
Keep Holding On | Avril Lavigne | 161 | iTunes | |
Some Say | Sum 41 | 162 | iTunes / Youtube | |
Keep It Together | Puddle of Mudd | 162 | iTunes | |
What About Now | Daughtry | 162 | iTunes | |
We Don't Have To Look Back Now | Puddle of Mudd | 163 | Youtube | |
Some Day | Nickelback | 163 | iTunes / Youtube | |
Don't Ever Let It End | Nickelback | 168 | iTunes | |
Losing My Mind | Daughtry | 168 | iTunes / Youtube |
ついでに、ジョギングに向いているかはともかくBPM 160前後の曲の紹介。
曲名 | アーティスト名 | BPM | リンク |
---|---|---|---|
ふでペン〜ボールペン | 放課後ティータイム | 153 | |
働く男 | ユニコーン | 160 | |
Woman Like You | Lee Brice | 160 | Youtube |
iYiY | Cody Simpson | 160 | iTunes / Youtube |
Sense | Amanda Mair | 165 | Youtube |
Got Me Good | Cody Simpson | 168 | Youtube |
このBPMは、BPM計測サービスで手動で測ってみたのだが、ちょっと感覚と違う。Blurry と Keep It Together は同じくらいだと思うんだけど。
まあいいや。参考まで。
(追記 2012/4/7) Nickelback のアルバムをiTunesで購入したので、二曲追加。
(追記 2012/4/14) iTunesへのリンクを追加 (別にアフィリエイトではない)。
(追記 2012/6/16) Cody SimpsonはBPM160前後の曲が多く探しやすいけど、中学生なんだよな、こいつ...。
ネットワークインタフェイス一覧
Linuxのネットワークインタフェイス一覧を取得する話。
ifconfig コマンドの出力がパースしにくい*1ので、もう少し簡単に取得できないかと調べた。ifconfig のソースコード*2読んだだけだが、役に立つ人もいるかもしれないので書いておく。
先にオチを言っておくと、パースするほうが簡単だった…。
ifconfig は、/proc/net/dev から読み取ったインタフェイス一覧*3と、ioctl(2) の SIOCGIFCONF リクエストで取り出した情報*4をマージしている。前者には IP エイリアス情報が含まれず、後者にはアクティブなインタフェイスしか含まれないからである。
話を元に戻すと、簡単に一覧を取得するには /proc/net/dev のほうはともかく、ioctl が厄介。ifconf 構造体を ioctl 関数に渡せばよいのだが、こいつが ifreq 構造体へのポインタを持っている。
struct ifconf { int ifc_len; /* Size of buffer. */ union { __caddr_t ifcu_buf; struct ifreq *ifcu_req; } ifc_ifcu; };
知らない人のために書いておくと、ioctl 関数は、(領域を割り当てた)構造体のポインタを渡すと、その構造体にリクエストしたデバイス情報を埋め込んで返してくれる。
Perl の ioctl 関数もまったく同じ。つまり、Perlでバッファ確保とそのポインタを渡す必要がある…。
*2:[https://developer.berlios.de/projects/net-tools/:title=net-tools]
*3:lib/interface.c の if_readlist_proc関数を参照
*4:lib/interface.c の if_readconf関数を参照