Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2008-02-09

EmacsのCommon Lispインデント

| 04:02 | EmacsのCommon Lispインデント - わだばLisperになる を含むブックマーク はてなブックマーク - EmacsのCommon Lispインデント - わだばLisperになる

EmacsでCommon Lispのコードを編集する時には、cl-indentを使用しているのですが、割とprogと、loopの時に思ったようにインデントしてくれないので、色々調整してみているのですが、どうも簡単な方法がみつからず結局、cl-indent.elの関数を変更することにしてみました。とはいえ、後で自作の関数を読み込みさせるだけですが…。

どういう風にインデントされて欲しいかというと、

(loop :for i = 0 :then (incf i)
      :if (< 10 i)
	:do (print "End.")
            (return res)
      :else
	:collect i :into res
      :end)

(prog (foo)
      (setq foo '(foo bar baz))
   L  (cond ((endp foo) (return)))
      (pop foo)
      (go L))

みたいな感じです。まあ、いまどきPROG使う人もいないと思うんですが、PROGの時はずらっと括弧の位置が揃ってると気持ち良いんですよね。

LOOPはとりあえず、2行目以降、7カラム目に揃ってれば良いんですが、doのときに、2つ字下げしてるのをLispマシンのマニュアルで発見したので、そういう風なのも良いかなと。

とりあえず、無理矢理な感じですが、設定をでっち上げました。

;; Common Lisp - インデント関係の設定
;; tagbody / prog
(setq lisp-prog-tag-indentation 3
      lisp-prog-tag-body-indentation 6
      lisp-tag-indentation 1
      lisp-tag-body-indentation 3)

;; lisp-indent-tagbodyをほんのちょっと改造
(defun lisp-indent-prog (path state indent-point sexp-column normal-indent)
  (if (not (null (cdr path)))
      normal-indent
    (save-excursion
      (goto-char indent-point)
      (beginning-of-line)
      (skip-chars-forward " \t")
      (list (cond ((looking-at "\\sw\\|\\s_")
                   ;; a tagbody tag
                   (+ sexp-column lisp-prog-tag-indentation))
                  ((integerp lisp-prog-tag-body-indentation)
                   (+ sexp-column lisp-prog-tag-body-indentation))
                  ((eq lisp-prog-tag-body-indentation 't)
                   (condition-case ()
                       (progn (backward-sexp 1) (current-column))
                     (error (1+ sexp-column))))
                  (t (+ sexp-column lisp-body-indent)))
            (elt state 1)))))

(put 'prog 'common-lisp-indent-function 'lisp-indent-prog)

;; loop
(defun common-lisp-loop-part-indentation (indent-point state)
  "Compute the indentation of loop form constituents."
  (let* ((loop-indentation (save-excursion
			     (goto-char (elt state 1))
			     (current-column))))
    (goto-char indent-point)
    (beginning-of-line)
    (cond ((looking-at "^\\s-*:?\\(do\\|collect\\)\\(\\s-\\|\(\\)\\(\\s-*\\|;\\)")
	   (+ loop-indentation lisp-loop-keyword-indentation 2))
	  ((looking-at "^\\s-*\\(:?\\sw+\\|;\\)")
	   (+ loop-indentation lisp-loop-keyword-indentation))
	  (t
	   (+ loop-indentation lisp-loop-forms-indentation))))))

(setq lisp-loop-forms-indentation 6
      lisp-loop-keyword-indentation 6
      loop-indentation 6)

(put 'loop 'common-lisp-indent-function 'common-lisp-loop-part-indentation)

;; (cl-indent 名前 手本)
(defun cl-indent (sym indent)
  (put sym 'common-lisp-indent-function
       (if (symbolp indent)
	   (get indent 'common-lisp-indent-function)
	 indent)))

(cl-indent 'iterate 'let)
(cl-indent 'collect 'progn)
(cl-indent 'mapping 'let)
(cl-indent 'define-syntax 'let)

PROGは、まあまあこれでできたのですが、LOOPが

(loop :for i = 0 :then (incf i)
      :if (< 10 i)
	:do (print "End.")
      (return res)
      :else
	:collect i :into res
      :end)

のようになるので、doの範囲を自分で字下げしないといけないという…。あと、lisp-indent-lineでは字下げしてくれますが、indent-regionとか、indent-sexpでは、doとかcollectは字下げしてくれないので、これも面倒だという。

何か簡単に調整してくれるEmacs Lispとか配布されてないんですかねー。

皆さんはどうされているのでしょう。