ひがきの日記

2009-03-18

comment-dwim のその後

昨日のエントリの comment-dwim は、あのままだと rcodetools とぶつかって、ruby-mode で => マークが付かなくなってしまう。

defadvice の NAME を変えれば OK ... と思ったら、それに気付くより先に lispxmpバージョンアップされて、comment-dwim もサポートされていた。

2009-03-17

xmp meets elisp

早速 scratch バッファで試してみた。

(require 'lispxmp)
lispxmp

(+ 3 4)    ; => 
Error in eval: (void-variable lispxmp)

2 行目 (require の結果) まで評価しようとしてる _| ̄|○

eval-last-sexp とか eval-region の xmp 版があればいいのかも知れない。

でも、それを作れるほど elisp に詳しくないので、ruby-scratch の要領で逃げてみた。

(add-hook 'emacs-lisp-mode-hook
	  (lambda ()
	    (define-key emacs-lisp-mode-map "\C-c\C-d" 'lispxmp)))
(defadvice comment-dwim (around rct-hack activate)
  "If comment-dwim is successively called, add => mark."
  (if (and (eq major-mode 'emacs-lisp-mode)
           (eq last-command 'comment-dwim))
      (insert " =>")
    ad-do-it))

comment-dwim の処理は rcodetools.el から、そのままコピった。
なるほど、こんなことできるんだ。

これで emacs-lisp-mode のバッファにいれば xmp し放題。
もう scratch バッファはいらない (かも?)

2008-10-30

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 が増えたときのためだと思えば ……

2008-08-30

世界のナベアツ

Rubyist SNS で世界のナベアツが話題になっていたので、emacs lisp で作ってたみた。

(defun nabep (n &optional base)
  "n は あほ になる数か?"
  (or base (setq base 3))
  (cond
   ((= (mod n base) 0)  t)
   ((string-match (format "%d" base) (format "%d" n))  t)
   (t  nil)))

(defun count-of-nabe (n)
  "ナベアツに n を読んでもらう"
  (cond
   ((and (nabep n)
	 (= (mod n 5) 0)) (format "%d あほ犬" n))
   ((= (mod n 5) 0)       (format "%d 犬" n))
   ((nabep n)             (format "%d あほ" n))
   (t                     (format "%d" n))))

(defun nabe-of-the-world (n)
  "ナベアツが 1 〜 n まで読んだ結果をリストで返す"
  (let (nabe)
    (while (> n 0)
      (setq nabe (cons (count-of-nabe n) nabe))
      (setq n (- n 1)))
    nabe))

普通の FizzBuzz と違って、3 の処理がスッキリ行かない。

動かしてみる。

(let ((omoro (nabe-of-the-world 40)))
  (while omoro
    (message (car omoro))
    (sit-for 1)
    (setq omoro (cdr omoro))))

メッセージバッファの内容。

1
2
3 あほ
4
5 犬
6 あほ
7
8
9 あほ
10 犬
11
12 あほ
13 あほ
14
15 あほ犬
16
17
18 あほ
19
20 犬
21 あほ
22
23 あほ
24 あほ
25 犬
26
27 あほ
28
29
30 あほ犬
31 あほ
32 あほ
33 あほ
34 あほ
35 あほ犬
36 あほ
37 あほ
38 あほ
39 あほ
40 犬