2011年2月25日金曜日

Emacsのカーソルを変更する cursor-chg.el

カーソルのタイプを状況に応じて変えてくれるelispがあった。これを利用すると、入力中やC-f等での移動中はbarタイプに、アイドル状態にはboxタイプに切り替わる。

入力中/移動中
barになる。
アイドル状態
boxになる。

上記はデフォルト設定の例。形や色を変えたい場合は、curchg-default-cursor-type, curchg-idle-cursor-type, curchg-default-cursor-color 等のカスタマイズ変数を変更する。

2011年2月21日月曜日

CygwinのGnuPGとEmacsでファイルの暗号化

Windowsの場合、ファイルを暗号化する際にEDというフリーソフトを使っていたのだが、先日Emacsを使う方式を知ったのでここに書いておく。

ただ、Emacsで読み書きすることからテキストファイルが中心になる。他の方法と併用、という感じ。

試した環境
Windows7。あらかじめ Cygwin で GnuPG をインストールしておく。Emacsのバージョンは 23.1.1。
暗号化する方法
ファイルを拡張子 "gpg" で保存するだけ。保存の際に聞かれるパスフレーズを入力してあげれば、自動的に暗号化される。
.gpg ファイルを開くときにもパスフレーズを聞かれるので、正しく入力すれば復号される。

2011年2月18日金曜日

VBAで一番下にある入力済みセルを求める

「一番下の入力済みセルの、次のセル」を選択するイディオム。とってもよく使うので記録しておく。

Dim Bottom As Long
Bottom = ActiveSheet.Rows.Count
Cells(Bottom,1).End(xlUp).Offset(1).Select

詳しいことは「Excel VBA Story」ていうサイトに蘊蓄を交えて書いてある。

また、変数宣言なしで

Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Offset(1).Select

…と書く場面のほうが現実的には多い気がする。

2011年2月14日月曜日

Emacs正規表現置換でのLispコード実行

EmacsWiki: Replace Regexp にて、例が十数個紹介されている。

覚えておくべき点は、マッチした部分を文字列とみなす場合は "\&, \0, \1, \2, ..." を、数とみなす場合は "\#&, \#0, \#1, \#2, ..." を使うこと。

1. 文字列とみなす例: Capitalize words
;;置換前
foo
bar
baz
;;置換後
Foo
Bar
Baz
置換のコマンド:
M-x replace-regexp
Replace regexp: \(\w+\)
Replace regexp with: \,(capitalize \1)
2. 数とみなす例: Promote header tags in HTML
;;置換前
<h1>foo</h1>
<h2>bar</h2>
<h3>baz</h3>
;;置換後
<h2>foo</h2>
<h3>bar</h3>
<h4>baz</h4>
置換のコマンド:
M-x replace-regexp
Replace regexp: <\(/?\)h\([0-9]\)>
Replace regexp with: <\1h\,(1+ \#2)>

2011年2月10日木曜日

Emacsのrepeatコマンド

コマンドをリピートするためのコマンドはrepeatrepeat-complex-commandの2種類(ほかにもっとあるかもしれない)。

repeat
直前に実行したコマンドをリピート。単純な例を挙げると、C-f(forward-charコマンド)を押した後にM-x repeatを実行すればC-fが繰り返される。
repeat-complex-command

直前に実行した、"complex command"をリピート。この "complex command" というのはミニバッファへの入力を要求するようなコマンドのこと。

たとえば query-replaceコマンドで文字列置換を行ってから、C-fを何回かタイプしたしたとする。この状態でM-x repeat-complex-commandを実行すると、C-fは無視され、"complex"である query-replaceコマンドが繰り返される。ただし、いきなり実行されるのではなくミニバッファへの入力待ち状態になる。

ちなみに、repeat と repeat-complex-command はそれぞれ C-x zC-x ESC ESC に割り当てられている。さらに C-x z の場合、2回目以降は z だけ打てばよい。

補足:「コマンド」という用語

Emacsにおける「コマンド」というのは M-x ...で実行できる関数。言い換えると (interactive) とともに(defun)されている関数。Emacs Lisp Reference Manual にも書いてある:

21.2 Defining Commands
======================

The special form `interactive' turns a Lisp function into a command.

ある関数がコマンドかどうか判別するために、commandpという関数もある。

(commandp 'isearch-forward)
=> t

(commandp 'string-match)
=> nil

2011年2月7日月曜日

Emacsの正規表現置換で使えるカウンタ、そして省略形

正規表現置換を行うコマンド、つまりreplace-regexpquery-replace-regexpquery-replace-regexp-evalにはカウンタが組み込まれており、replace-countという名前で参照することができる。これを利用すると、「letter: Emacs 番号をふる。query-replace-regexp-eval が便利」で紹介されているような作業が楽に行える。

※参照先の記事ではquery-replace-regexp-evalを使用しているが、Emacsのヘルプを確認したところ"This function is obsolete since 22.1"と書かれていた。だから、新し目のEmacsの場合はquery-replace-regexp-evalの代わりにquery-replace-regexpを使い、置換後の文字列の所に\,を指定するようにする。

(query-replace-regexp-eval REGEXP TO-EXPR &optional DELIMITED START END)

This function is obsolete since 22.1;
for interactive use, use the special `\,' feature of
`query-replace-regexp' instead.

replace-count の省略形: \#

ヘルプに書いてあることだが、replace-count と同じ意味を表すのに \# が使える。

これを利用すると、

aaa
bbb
ccc

1. aaa
2. bbb
3. ccc

へ置換するためのコマンドは次のようになる。

M-x query-replace-regexp[Enter] または M-x replace-regexp[Enter]
^[Enter]
(format "%d. " \,(1+ \#))[Enter]

少しだけキータイプの量が減らせたよ、と。

2011年2月6日日曜日

CGIの環境変数 SERVER_NAME と HTTP_HOST

ほかの誰かが作ったCGIを移行する仕事で、バグの原因になったので記録しておく。

症状

CGIで作成された、お問い合わせフォーム。このCGIが出力するHTMLは、head要素内のscript要素でJavaScriptファイルを参照し、ユーザーインターフェースを制御している。

www有りと無しの二通りのURLでアクセスが可能(http://www.example.com/form/ と http://example.com/form/)。しかし、www有りでアクセスした場合は、JavaScriptが正しく動作しない。

原因と対応

JavaScriptファイルのうち、動的に生成されるファイルにバグがあった。動的に生成される部分というのは XMLHTTPオブジェクトがアクセスするURLであり、環境変数SERVER_NAMEを使って生成されていた。次のように。

$url = "\/\/" . $ENV{'SERVER_NAME'} . $service_path . '?';
 $script =~ s/<url>/$url/g;  # $scriptの中身はJSのテンプレ。それを置換している。
 print "Pragma: no-cache\n";
 print "Cache-Control: no-cache\n";
 print "Content-type: text/plain; charset=UTF-8\n\n";
 print $script;

SERVER_NAMEの値はWebサーバーの設定に依存してしまうため、JavaScriptファイルを取得するときのリクエストが www.example.com なのに対して、XMLHTTPオブジェクトは example.com を参照してしまうという矛盾が生じた。これはクロスドメイン制限(cross-domain restrictions)に抵触、あるいは同一生成元ポリシー(same-origin policy)に反してしまう。よって、次のように修正すればOK。

$url = "\/\/" . $ENV{'HTTP_HOST'} . $service_path . '?';  # HTTP_HOST に変更
 $script =~ s/<url>/$url/g;
  (略)

SERVER_NAME と HTTP_HOST

CGIの環境変数のうち、SERVER_NAME と HTTP_HOST はよく似ていているのだが、意味が異なる。

これらの意味は、CGIに環境変数を渡しているApacheのドキュメントに書いてあるはずなのだが、いまいちみつからない。とりあえず、mod_rewriteの中に説明があったのでそこを引用しておく。

mod_rewrite - Apache HTTP Server
  • HTTP headers:
    • (略)
    • HTTP_HOST
    • (略)
  • server internals:
    • (略)
    • SERVER_NAME
    • (略)

These variables all correspond to the similarly named HTTP MIME-headers, C variables of the Apache server or struct tm fields of the Unix system. Most are documented elsewhere in the Manual or in the CGI specification.

SERVER_NAME and SERVER_PORT depend on the values of UseCanonicalName and UseCanonicalPhysicalPort respectively.

要するに、HTTP_HOSTのほうは"HTTP headers"、つまりブラウザからのリクエストヘッダに含まれるHOSTを表し、SERVER_NAMEのほうは"server interanals"、つまりApacheサーバー内の設定ファイル等に記述されているSERVER_NAMEを表すということ。したがって、HTTP_HOSTを扱うときはセキュリティ的に注意を要する、なんて話題も避けられない(変な文字列が送られてくる可能性があるから、内容をチェックしたりエスケープしたりする)。

このあたりの話は、Apacheから環境を引き継ぐプロセス全般に通用する話だから、PerlだけでなくPHPやRuby, Javaサーブレットなどを作るときにも頭に入っているとよいかもしれない。あと、mod_rewrite の条件を書く時にも。

Custom javascript dialog boxes

Custom JavaScript Dialog Boxes - Web Development Blog は、他のライブラリに依存しておらず、jsとcssを組み込むだけで手軽に使えるカスタムダイアログボックス。IE5.5 や IE6 でも動作する。

デザイン面ではパステルカラーと「×」や「?」などの背景画像を必要十分な程度に使ってあり、シンプル。そのせいか現在でも陳腐な感じがしない。

2008年4月以降に少しずつ更新が行われたようで、27 November 2009の日付でバージョン1.7が公開されている(Upgrade to Dialog Box Available)。

このバージョンのサンプルを見る限り、以下のオプションが指定できる。

  • ダイアログのスタイル6種類:Error, Warning, Success, Prompt, Message, Query
  • モーダル / ノンモーダル
  • auto hide(時間を指定して自動的に消去)
  • ボタンあり / なし
  • ダイアログボックスのサイズ指定 / 自動調整

ダイアログの例

モーダル(Error)

ノンモーダル(Warning)

モーダル+ボタンあり+サイズ指定(Success)

モーダル+ボタンあり+サイズ自動(Prompt)