perl -de 42 とかはどうも気に食わないんだけど、これと言って良さそうなものも見つけられず、とりあえずは mzp さんのやつをパクらせてもらって、ちょろっと改良したものを使うことにした。 何か、もっと良いのを知ってる人は教えてください。 irb みたいなのが欲しいんです。
% cat iperl
#!/usr/bin/env perl
package REPL;
use strict;
use warnings;
use Data::Dumper;
use Term::ReadLine;
local $Data::Dumper::Purity = 0;
local $Data::Dumper::Terse = 1;
sub main::p {
my @args = @_;
print Dumper(@args);
}
my $__term__ = new Term::ReadLine 'term';
my @__spool__ = ();
sub readline_from_term {
my $prompt = $#__spool__ < 0 ? 'perl> '
: ' | ';
$__term__->readline($prompt);
}
while (defined(my $__line__ = readline_from_term)) {
push(@__spool__, $__line__);
if ($__line__ =~ /;;$/) {
my @__result__ = do {
package main;
eval(join("\n", @__spool__));
};
if ($@) {
print $@;
} else {
print "=> ", Dumper(@__result__);
}
@__spool__ = ();
}
}
変数のうまい隠し方がわからなくて、eval するときに触れてしまうので、変数名にアンダースコアとか付けてみたり。 パッケージが絡んだときの変数のスコープの扱いが、他の慣れてる言語に比べるとクセがある感じでどうもうまくいかないんだよな。 あと、すごく適当に複数行入力をサポートするために、OCaml みたいに ;; を入力した時点で実行するようにした。 他には、Ruby の Kernel#p に相当する p 関数とかも用意してみた。
Perl 初心者なので、添削歓迎いたします。 (や、初心者じゃない言語のときも、添削おことわりってわけじゃないですょ)
via perl でインタラクティブなシェルを実現する perlsh - 川o・-・)<2nd life.
というわけで、教えてもらったので使ってみたり。 やっぱり CPAN で直接インストールする方法はわからなかったので、install Term::ReadLine::Gnu した後、CPAN のサイトの Source のリンクから直接ダウンロードして適当な場所に突っ込んだ。
良い感じではあるけど、複数行で書きたいときには改行前にバックスラッシュ入れなきゃないのがちょっと面倒。 まあ、ソースの長さから考えて irb と比べるのは無茶なんだとは思うけど。 つーか、irb はがんばりすぎ。 こっそり構文解析とかやってるからね(苦笑
なんか素の状態だと配列とかハッシュが返ったときの表示が残念すぎるので…
main[20]$ [1,2,3];
ARRAY(0x81f18bc)
main[21]$ {foo => 1, bar => 2};
HASH(0x81f18b0)
改造を決意。 つーかまあ、表示用の関数 printer を Data::Dumper 使ったもので上書きするだけ。 で、~/.perlshrc を起動時に読んでくれるので、
% cat ~/.perlshrc
$PerlSh::STRICT = 1;
use Data::Dumper;
sub PerlSh::printer {
my @args = @_;
print Dumper(@args);
undef;
}
てな感じにしておいた。
main[22]$ [1,2,3];
$VAR1 = [
1,
2,
3
];
main[23]$ {foo => 1, bar => 2};
$VAR1 = {
'bar' => 2,
'foo' => 1
};
それなりに嬉しくなったね。
さらに教えてもらったのでお試し中。 cpan で Shell::Perl をインストールするとコマンドも一緒に入る。
pirl @> [1,2,3]
[1, 2, 3]
pirl @> {foo => 1, bar => 2}
{ bar => 2, foo => 1 }
表示がとても普通っぽいのがよろしい。
pirl @> :set out Y pirl: YAML loaded ok pirl @> [1,2,3] --- - 1 - 2 - 3
とかすると YAML で出力してくれたりするのはおもろいな。 で、:set ctx を使うと eval する際のコンテキストが設定できるみたいなんだけど、何に使うんだこれ。
pirl $> :set ctx list pirl @> (1,2,3) (1, 2, 3) pirl @> :set ctx scalar pirl $> (1,2,3) Useless use of a constant in void context at (eval 60) line 1. 3
コンテキストによって動作が違う操作を試してみるのに使えば良いのかな。
全体的に perlsh よりは高機能って感じだけど、残念なことに複数行入力の仕組みが無い。 まあ、perlsh にしても単に最後がバックスラッシュだったら溜めておくって処理を入れてるだけだけど、そういう単純なことも全くやってないようだ。 man Shell::Perl すると TO DO の項目に、
Accept multiline statements;.
とか書いてあるんで、今後に期待というところかねえ。 とりあえず perlsh っぽくアドホックな対処でも入れとこうかと思ったけど、どうすんのが良いのかなー。 起動時のフックとかは無いみたいなんで、起動スクリプトごと自分で書いちゃうのが良いかね。 そもそも pirl ってスクリプトの中身って単に Shell::Perl->run_with_args を呼び出してるだけだという(苦笑
とりあえず pirl を直すより perlsh の printer を pirl のに直せばオッケーじゃね? ということで、Shell::Perl::Dumper のソースを見ながら以下のように修正。
% cat ~/.perlshrc
$PerlSh::STRICT = 1;
use Data::Dump;
sub PerlSh::printer {
print Data::Dump::dump(@_) . "\n";
undef;
}
% perlsh
main[26]$ [1,2,3]
[1, 2, 3]
main[27]$ {foo => 1, bar => 2, baz => 3}
{ bar => 2, baz => 3, foo => 1 }
しかし、Data::Dump やら Data::Dumper やら Data::Dump::Streamer やら、なんやらかんやら、Ruby なら inspect 一発なのになんだか色々あってカオスだねえ Perl は。
ともあれ、こんな感じで当面は perlsh を使うことにしよう。 コンテキスト依存な実験がしたいときには pirl を使うということで。 あと、pirl が複数行入力に対応したら乗り換えよう。
こんにちは。 perlsh というものがあります。 <br>http://d.hatena.ne.jp/secondlife/20060111/1136975310
おー、これは良い。ありがとうございます。
Shell::Perl についてくる pirl てのもありますよ。
おっと、情報どうもです。試してみます。