dimanche 16 août 2015

Generate gtkdoc-like comments in C code

I've worked on a C project where I needed to document C functions a certain way (similar to GtkDoc I think) using comments. I made a C prototype parser that mostly work.
The cursor has to be anywhere before the opening brace {. Given this example from PulseAudio:
int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) {
    pa_strbuf *buf = NULL;
    int c;
    int b;

    pa_assert(conf);
    pa_assert(argc > 0);
    pa_assert(argv);
    /* yada yada... */
}
You get this, with the cursor placed on the function description (right of the -):
/**
 * pa_cmdline_parse - 
 * @conf: 
 * @argc: 
 * @argv: 
 * @d: 
 *
 *
 */
int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) {
    pa_strbuf *buf = NULL;
    int c;
    int b;

    pa_assert(conf);
    pa_assert(argc > 0);
    pa_assert(argv);
    /* yada yada... */
}
Pretty cool huh? Here's the shitty C parser and doc generator:
(defun my-c-parse-function ()
  (interactive)
  (require 'cl)
  (let ((beg (point))
        end
        text
        fname
        args)
    (save-excursion
      (when (search-forward "{" nil t)
        (setq end (point)
              text (buffer-substring-no-properties beg end))
        (setq text (replace-regexp-in-string (rx (+ space)) " " text))
        (setq text (replace-regexp-in-string (rx (+ space)) " " text))
        (when (string-match (rx (group (+? (not space))) (* space) "(" (group (* any)) ")") text)
          (setq fname (match-string 1 text)
                args (match-string 2 text))

          (setq args (split-string args (rx (? space) "," (? space)) t))
          (setq args (mapcar (lambda (arg)
                               (setq arg (replace-regexp-in-string (rx bos (+ space)) "" arg))
                               (setq arg (replace-regexp-in-string (rx (+ space) eos) "" arg))
                               (setq arg (replace-regexp-in-string (rx
                                                                    "[" (* (not (any "]"))) "]")
                                                                   "" arg))
                               (if (string= arg "void")
                                   arg
                                 (let ((words (split-string arg (rx (any "*" space)) t)))
                                   (nth (1- (length words)) words)))) args))

          (message "fname = <%s>" fname)
          (dolist (a args)
            (message "arg<%s>" a))
          (append (list fname) (remove-if (lambda (x) (string= x "void")) args))
          )))))


(defun my-c-doc-function ()
  (interactive)
  (let* ((res (my-c-parse-function))
         (fname (car res))
         (args (cdr res))
         p)

    (insert "/**\n * " fname " - ")
    (setq p (point))
    (insert "\n")
    (dolist (a args)
      (insert " * @" a ": \n"))
    (insert " *\n *\n */")
    (goto-char p)))

Aucun commentaire:

Enregistrer un commentaire