magic comment を自動的に付ける
Ruby1.9 で漢字を扱うには、magic comment で文字コードを指定しないといけない。
この面倒な作業を自動的にやってくれる Emacs の設定がある。
1 ヶ月以上 何不自由なく使っていたんだけど、文字コード以外の magic comment が使えないことに気がついた。
何か設定していても消されてしまう。
拡張子を付けずにスクリプトを書いて chmod して使うことが多いので、普段から -*- ruby -*- とか書いている。困った。
Emacs の info を斜め読みして、いろいろ試してみた結果、以下のことが分かった。
- 名前だけを書くと major mode の設定になる。
# -*- ruby -*-
- 明示的に major mode の設定であることを宣言できる。
# -*- mode: ruby; -*-
- magic comment は複数行書けない。
- 先勝ち
# -*- coding: utf-8; -*- # -*- mode: ruby; -*- # この行は無効
- 複数の設定は 1 行にまとめて書く。
# -*- coding: utf-8; mode: ruby; -*-
最終的に、この形式にしたい。
Lisp は苦手だけど、やってみた。
(defun ruby-coding-from-buffer-file-coding-system () (let ((coding-system (symbol-name buffer-file-coding-system))) (cond ((string-match "japanese-iso-8bit\\|euc-j" coding-system) "euc-jp") ((string-match "shift.jis\\|sjis\\|cp932" coding-system) "shift_jis") ((string-match "utf-8" coding-system) "utf-8")))) (defun ruby-normalize-major-mode () (goto-char (point-at-bol)) (or (re-search-forward ":" (point-at-eol) t) (if (re-search-forward "^#\\s *-\\*-\\s *\\(\\S +\\)\\s *-\\*-\\s *$" (point-at-eol) t) (replace-match (format "# -*- mode: %s; -*-" (buffer-substring (match-beginning 1) (match-end 1))))))) (defun ruby-remove-coding () (goto-char (point-at-bol)) (if (re-search-forward "coding\\s *:\\s *[^ ;]+\\s *;?\\s *" (point-at-eol) t) (delete-region (match-beginning 0) (match-end 0)))) (defun ruby-insert-coding () (goto-char (point-at-bol)) (if (re-search-forward "^#\\s *-\\*-\\s *" (point-at-eol) t) (replace-match (format "# -*- coding: %s; " ruby-coding-system)))) (defun ruby-modify-magic-comment () (ruby-normalize-major-mode) (ruby-remove-coding) (ruby-insert-coding)) (defun ruby-set-coding-system-in-magic-comment () (save-excursion (goto-char 1) (when (looking-at "^#!") (forward-line 1)) (if (re-search-forward "^#.*-\\*-" (point-at-eol) t) (ruby-modify-magic-comment) (insert (format "# -*- coding: %s; -*-\n" ruby-coding-system))))) (defun ruby-set-coding-system-in-magic-comment-if-needed () (let ((ruby-coding-system (ruby-coding-from-buffer-file-coding-system))) (and ruby-coding-system (eq major-mode 'ruby-mode) (find-multibyte-characters (point-min) (point-max) 1) (ruby-set-coding-system-in-magic-comment)))) (add-hook 'before-save-hook 'ruby-set-coding-system-in-magic-comment-if-needed)
空白の許される位置が、これで当ってるのか分からんけど、なんとか動いた。
ところで、ちゃんと Emacs の info を読むと、interpreter-mode-alist を設定すれば、#! 行に書いたプログラム名を基に major mode を設定できるって書いてあった。
magic comment は不要。_| ̄|○
こんな感じかな。
(let ((mode '(("ruby" . ruby-mode) ("ruby19" . ruby-mode)))) (while mode (setq interpreter-mode-alist (cons (car mode) interpreter-mode-alist)) (setq mode (cdr mode))))
ま、将来 magic comment が増えたときのためだと思えば ……