From ad470f58f0317c84d27e24ce2ae9643805abdf51 Mon Sep 17 00:00:00 2001 From: Michele Pes Date: Sat, 10 Apr 2021 15:21:32 +0200 Subject: [PATCH] Various fixes for new version --- gendoxy.el | 169 +++++++++++++++++++++++++++++------------------------ readme.md | 111 +++++++++++++++++++++++------------ 2 files changed, 169 insertions(+), 111 deletions(-) diff --git a/gendoxy.el b/gendoxy.el index 01df75c..5d58696 100644 --- a/gendoxy.el +++ b/gendoxy.el @@ -67,6 +67,17 @@ ;; ;;; Change log: ;; +;; 1.0.11 (2021-04-10) +;; Fixed horrible documentation on parameters without underline +;; Fixed header generation +;; Removed non M-d friendly patterns +;; Removed bad name of non-conformant function +;; Added support for DLL prototypes +;; Improved comment for param/return in case of function pointer +;; If first parameter is out, it will be always inout +;; Added '()' on documented functions message +;; Improved documentation +;; ;; 1.0.10 (2020-08-08) ;; Replaced non-standard alias with core function (thanks to John DeRoo) ;; Improved function/var detection @@ -212,17 +223,10 @@ "^p_\\(\\([A-Z]\\|[a-z]\\)[a-z]\\{2,\\}\\)$" (1) - "Pointer to *" - "^p\\([A-Z][a-z]\\{2,\\}\\)$" - (1) - "The * of *" - "^\\(\\([A-Z]\\|[a-z]\\)[a-z]\\{3,\\}\\)_\\(\\([A-Z]\\|[a-z]\\)[a-z]\\{3,\\}\\)$" - (3 1) - - "The * of *" - "^\\(\\([A-Z]\\|[a-z]\\)[a-z]\\{3,\\}\\)\\([A-Z][a-z]\\{3,\\}\\)$" + "^\\(\\([A-Z]\\|[a-z]\\)[a-z]\\{2,\\}\\)_\\(\\([A-Z]\\|[a-z]\\)[a-z]\\{2,\\}\\)$" (3 1)) + "Parameters comment based on parameter name map") (defun gendoxy-tag-string () @@ -500,14 +504,15 @@ t))) nil)) -(defun gendoxy-have-return-p (str) - "Return nil on error, 0 for void, 1 if not void" +(defun gendoxy-have-return (str) + "Return nil on error, 0 for void, 1 if not void, 2 for function pointer" (if (string-match gendoxy-c-id-regex str) (if (or (not (string-match "void" str)) (string-match "\\*" str) (string-match "(" str)) - 1 - 0) + (let ( (pc (car (gendoxy-count-parenthesis str)))) + (if (>= pc 2) 2 1)) + 0) nil)) (defun gendoxy-get-direction (parameter) @@ -526,14 +531,16 @@ t nil))) -(defun gendoxy-dump-parameters (parameters) +(defun gendoxy-dump-parameters (parameters lap) "Insert passed parameters into buffer" (when parameters (progn - (insert (concat " * " (gendoxy-get-tag "param" 0) - (if (cadr parameters) "[in]" "[out]") " " (car parameters) - " " (car (cddr parameters)) gendoxy-nl)) - (gendoxy-dump-parameters (seq-drop parameters 3))))) + (insert (concat " * " (gendoxy-get-tag "param" 0))) + (insert (if (and (eq lap 0) (not (cadr parameters))) "[inout]" + (if (cadr parameters) "[in]" "[out]"))) + (insert (concat " " (car parameters) " " (car (cddr parameters)) + gendoxy-nl)) + (gendoxy-dump-parameters (seq-drop parameters 3) (1+ lap))))) (defun gendoxy-find-last (str pattern &optional index) "Find last occurrence of pattern in str. Pattern must be one character" @@ -626,18 +633,20 @@ (gendoxy-get-parameter-text-rec name ender))) nil)) -(defun gendoxy-get-parameter-text (name) +(defun gendoxy-get-parameter-text (name org-name) "Return a custom parameter description or gendoxy-default-text" - (let ((lst (gendoxy-get-parameter-text-rec name 0))) - (if lst - (let ( (doc (car lst)) (regx (cadr lst)) (indexes (car (cddr lst))) ) - (gendoxy-get-parameter-patterns doc regx name indexes)) - gendoxy-default-text))) + (let ((pc (gendoxy-count-parenthesis org-name))) + (if (> (car pc) 0) "A pointer to function" + (let ((lst (gendoxy-get-parameter-text-rec name 0))) + (if lst + (let ( (doc (car lst)) (regx (cadr lst)) (indexes (car (cddr lst)))) + (message "<%s>" doc) + (gendoxy-get-parameter-patterns doc regx name indexes)) + gendoxy-default-text))))) (defun gendoxy-get-parameters (parameters) "Take a list of comma-separated of (complex?) parameters. Return a list of \ - triples (name, 0 for in or 1 for out, txt). Return an empty list (nil) if \ - no parameters" + triples (name, 0 for in or 1 for out, txt). Return nil if no parameters" (if (or (not parameters) (and (eq (length parameters) 1) (string-equal (gendoxy-trim (car parameters)) "void"))) @@ -645,28 +654,32 @@ (let* ( (parameter-original (car parameters)) (direction (gendoxy-get-direction parameter-original)) (parameter (gendoxy-rtrim (substring parameter-original 0 - (string-match "\\[" + (string-match "\\[" parameter-original)))) (others (gendoxy-get-parameters (cdr parameters))) - (param-name (gendoxy-get-complex-name parameter)) ) + (param-name (gendoxy-get-complex-name parameter)) + (splitted (split-string parameter-original gendoxy-space-regex t)) ) (if (and param-name (cdr (split-string parameter-original - gendoxy-space-regex - t))) - (cons param-name (cons direction - (cons (gendoxy-get-parameter-text param-name) - others))) + gendoxy-space-ptr-regex + t))) + (cons param-name + (cons direction + (cons (gendoxy-get-parameter-text param-name + parameter-original) + others))) others)))) -(defun dump-function (name return-code parameters) +(defun gendoxy-dump-function (name return-code parameters) "Dump the function documentation" (gendoxy-add-line-before) (insert (concat "/**" gendoxy-nl " * " (gendoxy-get-tag "brief") "Summary" gendoxy-nl)) (gendoxy-add-details) - (gendoxy-dump-parameters parameters) - (when (eq return-code 1) + (gendoxy-dump-parameters parameters 0) + (when (>= return-code 1) (insert (concat " * " (gendoxy-get-tag "return") - gendoxy-default-text gendoxy-nl))) + (if (eq return-code 2) "A pointer to a function" + gendoxy-default-text) gendoxy-nl))) (insert (concat " */" gendoxy-nl))) (defun gendoxy-handle-complex-function (statement) @@ -679,15 +692,15 @@ (name-and-ret (substring statement 0 (- (length statement) (length parameters-string)))) - (have-return (gendoxy-have-return-p name-and-ret)) + (have-return (gendoxy-have-return name-and-ret)) (func-name (gendoxy-get-complex-name name-and-ret)) (parameters-array (gendoxy-get-parameters-array parameters-str)) (parameters (gendoxy-get-parameters parameters-array)) ) (if (and parameters-string parameters-str func-name have-return) (progn - (dump-function func-name have-return parameters) - (message "gendoxy: Function %s documented" func-name)) + (gendoxy-dump-function func-name have-return parameters) + (message "gendoxy: Function %s() documented" func-name)) (message "gendoxy: Invalid complex function was not documented"))) (message "gendoxy: Invalid complex function was not documented")))) @@ -703,7 +716,7 @@ (return-type (gendoxy-rtrim (substring ret-and-name 0 name-index))) - (have-return (gendoxy-have-return-p return-type)) + (have-return (gendoxy-have-return return-type)) (parameter-tokens (split-string (substring statement (1+ open-index) close-index) @@ -711,15 +724,19 @@ (parameters (gendoxy-get-parameters parameter-tokens)) ) (if have-return (progn - (dump-function func-name have-return parameters) - (message "gendoxy: Function %s documented" func-name)) + (gendoxy-dump-function func-name have-return parameters) + (message "gendoxy: Function %s() documented" func-name)) (message "gendoxy: Invalid function was not documented"))) (message "gendoxy: Invalid function was not documented")))) (defun gendoxy-handle-func-or-var () "Handle prototypes, (simple or complex (involving function pointers)) and \ variables" - (let ( (org (point)) (statement (gendoxy-get-statement)) ) + (let ( (org (point)) + (statement (replace-regexp-in-string + (concat gendoxy-space-regex "*__declspec" + gendoxy-space-regex "*\\([^)]+)\\)") " " + (gendoxy-get-statement)))) (goto-char org) (if statement (unless (gendoxy-try-var statement) ; try to document a variable @@ -753,19 +770,37 @@ (goto-char (point-min)) (insert (concat "/**" gendoxy-nl)) (insert (concat " * " (gendoxy-get-tag "file" 6) (buffer-name) gendoxy-nl)) - (insert (concat " * " (gendoxy-get-tag "copyright" 1) "BSD-3-Clause" + (insert (concat " * " (gendoxy-get-tag "brief" 5) "Header of" + gendoxy-nl)) + (insert (concat " * " (gendoxy-get-tag "date" 6) (current-time-string) gendoxy-nl)) (insert (concat " * " (gendoxy-get-tag "author" 4) (if (string= "" user-full-name) user-real-login-name user-full-name) gendoxy-nl)) - (insert (concat " * " (gendoxy-get-tag "date" 6) (current-time-string) - gendoxy-nl)) - (insert (concat " * " (gendoxy-get-tag "brief" 5) "Header of ..." + (insert (concat " * " (gendoxy-get-tag "copyright" 1) "BSD-3-Clause" gendoxy-nl)) - (gendoxy-add-details "This module..." 3) + (unless gendoxy-skip-details + (insert (concat " * " gendoxy-nl " * This module" gendoxy-nl))) (insert (concat " */" gendoxy-nl gendoxy-nl)) - (message "gendoxy: Header documented")) + (message "gendoxy: Header documented in file %s" (buffer-name))) + +(defun gendoxy-group-start () + "Generate general template for the beginning of a block of items" + (interactive) + (gendoxy-add-line-before) + (move-beginning-of-line nil) + (insert (concat "/**" gendoxy-nl " * " (gendoxy-get-tag "name") + "Group title" gendoxy-nl " * " gendoxy-default-text + gendoxy-nl " * " (gendoxy-get-tag "{" 0) + gendoxy-nl " */" gendoxy-nl))) + +(defun gendoxy-group-end () + "Generate general template for the beginning of a block of items" + (interactive) + (move-beginning-of-line 1) + (insert (concat "/**" gendoxy-nl " * " (gendoxy-get-tag "}" 0) gendoxy-nl + " */" gendoxy-nl))) (defun gendoxy-group-core (is-full) "Generate general template for a block of items and its items if requested" @@ -775,55 +810,39 @@ (if first-token (progn (when is-full - (progn (move-end-of-line 1) (insert " /**< Descirption... */"))) + (progn (move-end-of-line 1) (insert " /**< Description */"))) (while (and (< (line-number-at-pos) (prog2 (forward-line) (line-number-at-pos))) (string= first-token (gendoxy-get-first-token (gendoxy-get-current-line)))) (when is-full - (progn (move-end-of-line 1) (insert " /**< Descirption... */")))) + (progn (move-end-of-line 1) (insert " /**< Description */")))) (unless (char-after) (insert gendoxy-nl)) (gendoxy-group-end) (message "gendoxy: Group documented")) (message "gendoxy: Parser error")))) -(defun gendoxy-group-start () - "Generate general template for the beginning of a block of items" - (interactive) - (gendoxy-add-line-before) - (move-beginning-of-line nil) - (insert (concat "/**" gendoxy-nl " * " (gendoxy-get-tag "name") - gendoxy-default-text gendoxy-nl " * " (gendoxy-get-tag "{" 0) - gendoxy-nl " */" gendoxy-nl))) - -(defun gendoxy-group-end () - "Generate general template for the beginning of a block of items" +(defun gendoxy-group () + "Generate general template for a block of items and its items if requested" (interactive) - (move-beginning-of-line 1) - (insert (concat "/**" gendoxy-nl " * " (gendoxy-get-tag "}" 0) gendoxy-nl - " */" gendoxy-nl))) + (gendoxy-group-core t)) (defun gendoxy-group-header () "Generate general template for a block of items" (interactive) (gendoxy-group-core nil)) -(defun gendoxy-group () - "Generate general template for a block of items and its items if requested" - (interactive) - (gendoxy-group-core t)) +(defun gendoxy-tag () + "Generate general template for source item in current line and its items" + (interactive) + (gendoxy-tag-core t)) (defun gendoxy-tag-header () "Generate general template for source item in current line" (interactive) (gendoxy-tag-core nil)) -(defun gendoxy-tag () - "Generate general template for source item in current line and its items" - (interactive) - (gendoxy-tag-core t)) - (provide 'gendoxy-header) (provide 'gendoxy-tag) diff --git a/readme.md b/readme.md index 1b56a66..65b7830 100644 --- a/readme.md +++ b/readme.md @@ -1,47 +1,86 @@ -# gendoxy - An emacs package to generate doxygen documentation from C code -This plugin generates [doxygen](http://doxygen.org ) documentation from C source code. -It generates doxygen-aware documentation skeleton for the most common C constructs. -Moreover, function parameters documentation may be partially guessed, -according to some parameters name pattern. - -# Installation -Put file _gendoxy.el_ in a path accessible to emacs (add-to-list 'load-path ...) +# gendoxy + +## An emacs package to generate doxygen documentation from C code +This plugin generates [doxygen](http://doxygen.org ) documentation from C source code\ +It generates a doxygen documentation skeleton for the most common C constructs + +## Features +* Dedicated command for module documentation (author, file, date, copyright, etc) +* Support for _macros_, _functions_, _variables_, _struct_, _enum_ and _typedef_ +* Return tag added on non-void functions +* Function parameters have particular features: + * Added only if a name is specified, ignored if type only is present + * Direction is inferred by type (in, out, inout) + * Documentation can be guessed by name (` * @param buffer_len The length of buffer`) +* Support for [groups](#groups) + +## Installation +Put file _gendoxy.el_ in a path accessible to emacs (add-to-list 'load-path ...)\ Load it in your init file `(load "gendoxy.el")` -# Configuration +## Configuration Once the package is loaded, there are four variables that control documentation generation: * `gendoxy-backslash`: if not _nil_, will use backslash instead of ampersat * `gendoxy-default-text`: Default string used in generated documentation * `gendoxy-skip-details`: If not _nil_, will omit details in header and functions * `gendoxy-details-empty-line`: If not _nil_, will use an empty line instead of -the details tag to add details. Note that this has effect if _gendoxy-skip-details_ is _nil_ ONLY. - -# Usage -Put the cursor on the **first** line of a declaration to document -(not necessarily at the beginning of line), then run the command: -`M-x gendoxy-tag` -This will document your declaration and all its sub-items if any. -If you want to document a declaration, __but not__ its subitems, then run the command: -`M-x gendoxy-tag-header` - -### Groups -To to document a group of items, you can use the command: -M-x `gendoxy-group` -To document a group __but not__ the single items, use the command: -`M-x gendoxy-group-header` -For groups, since may not be easy to guess start and end of group, -two explicit commands have been added: -`gendoxy-group-start` and `gendoxy-group-end`. -The last command (but the first to use) is: -`M-x gendoxy-header` -that generates a header documentation for current file - -# Notes -The gendoxy package doesn't define a new mode, just offers some commands to use. +the details tag to add details. Note that this has effect **only** if _gendoxy-skip-details_ is _nil_ + + +## Groups +To to document a group of items (typically macros or variables), you can use the command:\ +M-x `gendoxy-group`\ +To document a group __but not__ the single items, use the command:\ +`M-x gendoxy-group-header`\ +Since sometimes may not be easy to guess start and end of group, two explicit commands have been added:\ +`gendoxy-group-start` and `gendoxy-group-end`. + +Example:\ +Assume you have these 4 macros. To properly identify a group, newlines must be present before and after + +```C +line 1: +line 2: #define M1 1 +line 3: #define M2 2 +line 4: #define M3 3 +line 5: #define M4 4 +line 6: +``` + +Now put your cursor on line 2: If you run command `gendoxy-group`, this will be the result: +```C +/** + * @name Group title + * Description + * @{ + */ +#define M1 1 /**< Description */ +#define M2 2 /**< Description */ +#define M3 3 /**< Description */ +#define M4 4 /**< Description */ +/** + * @} + */ +``` + +If gendoxy fails detecting your group, you can split the prologue and epilogue documentation with commands:\ +`gendoxy-group-start` and `gendoxy-group-end` + +## Usage +The first command is `gendoxy-header`, that generate documentation for current file\ +Then start documenting declarations with command `gendoxy-tag`:\ +Put the cursor on the **first** line of a declaration to document, (not necessarily +at the beginning of line) and run `M-x gendoxy-tag`\ +This will document your declaration and all its sub-items (on structs/enums) if any\ +If you want to document a declaration, **but not** its subitems, then use command `M-x gendoxy-tag-header` + +## Notes +The gendoxy package doesn't define a new mode, just offers some commands to use\ For a more productive environment, just [bind](https://www.gnu.org/software/emacs/manual/html_node/emacs/Key-Bindings.html) your favorite key to -`gendoxy-tag` and/or `gendoxy-tag-header` commands. -Additionally, you can set up your details/tag char configuration. +`gendoxy-tag` and/or `gendoxy-tag-header` commands.\ +Additionally, you can set up your details/tag char configuration.\ Once your setup is done, open a header file, add the header if missing and go with comments! -gendoxy is written in **purely functional** elisp (no setq or equivalent) +## Special +gendoxy is written in **purely functional** _elisp_ (no setq or equivalent)\ gendoxy **does not have** any external dependency, even _cl-lib_ is never called!