Emacsでインデントとスペースをいいかんじに(align-regexp, my-set-indent-tabs-mode)
githubをうろうろしていたらmoriyamahiroshiさんの.emacsに出会いました。
とても勉強になる内容だったのですが、そのなかに、(my-set-indent-tabs-mode)というものがあり、これを使うと、いいかんじにバッファ先頭のインデントを見て、バッファごとにインデントスタイルを設定できるようでした。
これで、インデントスタイルはメジャーモードごとに決まっていることが多い片方で、フレームワークごとにコーディング規約があったりして、悩ましかったのですが、これは空気を読んでくれるので、なかなかいいかんじでした。
関係部分だけ以下に抜きださせていただきます。
(if (not (fboundp 'defun-if-undefined))
    (defmacro defun-if-undefined (name &rest rest)
      `(unless (fboundp (quote ,name))
         (defun ,name ,@rest))))
(defun-if-undefined inside-string-or-comment-p ()
  (let ((state (parse-partial-sexp (point-min) (point))))
    (or (nth 3 state) (nth 4 state))))
(defun-if-undefined re-search-forward-without-string-and-comments (&rest args)
	(let ((value (apply #'re-search-forward args)))
		(if (and value (inside-string-or-comment-p))
				(apply #'re-search-forward-without-string-and-comments args)
			value)))
(defun my-buffer-indent-tabs-code-p (&optional buffer)
  "Check first indent char."
  (let ((buffer (or buffer (current-buffer))))
    (with-current-buffer buffer
      (save-excursion
        (save-restriction
          (widen)
          (goto-char (point-min))
          (and (re-search-forward-without-string-and-comments "^[ \t]"
                                                              (point-max) t)
               (string= (match-string 0) "\t")))))))
(defun my-set-indent-tabs-mode ()
  (setq indent-tabs-mode (my-buffer-indent-tabs-code-p)))
(add-hook 'emacs-lisp-mode-hook #'my-set-indent-tabs-mode)
(add-hook 'java-mode-hook #'my-set-indent-tabs-mode)
(add-hook 'html-mode-hook #'my-set-indent-tabs-mode)
(add-hook 'perl-mode-hook #'my-set-indent-tabs-mode)
(add-hook 'python-mode-hook #'my-set-indent-tabs-mode)
(add-hook 'ruby-mode-hook #'my-set-indent-tabs-mode)
(add-hook 'sh-mode-hook #'my-set-indent-tabs-mode)
以下は、ついでに僕の設定です。
(add-hook 'php-mode-hook
          '(lambda()
             (setq tab-width 2)
             (setq c-basic-offset 2)
             (my-set-indent-tabs-mode)))
align-regexp
Emacsのalign-regexpは、たいへん便利で、
$scfldpath = $scfldbase.'modules/'.$name.DS; $migrationpath = $scfldpath.'migrations/'; $configpath = $scfldpath.'config/'; $viewspath = $scfldpath.'views/'.$name;
こんなのを
M-x align-regexp RET = RET
で、一瞬でこんなのしてくれます。
$scfldpath = $scfldbase.'modules/'.$name.DS; $migrationpath = $scfldpath.'migrations/'; $configpath = $scfldpath.'config/'; $viewspath = $scfldpath.'views/'.$name;
で、ちょっと悩ましいのが、fuelphpのコーディング規約みたいなやつ。
すべてのインデントはスペースではなくタブを使用すべきです。
しかし、インデント後の整形はタブではなくスペースを使用します。
Emacsのalign-regexpとしては、indent-tabs-modeの値を見て、インデント後の整形も行うので、indent-tabs-modeがtなら、インデント後の整形も
$scfldpath = $scfldbase.'modules/'.$name.DS; $migrationpath = $scfldpath.'migrations/'; $configpath = $scfldpath.'config/'; $viewspath = $scfldpath.'views/'.$name;
となっちゃうので、fuelphpのコーディング規約から外れちゃう。これをうまいこと解決するのが、以下のadviceです。
(defadvice align-regexp (around advise-align-regexp activate) "Let align-regexp indent by spaces." (when indent-tabs-mode (setq indent-tabs-mode nil)) ad-do-it (my-set-indent-tabs-mode))
moriyamahiroshiさんの(my-set-indent-tabs-mode)が空気も読んでくれるので、快適です。
ちなみにphpでalign-regexpするには、てつじんにっきさんの「[php][Emacs] Emacsのphp-modeでalignする」の設定も必要です。Emacs24でもいけます。
ジャンル: Emacs

