jao-skel-cpp.el 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. ;;; jao-skel-cpp.el -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2004, 2005, 2008, 2009, 2022 Jose Antonio Ortega Ruiz
  3. ;; Author: Jose A Ortega Ruiz <jao@gnu.org>
  4. ;; Keywords: tools
  5. ;; This file is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation; either version 3, or (at your option)
  8. ;; any later version.
  9. ;; This file is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs; see the file COPYING. If not, write to
  15. ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16. ;; Boston, MA 02111-1307, USA.
  17. ;;; Commentary:
  18. ;; C/C++ skeletons.
  19. ;;; Code:
  20. (require 'jao-skel)
  21. (require 'thingatpt)
  22. ;;; Variables
  23. (defvar jao-skel-cpp-root-namespace nil
  24. "The root C++ namespace")
  25. (defvar jao-skel-cpp-brief-header-p nil
  26. "If non-nil, generate brief header comments")
  27. (defvar jao-skel-cpp-make-guard-function #'jao-skel-cpp-make-guard-name
  28. "Function generating #include guards")
  29. (defvar jao-skel-cpp-use-namespaces t
  30. "Whether to generate namespaces")
  31. (defvar jao-skel-cpp-single-line-namespaces t
  32. "Whether to put consecutive namespace decls in a single line")
  33. (defvar jao-skel-cpp-header-extension "hpp")
  34. ;;; Auxiliar functions
  35. (defun jao-skel-cpp--find-other (ext)
  36. (file-name-nondirectory
  37. (or (ff-other-file-name)
  38. (concat (file-name-sans-extension (buffer-name)) "." ext))))
  39. (defun jao-skel-cpp-make-guard-name (ns)
  40. "Create a standard include guard name"
  41. (upcase (mapconcat #'identity
  42. `(,@ns ,(jao-skel-basename) ,(jao-skel-extension)
  43. ,(user-login-name)
  44. ,(format-time-string "%y%m%d%H%M"))
  45. "_")))
  46. ;; namespaces
  47. (defsubst jao-skel-cpp--read-ns (curr)
  48. (read-string (format "Add namespace (current: %s): " (or curr "[none]"))))
  49. (defsubst jao-skel-cpp--ns2str (ns) (mapconcat 'identity ns "::"))
  50. (defun jao-skel-cpp--get-ns-list (&optional acc)
  51. (do* ((result acc (cons next result))
  52. (next (jao-skel-cpp--read-ns (jao-skel-cpp--ns2str acc))
  53. (jao-skel-cpp--read-ns (jao-skel-cpp--ns2str (reverse result)))))
  54. ((string= next "") (reverse result))))
  55. (defun jao-skel-cpp--insert-open-ns-list (ns)
  56. (dolist (n ns)
  57. (insert (format "namespace %s {%s"
  58. n
  59. (if jao-skel-cpp-single-line-namespaces " " "\n")))
  60. (indent-according-to-mode))
  61. (when jao-skel-cpp-single-line-namespaces
  62. (newline)
  63. (indent-according-to-mode)))
  64. (defun jao-skel-cpp--insert-close-ns-list (ns)
  65. (if jao-skel-cpp-single-line-namespaces
  66. (insert (format "%s // namespace %s\n"
  67. (make-string (length ns) ?})
  68. (jao-skel-cpp--ns2str ns)))
  69. (dolist (n (reverse ns))
  70. (insert (format "} // namespace %s\n" n)))))
  71. (defun jao-skel-cpp--copy-ns-lines ()
  72. (let ((lines))
  73. (save-excursion
  74. (goto-char (point-min))
  75. (while (re-search-forward "namespace\\s-\\w+\\s-{\\|}+\\s-//\\s-namespace"
  76. nil t)
  77. (push (thing-at-point 'line) lines)
  78. (next-line)))
  79. lines))
  80. (defun jao-skel-cpp--copy-namespace ()
  81. (let* ((name (ff-other-file-name))
  82. (buff (and name (find-file-noselect name)))
  83. (nlines))
  84. (when buff
  85. (let ((lines (save-current-buffer
  86. (set-buffer buff)
  87. (jao-skel-cpp--copy-ns-lines))))
  88. (dolist (line lines)
  89. (push line nlines)
  90. (when (string-match "}" line)
  91. (push "\n\n\n\n" nlines)))))
  92. (mapconcat #'identity nlines "\n")))
  93. (defsubst jao-skel-cpp--get-new-namespace ()
  94. (when jao-skel-cpp-use-namespaces
  95. (jao-skel-cpp--get-ns-list
  96. (and jao-skel-cpp-root-namespace (list jao-skel-cpp-root-namespace)))))
  97. ;; skeletons
  98. (define-skeleton jao-skel-cpp-header-long
  99. "Initial file header blurb"
  100. "Brief file description: "
  101. "/**"
  102. > \n
  103. "* @file " (file-name-nondirectory (buffer-file-name))
  104. > \n
  105. "* @brief " str
  106. > \n
  107. "* @author " (user-full-name) " <"user-mail-address">"
  108. > \n
  109. "* @date " (format-time-string "%a %b %d, %Y %H:%M")
  110. > \n
  111. "*"
  112. > \n
  113. (jao-skel-copyright-line "* " "")
  114. "*"
  115. > ?\n
  116. (jao-skel-insert-license)
  117. > \n \n _)
  118. (define-skeleton jao-skel-cpp-header-brief
  119. "Brief initial header blurb"
  120. nil
  121. (jao-skel-copyright-line "/* " " */")
  122. \n)
  123. (define-skeleton jao-skel-cpp-header-comment
  124. "Insert a standard comment block"
  125. nil
  126. '(if jao-skel-cpp-brief-header-p
  127. (jao-skel-cpp-header-brief)
  128. (jao-skel-cpp-header-long)))
  129. ;; source C/C++ file ------------------------------------------------------
  130. (define-skeleton jao-skel-cpp-source-header
  131. "Insert a standard C++ source header"
  132. nil
  133. '(jao-skel-cpp-header-comment)
  134. ? \n
  135. "#include \"" (jao-skel-cpp--find-other jao-skel-cpp-header-extension) "\""
  136. > \n \n _
  137. (jao-skel-cpp--copy-namespace)
  138. \n)
  139. (define-skeleton jao-skel-c-source-header
  140. "Insert a standard C source header"
  141. nil
  142. '(jao-skel-cpp-header-comment)
  143. "#include \"" (jao-skel-cpp--find-other "h") "\""
  144. > _ \n \n \n \n
  145. > \n)
  146. ;; header C/C++ files ------------------------------------------------------
  147. ;; header guard
  148. ;; class definition
  149. (define-skeleton jao-skel-cpp-class-def
  150. "Insert a class definition"
  151. nil
  152. '(setq v1 (jao-skel-basename))
  153. > \n
  154. "/**"
  155. > \n
  156. "*"
  157. > \n
  158. "*"
  159. > \n
  160. "*/"
  161. > \n
  162. "class " v1
  163. > \n
  164. "{"
  165. > \n
  166. "public:"
  167. > \n
  168. "~" v1 "();"
  169. > \n
  170. v1 "();"
  171. > \n
  172. v1 "(const " v1 "& other);"
  173. > \n \n
  174. "private:"
  175. > \n
  176. "};"
  177. > \n)
  178. (define-skeleton jao-skel-cpp-header
  179. "Insert a standard C++ header (hpp files)"
  180. nil
  181. '(setq v1 (jao-skel-cpp--get-new-namespace))
  182. '(setq v2 (funcall jao-skel-cpp-make-guard-function v1))
  183. '(jao-skel-cpp-header-comment)
  184. > \n
  185. "#ifndef " v2
  186. > \n
  187. "#define " v2
  188. > \n \n
  189. '(when v1 (jao-skel-cpp--insert-open-ns-list v1))
  190. _ '(jao-skel-cpp-class-def)
  191. > \n \n
  192. '(when v1 (jao-skel-cpp--insert-close-ns-list v1))
  193. > \n \n
  194. "#endif // " v2
  195. > \n)
  196. (define-skeleton jao-skel-c-header
  197. "Insert a standard C header (.h files)"
  198. nil
  199. '(jao-skel-cpp-header-comment)
  200. > \n
  201. '(setq v1 (funcall jao-skel-cpp-make-guard-function nil))
  202. "#ifndef " v1
  203. > \n
  204. "#define " v1
  205. > _ \n \n \n \n
  206. "#endif /* " v1 " */"
  207. > \n > \n)
  208. (jao-skel-install*
  209. '(("\\.cpp$" jao-skel-cpp-source-header)
  210. ("\\.hpp$" jao-skel-cpp-header)
  211. ("\\.c$" jao-skel-c-source-header)
  212. ("\\.h$" jao-skel-c-header)))
  213. (provide 'jao-skel-cpp)
  214. ;;; jao-skel-cpp.el ends here