2014年11月7日金曜日

インクルードガードをemacs lispで自動生成する

Goに移るかとおもいきや、普段はC++を書くこと多いです。 C++を書いていると、しょっちゅうインクルードガードを書くことになります。 今日はインクルードガードを簡単にするemacs lispを紹介。

「#pragma onceは甘え」「あれは実はダメ」とかあって、結局#ifdefに落ち着くのですが、#defineする変数名はどうしてますか? ソースディレクトリからのフルパスを使うというのをJubatus含めて、以前は使っていたのですが、pepshisoさんに「ソースの位置が変わると全部書き直しなので、uuidの方がよい」という、至極もっともな指摘をされました。 毎回uuidを手で入力すると日が暮れてしまいそうになるので、emacs lispを作りました。 大変便利です。

それはそうと、emacs lispはライブラリが本当に大変使いにくくて、発狂しそうになりますね。 外部コマンドに全部書いて、それを呼べばいい気がしてきました・・・。

(defun replace-regexp-case-ignore (pat replace str)
  (let ((def-case case-fold-search))
    (setq case-fold-search nil)
    (let ((res (replace-regexp-in-string pat replace str)))
      (setq case-fold-search def-case)
      res)))
(defun make-capital-var (s)
  (setq case-fold-search nil)
  (concat
   (upcase
    (replace-regexp-case-ignore
     "[_\\.]" "_" 
     (replace-regexp-case-ignore "\\([a-z]\\)\\([A-Z]\\)" "\\1_\\2" s)))
   "_"))
(defun insert-include (f)
  (interactive "b")
  (let* ((uuid (shell-command-to-string "uuidgen"))
         (no_new_line (replace-regexp-in-string "\n" "" uuid))
         (id (replace-regexp-in-string "-" "_" no_new_line))
         (var (make-capital-var (concat f "_" id))))
    (save-excursion
      (beginning-of-buffer)
      (insert (concat "#ifndef " var "\n"))
      (insert (concat "#define " var "\n")))
    (save-excursion
      (end-of-buffer)
      (insert (concat "#endif  // " var "\n")))))

私は、これを"C-c C-i"に割り当てて使っています。

(add-hook
 'c++-mode-hook
 (lambda ()
   (local-set-key (kbd "C-c C-i") 'insert-include)))

0 件のコメント:

コメントを投稿