svk の shell が欲しい
と思って探したら,ありました。
svk使ってると「svk st」→「svk di」→「svk ci ファイル名 -m ほげほげ」とかよくやるんですが、「svk」の部分がDRYじゃないと思ったので超簡易SVKシェルを作ってみましたよ。
いちいち「svk なんちゃら」って打つのが面倒な人のためのSVKシェル - Greenbear Diary
Ruby 使って readline と system を利用してます。のでびっくりするほどシンプル。
2008/01/25 追記: yhara さんがさらに発展させた Reposh というシェルをリリースなさってます。
んで,svk はせっかく Perl で書かれていますし,モジュールもあるので,Perl で書いてみました。まるでシンプルじゃなくなってしまった罠。
Term::ShellUI は神! でも,このスクリプトのままだとファイル名補完とか使えないです。もっとあれこれいじるとできそうなんですが,とりあえず。
#!/usr/bin/perl use strict; use warnings; our $SUPPORT_ESCAPE_COMMAND = 0; use SVK 2.0; use SVK::I18N; use autouse 'SVK::Util' => qw( get_anchor catfile catdir find_dotsvk ); use Class::Autouse qw( SVK::Command SVK::XD ); use Cwd; use Term::ShellUI; use YAML; $YAML::UseCode = $YAML::UseCode = 1; # avoid warn my $term_settings = Load(<<'END_TERM_SETTINGS'); --- app: svk prompt: !!perl/code | { prompt(); } commands: quit: method: !!perl/code | { shift->exit_requested(1); } q: alias: quit exclude_from_completion: 1 exit: alias: quit help: proc: !!perl/code | { help(@_); } h: alias: help exclude_from_completion: 1 "?": alias: help exclude_from_completion: 1 version: proc: !!perl/code | { show_version(); } v: alias: version exclude_from_completion: 1 # pwd pwd: proc: !!perl/code: | { pwd(@_); } # local ls lls: proc: !!perl/code: | { lls(@_); } # local cd lcd: proc: !!perl/code: | { lcd(@_); } cd: alias: lcd # fallbacks "": method: !!perl/code | { invoke(@_); } END_TERM_SETTINGS $ENV{HOME} ||= ( $ENV{HOMEDRIVE} ? catdir(@ENV{qw( HOMEDRIVE HOMEPATH )}) : '' ) || (getpwuid($<))[7]; $ENV{USER} ||= ( (defined &Win32::LoginName) ? Win32::LoginName() : '' ) || $ENV{USERNAME} || (getpwuid($<))[0]; our $svkpath = find_dotsvk || $ENV{SVKROOT} || catfile($ENV{HOME}, ".svk"); our $floating = undef; if (-e catfile($svkpath, 'floating')) { require Path::Class; $floating = Path::Class::Dir->new( $svkpath )->parent(); } my $term = Term::ShellUI->new(%$term_settings); show_version(); print "using ", $term->{term}->ReadLine, ", "; if (! $term->{term}->can('history_expand')) { $term->{disable_history_expansion} = 1; } if ($term->{disable_history_expansion} || $SUPPORT_ESCAPE_COMMAND) { print "doesn't support history expansion.\n"; $SUPPORT_ESCAPE_COMMAND = 1; } else { print "support history expansion.\n"; } $term->run(); exit; sub invoke { my ($term, $params) = @_; my $ret; my $cmd = $params->{cname}->[0]; my @argv = @{ $params->{args} }; if ($SUPPORT_ESCAPE_COMMAND && $cmd =~ s{ \A ! \s* }{}xmso) { if ($cmd =~ m{ \A \s* \z }xmso) { $cmd = shift @argv; } unshift @argv, $cmd; system $cmd @argv; return; } my $xd = SVK::XD->new ( giantlock => catfile($svkpath, 'lock'), statefile => catfile($svkpath, 'config'), svkpath => $svkpath, floating => $floating, ); $xd->load(); local $SIG{INT} = sub { die loc("Interrupted.\n"); }; $ret = SVK::Command->invoke ( $xd, $cmd, undef, @argv ); $xd->store (); } sub help { SVK::Command->invoke(undef, 'help', undef, @_); } sub pwd { print getcwd, "\n"; } sub lls { system 'ls', @_; } sub lcd { my $wd = @_ ? shift : $ENV{HOME}; chdir $wd; } sub show_version { print loc("This is svk, version %1 (using Subversion bindings %2)\n", $SVK::VERSION, $SVN::Core::VERSION); } my $cmd_index = 0; sub prompt { return sprintf 'svk[%d]> ', ++ $cmd_index; }
無駄に YAML 使ってたり不味いコード書いてたりして見通しが悪くなってますが,Term::ShellUI はほんとおすすめです。ヒストリも(上記コードでは有効にしてませんが)簡単にとれるようにできるし。