;;; qpid-c++-mode.el --- Qpid specific c++-mode customizations. ;; ;; Licensed to the Apache Software Foundation (ASF) under one or more ;; contributor license agreements. See the NOTICE file distributed ;; with this work for additional information regarding copyright ;; ownership. The ASF licenses this file to you under the Apache ;; License, Version 2.0 (the * "License") ; you may not use this file ;; except in compliance with the License. You may obtain a copy of ;; the License at ;; ;; http://www.apache.org/licenses/LICENSE-2.0 ;; ;; Unless required by applicable law or agreed to in writing, software ;; distributed under the License is distributed on an "AS IS" BASIS, ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ;; implied. See the License for the specific language governing ;; permissions and limitations under the License. ;; ;;;===================================================================== ;;; Commentary: ;; ;; C++ customizations to make c++ mode follow the Qpid style guidelines, ;; along with some other handy functions to generate initial starting point ;; .h and .cpp files etc. ;; ;; I have this in my .emacs: ;; (add-to-list 'auto-mode-alist '("\\.h$" . c++-mode)) ;; (require 'qpid-c++-mode) ;; ;; Written by Alan Conway: aconway@redhat.com ;; ;; For latest version, check ;; http://svn.apache.org/repos/asf/qpid/trunk/qpid/cpp/etc/emacs/qpid-c++-mode.el ;; (require 'cc-mode) ;; Increment the version number if you change this file. (defconst qpid-c++-version "1.00" "Qpid C++ style support version number.") (defun qpid-c++-version () "Echo the current version of qpid-c++-mode in the minibuffer." (interactive) (message "Using qpid-c++-mode version %s" qpid-c++-version)) (defun qpid-c++-mode () "Qpid C++ mode customizations" (c-add-style "qpid-c++" '("gnu" (indent-tabs-mode . nil) (c-basic-offset . 4) (c-offsets-alist . ((statement-case-intro . *) (statement-case-open . *) (substatement-open . 0) (case-label . *) (access-label . /) (friend . /) (arglist-intro . +) (arglist-cont . 0) (arglist-close . 0) (inline-open . 0) (brace-list-open . 0) (innamespace . 0) ))) ) (c-set-style "qpid-c++") (setq c-hungry-delete-key t) (setq c-tab-always-indent t) (setq c-hanging-braces-alist '((substatement-open . (after)) (extern-lang-open . (after)) (defun-open . (after)) (class-open . (after)) (block-open . (after)) (inline-open . (after)) (defun-block-intro . (after)) (inclass . (after)) (topmost-intro . (after)) (brace-list-open) (brace-list-close) (namespace-open) )) (setq c-hanging-colons-alist '((member-init-intro) (inher-intro) (case-label) (label) (access-label))) (setq mode-name "Qpid C++")) (defun copyright () (interactive) (insert "/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * \"License\"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */")) (defun indent-buffer () (interactive) (indent-region (point-min) (point-max) nil)) (defun path-to-namespace (path) (replace-regexp-in-string "/" "::" (replace-regexp-in-string "/$" "" path))) (defun src-subpath (path) (if (string-match "/src/\\(.*\\)$" path) (match-string 1 path) "")) (defun namespace-for-file (file) (path-to-namespace (src-subpath (file-name-directory file)))) (defun cpp-guard-for-file (file) (upcase (replace-regexp-in-string "[/.-]" "_" (src-subpath file)))) (defun ask-for-namespace () (read-from-minibuffer "Namespace: " (namespace-for-file (buffer-file-name)))) ;;; Generate starting point code for new files (defun insert-ns-open (namespaces) (mapcar (lambda (ns) (insert "namespace " ns " {\n")) namespaces)) (defun insert-ns-close (namespaces) (mapcar (lambda (ns) (insert "}")) namespaces) (insert " // namespace " (mapconcat 'identity namespaces "::") "\n")) (defun ns-around-region (namespace) (interactive (list (ask-for-namespace))) (save-excursion (let ((namespaces (split-string namespace "::"))) (if (< (mark) (point)) (exchange-point-and-mark)) (insert "\n") (insert-ns-open namespaces) (goto-char (mark)) (insert "\n") (insert-ns-close namespaces)))) (defun insert-class.h (class namespaces) "Insert class skeleton in .h file" (insert-ns-open namespaces) (insert "\n" "/**\n *\n */\n" " class " class "\n" " {\n public:\nprivate:\n};\n" ) (insert-ns-close namespaces)) (defun insert-platform.h (class namespaces) "Insert platform #include for platform class." (insert "#include \n" "#include QPID_PLATFORM_H(" class ".h)\n")) (defun .h (namespace &optional content) "Initialize a .h file with Qpid copyright etc." (interactive (list (ask-for-namespace))) (copyright) (let ((content (or content 'insert-class.h)) (class (file-name-nondirectory (file-name-sans-extension(buffer-file-name)))) (namespaces (split-string namespace "::"))) (insert "\n") (apply content class namespaces nil) (insert "\n")) (previous-line 1) (beginning-of-line) (indent-buffer) (save-excursion (cpp-guard))) (defun .cpp (namespace) "Initialize an empty .cpp file with Qpid copyright etc." (interactive (list (ask-for-namespace))) (copyright) (insert "\n#include \"" (file-name-sans-extension (file-name-nondirectory buffer-file-name)) ".h\"\n\n") (let ((namespaces (split-string namespace "::"))) (insert-ns-open namespaces) (insert-ns-close namespaces)) (indent-buffer)) (defun cpp-guard () "Insert C preprocessor macro guard to prevent file rescanning. The guard macro is defined from the name of the immediate containing directory and the name of the file." (interactive) (let ((name (cpp-guard-for-file (buffer-file-name)))) (goto-char (point-min)) (save-excursion (if (looking-at "#ifndef .*\n#define .*\n\n") (let ((ifndef (match-data 0))) (goto-char (point-max)) (previous-line 1) (beginning-of-line) (if (looking-at "#endif") (progn (kill-line 1) (kill-region (car ifndef) (cadr ifndef))))))) (insert "#ifndef " name "\n#define " name "\n\n") (goto-char (point-max)) (beginning-of-line) (insert (format "#endif /*!%s*/\n" name)))) (add-hook 'c++-mode-hook 'qpid-c++-mode) (provide 'qpid-c++-mode)