[ C++で開発 ]
Emacsには、C++-modeがあります。Emacsは、以下の表に示すようにファイル拡張子によって編集モードを判断しています。
拡張子 | モード | 拡張子 | モード |
---|---|---|---|
.h | c-mode | .c | c-mode |
.hh | c++-mode | .cc | c++-mode |
.hpp | .cpp | ||
.H | .C | ||
.hxx | .cxx | ||
.h++ | .c++ |
この場合、ヘッダファイルを拡張子'.h'としているとc-modeになってしまいます。c++-modeにする設定をEmacsに行います。
M-x c++-mode RET
// -*- C++ -*-
;; C++ ; ヘッダファイル(.h)をc++モードで開く (setq auto-mode-alist (append '(("\\.h$" . c++-mode)) auto-mode-alist))
ヘッダファイルを新規に作成する場合、auto-insert-modeを有効にしておくと、ファイル名に応じたインクルードガードを生成します。
M-x auto-insert-mode [RET] としてから、C-x C-fで新規ファイル(例:Hello.h)を開くと、
#ifndef HELLO_H #define HELLO_H #endif |
となります。
autoinsertには、ユーザで定義した雛形を適用する機能もあります。あらかじめ用意しておいたヘッダファイル、ソースファイルの雛形に、新規作成するファイル名などを展開します。
まず、拡張子.hおよび.cppを持つファイルを新規作成するときに、それぞれの雛形ファイルを設定します。
(require 'autoinsert) ;; テンプレート格納用ディレクトリ (setq auto-insert-directory "~/.emacs.d/insert/") ;; ファイル拡張子とテンプレートの対応 (setq auto-insert-alist (append '( ("\\.cpp$" . ["template.cpp" my-template]) ("\\.h$" . ["template.h" my-template]) ) auto-insert-alist)) (add-hook 'find-file-hooks 'auto-insert)
ここでは、ホームディレクトリの .emacs.d/insert/の中に、拡張子.cpp用の雛形ファイルtemplate.cppと拡張子.h用の雛形ファイルtemplate.hを置いた設定を行っています。
(require 'cl) (defvar template-replacements-alists '(("%file%" . (lambda () (file-name-nondirectory (buffer-file-name)))) ("%file-without-ext%" . (lambda () (setq file-without-ext (file-name-sans-extension (file-name-nondirectory (buffer-file-name)))))) ("%namespace%" . (lambda () (setq namespace (read-from-minibuffer "namespace: ")))) ("%include%" . (lambda () (cond ((string= namespace "") (concat "\"" file-without-ext ".h\"")) (t (concat "<" (replace-regexp-in-string "::" "/" namespace) "/" file-without-ext ".h>"))))) ("%include-guard%" . (lambda () (format "%s_H_" (upcase (concat (replace-regexp-in-string "::" "_" namespace) (unless (string= namespace "") "_") file-without-ext))))) ("%name%" . user-full-name) ("%mail%" . (lambda () (identity user-mail-address))) ("%cyear%" . (lambda () (substring (current-time-string) -4))) ("%bdesc%" . (lambda () (read-from-minibuffer "Brief description: "))) ("%namespace-open%" . (lambda () (cond ((string= namespace "") "") (t (progn (setq namespace-list (split-string namespace "::")) (setq namespace-text "") (while namespace-list (setq namespace-text (concat namespace-text "namespace " (car namespace-list) " {\n")) (setq namespace-list (cdr namespace-list)) ) (eval namespace-text)))))) ("%namespace-close%" . (lambda () (cond ((string= namespace "") "") (t (progn (setq namespace-list (reverse (split-string namespace "::"))) (setq namespace-text "") (while namespace-list (setq namespace-text (concat namespace-text "} // " (car namespace-list) "\n")) (setq namespace-list (cdr namespace-list)) ) (eval namespace-text)))))) ))
ここでは、%file% をはじめとしたマクロ定義をしています。これらマクロを雛形ファイルに記述すると、新規ファイル作成時にマクロが実体に展開されます。
(defun my-template () (time-stamp) (mapc #'(lambda(c) (progn (goto-char (point-min)) (replace-string (car c) (funcall (cdr c)) nil))) template-replacements-alists) (goto-char (point-max)) (message "done.")) (add-hook 'find-file-not-found-hooks 'auto-insert)
/** * %file% - %bdesc% * * Copyright (c) 2009 TAKAHASHI,Toru <torutk@gmail.com> * * */ #ifndef %include-guard% #define %include-guard% #include <iosfwd> %namespace-open% class %file-without-ext% { public: /// Default constructor %file-without-ext%(); /// Destructor ~%file-without-ext%(); /// Copy constructor %file-without-ext%(const %file-without-ext%& rhs); /// Assignment operator %file-without-ext%& operator=(const %file-without-ext%& rhs); }; /// stream output operator std::ostream& operator<<(std::ostream& lhs, const %file-without-ext%& rhs); %namespace-close% #endif /* %include-guard% */
ファイル先頭コメント、インクルードガード、名前空間、クラスの雛形定義を行っています。
クラスの雛形定義では、デフォルトコンストラクタ、デストラクタ、コピーコンストラクタ、代入演算子、そして外部関数でクラスのストリーム出力を宣言しています。
/** * %file% - %bdesc% * * Copyright (c) 2009 TAKAHASHI,Toru <torutk@gmail.com> * * */ #include %include% #include <ostream> %namespace-open% /** * Default constructor */ %file-without-ext%::%file-without-ext%() { } /** * Default destructor */ %file-without-ext%::~%file-without-ext%() { } /** * Copy constructor */ %file-without-ext%::%file-without-ext%(const %file-without-ext%& rhs) { } /** * Assignment operator */ %file-without-ext%& %file-without-ext%::operator=(const %file-without-ext%& rhs) { if (this != &rhs) { // TODO: implement copy } return *this; } /** * stream output operator */ std::ostream& operator<<(std::ostream& lhs, const %file-without-ext%& rhs) { lhs << "%namespace%::%file-without-ext%{" << // TODO: implement out stream of member data "}"; return lhs; } %namespace-close%
雛形で定義したクラス、宣言した外部関数の実装を定義しています。