もちろん編集にはVimを使っているかと思います。
でも編集だけ?
違うよね!
Vim scriptはウェブアプリケーション記述言語なんだよ!
Plack::App::Vim
package Plack::App::Vim;
use strict;
use warnings;
use parent qw/Plack::Component/;
use Plack::Request;
use Encode;
use JSON::PP;
sub prepare_app {
my $self = shift;
$self->{vim} ||= 'vim';
if (!$self->{server}) {
open(my $f, "vim --serverlist|");
my $server = <$f>;
close($f);
chomp $server;
$self->{server} = $server;
}
if (!$self->{encoding}) {
open(my $f, sprintf("%s --servername %s --remote-expr \"&encoding\"|",
$self->{vim}, $self->{server}));
my $encoding = <$f>;
close($f);
chomp $encoding;
$self->{encoding} = $encoding;
}
$self;
}
sub call {
my ($self, $env) = @_;
my $req = Plack::Request->new($env);
my $json = JSON::PP->new->ascii
->allow_singlequote->allow_blessed->allow_nonref;
my $str = $json->encode({
uri => $env->{PATH_INFO}||'',
method => $req->method,
headers => [split( /\n/, $req->headers->as_string)],
content => $req->content,
});
$str =~ s!"!\\x22!g;
my $command;
if ($^O eq 'MSWin32') {
$command = sprintf(
'%s --servername %s --remote-expr "vimplack#handle("""%s""")"',
$self->{vim}, $self->{server},
encode($self->{encoding} || 'utf8', $str));
} else {
$command = sprintf(
"%s --servername %s --remote-expr 'vimplack#handle(\"%s\")'",
$self->{vim}, $self->{server},
encode($self->{encoding} || 'utf8', $str));
}
open(my $f, "$command|");
binmode $f, ':utf8';
my $out = <$f>;
close $f;
my $res = $json->decode($out);
$res->[2][0] = encode_utf8 $res->[2][0] if $res;
$res || [500, ['Content-Type' => 'text/plain'], ['Internal Server Error']];
}
1;
__END__
=head1 NAME
Plack::App::Vim - The Vim App in Plack
=head1 SYNOPSIS
use Plack::Builder;
use Plack::App::Vim;
builder {
mount "/" => Plack::App::Vim->new(server => 'VIM');
};
=head1 DESCRIPTION
Plack::App::Vim allows you to write web application with Vim script.
=head1 AUTHOR
Yasuhiro Matsumoto
=head1 SEE ALSO
L<Plack>
=cut
Plack::App
のアプリケーションハンドラを書いたよ。これを起動するpsgiファイルを用意するよ!app.psgi
#!perl
use lib qw/lib/;
use Plack::Builder;
use Plack::App::Vim;
builder {
mount "/" => Plack::App::Vim->new(server => 'VIM');
};
引数のserver
にはclientserver機能が使えるVimを立ち上げ、そのサーバIDを指定しておく必要があるよ!そしてVim側にハンドラを書くよ!
autoload/vimplack.vim
scriptencoding utf-8
function! vimplack#handle(req)
let req = json#decode(a:req)
let res = [200, {}, ["hello world"]]
return json#encode(res)
endfunction
PSGIプロトコルそのままですね!便利!起動しよう!
# plackup app.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
ブラウザでhttp://localhost:5000
を開こう!やたー!
あとはアプリケーション書き放題ですね!
試しに掲示板書いてみるよ!
autoload/vimplack.vim
scriptencoding utf-8
let s:comments = get(s:, 'comments', [])
function! vimplack#handle(req)
let req = json#decode(a:req)
if req.uri == "/"
let res = [200, {"Content-Type": "text/html; charset=utf-8"}, [""
\."<html>"
\."<link rel='shortcut icon' href='/static/favicon.ico'>"
\."<title>comment board</title>"
\."<body>"
\."<form action='/regist' method='post'>"
\."コメント:<input type='text' name='comment' value='' /><br />"
\."<input type='submit' value='登録' />"
\."</form>"
\.join(map(copy(s:comments), 'html#encodeEntityReference(v:val)'), '<br />')
\."</body>"
\."</html>"
\]]
elseif req.uri == '/regist' && req.method == 'POST'
let params = {}
for _ in map(split(req.content, '&'), 'split(v:val,"=")')
let params[_[0]] = iconv(http#decodeURI(_[1]), 'utf-8', &encoding)
endfor
if has_key(params, 'comment')
call add(s:comments, params['comment'])
endif
let res = [302, {"Location": "/"}, [""]]
else
let res = [404, {}, ["404 Dan Not Found"]]
endif
return json#encode(res)
endfunction
アプリケーションの更新はVimを再起動するかautoload/vimplack.vim
を開いている常態なら
:so %
で行けるよ!知らんかったー
Vim scriptはウェブアプリケーション記述言語やったんやー
mattn/p5-Plack-App-Vim - GitHub
Vim Application Handler for PSGI
https://github.com/mattn/p5-Plack-App-Vim