ブログが続かないわけ

この日記のはてなブックマーク数
Webエンジニアが思うこと by junichiro on Facebook

Lisp はわからないけどEmacs で選択範囲に対してごにょごにょしたい

このエントリーを含むはてなブックマーク hateb
Emacs を使っていると、選択範囲に対してなにか処理したいということはよくある。それなのに、Lisp がわからないからということで、あきらめてしまってはいないだろうか。Emacs でいろいろなことをやるにはLisp は必須だけど、「選択範囲に対して何か処理を施す」というだけであれば、Lisp はほとんど知らなくても実現できてしまう。

要は、選択範囲を引数として自作のスクリプトに渡して、それの戻り値を受取ることができればいいわけだ。選択範囲をスクリプトに渡すという部分はLisp で書かなければいけないんだけど、そこはここで示すテンプレートをコピーして使うだけで問題ない。

それでは、例として、選択範囲の小文字を全て大文字に変換するというものを作ってみよう。
(これ自体はEmacs の標準のコマンドでできるけど、ここは例としてこれを作る)

まず、雛形となるLisp のテンプレート

my-func.el
(defun [コマンド名] ()
"[コマンドの概要]"
(interactive)
(save-excursion
(shell-command-on-region (point) (mark) "[処理したい内容を書いたスクリプトのパス]" nil t)))
これで準備は整った。編集しなければいけないのは3カ所だけ
  • [コマンド名]
  • [コマンドの概要]
  • [処理したい内容を書いたスクリプトのパス]

例えば、今回作成する大文字小文字変換の関数をこう定義してみることにしよう。
  • [コマンド名] = my-uc
  • [コマンドの概要] = Returns an uppercased version
  • [処理したい内容を書いたスクリプトのパス] = /Users/junichiro/bin/my_uc.pl

そうすると、my-func.el はこうなる。
(defun my-uc ()
"Returns an uppercased version"
(interactive)
(save-excursion
(shell-command-on-region (point) (mark) "/Users/junichiro/bin/my_uc.pl" nil t)))

さて、実際に変換の処理を行うスクリプトはどうかけばいいんだろう。
ポイントはどうやって選択範囲が渡されるかということと、どうやってEmacs に値を返すかの2点だけだ。
結論から言うと、値は標準入力として渡され、標準出力すれば返すことができる。
それさえわかればあとはなんてことはない。
my_uc.pl
#!/usr/bin/perl

use strict;
use warnings;

my $text;
{
local $/;
$text = <>;
}
print uc $text;
perl の例で恐縮だが、$text に標準入力の値を渡している(改行も含めて)。
※uc は引数で与えられた値をすべて大文字に変換するperl の関数。

これで、my_uc.pl に実行権限を与えて、さらにmy-func.el をLisp のパスが通ったところに置けばmy-uc という関数が使えるようになる。Emacs の中で適当に範囲を選択して、M-x my-uc と実行してやれば、選択範囲に含まれる小文字が全部大文字になるのがわかるだろう。

やり方はここまでだが、具体例として僕が使っている便利な「選択範囲処理系スクリプト」を2つほど紹介しよう。
ひとつは、選択範囲のURL をそのサイトのタイトル付きで<a href="[URL]">[title]</a>という形式に変換してくれるもの。
もうひとつは、選択範囲をMarkdown 記法と解釈して、HTML に変換してくれるもの。

ちなみに、my-func にはいくつでも関数の定義が書けるので、こんな感じになる。
; link a_href for blog func;
(defun create-link-region ()
"Run create link on the current region."
(interactive)
(save-excursion
(shell-command-on-region (point) (mark) "/Users/junichiro/bin/create_link.pl" nil t)))

; text markdown for blog func;
(defun markdown-region ()
"Run markdown format on the current region."
(interactive)
(save-excursion
(shell-command-on-region (point) (mark) "/Users/junichiro/bin//markdown.pl" nil t)))
my-func の方は雛形を少し改変するだけなので、簡単だ。
create_link.pl
#!/usr/bin/perl

use strict;
use warnings;
use URI::Title qw(title);
binmode(STDOUT, ":utf8");

my $href = <>;
chomp($href);
my $title = title($href) || '';
print '<a href="', $href, '">', $title, '</a>';
これは1行しか取り込む必要がないので、標準入力の取込み方が先ほどの例よりシンプルになっている。
(my $href = <>; の部分)

これをたとえば、「http://en.yummy.stripper.jp」を選択して実行(M-x create-link-region)すると、
「<a href="http://en.yummy.stripper.jp">ブログが続かないわけ</a>」となる。

markdown.pl
#!/usr/bin/perl

use strict;
use warnings;
use Text::Markdown 'markdown';

my $text;
{
local $/;
$text = <>;
}
my $html = markdown($text);
print $html;
この2つの例で見ればわかるように、CPAN モジュールを活用している。このように、外部スクリプトに処理させることにより、普段自分が使い慣れている言語で書けるとともに、その言語のバックエンドにある膨大なモジュールの力を借りることができるというのも大きい。
この記事のトラックバックURL
http://en.yummy.stripper.jp/trackback/1211312
トラックバック
URI::Title が動かなくなったので代替手段を探った
Emacs でブログを書くときの補助ツールとして、選択したurl をそのページのタイトルつきで、リンクのタグに変換するPerlスクリプトを使っていたのですが、いつからか動かなくなってしまっていました。 ちなみに、Lisp がわからなくても選択範囲に対してPerl などを
| ブログが続かないわけ | 2011/02/24 6:31 PM |
Meadow のリージョンにPerlを仕掛ける
Lisp はわからないけどEmacs で選択範囲に対してごにょごにょしたいを読んでこれに書かれてることをMeadowでやろうと思った。 以下はMeadowのための設定。 シェルは cygwin を使用。 (1) ホームディ...
| title variable | 2011/10/10 12:35 AM |
コメント









関連情報