その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

ファイルハンドルに対するbinmodeの変更が及ぼす影響を小さくしたい

ファイルハンドルをbinmodeで変更して,そのファイルハンドルを用いて何らかの処理を行いたい,という欲求がしばしばあると思います.
単純に書くと以下のようになるでしょう.

このコードではファイルハンドルを普通にopenして,それをawesome_function()に渡して,そのawesome_function()内でbinmode $fh, ':encoding(utf-8)'を使ってファイルハンドルのencodingを変更して,そのファイルハンドルで何らかの処理を行っています.
ぱっと見これで良い感じがしますが,このコードには問題があって,awesome_function()内でのファイルハンドル$fhの変更は他の箇所,つまりawesome_function()の外にも影響を及ぼします.
上のコードを例に取ると,awesome_function()を呼ぶ前のファイルハンドル$fhはencodingが変更されていませんが,呼び出した後のファイルハンドル$fhはencodingが変更されています.これだと具合が悪い時がままある.


こうした場合に,ファイルハンドルへの変更をawesome_function()内で留めたい場合どうすれば良いのかと考えた時に,とりあえずファイルハンドルを複製して,その複製したファイルハンドルに対して変更を与えてからそれを使って処理すれば良いのではないか,という感じになりました.こんな感じ.

awesome_function()内でファイルハンドルを複製して *1,その複製したファイルハンドル$fh_copyに対してbinmodeでencodingを変更してやってから$fh_copyを使って処理を行なってやれば,元のファイルハンドルに変更を及ぼすことが無くなります.つまり,awesome_function()を呼んだ後であっても元のファイルハンドルは変更されません.


こうした場合はファイルハンドルの複製でなんとかなるんじゃないかと思った次第です.なんか駄目そうだったら教えて下さい.


なおファイルハンドルの詳細な情報 (layer) はPerlIOの関数であるget_layers()に対してdetailsフラグを立てて実行すると参照することが出来ます.上記コードだと以下の様な出力が得られます.

$VAR1 = 'unix';
$VAR2 = undef;
$VAR3 = 2098176;
$VAR4 = 'perlio';
$VAR5 = undef;
$VAR6 = 4195328;
$VAR7 = 'encoding';
$VAR8 = 'utf-8-strict';
$VAR9 = 4228096;

この結果から,encodingがutf-8-strictであることがわかりますね.

ちなみにdetailsを使ったPerlIO::get_layersにのドキュメントには“Implementation details follow, please close your eyes.”とか書いてあって大変クール!


CLOSE YOUR EYES/YAMATO-男たちの大和 主題歌-

CLOSE YOUR EYES/YAMATO-男たちの大和 主題歌-

*1:ファイルハンドルの複製についてはopen()を参照して下さい http://perldoc.perl.org/functions/open.html

Text::LTSVの新しいバージョンではメソッドにファイルハンドルを渡せるようになって便利

Text::LTSVparse_fileparse_file_utf8には元々ファイルパスしか引数として与えられなかったのですが,Version 0.08以降はここにOpenしてあるファイルハンドルを渡せるようになって便利です.

処理がスマートに書けるようになって大変満足!

git-checkout-here.vimというプラグインを書いた

git-checkout-here.vim

https://github.com/moznion/git-checkout-here.vim


何をやるプラグインかと言うと,カーソルの現在行が所属する部分 (後述) をgit checkout HEADするというプラグインです.
プログラムを書いていると,「ここの部分は残しておきたいけれど,ここの部分はHEADに戻したい」みたいな事がままあって,そういう時はgit checkout --patch HEAD*1 したり,あるいは手で書き直したり(!)すれば良いわけですが,一回エディタを抜けてgitコマンド叩くのもアレだし,ましてや手で書きなおしたりするとミスを犯す可能性があるので,それだったらエディタ上で処理を完結させたい! というモチベーションに基いて書きました.


内部的にはやはりgit checkout --patch HEADを実行していて,上記の「カーソルの現在行が所属している部分」というのは,つまりgit checkout --patch HEADした時のパッチレベルのことです.
(従ってこのプラグインでは,git checkout --patch HEADよりも細かい粒度でcheckoutする事は不可能です)
--patchオプションは普通に使うとコマンドの処理はインタラクティブなモードになるんですが,echo -e "\n\n\y\y" | git checkout --patchという風に標準入力で渡して使ってやると,非インタラクティブモードでコマンドを実行できるので便利ですね)


まあ,便利なのかどうかイマイチわからない……というか,まあ僕は便利だと思って使っているんですがどんな塩梅でしょうか.


それはそうと今改めてこのプラグインの説明文を読み返しましたがわかりにくいですね! 日本語難しい!

CROSS 2014のぶつかり稽古に出演します

― あのぶつかり稽古がまた来る...


http://www.cross-party.com/programs/butsukari/

明日1月17日(金)にCROSS 2014で催される異色のイベント,ぶつかり稽古に弟子役として出演します.
色々あって色々大変な感じになりました.ほんとうにもう!!!!

当日はYappoさんにボコボコにタコ殴りにされる僕の姿が見れますので,是非見に来て頂きたく存じます.

VimでもJavaScriptのfunctionを寿にしたい

http://hitode909.hatenablog.com/entry/2013/10/26/132041
ここで書かれているように,JavaScriptをいじっている時にfunctionが寿になると嬉しい.
(最初は寿じゃなくてλだった気もしますが,この際それは脇に避けます)

2014-01-15 17:50 追記

結論から言って,
http://labs.timedia.co.jp/2011/04/javascript-function-lambda-vim.html
を見ると良いです.コメントで教えてくださったid:thincaさんありがとうございます!
[追記ここまで]

2014-01-16 0:35 追記

いちいちsyntax/javascript.vimに書くのだるいし,複数マシンで共有するのも面倒だったので,
NeoBundle等でさくっとインストール出来るようにリポジトリ立てました.
https://github.com/moznion/jskotobuki-vim

:Kotobuki:NoKotobukiといったコマンドもサポートしています.
(:Kotobukiするとfunctionが寿になって,:NoKotobukiすると寿になりません)

また,g:jskotobukiCharacterに任意の文字を代入すると「寿」以外の文字で置換されるようにしました.
[追記ここまで]


!!! という訳で以下に書かれている内容は本当に良くないので参考にしないで下さい !!!


Emacsだとid:hitode909さんの記事に書かれているようなEmacs LISPを書くと動くわけですが,
Vimだとどうやれば良いのかよくわからなかったのでざっくり適当に書きました.


gist8431877


この実装,「寿」を1文字削除しようとすると理想的には“functio”になるべきなのに全部消え去ってしまったり,
JSのキーワードではない文字列の「寿」も置換されてしまったりと,諸般の問題を抱えていてあまり良くない感じがします.

というか,そもそも見た目だけを変えたいのにファイルごと書き換えていてマズい.
Vimが途中で不慮の事故で落ちると,JSのファイルは寿のままになってしまって具合が悪い.

発想が乱暴だし実装も乱暴だし,実装者も乱暴なので,乱暴そのものと化してしまっていて厳しい.


もっと良いやり方があるはず.教えてください!!!!!!

Text::XslateにテンプレートのSyntaxをチェックするメソッドが追加されて便利

Text::Xslateのバージョン3.1.0から,テンプレートのSyntaxが正しいかそうでないかをチェックするメソッドが追加されていて便利です.


以下のように,テストしたい対象のテンプレートファイルをvalidate()メソッドの引数として食べさせてあげると,そのテンプレートファイルのSyntaxをチェックしてくれます (@filesの中身はテスト対象となるテンプレートファイルのパスのリスト).

use Text::Xslate;

my $tx = Text::Xslate->new;
for my $file (@files) {
    $tx->validate($file);
}

Syntaxが正しい時には何も起きず,Syntaxが誤っている時は以下のようなメッセージと共に例外が送出されます.

Text::Xslate::Syntax::Kolon: Expected a semicolon or block end, but got 'content', near verride, while parsing templates (/Users/owner/MyApp/tmpl/index.tx:3) at bin/check_tmpl.pl line 16.
----------------------------------------------------------------------------

: verride content -> {

----------------------------------------------------------------------------


以下のように書くと,簡単にテンプレートファイルのSyntaxのTestが一括で出来て便利では無いかと思った次第です.

use Test::More;
use Text::Xslate;

my $tx = Text::Xslate->new;
for my $file (@files) {
    eval { $tx->validate($file) };
    ok !$@, qq/Xslate Syntax OK: "$file"/;
}

done_testing;


大変便利な機能でgfx++という感じですが,なぜかundocumentedな機能だったのでさっきドキュメント書いてPull Requestしました!


[2014/01/08 22:44 追記]
gfxさんにマージしてもらったので次のバージョンあたりから当該機能はドキュメント化されていると思います!
ありがとうございます!