`(Hello ,world)

ツッコミ、添削大歓迎です。いろいろ教えてください。

2010-09-14

xyzzyでArcのifのインデント

ArcのifはLisp/Schemeのcondの括弧が少ない版といった感じで

(if pred1
    exp1
  pred2
    exp2
  ...
    ...
  else-value)

という風に複数の条件を続けて書ける。このオートインデントをxyzzyで実現しようと思うと元々のlispmodeのインデント計算のままではうまくいかない。lispmodeのインデント計算はifなどのシンボルによって、引数の何個目までは*lisp-body-indent*の2倍、それ以降は*lisp-body-indent*、となってしまっていて融通が利かない。

そこで、シンボルに関数を設定できるようにする。lispmode.lのcalc-lisp-indent関数内でシンボルのlisp-indent-hookに設定された値の型が関数だったら、その関数を呼び出してインデントを決定するようにする:

(defun calc-lisp-indent (opoint)
  ...
                     (cond ((numberp method)
                            ...)

                           ;追加
                           ((functionp method)
                            (let ((count -1))
                              (while (< (point) opoint)  ; 何個目の引数かを数える
                                (skip-white-forward)
                                (setq count (+ count 1))
                                (or (forward-sexp 1 t)
                                    (return)))
                              (+ column -1
                                 (funcall method count))))

                           (method
                            ...

こうして、ifのlisp-indent-hookに関数を設定する:

(setf (get 'if 'lisp-indent-hook)
      #'(lambda (count)
          (if (zerop (mod count 2))
              *lisp-body-indent*
            (* *lisp-body-indent* 2))))

でOK。

注意点は、M-x byte-compile-file で lispmode.l をバイトコンパイルするだけじゃなく、いったんxyzzy.wxpを削除しないと反映されなくてハマった。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20100914