[ 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%
雛形で定義したクラス、宣言した外部関数の実装を定義しています。