1889 lines
68 KiB
EmacsLisp
1889 lines
68 KiB
EmacsLisp
;;; -*-emacs-lisp-*-
|
||
;;; doxymacs.el --- ELisp package for making doxygen related stuff easier.
|
||
;;
|
||
;;
|
||
;; Copyright (C) 2001-2010 Ryan T. Sammartino
|
||
;;
|
||
;; Author: Ryan T. Sammartino <ryan.sammartino at gmail dot com>
|
||
;; Kris Verbeeck <kris.verbeeck at advalvas dot be>
|
||
;; Created: 24/03/2001
|
||
;; Version: @VERSION@
|
||
;; Keywords: doxygen documentation
|
||
;;
|
||
;; This file is NOT part of GNU Emacs or XEmacs.
|
||
;;
|
||
;; This program is free software; you can redistribute it and/or
|
||
;; modify it under the terms of the GNU General Public License
|
||
;; as published by the Free Software Foundation; either version 2
|
||
;; of the License, or (at your option) any later version.
|
||
;;
|
||
;; This program is distributed in the hope that it will be useful,
|
||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
;; GNU General Public License for more details.
|
||
;;
|
||
;; You should have received a copy of the GNU General Public License
|
||
;; along with this program; if not, write to the Free Software
|
||
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
;;
|
||
;; Doxymacs homepage: http://doxymacs.sourceforge.net/
|
||
|
||
;; Commentary:
|
||
;;
|
||
;; Doxymacs depends on the following packages:
|
||
;;
|
||
;; - W3 http://www.cs.indiana.edu/usr/local/www/elisp/w3/docs.html
|
||
;; - tempo http://www.lysator.liu.se/~davidk/elisp/
|
||
;; - libxml2 http://www.libxml.org/
|
||
;;
|
||
;; Be sure these are properly configured and installed before proceeding.
|
||
;;
|
||
;; - Use the configure script to configure doxymacs:
|
||
;;
|
||
;; $ ./configure
|
||
;; $ make
|
||
;; $ make install
|
||
;;
|
||
;; Use ./configure --help for help on customising your configuration.
|
||
;;
|
||
;; If you get
|
||
;;
|
||
;; !! File error (("Cannot open load file" "url"))
|
||
;;
|
||
;; (or something similar) then set the variable EMACSLOADPATH before
|
||
;; doing make:
|
||
;;
|
||
;; $ EMACSLOADPATH=... make
|
||
;;
|
||
;; where ... is a colon separated list of directories to search for
|
||
;; packages. To byte compile with XEmacs, set the variable EMACS:
|
||
;;
|
||
;; $ EMACS=xemacs make
|
||
;;
|
||
;; If you would rather not byte compile the .el files at all, then do:
|
||
;;
|
||
;; $ make ELCFILES=
|
||
;;
|
||
;; - Customise the variable doxymacs-doxygen-dirs.
|
||
;;
|
||
;; - If your tags file is quite large (say, > 1 MB), consider setting
|
||
;; doxymacs-use-external-xml-parser to t and be sure to set
|
||
;; doxymacs-external-xml-parser-executable to the right value (the
|
||
;; default should usually be fine). A suitable program is
|
||
;; distributed along with this file in the directory doxymacs/c/.
|
||
;; With an 11 MB XML tag file, the internal process takes 20 minutes
|
||
;; on a PIII 800 with 1 GB of RAM, whereas the external process
|
||
;; takes 12 seconds.
|
||
;;
|
||
;; - Put (require 'doxymacs) in your .emacs
|
||
;;
|
||
;; - Invoke doxymacs-mode with M-x doxymacs-mode. To have doxymacs-mode
|
||
;; invoked automatically when in C/C++ mode, put
|
||
;;
|
||
;; (add-hook 'c-mode-common-hook 'doxymacs-mode)
|
||
;;
|
||
;; in your .emacs.
|
||
;;
|
||
;; - If you want Doxygen keywords fontified use M-x doxymacs-font-lock.
|
||
;; To do it automatically, add the following to your .emacs:
|
||
;;
|
||
;; (defun my-doxymacs-font-lock-hook ()
|
||
;; (if (or (eq major-mode 'c-mode) (eq major-mode 'c++-mode))
|
||
;; (doxymacs-font-lock)))
|
||
;; (add-hook 'font-lock-mode-hook 'my-doxymacs-font-lock-hook)
|
||
;;
|
||
;; This will add the Doxygen keywords to c-mode and c++-mode only.
|
||
;;
|
||
;; - Default key bindings are:
|
||
;; - C-c d ? will look up documentation for the symbol under the point.
|
||
;; - C-c d r will rescan your Doxygen tags file.
|
||
;; - C-c d f will insert a Doxygen comment for the next function.
|
||
;; - C-c d i will insert a Doxygen comment for the current file.
|
||
;; - C-c d ; will insert a Doxygen comment for the current member.
|
||
;; - C-c d m will insert a blank multiline Doxygen comment.
|
||
;; - C-c d s will insert a blank singleline Doxygen comment.
|
||
;; - C-c d @ will insert grouping comments around the current region.
|
||
;;
|
||
;; Doxymacs has been tested on and works with:
|
||
;; - GNU Emacs 20.7.1, 21.1.1, 21.2.1, 21.2.92.1, 21.3, 21.4.1, 23.1.1
|
||
;; - XEmacs 21.1 (patch 14), 21.4 (patches 4-17)
|
||
;;
|
||
;; If you have success or failure with other version of {X}Emacs, please
|
||
;; let the authors know.
|
||
|
||
;; Change log:
|
||
;;
|
||
;; 07/03/2010 - feature #1569376: Interactively insert doxygen commands.
|
||
;; 19/02/2010 - patch #2954452: Add new documentation style C++!.
|
||
;; bug #1862867: Remove trailing whitespace in JavaDoc function
|
||
;; template.
|
||
;; 18/02/2010 - Support new tparam doxygen command.
|
||
;; 10/06/2007 - version 1.8.0
|
||
;; 02/02/2007 - bug #1490021: Allow spaces in @param [in] documentation.
|
||
;; bug #1496399: Allow for different ways of user-mail-address
|
||
;; to be defined.
|
||
;; 22/04/2006 - feature #1338245: Add tokens to filladapt to match
|
||
;; doxygen markup.
|
||
;; - version 1.7.0
|
||
;; 04/06/2005 - version 1.6.0
|
||
;; 14/04/2005 - Use doxymacs-url-exists-p to wrap the various ways of
|
||
;; checking whether a URL exists.
|
||
;; - Clean up symbol-near-point hack.
|
||
;; 13/04/2005 - feature request #868413: ability to customize the browser
|
||
;; doxymacs uses to display documentation.
|
||
;; 12/04/2005 - bug #990123: grouping comments do not work.
|
||
;; - add some missing doxygen keywords.
|
||
;; 01/04/2005 - patch #1024026: use new font-lock-add-keywords function if
|
||
;; available.
|
||
;; 31/03/2005 - patch #1102042: handle @param[in] etc. constructs
|
||
;; 25/01/2003 - remove hard coded version number from comments.
|
||
;; - add instructions to avoid byte compiling files.
|
||
;; - version 1.5.0
|
||
;; 11/01/2003 - feature #665470: C++ style.
|
||
;; - fix bug #665099: missing @var fontification.
|
||
;; - fix bug #665372: @example not fontified properly.
|
||
;; - fix fontification for other keywords as well.
|
||
;; - new customisation variable doxymacs command-character
|
||
;; which allows for customisation of the character used
|
||
;; to introduce Doxygen commands independent of the
|
||
;; current style.
|
||
;; 05/01/2003 - autoconf-ise.
|
||
;; - version 1.4.0
|
||
;; 09/12/2002 - turn off buffer modified flag for doxytags to avoid
|
||
;; prompting user for killing a modified buffer.
|
||
;; 08/12/2002 - move to association lists to support multiple Doxygen
|
||
;; generates.
|
||
;; 30/11/2002 - apply patch 636146:
|
||
;; - several FIXMEs fixed
|
||
;; - user-defined "void" types
|
||
;; - thanks to Georg Drenkhahn
|
||
;; 31/08/2002 - bug #601028 fixed... functions with blank lines in their
|
||
;; argument list confused doxymacs-extract-args-list
|
||
;; - version 1.3.2
|
||
;; 09/05/2002 - fix issues compiling doxymacs_parser.c on Mac OS X.
|
||
;; - version 1.3.1
|
||
;; 19/11/2001 - doxymacs has been tested on and works with XEmacs 21.4
|
||
;; (patch 5) and GNU Emacs 21.1.1
|
||
;; 04/11/2001 - add some documentation for default templates.
|
||
;; - implement grouping comments (C-c d @)
|
||
;; - version 1.3.0
|
||
;; 30/09/2001 - doxymacs has been tested on and works with XEmacs 21.4
|
||
;; (patch 4)
|
||
;; 15/09/2001 - bug #460396 fixed... wrong number of arguments for
|
||
;; doxymacs-parm-tempo-element in
|
||
;; doxymacs-Qt-function-comment-template
|
||
;; - version 1.2.1
|
||
;; 26/08/2001 - feature request #454122 (single line member comments) done.
|
||
;; - feature request #454123 (key bindings description) done.
|
||
;; - clean up template code to make it easier to add new templates
|
||
;; and to catch bad settings.
|
||
;; - clean up documentation to be more standards conforming.
|
||
;; - version 1.2.0
|
||
;; 23/08/2001 - fix bug #454563... missing @endlink in fontification,
|
||
;; fix @b, @em, @c, @p and @link fontification.
|
||
;; - make fontification regexps easier to read.
|
||
;; - version 1.1.4
|
||
;; 07/07/2001 - make external XML parser work with libxml2. Now requires
|
||
;; version 2.3.4 or greater
|
||
;; - version 1.1.3
|
||
;; 04/07/2001 - GNU Emacs doesn't understand ?: in regexps, so take them out
|
||
;; - version 1.1.2
|
||
;; 20/06/2001 - fix bug #432837 missing @see keyword
|
||
;; - fix bug #432836 Font lock for @ingroup not correct
|
||
;; - version 1.1.1
|
||
;; 12/06/2001 - add font lock keywords for Doxygen keywords
|
||
;; - version 1.1.0
|
||
;; 06/06/2001 - fix bug #427660 (mouse selection problems).
|
||
;; - version 1.0.0
|
||
;; 26/05/2001 - fix bug #427351 (thinks "void" is a parameter) and bug
|
||
;; #427350 (can't document constructors/destructors), and
|
||
;; generally made the whole doxymacs-find-next-func function
|
||
;; much more robust. Small update to default styles when
|
||
;; inserting functions that return "void"
|
||
;; - version 0.2.1
|
||
;; 21/05/2001 - now able to optionally use an "external" XML parser to speed
|
||
;; things up.
|
||
;; - version 0.2.0
|
||
;; 12/05/2001 - fix some bugs on GNU Emacs... tested and works with GNU
|
||
;; Emacs 20.7.1
|
||
;; - version 0.1.2
|
||
;; 09/05/2001 - change C-? to C-c d ?, since hitting DEL also triggers C-?
|
||
;; - update progress while parsing XML file
|
||
;; - version 0.1.1
|
||
;; 07/05/2001 - minor mode thanks to Kris, and default key map.
|
||
;; - released as version 0.1.0 (Alpha)
|
||
;; 06/05/2001 - Now using tempo templates for the comments... also allow for
|
||
;; user defined templates.
|
||
;; 29/04/2001 - The doxytags.pl PERL script is no longer necessary, as we can
|
||
;; now parse the XML file that doxygen creates directly.
|
||
;; 22/04/2001 - Function documentation.
|
||
;; 18/04/2001 - Going with Kris' "new style" look up code. It's excellent.
|
||
;; - Load tags from URL.
|
||
;; 11/04/2001 - added ability to insert blank doxygen comments with either
|
||
;; Qt or JavaDoc style.
|
||
;; - also did "file" comments
|
||
;; 31/03/2001 - added ability to choose which symbol to look up if more than
|
||
;; one match
|
||
;; - slightly changed the format of the list that
|
||
;; doxymacs-get-matches returns
|
||
;; 28/03/2001 - added doxymacs to the "tools" customisation group.
|
||
;; - removed doxymacs-browser (just use user's default browser)
|
||
;; - minor formatting updates
|
||
;; 24/03/2001 - initial version. Pretty lame. Need some help.
|
||
|
||
;; TODO:
|
||
;;
|
||
;; - better end-user documentation
|
||
;; - fix all FIXMEs (of course)
|
||
;; - other stuff?
|
||
|
||
;; Front matter and variables
|
||
|
||
(provide 'doxymacs)
|
||
|
||
(require 'custom)
|
||
(require 'xml-parse)
|
||
(require 'url)
|
||
(require 'tempo)
|
||
|
||
(defconst doxymacs-version "@VERSION@"
|
||
"Doxymacs version number")
|
||
|
||
(defun doxymacs-version ()
|
||
"Report the current version of doxymacs in the minibuffer."
|
||
(interactive)
|
||
(message "Using doxymacs version %s" doxymacs-version))
|
||
|
||
|
||
(defgroup doxymacs nil
|
||
"Find documentation created by Doxygen, and create Doxygen comments."
|
||
:group 'tools)
|
||
|
||
(defcustom doxymacs-doxygen-dirs
|
||
nil
|
||
"List associating pathnames with Doxygen documentation.
|
||
Each item on the list is a list of the form (DIR-REGEXP XML URL)
|
||
where:
|
||
|
||
DIR-REGEXP is a regular expression that matches a directory;
|
||
XML is the file name or URL of the corresponding Doxygen XML tags; and
|
||
URL is the URL of the Doxygen documentation that matches that directory.
|
||
|
||
For example, if all the files in /home/me/project/foo have their documentation
|
||
at http://someplace.com/doc/foo/ and the XML tags file is at
|
||
http://someplace.com/doc/foo/foo.xml, and all the files in
|
||
/home/me/project/bar have their documentation at
|
||
file:///home/me/project/bar/doc/ and the XML tags file is at
|
||
/home/me/project/bar/doc/bar.xml, then you would set this list to
|
||
|
||
'((\"^/home/me/project/foo/\"
|
||
\"http://someplace.com/doc/foo/foo.xml\"
|
||
\"http://someplace.com/doc/foo/\")
|
||
(\"^/home/me/project/bar/\"
|
||
\"~/project/bar/doc/bar.xml\"
|
||
\"file:///home/me/project/bar/doc/\"))"
|
||
:type 'list
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-doxygen-style
|
||
"@DOXYMACS_DEFAULT_STYLE@"
|
||
"The style of comments to insert into code.
|
||
See http://www.stack.nl/~dimitri/doxygen/docblocks.html#docblocks for examples
|
||
of the various styles.
|
||
|
||
Must be one of \"JavaDoc\", \"Qt\" \"C++\" or \"C++!\". Setting this variable
|
||
to anything else will generate errors."
|
||
:type '(radio (const :tag "JavaDoc" "JavaDoc")
|
||
(const :tag "Qt" "Qt")
|
||
(const :tag "C++" "C++")
|
||
(const :tag "C++!" "C++!"))
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-command-character
|
||
nil
|
||
"The character to use to introduce Doxygen commands when inserting comments.
|
||
If nil, then use the default dictated by `doxymacs-doxygen-style'. Otherwise,
|
||
must be one of \"@\" or \"\\\"."
|
||
:type '(choice (const :tag "None" nil)
|
||
string)
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-use-external-xml-parser
|
||
@DOXYMACS_USE_EXTERNAL_XML_PARSER@
|
||
"*Use the external (written in C) XML parser or the internal (LISP) parser.
|
||
For smallish tag files, you are better off with the internal parser.
|
||
For larger tag files, you are better off with the external one.
|
||
Set to non-nil to use the external XML parser."
|
||
:type '(choice (const :tag "Yes" t)
|
||
(const :tag "No" nil))
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-external-xml-parser-executable
|
||
"@DOXYMACS_PARSER@"
|
||
"*Where the external XML parser executable is."
|
||
:type 'string
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-browse-url-function
|
||
'browse-url
|
||
"*Function to call to launch a browser to display Doxygen documentation.
|
||
This function should take one argument, a string representing the URL to
|
||
display."
|
||
:type 'function
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-blank-multiline-comment-template
|
||
nil
|
||
"A tempo template to insert for `doxymacs-insert-blank-multiline-comment'.
|
||
If nil, then a default template based on the current style as indicated
|
||
by `doxymacs-doxygen-style' will be used.
|
||
|
||
For help with tempo templates, see http://www.lysator.liu.se/~davidk/elisp/"
|
||
:type 'list
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-blank-singleline-comment-template
|
||
nil
|
||
"A tempo template to insert for `doxymacs-insert-blank-singleline-comment'.
|
||
If nil, then a default template based on the current style as indicated
|
||
by `doxymacs-doxygen-style' will be used.
|
||
|
||
For help with tempo templates, see http://www.lysator.liu.se/~davidk/elisp/"
|
||
:type 'list
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-file-comment-template
|
||
nil
|
||
"A tempo template to insert for `doxymacs-insert-file-comment'.
|
||
If nil, then a default template based on the current style as indicated
|
||
by `doxymacs-doxygen-style' will be used.
|
||
|
||
For help with tempo templates, see http://www.lysator.liu.se/~davidk/elisp/"
|
||
:type 'list
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-function-comment-template
|
||
nil
|
||
"A tempo template to insert for `doxymacs-insert-function-comment'.
|
||
If nil, then a default template based on the current style as
|
||
indicated by `doxymacs-doxygen-style' will be used. Note that the
|
||
function `doxymacs-find-next-func' is available to you... it returns
|
||
an assoc list with the function's name, argument list (BUG: may be
|
||
incorrect for parameters that require parentheses), and return
|
||
value:
|
||
|
||
(cdr (assoc 'func (doxymacs-find-next-func))) is the function name (string).
|
||
(cdr (assoc 'args (doxymacs-find-next-func))) is a list of arguments.
|
||
(cdr (assoc 'return (doxymacs-find-next-func))) is the return type (string).
|
||
|
||
The argument list is a list of strings.
|
||
|
||
For help with tempo templates, see http://www.lysator.liu.se/~davidk/elisp/"
|
||
:type 'list
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-void-types
|
||
"void"
|
||
"String with void-kind variable types. Extend this string if there
|
||
are typedefs of void. Example: \"void tVOID\"."
|
||
:type 'string
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-member-comment-start
|
||
nil
|
||
"String to insert to start a new member comment.
|
||
If nil, use a default one based on the current style as indicated by
|
||
`doxymacs-doxygen-style'."
|
||
:type '(choice (const :tag "None" nil)
|
||
string)
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-member-comment-end
|
||
nil
|
||
"String to insert to end a new member comment.
|
||
If nil, use a default one based on the current style as indicated by
|
||
`doxymacs-doxygen-style'.
|
||
|
||
Should be an empty string if comments are terminated by end-of-line."
|
||
:type '(choice (const :tag "None" nil)
|
||
string)
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-group-comment-start
|
||
nil
|
||
"A string to begin a grouping comment (`doxymacs-insert-grouping-comments').
|
||
If nil, then a default template based on the current style as indicated
|
||
by `doxymacs-doxygen-style' will be used."
|
||
:type '(choice (const :tag "None" nil)
|
||
string)
|
||
:group 'doxymacs)
|
||
|
||
(defcustom doxymacs-group-comment-end
|
||
nil
|
||
"A string to end a grouping comment (`doxymacs-insert-grouping-comments').
|
||
If nil, then a default template based on the current style as indicated
|
||
by `doxymacs-doxygen-style' will be used."
|
||
:type '(choice (const :tag "None" nil)
|
||
string)
|
||
:group 'doxymacs)
|
||
|
||
;; End of customisable variables
|
||
|
||
(defvar doxymacs-tags-buffers nil
|
||
"The buffers with our Doxygen tags; a list of the form
|
||
'((DIR . BUFFER) (...)) where:
|
||
|
||
DIR is one of the directories from `doxymacs-doxygen-dirs'; and
|
||
BUFFER is the buffer holding the Doxygen tags for that DIR.")
|
||
|
||
;; The structure of this list has been chosen for ease of use in the
|
||
;; completion functions.
|
||
(defvar doxymacs-completion-lists nil
|
||
"The lists with doxytags completions.
|
||
The structure is as follows:
|
||
|
||
( (dir1 . (symbol-1 . ((description-1a . url-1a) (description-1b . url-1b)))
|
||
(symbol-2 . ((description-2a . url-2a))))
|
||
... )
|
||
|
||
where
|
||
|
||
dir1 is one of the directories from `doxymacs-doxygen-dirs';
|
||
symbol-1 is one of the symbols in the associated Doxygen XML file;
|
||
description-1a is one of symbol-1's description from the XML file; and
|
||
url-1a is the associated URL.")
|
||
|
||
(defvar doxymacs-current-completion-list nil
|
||
"The current list we are building")
|
||
|
||
(defvar doxymacs-completion-buffer "*Completions*"
|
||
"The buffer used for displaying multiple completions.")
|
||
|
||
|
||
|
||
;; Minor mode implementation
|
||
|
||
(defvar doxymacs-mode nil
|
||
"nil disables doxymacs, non-nil enables.")
|
||
|
||
(make-variable-buffer-local 'doxymacs-mode)
|
||
|
||
(defun doxymacs-mode (&optional arg)
|
||
;; All of the following text shows up in the "mode help" (C-h m)
|
||
"Minor mode for using/creating Doxygen documentation.
|
||
To submit a problem report, request a feature or get support, please
|
||
visit doxymacs' homepage at http://doxymacs.sourceforge.net/.
|
||
|
||
To see what version of doxymacs you are running, enter
|
||
`\\[doxymacs-version]'.
|
||
|
||
In order for `doxymacs-lookup' to work you will need to customise the
|
||
variable `doxymacs-doxygen-dirs'.
|
||
|
||
Key bindings:
|
||
\\{doxymacs-mode-map}"
|
||
(interactive "P")
|
||
(setq doxymacs-mode
|
||
(if (null arg)
|
||
;; Toggle mode
|
||
(not doxymacs-mode)
|
||
;; Enable/Disable according to arg
|
||
(> (prefix-numeric-value arg) 0)))
|
||
(when doxymacs-mode
|
||
(when (boundp 'filladapt-token-table)
|
||
;; add tokens to filladapt to match doxygen markup
|
||
(let ((bullet-regexp (concat "[@\\]"
|
||
"\\(param\\(?:\\s-*"
|
||
"\\[\\(?:in\\|out\\|in,out\\)\\]\\)?"
|
||
"\\s-+\\sw+"
|
||
"\\|tparam\\s-+\\sw+"
|
||
"\\|return\\|attention\\|note"
|
||
"\\|brief\\|li\\|arg\\|remarks"
|
||
"\\|invariant\\|post\\|pre"
|
||
"\\|todo\\|warning\\|bug"
|
||
"\\|deprecated\\|since\\|test\\)")))
|
||
(unless (assoc bullet-regexp filladapt-token-table)
|
||
(setq filladapt-token-table
|
||
(append filladapt-token-table
|
||
(list (list bullet-regexp 'bullet)))))))))
|
||
|
||
;; Keymap
|
||
|
||
(defvar doxymacs-mode-map (make-sparse-keymap)
|
||
"Keymap for doxymacs minor mode.")
|
||
|
||
(define-key doxymacs-mode-map "\C-cd?"
|
||
'doxymacs-lookup)
|
||
(define-key doxymacs-mode-map "\C-cdr"
|
||
'doxymacs-rescan-tags)
|
||
|
||
(define-key doxymacs-mode-map "\C-cd\r"
|
||
'doxymacs-insert-command)
|
||
(define-key doxymacs-mode-map "\C-cdf"
|
||
'doxymacs-insert-function-comment)
|
||
(define-key doxymacs-mode-map "\C-cdi"
|
||
'doxymacs-insert-file-comment)
|
||
(define-key doxymacs-mode-map "\C-cdm"
|
||
'doxymacs-insert-blank-multiline-comment)
|
||
(define-key doxymacs-mode-map "\C-cds"
|
||
'doxymacs-insert-blank-singleline-comment)
|
||
(define-key doxymacs-mode-map "\C-cd;"
|
||
'doxymacs-insert-member-comment)
|
||
(define-key doxymacs-mode-map "\C-cd@"
|
||
'doxymacs-insert-grouping-comments)
|
||
|
||
|
||
;;;###autoload
|
||
(or (assoc 'doxymacs-mode minor-mode-alist)
|
||
(setq minor-mode-alist
|
||
(cons '(doxymacs-mode " doxy") minor-mode-alist)))
|
||
|
||
(or (assoc 'doxymacs-mode minor-mode-map-alist)
|
||
(setq minor-mode-map-alist
|
||
(cons (cons 'doxymacs-mode doxymacs-mode-map)
|
||
minor-mode-map-alist)))
|
||
|
||
;; This stuff has to do with fontification
|
||
;; Thanks to Alec Panovici for the idea.
|
||
|
||
(defconst doxymacs-doxygen-keywords
|
||
(list
|
||
(list
|
||
;; One shot keywords that take no arguments
|
||
(concat "\\([@\\\\]\\(brief\\|li\\|\\(end\\)?code\\|sa"
|
||
"\\|note\\|\\(end\\)?verbatim\\|return\\|arg\\|fn"
|
||
"\\|hideinitializer\\|showinitializer"
|
||
;; FIXME
|
||
;; How do I get & # < > % to work?
|
||
;;"\\|\\\\&\\|\\$\\|\\#\\|<\\|>\\|\\%"
|
||
"\\|\\$"
|
||
"\\|internal\\|nosubgrouping\\|author\\|date\\|endif"
|
||
"\\|invariant\\|post\\|pre\\|remarks\\|since\\|test\\|version"
|
||
"\\|\\(end\\)?htmlonly\\|\\(end\\)?latexonly\\|f\\$\\|file"
|
||
"\\|\\(end\\)?xmlonly\\|\\(end\\)?manonly\\|property"
|
||
"\\|mainpage\\|name\\|overload\\|typedef\\|deprecated\\|par"
|
||
"\\|addindex\\|line\\|skip\\|skipline\\|until\\|see"
|
||
"\\|endlink\\|callgraph\\|endcond\\|else\\)\\)\\>")
|
||
'(0 font-lock-keyword-face prepend))
|
||
;; attention, warning, etc. given a different font
|
||
(list
|
||
"\\([@\\\\]\\(attention\\|warning\\|todo\\|bug\\)\\)\\>"
|
||
'(0 font-lock-warning-face prepend))
|
||
;; keywords that take a variable name as an argument
|
||
(list
|
||
(concat "\\([@\\\\]\\(param\\(?:\\s-*\\[\\(?:in\\|out\\|in,out\\)\\]\\)?"
|
||
"\\|tparam\\|a\\|namespace\\|relates\\(also\\)?"
|
||
"\\|var\\|def\\)\\)\\s-+\\(\\sw+\\)")
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(4 font-lock-variable-name-face prepend))
|
||
;; keywords that take a type name as an argument
|
||
(list
|
||
(concat "\\([@\\\\]\\(class\\|struct\\|union\\|exception\\|enum"
|
||
"\\|throw\\|interface\\|protocol\\)\\)\\s-+\\(\\(\\sw\\|:\\)+\\)")
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(3 font-lock-type-face prepend))
|
||
;; keywords that take a function name as an argument
|
||
(list
|
||
"\\([@\\\\]retval\\)\\s-+\\([^ \t\n]+\\)"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(2 font-lock-function-name-face prepend))
|
||
;; bold
|
||
(list
|
||
"\\([@\\\\]b\\)\\s-+\\([^ \t\n]+\\)"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(2 (quote bold) prepend))
|
||
;; code
|
||
(list
|
||
"\\([@\\\\][cp]\\)\\s-+\\([^ \t\n]+\\)"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(2 (quote underline) prepend))
|
||
;; italics/emphasised
|
||
(list
|
||
"\\([@\\\\]e\\(m\\)?\\)\\s-+\\([^ \t\n]+\\)"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(3 (quote italic) prepend))
|
||
;; keywords that take a list
|
||
(list
|
||
"\\([@\\\\]ingroup\\)\\s-+\\(\\(\\sw+\\s-*\\)+\\)\\s-*$"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(2 font-lock-string-face prepend))
|
||
;; one argument that can contain arbitrary non-whitespace stuff
|
||
(list
|
||
(concat "\\([@\\\\]\\(link\\|copydoc\\|xrefitem"
|
||
"\\|if\\(not\\)?\\|elseif\\)\\)"
|
||
"\\s-+\\([^ \t\n]+\\)")
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(4 font-lock-string-face prepend))
|
||
;; one optional argument that can contain arbitrary non-whitespace stuff
|
||
(list
|
||
"\\([@\\\\]\\(cond\\|dir\\)\\(\\s-+[^ \t\n]+\\)?\\)"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(3 font-lock-string-face prepend t))
|
||
;; one optional argument with no space between
|
||
(list
|
||
"\\([@\\\\]\\(~\\)\\([^ \t\n]+\\)?\\)"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(3 font-lock-string-face prepend t))
|
||
;; one argument that has to be a filename
|
||
(list
|
||
(concat "\\([@\\\\]\\(example\\|\\(dont\\)?include\\|includelineno"
|
||
"\\|htmlinclude\\|verbinclude\\)\\)\\s-+"
|
||
"\\(\"?[~:\\/a-zA-Z0-9_. ]+\"?\\)")
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(4 font-lock-string-face prepend))
|
||
;; dotfile <file> ["caption"]
|
||
(list
|
||
(concat "\\([@\\\\]dotfile\\)\\s-+"
|
||
"\\(\"?[~:\\/a-zA-Z0-9_. ]+\"?\\)\\(\\s-+\"[^\"]+\"\\)?")
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(2 font-lock-string-face prepend)
|
||
'(3 font-lock-string-face prepend t))
|
||
;; image <format> <file> ["caption"] [<sizeindication>=<size>]
|
||
(list
|
||
"\\([@\\\\]image\\)\\s-+\\(html\\|latex\\)\\s-+\\(\"?[~:\\/a-zA-Z0-9_. ]+\"?\\)\\(\\s-+\"[^\"]+\"\\)?\\(\\s-+\\sw+=[0-9]+\\sw+\\)?"
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(2 font-lock-string-face prepend)
|
||
'(3 font-lock-string-face prepend)
|
||
'(4 font-lock-string-face prepend t)
|
||
'(5 font-lock-string-face prepend t))
|
||
;; one argument that has to be a word
|
||
(list
|
||
(concat "\\([@\\\\]\\(addtogroup\\|defgroup\\|weakgroup"
|
||
"\\|page\\|anchor\\|ref\\|section\\|subsection"
|
||
"\\)\\)\\s-+\\(\\sw+\\)")
|
||
'(1 font-lock-keyword-face prepend)
|
||
'(3 font-lock-string-face prepend))))
|
||
|
||
(defun doxymacs-font-lock ()
|
||
"Turn on font-lock for Doxygen keywords."
|
||
;; FIXME How do I turn *off* font-lock for Doxygen keywords?
|
||
(interactive)
|
||
(if (functionp 'font-lock-add-keywords)
|
||
;; Use new (proper?) font-lock-add-keywords function
|
||
(font-lock-add-keywords nil doxymacs-doxygen-keywords)
|
||
;; Use old-school way
|
||
(let ((old (if (eq (car-safe font-lock-keywords) t)
|
||
(cdr font-lock-keywords)
|
||
font-lock-keywords)))
|
||
(setq font-lock-keywords (append old doxymacs-doxygen-keywords)))))
|
||
|
||
|
||
|
||
|
||
;;These functions have to do with looking stuff up in doxygen generated
|
||
;;documentation
|
||
|
||
|
||
;; Utility functions to look up filenames in the various association lists
|
||
;; we have
|
||
|
||
(defun doxymacs-filename-to-element (f a)
|
||
"Lookup filename in one of our association lists and return associated
|
||
element"
|
||
(catch 'done
|
||
(while a
|
||
(if (string-match (caar a) f)
|
||
(throw 'done
|
||
(cdar a))
|
||
(setq a (cdr a))))))
|
||
|
||
(defun doxymacs-filename-to-xml (f)
|
||
"Lookup filename in `doxymacs-doxygen-dirs' and return associated XML tags
|
||
file."
|
||
(let ((xml-url (doxymacs-filename-to-element f doxymacs-doxygen-dirs)))
|
||
(if xml-url
|
||
(car xml-url))))
|
||
|
||
(defun doxymacs-filename-to-url (f)
|
||
"Lookup filename in `doxymacs-doxygen-dirs' and return associated Doxygen
|
||
documentation URL root."
|
||
(let ((xml-url (doxymacs-filename-to-element f doxymacs-doxygen-dirs)))
|
||
(if xml-url
|
||
(cadr xml-url))))
|
||
|
||
(defun doxymacs-filename-to-buffer (f)
|
||
"Lookup filename in `doxymacs-tags-buffers' and return associated buffer."
|
||
(doxymacs-filename-to-element f doxymacs-tags-buffers))
|
||
|
||
(defun doxymacs-filename-to-completion-list (f)
|
||
"Lookup filename in `doxymacs-completion-lists' and return associated
|
||
completion list."
|
||
(doxymacs-filename-to-element f doxymacs-completion-lists))
|
||
|
||
(defun doxymacs-filename-to-dir (f)
|
||
"Lookup filename in `doxymacs-doxygen-dirs' and return associated dir."
|
||
(catch 'done
|
||
(let ((dirs doxymacs-doxygen-dirs))
|
||
(while dirs
|
||
(if (string-match (caar dirs) f)
|
||
(throw 'done
|
||
(caar dirs))
|
||
(setq dirs (cdr dirs)))))))
|
||
|
||
(defun doxymacs-set-dir-element (dir l e)
|
||
"Set the element associated with dir in l to e."
|
||
(catch 'done
|
||
(while l
|
||
(let ((pair (car l)))
|
||
(if (string= (car pair) dir)
|
||
(throw 'done
|
||
(setcdr pair e))
|
||
(setq l (cdr l)))))))
|
||
|
||
(defun doxymacs-set-tags-buffer (dir buffer)
|
||
"Set the buffer associated with dir in `doxymacs-tags-buffers' to the given
|
||
buffer."
|
||
(doxymacs-set-dir-element dir doxymacs-tags-buffers buffer))
|
||
|
||
(defun doxymacs-set-completion-list (dir comp-list)
|
||
"Set the completion list associated with dir in `doxymcas-completion-lists'
|
||
to comp-list."
|
||
(doxymacs-set-dir-element dir doxymacs-completion-lists comp-list))
|
||
|
||
(defun doxymacs-url-exists-p (url)
|
||
"Return t iff the URL exists."
|
||
(let* ((urlobj (url-generic-parse-url url))
|
||
(type (url-type urlobj))
|
||
(exists nil))
|
||
(cond
|
||
((equal type "http")
|
||
(cond
|
||
;; Try url-file-exists, if it exists
|
||
((fboundp 'url-file-exists)
|
||
(setq exists (url-file-exists url)))
|
||
;; Otherwise, try url-file-exists-p (newer url.el)
|
||
((fboundp 'url-file-exists-p)
|
||
(setq exists (url-file-exists-p url)))
|
||
;; Otherwise, try wget
|
||
((executable-find (if (eq system-type 'windows-nt) "wget.exe" "wget"))
|
||
(if (string-match "200 OK"
|
||
(shell-command-to-string
|
||
(concat "wget -S --spider " url)))
|
||
(setq exists t)))
|
||
;; Otherwise, try lynx
|
||
((executable-find (if (eq system-type 'windows-nt) "lynx.exe" "lynx"))
|
||
(if (string-match "200 OK"
|
||
(shell-command-to-string
|
||
(concat "lynx -head -source " url)))
|
||
(setq exists t)))
|
||
;; Give up.
|
||
(t (error "Could not find url-file-exists, url-file-exists-p, wget or lynx"))))
|
||
((equal type "file")
|
||
(setq exists (file-exists-p (url-filename urlobj))))
|
||
(t (error (concat "Scheme " type " not supported for URL " url))))
|
||
exists))
|
||
|
||
(defun doxymacs-load-tags (f)
|
||
"Loads a Doxygen generated XML tags file into the buffer *doxytags*."
|
||
(let* ((tags-buffer (doxymacs-filename-to-buffer f))
|
||
(dir (doxymacs-filename-to-dir f))
|
||
(xml (doxymacs-filename-to-xml f)))
|
||
(if (and xml dir)
|
||
(if (or (eq tags-buffer nil)
|
||
(eq (buffer-live-p tags-buffer) nil))
|
||
(let ((new-buffer (generate-new-buffer "*doxytags")))
|
||
(if tags-buffer
|
||
;; tags-buffer is non-nil, which means someone
|
||
;; killed the buffer... so reset it
|
||
(doxymacs-set-tags-buffer dir new-buffer)
|
||
;; Otherwise add to list
|
||
(setq doxymacs-tags-buffers
|
||
(cons (cons dir new-buffer) doxymacs-tags-buffers)))
|
||
(message (concat "Loading " xml "..."))
|
||
(let ((currbuff (current-buffer)))
|
||
(if (file-regular-p xml)
|
||
;;It's a regular file, so just grab it.
|
||
(progn
|
||
(set-buffer new-buffer)
|
||
(insert-file-contents xml))
|
||
;; Otherwise, try and grab it as a URL
|
||
(progn
|
||
(if (doxymacs-url-exists-p xml)
|
||
(progn
|
||
(set-buffer new-buffer)
|
||
(url-insert-file-contents xml)
|
||
(set-buffer-modified-p nil))
|
||
(progn
|
||
(kill-buffer new-buffer)
|
||
(set-buffer currbuff)
|
||
(error (concat
|
||
"Tag file " xml " not found."))))))
|
||
(set-buffer currbuff))))
|
||
;; Couldn't find this file in doxymacs-doxygen-dirs
|
||
(error (concat "File " (buffer-file-name)
|
||
" does not match any directories in"
|
||
" doxymacs-doxygen-dirs.")))))
|
||
|
||
(defun doxymacs-add-to-completion-list (symbol desc url)
|
||
"Add a symbol to our completion list, along with its description and URL."
|
||
(let ((check (assoc symbol doxymacs-current-completion-list)))
|
||
(if check
|
||
;; There is already a symbol with the same name in the list
|
||
(if (not (assoc desc (cdr check)))
|
||
;; If there is not yet a symbol with this desc, add it
|
||
;; FIXME: what to do if there is already a symbol??
|
||
(setcdr check (cons (cons desc url)
|
||
(cdr check))))
|
||
;; There is not yet a symbol with this name in the list
|
||
(setq doxymacs-current-completion-list
|
||
(cons (cons symbol (list (cons desc url)))
|
||
doxymacs-current-completion-list)))))
|
||
|
||
(defun doxymacs-fill-completion-list-with-external-parser (f)
|
||
"Use external parser to parse Doxygen XML tags file and get the
|
||
completion list."
|
||
(doxymacs-load-tags f)
|
||
(let ((currbuff (current-buffer))
|
||
(dir (doxymacs-filename-to-dir f))
|
||
(comp-list (doxymacs-filename-to-completion-list f))
|
||
(tags-buffer (doxymacs-filename-to-buffer f)))
|
||
(set-buffer tags-buffer)
|
||
(goto-char (point-min))
|
||
(doxymacs-set-completion-list dir nil)
|
||
(message (concat
|
||
"Executing external process "
|
||
doxymacs-external-xml-parser-executable
|
||
"..."))
|
||
(let ((status (call-process-region
|
||
(point-min) (point-max)
|
||
doxymacs-external-xml-parser-executable
|
||
t t)))
|
||
(if (eq status 0)
|
||
(progn
|
||
(goto-char (point-min))
|
||
(message "Reading completion list...")
|
||
(let ((new-list (read (current-buffer))))
|
||
(if comp-list
|
||
;; Replace
|
||
(doxymacs-set-completion-list dir new-list)
|
||
;; Add
|
||
(setq doxymacs-completion-lists
|
||
(cons (cons dir new-list)
|
||
doxymacs-completion-lists))))
|
||
(message "Done.")
|
||
(set-buffer-modified-p nil)
|
||
(kill-buffer tags-buffer)
|
||
(set-buffer currbuff))
|
||
(progn
|
||
(switch-to-buffer tags-buffer)
|
||
(message (concat
|
||
"There were problems parsing "
|
||
(doxymacs-filename-to-xml f) ".")))))))
|
||
|
||
|
||
(defun doxymacs-xml-progress-callback (amount-done)
|
||
"Let the user know how far along the XML parsing is."
|
||
(message (concat "Parsing ... " (format "%0.1f" amount-done) "%%")))
|
||
|
||
(defun doxymacs-fill-completion-list-with-internal-parser (f)
|
||
"Load and parse the tags from the *doxytags* buffer, constructing our
|
||
`doxymacs-completion-list' from it using the internal XML file parser."
|
||
(doxymacs-load-tags f)
|
||
(let ((currbuff (current-buffer))
|
||
(dir (doxymacs-filename-to-dir f))
|
||
(tags-buffer (doxymacs-filename-to-buffer f)))
|
||
(set-buffer tags-buffer)
|
||
(goto-char (point-min))
|
||
(setq doxymacs-current-completion-list nil)
|
||
(let ((xml (read-xml 'doxymacs-xml-progress-callback))) ;Parse the file
|
||
(let* ((compound-list (xml-tag-children xml))
|
||
(num-compounds (length compound-list))
|
||
(curr-compound-num 0))
|
||
(if (not (string= (xml-tag-name xml) "tagfile"))
|
||
(error (concat "Invalid tag file: " (doxymacs-filename-to-xml f)))
|
||
;; Go through the compounds, adding them and their members to the
|
||
;; completion list.
|
||
(while compound-list
|
||
(let* ((curr-compound (car compound-list))
|
||
(compound-name (cadr (xml-tag-child curr-compound "name")))
|
||
(compound-kind (xml-tag-attr curr-compound "kind"))
|
||
(compound-url (cadr
|
||
(xml-tag-child curr-compound "filename")))
|
||
(compound-desc (concat compound-kind " " compound-name)))
|
||
;; Work around apparent bug in Doxygen 1.2.18
|
||
(if (not (string-match "\\.html$" compound-url))
|
||
(setq compound-url (concat compound-url ".html")))
|
||
|
||
;; Add this compound to our completion list for this directory
|
||
(doxymacs-add-to-completion-list compound-name
|
||
compound-desc
|
||
compound-url)
|
||
;; Add its members
|
||
(doxymacs-add-compound-members curr-compound
|
||
compound-name
|
||
compound-url)
|
||
;; On to the next compound
|
||
(message (concat
|
||
"Building completion table... "
|
||
(format "%0.1f"
|
||
(* (/
|
||
(float curr-compound-num)
|
||
(float num-compounds))
|
||
100))
|
||
"%%"))
|
||
(setq curr-compound-num (1+ curr-compound-num))
|
||
(setq compound-list (cdr compound-list)))))))
|
||
(if (doxymacs-filename-to-completion-list f)
|
||
;; Replace
|
||
(doxymacs-set-completion-list dir doxymacs-current-completion-list)
|
||
;; Add
|
||
(setq doxymacs-completion-lists
|
||
(cons (cons dir doxymacs-current-completion-list)
|
||
doxymacs-completion-lists)))
|
||
(setq doxymacs-current-completion-list nil)
|
||
(message "Done.")
|
||
;; Don't need the doxytags buffer anymore
|
||
(set-buffer-modified-p nil)
|
||
(kill-buffer tags-buffer)
|
||
(set-buffer currbuff)))
|
||
|
||
(defun doxymacs-add-compound-members (compound compound-name compound-url)
|
||
"Get the members of the given compound"
|
||
(let ((children (xml-tag-children compound)))
|
||
;; Run through the children looking for ones with the "member" tag
|
||
(while children
|
||
(let* ((curr-child (car children)))
|
||
(if (string= (xml-tag-name curr-child) "member")
|
||
;; Found a member. Throw it on the list.
|
||
(let* ((member-name (cadr (xml-tag-child curr-child "name")))
|
||
(member-anchor (cadr (xml-tag-child curr-child "anchor")))
|
||
(member-url (concat compound-url "#" member-anchor))
|
||
(member-args (if (cdr (xml-tag-child curr-child "arglist"))
|
||
(cadr (xml-tag-child curr-child "arglist"))
|
||
""))
|
||
(member-desc (concat compound-name "::"
|
||
member-name member-args)))
|
||
(doxymacs-add-to-completion-list member-name
|
||
member-desc
|
||
member-url)))
|
||
(setq children (cdr children))))))
|
||
|
||
(defun doxymacs-display-url (root url)
|
||
"Displays the given match."
|
||
(apply doxymacs-browse-url-function (list (concat root "/" url))))
|
||
|
||
;; Some versions of GNU Emacs don't have symbol-near-point apparently
|
||
;; stolen from browse-cltl2.el, and in turn:
|
||
;; stolen from XEmacs 19.15 syntax.el
|
||
(defun doxymacs-symbol-near-point ()
|
||
"Return the first textual item to the nearest point."
|
||
(if (fboundp 'symbol-near-point)
|
||
(symbol-near-point)
|
||
;;alg stolen from etag.el
|
||
(save-excursion
|
||
(if (not (memq (char-syntax (preceding-char)) '(?w ?_)))
|
||
(while (not (looking-at "\\sw\\|\\s_\\|\\'"))
|
||
(forward-char 1)))
|
||
(while (looking-at "\\sw\\|\\s_")
|
||
(forward-char 1))
|
||
(if (re-search-backward "\\sw\\|\\s_" nil t)
|
||
(regexp-quote
|
||
(progn (forward-char 1)
|
||
(buffer-substring (point)
|
||
(progn (forward-sexp -1)
|
||
(while (looking-at "\\s'")
|
||
(forward-char 1))
|
||
(point)))))
|
||
nil))))
|
||
|
||
(defun doxymacs-lookup (symbol &optional filename)
|
||
"Look up the symbol under the cursor in Doxygen generated documentation."
|
||
(interactive
|
||
(let* ((f (buffer-file-name))
|
||
(completion-list (doxymacs-filename-to-completion-list f)))
|
||
(if (eq f nil)
|
||
(error "Current buffer has no file name associated with it.")
|
||
(progn
|
||
(save-excursion
|
||
(if (eq completion-list nil)
|
||
;;Build our completion list if not already done
|
||
(if doxymacs-use-external-xml-parser
|
||
(doxymacs-fill-completion-list-with-external-parser f)
|
||
(doxymacs-fill-completion-list-with-internal-parser f)))
|
||
(let ((symbol (completing-read
|
||
"Look up: "
|
||
completion-list nil nil
|
||
(doxymacs-symbol-near-point)))
|
||
(filename f))
|
||
(list symbol filename)))))))
|
||
(let ((url (doxymacs-symbol-completion
|
||
symbol
|
||
(doxymacs-filename-to-completion-list filename))))
|
||
(if url
|
||
(doxymacs-display-url (doxymacs-filename-to-url filename) url))))
|
||
|
||
(defun doxymacs-display-completions (initial collection &optional pred)
|
||
"Display available completions."
|
||
(let ((matches (all-completions initial collection pred)))
|
||
;; FIXME - Is this the proper way of doing this? Seems to work, but...
|
||
(set-buffer (format " *Minibuf-%d*"
|
||
;; Here's a kludge.
|
||
(if (featurep 'xemacs)
|
||
(minibuffer-depth)
|
||
(1+ (minibuffer-depth)))))
|
||
(with-output-to-temp-buffer doxymacs-completion-buffer
|
||
(display-completion-list (sort matches 'string-lessp)))))
|
||
|
||
(defun doxymacs-symbol-completion (initial collection &optional pred)
|
||
"Do completion for given symbol."
|
||
(let ((completion (try-completion initial collection pred)))
|
||
(cond ((eq completion t)
|
||
;; Only one completion found. Validate it.
|
||
(doxymacs-validate-symbol-completion initial collection pred))
|
||
((null completion)
|
||
;; No completion found
|
||
(message "No documentation for '%s'" initial)
|
||
(ding))
|
||
(t
|
||
;; There is more than one possible completion
|
||
(doxymacs-display-completions initial collection pred)
|
||
(let ((completion (completing-read
|
||
"Select: "
|
||
collection pred nil initial)))
|
||
(delete-window (get-buffer-window doxymacs-completion-buffer))
|
||
(if completion
|
||
;; If there is a completion, validate it.
|
||
(doxymacs-validate-symbol-completion
|
||
completion collection pred)
|
||
;; Otherwise just return nil
|
||
nil))))))
|
||
|
||
(defun doxymacs-validate-symbol-completion (initial collection &optional pred)
|
||
"Checks whether the symbol (initial) has multiple descriptions, and if so
|
||
continue completion on those descriptions. In the end it returns the URL for
|
||
the completion or nil if canceled by the user."
|
||
(let ((new-collection (cdr (assoc initial collection))))
|
||
(if (> (length new-collection) 1)
|
||
;; More than one
|
||
(doxymacs-description-completion "" new-collection pred)
|
||
;; Only one, return the URL
|
||
(cdar new-collection))))
|
||
|
||
(defun doxymacs-description-completion (initial collection &optional pred)
|
||
"Do completion for given description."
|
||
(doxymacs-display-completions initial collection pred)
|
||
(let ((completion (completing-read "Select: " collection pred nil initial)))
|
||
(delete-window (get-buffer-window doxymacs-completion-buffer))
|
||
(if completion
|
||
;; Return the URL if there is a completion
|
||
(cdr (assoc completion collection)))))
|
||
|
||
;;This is mostly a convenience function for the user
|
||
(defun doxymacs-rescan-tags ()
|
||
"Rescan the Doxygen XML tags file in `doxymacs-doxygen-tags'."
|
||
(interactive)
|
||
(let* ((f (buffer-file-name))
|
||
(tags-buffer (doxymacs-filename-to-buffer f)))
|
||
(if (buffer-live-p tags-buffer)
|
||
(kill-buffer tags-buffer))
|
||
(if doxymacs-use-external-xml-parser
|
||
(doxymacs-fill-completion-list-with-external-parser f)
|
||
(doxymacs-fill-completion-list-with-internal-parser f))))
|
||
|
||
|
||
;; These functions have to do with inserting doxygen commands in code
|
||
|
||
;; FIXME
|
||
;; So, in the source code for XEmacs 21.1.14, they commented out the
|
||
;; definition of deactivate-mark for some reason... and the tempo package
|
||
;; needs it. So, here is a placeholder just to get it to stop
|
||
;; complaining. This is a hack, since I don't know what the proper fix
|
||
;; should be.
|
||
(if (not (fboundp 'deactivate-mark))
|
||
(defsubst deactivate-mark ()
|
||
(zmacs-deactivate-region))) ; Is this correct?
|
||
;; Also need a hack for mark-active
|
||
(if (not (boundp 'mark-active))
|
||
(defvar mark-active nil)) ; Is this correct? Probably not.
|
||
|
||
;; Inserting commands with completion
|
||
|
||
(defvar doxymacs-insert-command-history nil)
|
||
|
||
(defvar doxymacs-commands
|
||
'(("a" (word "Argument"))
|
||
("addindex" (newline "Text to add to LaTeX index"))
|
||
("addtogroup" (word "Name of group") (newline optional "Title of group"))
|
||
("anchor" (word "Name of anchor"))
|
||
("arg" "Argument description")
|
||
("attention" "Attention text")
|
||
("author" "List of authors")
|
||
("b" (word "Word to display in bold"))
|
||
("brief" "Brief description")
|
||
("bug" "Bug description")
|
||
("c" "Word to display as code")
|
||
("callgraph")
|
||
("callergraph")
|
||
("category" (word "Name of category") (optional word "Header file")
|
||
(optional word "Header name"))
|
||
("class" (word "Name of class") (optional word "Header file")
|
||
(optional word "Header name"))
|
||
("code")
|
||
("cond" (optional word "Section label"))
|
||
("copybrief" (word "Link object"))
|
||
("copydetails" (word "Link object"))
|
||
("copydoc" (word "Link object"))
|
||
("date" "Date description")
|
||
("def" (word "#define macro name"))
|
||
("defgroup" (word "Name of group") (newline "Group title"))
|
||
("deprecated" "Deprecated description")
|
||
("details" "Detailed description")
|
||
("dir" (word optional "Path fragment"))
|
||
("dontinclude" (word "File name"))
|
||
("dot")
|
||
("dotfile" (word "File name") (optional "Caption (must be in quotes)"))
|
||
("e" (word "Word to display in italics"))
|
||
("else")
|
||
("elseif" (word "Section label"))
|
||
("em" (word "Word to display in italics"))
|
||
("endcode")
|
||
("endcond")
|
||
("enddot")
|
||
("endhtmlonly")
|
||
("endif")
|
||
("endlatexonly")
|
||
("endlink")
|
||
("endmanonly")
|
||
("endmsc")
|
||
("endverbatim")
|
||
("endxmlonly")
|
||
("enum" (word "Enumeration name"))
|
||
("example" (word "File name"))
|
||
("exception" (word "Exception object") "Exception description")
|
||
("extends" (word "Name"))
|
||
("f$")
|
||
("f[")
|
||
("f]")
|
||
("f{" "Environment")
|
||
("f}")
|
||
("file" (optional word "File name"))
|
||
("fn" (newline "Function declaration"))
|
||
("headerfile" (word "Header file") (optional word) "Header name")
|
||
("hideinitializer")
|
||
("htmlinclude" (word "File name"))
|
||
("htmlonly")
|
||
("if" (word "Section label"))
|
||
("ifnot" (word "Section label"))
|
||
("image" (word "Format") (word "File name")
|
||
(optional "Caption (must be in quotes)") (optional "Size indication"))
|
||
("implements" (word "Name"))
|
||
("include" (word "File name"))
|
||
("includelineno" (word "File name"))
|
||
("ingroup" (word "Group name"))
|
||
("internal")
|
||
("invariant" "Invariant description")
|
||
("interface" (word "Name") (optional word "Header file")
|
||
(optional word "Header Name"))
|
||
("latexonly")
|
||
("li" "Item description")
|
||
("line" (newline "Line pattern"))
|
||
("link" (word "Link object"))
|
||
("mainpage" (newline optional "Title"))
|
||
("manonly")
|
||
("memberof" (word "Name"))
|
||
("msc")
|
||
("n")
|
||
("name" (newline "Header"))
|
||
("namespace" (word "Name"))
|
||
("nosubgrouping")
|
||
("note" "Text of note")
|
||
("overload" (newline optional "Function declaration"))
|
||
("p" (word "Word to display as a parameter"))
|
||
("package" (word "Name"))
|
||
("page" (word "Name") (newline "Title"))
|
||
("par" (newline optional "Title") "Paragraph text")
|
||
("paragraph" (word "Paragraph name") (newline "Paragraph title"))
|
||
("param" (word "Parameter") "Parameter description")
|
||
("param[in]" (word "Parameter") "Parameter description")
|
||
("param[out]" (word "Parameter") "Parameter description")
|
||
("param[in,out]" (word "Parameter") "Parameter description")
|
||
("post" "Post-condition description")
|
||
("pre" "Pre-condition description")
|
||
("private")
|
||
("privatesection")
|
||
("property" (newline "Qualified property name"))
|
||
("protected")
|
||
("protectedsection")
|
||
("protocol" (word "Name") (optional word "Header file")
|
||
(optional word "Header name"))
|
||
("public")
|
||
("publicsection")
|
||
("ref" (word "Name") (newline optional "Text"))
|
||
("relates" (word "Name"))
|
||
("relatesalso" (word "Name"))
|
||
("remarks" "Remarks text")
|
||
("return" "Description of return value")
|
||
("retval" (word "Return value") "Description")
|
||
("sa" "References")
|
||
("section" (word "Section name") (newline "Section title"))
|
||
("see" "References")
|
||
("showinitializer")
|
||
("since" "Text")
|
||
("skip" (newline "Pattern"))
|
||
("skipline" (newline "Pattern"))
|
||
("struct" (word "Name") (optional word "Header file")
|
||
(optional word "Header name"))
|
||
("subpage" (word "Name") (newline optional "Text"))
|
||
("subsection" (word "Name") (newline optional "Title"))
|
||
("subsubsection" (word "Name") (newline optional "Title"))
|
||
("test" "Paragraph describing test case")
|
||
("throw" (word "Exception object") "Exception description")
|
||
("todo" "Paragraph describing what needs to be done")
|
||
("tparam" (word "Template parameter") "Description")
|
||
("typedef" (newline "Typedef declaration"))
|
||
("union" (word "Name") (optional word "Header file")
|
||
(optional word "Header name"))
|
||
("until" (newline "Pattern"))
|
||
("var" (newline "Variable declaration"))
|
||
("verbatim")
|
||
("verbinclude" (word "File name"))
|
||
("version" "Version number")
|
||
("warning" "Warning message")
|
||
("weakgroup" (word "Name") (newline optional "Title"))
|
||
("xmlonly")
|
||
("xrefitem" (word "Key") "Heading (must be in quotes)"
|
||
"List title (must be in quotes)" "Text")
|
||
("$")
|
||
("@")
|
||
("\\")
|
||
("&")
|
||
("~" (optional "Language ID"))
|
||
("<")
|
||
(">")
|
||
("#")
|
||
("%")
|
||
("\""))
|
||
"Available doxygen commands. Format is
|
||
|
||
'((\"command\" args) ...)
|
||
|
||
where:
|
||
|
||
- command is the doxygen command.
|
||
- args is a list of prompts to display for each argument to the
|
||
command. An element of args could also be a list, the last element of which must be a string to use for the prompt, and other elements may be:
|
||
- newline to indicate a newline should be appended to the user's input.
|
||
- word to indicate the argument accepts a single word only.
|
||
- optional to indicate the argument is optional.")
|
||
|
||
(defun doxymacs-insert-command (cmd)
|
||
"Insert a doxymacs command with completion."
|
||
(interactive (list (completing-read
|
||
"Insert doxygen command: "
|
||
doxymacs-commands
|
||
nil nil nil 'doxymacs-insert-command-history)))
|
||
(insert (concat (doxymacs-doxygen-command-char) cmd))
|
||
(dolist (arg-prompt (cdr-safe (assoc cmd doxymacs-commands)))
|
||
(let ((arg (doxymacs-read-arg arg-prompt)))
|
||
(if (or (= (length arg) 0) (string= "\n" arg))
|
||
;; If nothing is entered no point in prompting for the rest of
|
||
;; the args.
|
||
(return)
|
||
(insert (concat " " arg))))))
|
||
|
||
(defun doxymacs-read-arg (arg)
|
||
(let* ((newline (and (listp arg) (memq 'newline arg)))
|
||
(word (and (listp arg) (memq 'word arg)))
|
||
(optional (and (listp arg) (memq 'optional arg)))
|
||
(prompt (if (listp arg) (car (last arg)) arg))
|
||
(final-prompt (concat prompt
|
||
(if optional (concat " (optional)"))
|
||
(if word (concat " (word)"))
|
||
": ")))
|
||
(concat
|
||
(cond (word
|
||
(read-no-blanks-input final-prompt))
|
||
(t
|
||
(read-string final-prompt)))
|
||
(if newline "\n"))))
|
||
|
||
|
||
;; Default templates
|
||
|
||
(defconst doxymacs-JavaDoc-blank-multiline-comment-template
|
||
'("/**" > n "* " p > n "* " > n "*/" > n)
|
||
"Default JavaDoc-style template for a blank multiline doxygen comment.")
|
||
|
||
(defconst doxymacs-Qt-blank-multiline-comment-template
|
||
'("//! " p > n "/*! " > n > n "*/" > n)
|
||
"Default Qt-style template for a blank multiline doxygen comment.")
|
||
|
||
(defconst doxymacs-C++-blank-multiline-comment-template
|
||
'("///" > n "/// " p > n "///" > n)
|
||
"Default C++-style template for a blank multiline doxygen comment.")
|
||
|
||
(defconst doxymacs-C++!-blank-multiline-comment-template
|
||
'("//!" > n "//! " p > n "//!" > n)
|
||
"Default C++!-style template for a blank multiline doxygen comment.")
|
||
|
||
(defconst doxymacs-JavaDoc-blank-singleline-comment-template
|
||
'("/// " > p)
|
||
"Default JavaDoc-style template for a blank single line doxygen comment.")
|
||
|
||
(defconst doxymacs-Qt-blank-singleline-comment-template
|
||
'("//! " > p)
|
||
"Default Qt-style template for a blank single line doxygen comment.")
|
||
|
||
(defconst doxymacs-C++-blank-singleline-comment-template
|
||
'("/// " > p)
|
||
"Default C++-style template for a blank single line doxygen comment.")
|
||
|
||
(defconst doxymacs-C++!-blank-singleline-comment-template
|
||
'("//! " > p)
|
||
"Default C++!-style template for a blank single line doxygen comment.")
|
||
|
||
(defun doxymacs-doxygen-command-char ()
|
||
(cond
|
||
(doxymacs-command-character doxymacs-command-character)
|
||
((string= doxymacs-doxygen-style "JavaDoc") "@")
|
||
((string= doxymacs-doxygen-style "Qt") "\\")
|
||
((string= doxymacs-doxygen-style "C++") "@")
|
||
((string= doxymacs-doxygen-style "C++!") "\\")
|
||
(t "@")))
|
||
|
||
(defun doxymacs-user-mail-address ()
|
||
"Return the user's email address"
|
||
(or
|
||
(and (and (fboundp 'user-mail-address) (user-mail-address))
|
||
(list 'l " <" (user-mail-address) ">"))
|
||
(and (and (boundp 'user-mail-address) user-mail-address)
|
||
(list 'l " <" user-mail-address ">"))))
|
||
|
||
(defconst doxymacs-JavaDoc-file-comment-template
|
||
'("/**" > n
|
||
" * " (doxymacs-doxygen-command-char) "file "
|
||
(if (buffer-file-name)
|
||
(file-name-nondirectory (buffer-file-name))
|
||
"") > n
|
||
" * " (doxymacs-doxygen-command-char) "author " (user-full-name)
|
||
(doxymacs-user-mail-address)
|
||
> n
|
||
" * " (doxymacs-doxygen-command-char) "date " (current-time-string) > n
|
||
" * " > n
|
||
" * " (doxymacs-doxygen-command-char) "brief " (p "Brief description of this file: ") > n
|
||
" * " > n
|
||
" * " p > n
|
||
" */" > n)
|
||
"Default JavaDoc-style template for file documentation.")
|
||
|
||
(defconst doxymacs-Qt-file-comment-template
|
||
'("/*!" > n
|
||
" " (doxymacs-doxygen-command-char) "file "
|
||
(if (buffer-file-name)
|
||
(file-name-nondirectory (buffer-file-name))
|
||
"") > n
|
||
" " (doxymacs-doxygen-command-char) "author " (user-full-name)
|
||
(doxymacs-user-mail-address)
|
||
> n
|
||
" " (doxymacs-doxygen-command-char) "date " (current-time-string) > n
|
||
" " > n
|
||
" " (doxymacs-doxygen-command-char) "brief " (p "Brief description of this file: ") > n
|
||
" " > n
|
||
" " p > n
|
||
"*/" > n)
|
||
"Default Qt-style template for file documentation.")
|
||
|
||
(defconst doxymacs-C++-file-comment-template
|
||
'("///" > n
|
||
"/// " (doxymacs-doxygen-command-char) "file "
|
||
(if (buffer-file-name)
|
||
(file-name-nondirectory (buffer-file-name))
|
||
"") > n
|
||
"/// " (doxymacs-doxygen-command-char) "author " (user-full-name)
|
||
(doxymacs-user-mail-address)
|
||
> n
|
||
"/// " (doxymacs-doxygen-command-char) "date " (current-time-string) > n
|
||
"/// " > n
|
||
"/// " (doxymacs-doxygen-command-char) "brief " (p "Brief description of this file: ") > n
|
||
"/// " > n
|
||
"/// " p > n
|
||
"///" > n)
|
||
"Default C++-style template for file documentation.")
|
||
|
||
(defconst doxymacs-C++!-file-comment-template
|
||
'("//!" > n
|
||
"//! " (doxymacs-doxygen-command-char) "file "
|
||
(if (buffer-file-name)
|
||
(file-name-nondirectory (buffer-file-name))
|
||
"") > n
|
||
"//! " (doxymacs-doxygen-command-char) "author " (user-full-name)
|
||
(doxymacs-user-mail-address)
|
||
> n
|
||
"//! " (doxymacs-doxygen-command-char) "date " (current-time-string) > n
|
||
"//! " > n
|
||
"//! " (doxymacs-doxygen-command-char) "brief " (p "Brief description of this file: ") > n
|
||
"//! " > n
|
||
"//! " p > n
|
||
"//!" > n)
|
||
"Default C++!-style template for file documentation.")
|
||
|
||
|
||
(defun doxymacs-parm-tempo-element (parms)
|
||
"Inserts tempo elements for the given parms in the given style."
|
||
(if parms
|
||
(let ((prompt (concat "Parameter " (car parms) ": ")))
|
||
(cond
|
||
((string= doxymacs-doxygen-style "JavaDoc")
|
||
(list 'l " * " (doxymacs-doxygen-command-char)
|
||
"param " (car parms) " " (list 'p prompt) '> 'n
|
||
(doxymacs-parm-tempo-element (cdr parms))))
|
||
((string= doxymacs-doxygen-style "Qt")
|
||
(list 'l " " (doxymacs-doxygen-command-char)
|
||
"param " (car parms) " " (list 'p prompt) '> 'n
|
||
(doxymacs-parm-tempo-element (cdr parms))))
|
||
((string= doxymacs-doxygen-style "C++")
|
||
(list 'l "/// " (doxymacs-doxygen-command-char)
|
||
"param " (car parms) " " (list 'p prompt) '> 'n
|
||
(doxymacs-parm-tempo-element (cdr parms))))
|
||
((string= doxymacs-doxygen-style "C++!")
|
||
(list 'l "//! " (doxymacs-doxygen-command-char)
|
||
"param " (car parms) " " (list 'p prompt) '> 'n
|
||
(doxymacs-parm-tempo-element (cdr parms))))
|
||
(t
|
||
(doxymacs-invalid-style))))
|
||
nil))
|
||
|
||
|
||
(defconst doxymacs-JavaDoc-function-comment-template
|
||
'((let ((next-func (doxymacs-find-next-func)))
|
||
(if next-func
|
||
(list
|
||
'l
|
||
"/** " '> 'n
|
||
" * " 'p '> 'n
|
||
" *" '> 'n
|
||
(doxymacs-parm-tempo-element (cdr (assoc 'args next-func)))
|
||
(unless (string-match
|
||
(regexp-quote (cdr (assoc 'return next-func)))
|
||
doxymacs-void-types)
|
||
'(l " *" > n " * " (doxymacs-doxygen-command-char)
|
||
"return " (p "Returns: ") > n))
|
||
" */" '>)
|
||
(progn
|
||
(error "Can't find next function declaration.")
|
||
nil))))
|
||
"Default JavaDoc-style template for function documentation.")
|
||
|
||
(defconst doxymacs-Qt-function-comment-template
|
||
'((let ((next-func (doxymacs-find-next-func)))
|
||
(if next-func
|
||
(list
|
||
'l
|
||
"//! " 'p '> 'n
|
||
"/*! " '> 'n
|
||
" " '> 'n
|
||
(doxymacs-parm-tempo-element (cdr (assoc 'args next-func)))
|
||
(unless (string-match
|
||
(regexp-quote (cdr (assoc 'return next-func)))
|
||
doxymacs-void-types)
|
||
'(l " " > n " " (doxymacs-doxygen-command-char)
|
||
"return " (p "Returns: ") > n))
|
||
" */" '>)
|
||
(progn
|
||
(error "Can't find next function declaraton.")
|
||
nil))))
|
||
"Default Qt-style template for function documentation.")
|
||
|
||
(defconst doxymacs-C++-function-comment-template
|
||
'((let ((next-func (doxymacs-find-next-func)))
|
||
(if next-func
|
||
(list
|
||
'l
|
||
"/// " 'p '> 'n
|
||
"///" '> 'n
|
||
(doxymacs-parm-tempo-element (cdr (assoc 'args next-func)))
|
||
(unless (string-match
|
||
(regexp-quote (cdr (assoc 'return next-func)))
|
||
doxymacs-void-types)
|
||
'(l "///" > n "/// " (doxymacs-doxygen-command-char)
|
||
"return " (p "Returns: ") > n))
|
||
"///" '>)
|
||
(progn
|
||
(error "Can't find next function declaraton.")
|
||
nil))))
|
||
"Default C++-style template for function documentation.")
|
||
|
||
(defconst doxymacs-C++!-function-comment-template
|
||
'((let ((next-func (doxymacs-find-next-func)))
|
||
(if next-func
|
||
(list
|
||
'l
|
||
"//! " 'p '> 'n
|
||
"//!" '> 'n
|
||
(doxymacs-parm-tempo-element (cdr (assoc 'args next-func)))
|
||
(unless (string-match
|
||
(regexp-quote (cdr (assoc 'return next-func)))
|
||
doxymacs-void-types)
|
||
'(l "//!" > n "//! " (doxymacs-doxygen-command-char)
|
||
"return " (p "Returns: ") > n))
|
||
"//!" '>)
|
||
(progn
|
||
(error "Can't find next function declaraton.")
|
||
nil))))
|
||
"Default C++!-style template for function documentation.")
|
||
|
||
(defun doxymacs-invalid-style ()
|
||
"Warn the user that he has set `doxymacs-doxygen-style' to an invalid
|
||
style."
|
||
(error (concat
|
||
"Invalid `doxymacs-doxygen-style': "
|
||
doxymacs-doxygen-style
|
||
": must be one of \"JavaDoc\", \"Qt\", \"C++\" or \"C++!\".")))
|
||
|
||
;; This should make it easier to add new templates and cut down
|
||
;; on copy-and-paste programming.
|
||
(defun doxymacs-call-template (template-name)
|
||
"Insert the given template."
|
||
(let* ((user-template-name (concat "doxymacs-" template-name "-template"))
|
||
(user-template (car (read-from-string user-template-name)))
|
||
(default-template-name (concat "doxymacs-"
|
||
doxymacs-doxygen-style "-"
|
||
template-name "-template"))
|
||
(default-template (car (read-from-string default-template-name))))
|
||
(cond
|
||
((and (boundp user-template) ; Make sure it is a non-nil list
|
||
(listp (eval user-template))
|
||
(eval user-template))
|
||
;; Use the user's template
|
||
(tempo-insert-template user-template tempo-insert-region))
|
||
((and (boundp default-template)
|
||
(listp (eval default-template))
|
||
(eval default-template))
|
||
;; Use the default template, based on the current style
|
||
(tempo-insert-template default-template tempo-insert-region))
|
||
(t
|
||
;; Most likely, `doxymacs-doxygen-style' has been set wrong.
|
||
(doxymacs-invalid-style)))))
|
||
|
||
(defun doxymacs-insert-blank-multiline-comment ()
|
||
"Inserts a multi-line blank Doxygen comment at the current point."
|
||
(interactive "*")
|
||
(doxymacs-call-template "blank-multiline-comment"))
|
||
|
||
(defun doxymacs-insert-blank-singleline-comment ()
|
||
"Inserts a single-line blank Doxygen comment at current point."
|
||
(interactive "*")
|
||
(doxymacs-call-template "blank-singleline-comment"))
|
||
|
||
(defun doxymacs-insert-file-comment ()
|
||
"Inserts Doxygen documentation for the current file at current point."
|
||
(interactive "*")
|
||
(doxymacs-call-template "file-comment"))
|
||
|
||
(defun doxymacs-insert-function-comment ()
|
||
"Inserts Doxygen documentation for the next function declaration at
|
||
current point."
|
||
(interactive "*")
|
||
(doxymacs-call-template "function-comment"))
|
||
|
||
;; FIXME
|
||
;; The following was borrowed from "simple.el".
|
||
;; If anyone knows of a better/simpler way of doing this, please let me know.
|
||
(defconst doxymacs-comment-indent-function
|
||
(lambda (skip)
|
||
(save-excursion
|
||
(beginning-of-line)
|
||
(let ((eol (save-excursion (end-of-line) (point))))
|
||
(and skip
|
||
(re-search-forward skip eol t)
|
||
(setq eol (match-beginning 0)))
|
||
(goto-char eol)
|
||
(skip-chars-backward " \t")
|
||
(max comment-column (1+ (current-column))))))
|
||
"Function to compute desired indentation for a comment.
|
||
This function is called with skip and with point at the beginning of
|
||
the comment's starting delimiter.")
|
||
|
||
(defun doxymacs-insert-member-comment ()
|
||
"Inserts Doxygen documentation for the member on the current line in
|
||
the column given by `comment-column' (much like \\[indent-for-comment])."
|
||
(interactive "*")
|
||
(let* ((empty (save-excursion (beginning-of-line)
|
||
(looking-at "[ \t]*$")))
|
||
(starter (or doxymacs-member-comment-start
|
||
(cond
|
||
((string= doxymacs-doxygen-style "JavaDoc")
|
||
"/**< ")
|
||
((string= doxymacs-doxygen-style "Qt")
|
||
"/*!< ")
|
||
((string= doxymacs-doxygen-style "C++")
|
||
"///< ")
|
||
((string= doxymacs-doxygen-style "C++!")
|
||
"//!< ")
|
||
(t
|
||
(doxymacs-invalid-style)))))
|
||
(skip (concat (regexp-quote starter) "*"))
|
||
(ender (or doxymacs-member-comment-end
|
||
(cond
|
||
((string= doxymacs-doxygen-style "JavaDoc")
|
||
" */")
|
||
((string= doxymacs-doxygen-style "Qt")
|
||
" */")
|
||
((string= doxymacs-doxygen-style "C++")
|
||
"")
|
||
((string= doxymacs-doxygen-style "C++!")
|
||
"")
|
||
(t
|
||
(doxymacs-invalid-style))))))
|
||
(if empty
|
||
;; Insert a blank single-line comment on empty lines
|
||
(doxymacs-insert-blank-singleline-comment)
|
||
(if (null starter)
|
||
(error "No Doxygen member comment syntax defined")
|
||
(let* ((eolpos (save-excursion (end-of-line) (point)))
|
||
cpos indent begpos)
|
||
(beginning-of-line)
|
||
(if (re-search-forward skip eolpos 'move)
|
||
(progn (setq cpos (point-marker))
|
||
;; Find the start of the comment delimiter.
|
||
;; If there were paren-pairs in skip,
|
||
;; position at the end of the first pair.
|
||
(if (match-end 1)
|
||
(goto-char (match-end 1))
|
||
;; If skip matched a string with
|
||
;; internal whitespace (not final whitespace) then
|
||
;; the delimiter start at the end of that
|
||
;; whitespace. Otherwise, it starts at the
|
||
;; beginning of what was matched.
|
||
(skip-syntax-backward " " (match-beginning 0))
|
||
(skip-syntax-backward "^ " (match-beginning 0)))))
|
||
(setq begpos (point))
|
||
;; Compute desired indent.
|
||
(cond
|
||
((= (current-column) 0)
|
||
(goto-char begpos))
|
||
((= (current-column)
|
||
(setq indent (funcall doxymacs-comment-indent-function skip)))
|
||
(goto-char begpos))
|
||
(t
|
||
;; If that's different from current, change it.
|
||
(skip-chars-backward " \t")
|
||
(delete-region (point) begpos)
|
||
(indent-to indent)))
|
||
;; An existing comment?
|
||
(if cpos
|
||
(progn (goto-char cpos)
|
||
(set-marker cpos nil))
|
||
;; No, insert one.
|
||
(insert starter)
|
||
(save-excursion
|
||
(insert ender))))))))
|
||
|
||
(defun doxymacs-insert-grouping-comments (start end)
|
||
"Inserts doxygen grouping comments around the current region."
|
||
(interactive "*r")
|
||
(let* ((starter (or doxymacs-group-comment-start
|
||
(cond
|
||
((string= doxymacs-doxygen-style "JavaDoc")
|
||
"//@{")
|
||
((string= doxymacs-doxygen-style "Qt")
|
||
"/*@{*/")
|
||
((string= doxymacs-doxygen-style "C++")
|
||
"/// @{")
|
||
((string= doxymacs-doxygen-style "C++!")
|
||
"//! @{")
|
||
(t
|
||
(doxymacs-invalid-style)))))
|
||
(ender (or doxymacs-group-comment-end
|
||
(cond
|
||
((string= doxymacs-doxygen-style "JavaDoc")
|
||
"//@}")
|
||
((string= doxymacs-doxygen-style "Qt")
|
||
"/*@}*/")
|
||
((string= doxymacs-doxygen-style "C++")
|
||
"/// @}")
|
||
((string= doxymacs-doxygen-style "C++!")
|
||
"//! @}")
|
||
(t
|
||
(doxymacs-invalid-style))))))
|
||
(save-excursion
|
||
(goto-char end)
|
||
(end-of-line)
|
||
(insert ender)
|
||
(goto-char start)
|
||
(beginning-of-line)
|
||
(insert starter))))
|
||
|
||
|
||
|
||
;; These are helper functions that search for the next function
|
||
;; declerations/definition and extract its name, return type and
|
||
;; argument list. Used for documenting functions.
|
||
|
||
(defun doxymacs-extract-args-list (args-string)
|
||
"Extracts the arguments from the given list (given as a string)."
|
||
(cond
|
||
;; arg list is empty
|
||
((string-match "\\`[ \t\n]*\\'" args-string)
|
||
nil)
|
||
;; argument list consists of one word
|
||
((string-match "\\`[ \t\n]*\\([a-zA-Z0-9_]+\\)[ \t\n]*\\'" args-string)
|
||
;; ... extract this word
|
||
(let ((arg (substring args-string (match-beginning 1) (match-end 1))))
|
||
;; if this arg is a void type return nil
|
||
(if (string-match (regexp-quote arg) doxymacs-void-types)
|
||
nil
|
||
;; else return arg
|
||
(list arg))))
|
||
;; else split the string and extact var names from args
|
||
(t
|
||
(doxymacs-extract-args-list-helper
|
||
(doxymacs-save-split args-string)))))
|
||
|
||
|
||
(defun doxymacs-save-split (args-string)
|
||
"Splits a declaration list as string and returns list of single
|
||
declarations."
|
||
(let ((comma-pos (string-match "," args-string))
|
||
(paren-pos (string-match "(" args-string)))
|
||
(cond
|
||
;; no comma in string found
|
||
((null comma-pos) (list args-string))
|
||
;; comma but no parenthethes: split-string is save
|
||
((null paren-pos) (split-string args-string ","))
|
||
;; comma first then parenthesis
|
||
((< comma-pos paren-pos)
|
||
(cons (substring args-string 0 comma-pos)
|
||
(doxymacs-save-split (substring args-string (1+ comma-pos)))))
|
||
;; parenthesis first then comma. there must exist a closing parenthesis
|
||
(t
|
||
;; cut off the (...) part
|
||
(save-excursion
|
||
;; create temporary buffer
|
||
(set-buffer (get-buffer-create "*doxymacs-scratch*"))
|
||
(erase-buffer)
|
||
(insert args-string)
|
||
(beginning-of-buffer)
|
||
(search-forward "(")
|
||
(prog1
|
||
(let ((depth 1)
|
||
(exit)
|
||
(comma-found))
|
||
(while (not exit)
|
||
;; step through buffer
|
||
(forward-char 1)
|
||
(cond
|
||
;; end of buffer: exit
|
||
((= (point) (point-max)) (setq exit t))
|
||
;; decrease depth counter
|
||
((looking-at ")") (setq depth (1- depth)))
|
||
;; increase depth counter
|
||
((looking-at "(") (setq depth (1+ depth)))
|
||
;; comma at depth 0, thats it!
|
||
((and (looking-at ",") (= 0 depth))
|
||
(setq exit t)
|
||
(setq comma-found t))))
|
||
(if (not comma-found)
|
||
;; whole string is one arg
|
||
(list (buffer-substring 1 (point)))
|
||
;; else split at comma ...
|
||
(cons (buffer-substring 1 (point))
|
||
;; and split rest of declaration list
|
||
(doxymacs-save-split
|
||
(buffer-substring (1+ (point)) (point-max))))))
|
||
(kill-buffer (current-buffer))))))))
|
||
|
||
|
||
;; This regexp fails if the opt. parentheses
|
||
;; contain another level of parentheses. E.g. for:
|
||
;; int f(int (*g)(int (*h)()))
|
||
(defun doxymacs-extract-args-list-helper (args-list)
|
||
"Recursively get names of arguments."
|
||
(if args-list
|
||
(if (string-match
|
||
(concat
|
||
"\\("
|
||
"([ \t\n]*\\*[ \t\n]*\\([a-zA-Z0-9_]+\\)[ \t\n]*)"; (*varname)
|
||
"\\|" ; or
|
||
"\\*?[ \t\n]*\\([a-zA-Z0-9_]+\\)" ; opt. *, varname
|
||
"\\)"
|
||
"[ \t\n]*" ; opt. spaces
|
||
"\\(\\[[ \t\n]*[a-zA-Z0-9_]*[ \t\n]*\\]\\|" ; opt. array bounds
|
||
"([^()]*)\\)?" ; or opt. func args
|
||
"[ \t\n]*" ; opt. spaces
|
||
"\\(=[ \t\n]*[^ \t\n]+[ \t\n]*\\)?" ; optional assignment
|
||
"[ \t\n]*\\'" ; end
|
||
) (car args-list))
|
||
(cons
|
||
(cond
|
||
;; var name in: (*name)
|
||
((match-beginning 2)
|
||
(substring (car args-list) (match-beginning 2) (match-end 2)))
|
||
;; var name in: *name
|
||
((match-beginning 3)
|
||
(substring (car args-list) (match-beginning 3) (match-end 3)))
|
||
;; no match: return complete declaration
|
||
(t
|
||
(car args-list)))
|
||
(doxymacs-extract-args-list-helper (cdr args-list)))
|
||
;; else there is no match
|
||
nil)))
|
||
|
||
(defun doxymacs-core-string (s)
|
||
"Returns the argument string with leading and trailing blank
|
||
and new-line characters cut off."
|
||
(string-match "\\`[ \t\n]*\\(.*?\\)[ \t\n]*\\'" s)
|
||
(if (match-beginning 1)
|
||
(substring s (match-beginning 1) (match-end 1))
|
||
s))
|
||
|
||
(defun doxymacs-find-next-func ()
|
||
"Returns a list describing next function declaration, or nil if not found.
|
||
|
||
(cdr (assoc 'func (doxymacs-find-next-func))) is the function name (string).
|
||
(cdr (assoc 'args (doxymacs-find-next-func))) is a list of arguments.
|
||
(cdr (assoc 'return (doxymacs-find-next-func))) is the return type (string).
|
||
|
||
The argument list is a list of strings."
|
||
(interactive)
|
||
(save-excursion
|
||
(if (re-search-forward
|
||
(concat
|
||
;; return type
|
||
"\\(\\(const[ \t\n]+\\)?[a-zA-Z0-9_]+[ \t\n*&]+\\)?"
|
||
|
||
;; name
|
||
"\\(\\([a-zA-Z0-9_~:<,>*&]\\|\\([ \t\n]+::[ \t\n]+\\)\\)+"
|
||
"\\(o?perator[ \t\n]*.[^(]*\\)?\\)[ \t\n]*("
|
||
) nil t)
|
||
|
||
(let* ((func (buffer-substring (match-beginning 3) (match-end 3)))
|
||
(args (buffer-substring (point) (progn
|
||
(backward-char 1)
|
||
(forward-list)
|
||
(backward-char 1)
|
||
(point))))
|
||
(ret (cond
|
||
;; Return type specified
|
||
((match-beginning 1)
|
||
(buffer-substring (match-beginning 1) (match-end 1)))
|
||
;;Constructor/destructor
|
||
((string-match
|
||
"^\\([a-zA-Z0-9_<,>:*&]+\\)[ \t\n]*::[ \t\n]*~?\\1$"
|
||
func) "void")
|
||
;;Constructor in class decl.
|
||
((save-match-data
|
||
(re-search-backward
|
||
(concat
|
||
"class[ \t\n]+" (regexp-quote func) "[ \t\n]*{")
|
||
nil t))
|
||
"void")
|
||
;;Destructor in class decl.
|
||
((save-match-data
|
||
(and (string-match "^~\\([a-zA-Z0-9_]+\\)$" func)
|
||
(save-match-data
|
||
(re-search-backward
|
||
(concat
|
||
"class[ \t\n]+" (regexp-quote
|
||
(match-string 1 func))
|
||
"[ \t\n]*{") nil t))))
|
||
"void")
|
||
;;Default
|
||
(t "int"))))
|
||
(list (cons 'func func)
|
||
(cons 'args (doxymacs-extract-args-list args))
|
||
(cons 'return (doxymacs-core-string ret))))
|
||
nil)))
|
||
|
||
;;; doxymacs.el ends here
|