summaryrefslogtreecommitdiff
path: root/doc/maint/docstring.el
diff options
context:
space:
mode:
Diffstat (limited to 'doc/maint/docstring.el')
-rw-r--r--doc/maint/docstring.el622
1 files changed, 0 insertions, 622 deletions
diff --git a/doc/maint/docstring.el b/doc/maint/docstring.el
deleted file mode 100644
index a01558fbb..000000000
--- a/doc/maint/docstring.el
+++ /dev/null
@@ -1,622 +0,0 @@
-;;; docstring.el --- utilities for Guile docstring maintenance
-;;;
-;;; Copyright (C) 2001 Neil Jerram
-;;;
-;;; This file is not part of GNU Emacs, but the same permissions apply.
-;;;
-;;; GNU Emacs 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, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; The basic premise of these utilities is that - at least in the
-;; short term - we can get a lot of reference manual mileage by
-;; co-opting the docstrings that are snarfed automatically from
-;; Guile's C and Scheme source code. But this leads to problems of
-;; synchronization... How do you track when a docstring has been
-;; updated in the source and so needs updating in the reference
-;; manual. What if a procedure is removed from the Guile source? And
-;; so on. To complicate matters, the exact snarfed docstring text
-;; will probably need to be modified so that it fits into the flow of
-;; the manual section in which it appears. Can we design solutions to
-;; synchronization problems that continue to work even when the manual
-;; text has been enhanced in this way?
-;;
-;; This file implements an approach to this problem that I have found
-;; useful. It involves keeping track of three copies of each
-;; docstring:
-;;
-;; "MANUAL" = the docstring as it appears in the reference manual.
-;;
-;; "SNARFED" = the docstring as snarfed from the current C or Scheme
-;; source.
-;;
-;; "TRACKING" = the docstring as it appears in a tracking file whose
-;; purpose is to record the most recent snarfed docstrings
-;; that are known to be in sync with the reference manual.
-;;
-;; The approaches are as follows.
-;;
-;; 1. Comparison of MANUAL-DOC, SOURCE-DOC and TRACK-DOC, to produce a
-;; summary output buffer in which keystrokes are defined to bring up
-;; detailed comparisons.
-;;
-;; 2. Comparison of MANUAL-DOC, SOURCE-DOC and TRACK-DOC using Ediff.
-;;
-;; Here is a brief list of commands available (via "M-x COMMAND"):
-;;
-;; docstring-process-current-buffer
-;; docstring-process-current-region BEG END
-;; docstring-process-module MODULE
-;; docstring-ediff-this-line
-;; docstring-show-source
-
-
-(defvar guile-core-dir (or (getenv "GUILE_MAINTAINER_GUILE_CORE_DIR")
- (error "GUILE_MAINTAINER_GUILE_CORE_DIR not set"))
- "*Full path of guile-core source directory.")
-
-(defvar guile-build-dir (or (getenv "GUILE_MAINTAINER_BUILD_CORE_DIR")
- guile-core-dir)
- "*Full path of guile-core build directory. Defaults to guile-core-dir.")
-
-(defvar docstring-manual-directory (expand-file-name "doc/ref" guile-core-dir)
- "*The directory containing the Texinfo source for the Guile reference manual.")
-
-(defvar docstring-tracking-root (expand-file-name "doc/maint" guile-core-dir)
- "*Root directory for docstring tracking files. The tracking file
-for module (a b c) is expected to be in the file
-<docstring-tracking-root>/a/b/c.texi.")
-
-(defvar docstring-snarfed-roots (mapcar
- #'(lambda (frag)
- (expand-file-name frag guile-build-dir))
- '("libguile" "ice-9" "oop"))
- "*List of possible root directories for snarfed docstring files.
-For each entry in this list, the snarfed docstring file for module (a
-b c) is looked for in the file <entry>/a/b/c.texi.")
-
-(defvar docstring-manual-files
- (directory-files docstring-manual-directory nil "\\.texi$" t)
- "List of Texinfo source files that comprise the Guile reference manual.")
-
-(defvar docstring-new-docstrings-file "new-docstrings.texi"
- "The name of a file in the Guile reference manual source directory
-to which new docstrings should be added.")
-
-;; Apply FN in turn to each element in the list CANDIDATES until the
-;; first application that returns non-nil.
-(defun or-map (fn candidates args)
- (let ((result nil))
- (while candidates
- (setq result (apply fn (car candidates) args))
- (if result
- (setq result (cons (car candidates) result)
- candidates nil)
- (setq candidates (cdr candidates))))
- result))
-
-;; Return t if the current buffer position is in the scope of the
-;; specified MODULE, as determined by "@c module ..." comments in the
-;; buffer. DEFAULT-OK specifies the return value in the case that
-;; there are no preceding module comments at all.
-(defun docstring-in-module (module default-ok)
- (save-excursion
- (if (re-search-backward "^@c module " nil t)
- (progn
- (search-forward "@c module ")
- (equal module (read (current-buffer))))
- default-ok)))
-
-;; Find a docstring in the specified FILE-NAME for the item in module
-;; MODULE and with description DESCRIPTION. MODULE should be a list
-;; of symbols, Guile-style, for example: '(ice-9 session).
-;; DESCRIPTION should be the string that is expected after the @deffn,
-;; for example "primitive acons" or "syntax let*".
-(defun find-docstring (file-name module description)
- (and (file-exists-p file-name)
- (let ((buf (find-file-noselect file-name))
- (deffn-regexp (concat "^@deffnx? "
- (regexp-quote description)
- "[ \n\t]"))
- found
- result)
- (save-excursion
- (set-buffer buf)
- (goto-char (point-min))
- (while (and (not found)
- (re-search-forward deffn-regexp nil t))
- (save-excursion
- (goto-char (match-beginning 0))
- (beginning-of-line)
- (if (docstring-in-module module t)
- (setq found t))))
- (if found
- (setq result
- (list (current-buffer)
- (progn
- (re-search-backward "^@deffn ")
- (beginning-of-line)
- (point))
- (progn
- (re-search-forward "^@end deffn")
- (forward-line 1)
- (point))))))
- result)))
-
-;; Find the reference manual version of the specified docstring.
-;; MODULE and DESCRIPTION specify the docstring as per
-;; `find-docstring'. The set of files that `find-manual-docstring'
-;; searches is determined by the value of the `docstring-manual-files'
-;; variable.
-(defun find-manual-docstring (module description)
- (let* ((result
- (or-map 'find-docstring
- (mapcar (function (lambda (file-name)
- (concat docstring-manual-directory
- "/"
- file-name)))
- (cons docstring-new-docstrings-file
- docstring-manual-files))
- (list module
- description)))
- (matched-file-name (and (cdr result)
- (file-name-nondirectory (car result)))))
- (if matched-file-name
- (setq docstring-manual-files
- (cons matched-file-name
- (delete matched-file-name docstring-manual-files))))
- (cdr result)))
-
-;; Convert MODULE to a directory subpath.
-(defun module-to-path (module)
- (mapconcat (function (lambda (component)
- (symbol-name component)))
- module
- "/"))
-
-;; Find the current snarfed version of the specified docstring.
-;; MODULE and DESCRIPTION specify the docstring as per
-;; `find-docstring'. The file that `find-snarfed-docstring' looks in
-;; is automatically generated from MODULE.
-(defun find-snarfed-docstring (module description)
- (let ((modpath (module-to-path module)))
- (cdr (or-map (function (lambda (root)
- (find-docstring (concat root
- "/"
- modpath
- ".texi")
- module
- description)))
- docstring-snarfed-roots
- nil))))
-
-;; Find the tracking version of the specified docstring. MODULE and
-;; DESCRIPTION specify the docstring as per `find-docstring'. The
-;; file that `find-tracking-docstring' looks in is automatically
-;; generated from MODULE.
-(defun find-tracking-docstring (module description)
- (find-docstring (concat docstring-tracking-root
- "/"
- (module-to-path module)
- ".texi")
- module
- description))
-
-;; Extract an alist of modules and descriptions from the current
-;; buffer.
-(defun make-module-description-list ()
- (let ((alist nil)
- (module '(guile)))
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "^\\(@c module \\|@deffnx? \\({[^}]+}\\|[^ ]+\\) \\([^ \n]+\\)\\)"
- nil
- t)
- (let ((matched (buffer-substring (match-beginning 1)
- (match-end 1))))
- (if (string-equal matched "@c module ")
- (setq module (read (current-buffer)))
- (let ((type (buffer-substring (match-beginning 2)
- (match-end 2))))
- (if (string-equal type "{C Function}")
- nil
- (setq matched
- (concat type
- " "
- (buffer-substring (match-beginning 3)
- (match-end 3))))
- (message "Found docstring: %S: %s" module matched)
- (let ((descriptions (assoc module alist)))
- (setq alist
- (cons (cons module (cons matched (cdr-safe descriptions)))
- (if descriptions
- (delete descriptions alist)
- alist))))))))))
- alist))
-
-;; missing in some environments?
-(defun caddr (list)
- (nth 2 list))
-
-;; Return the docstring from the specified LOCATION. LOCATION is a
-;; list of three elements: buffer, start position and end position.
-(defun location-to-docstring (location)
- (and location
- (save-excursion
- (set-buffer (car location))
- (buffer-substring (cadr location) (caddr location)))))
-
-;; Perform a comparison of the specified docstring. MODULE and
-;; DESCRIPTION are as per usual.
-(defun docstring-compare (module description)
- (let* ((manual-location (find-manual-docstring module description))
- (snarf-location (find-snarfed-docstring module description))
- (track-location (find-tracking-docstring module description))
-
- (manual-docstring (location-to-docstring manual-location))
- (snarf-docstring (location-to-docstring snarf-location))
- (track-docstring (location-to-docstring track-location))
-
- action
- issue)
-
- ;; Decide what to do.
- (cond ((null snarf-location)
- (setq action nil
- issue (if manual-location
- 'consider-removal
- nil)))
-
- ((null manual-location)
- (setq action 'add-to-manual issue nil))
-
- ((null track-location)
- (setq action nil
- issue (if (string-equal manual-docstring snarf-docstring)
- nil
- 'check-needed)))
-
- ((string-equal track-docstring snarf-docstring)
- (setq action nil issue nil))
-
- ((string-equal track-docstring manual-docstring)
- (setq action 'auto-update-manual issue nil))
-
- (t
- (setq action nil issue 'update-needed)))
-
- ;; Return a pair indicating any automatic action that can be
- ;; taken, and any issue for resolution.
- (cons action issue)))
-
-;; Add the specified docstring to the manual.
-(defun docstring-add-to-manual (module description)
- (let ((buf (find-file-noselect (concat docstring-manual-directory
- "/"
- docstring-new-docstrings-file))))
- (save-excursion
- (set-buffer buf)
- (goto-char (point-max))
- (or (docstring-in-module module nil)
- (insert "\n@c module " (prin1-to-string module) "\n"))
- (insert "\n" (location-to-docstring (find-snarfed-docstring module
- description))))))
-
-;; Auto-update the specified docstring in the manual.
-(defun docstring-auto-update-manual (module description)
- (let ((manual-location (find-manual-docstring module description))
- (track-location (find-tracking-docstring module description)))
- (save-excursion
- (set-buffer (car manual-location))
- (goto-char (cadr manual-location))
- (delete-region (cadr manual-location) (caddr manual-location))
- (insert (location-to-docstring (find-snarfed-docstring module
- description))))))
-
-;; Process an alist of modules and descriptions, and produce a summary
-;; buffer describing actions taken and issues to be resolved.
-(defun docstring-process-alist (alist)
- (let (check-needed-list
- update-needed-list
- consider-removal-list
- added-to-manual-list
- auto-updated-manual-list)
-
- (mapcar
- (function (lambda (module-list)
- (let ((module (car module-list)))
- (message "Module: %S" module)
- (mapcar
- (function (lambda (description)
- (message "Comparing docstring: %S: %s" module description)
- (let* ((ai (docstring-compare module description))
- (action (car ai))
- (issue (cdr ai)))
-
- (cond ((eq action 'add-to-manual)
- (docstring-add-to-manual module description)
- (setq added-to-manual-list
- (cons (cons module description)
- added-to-manual-list)))
-
- ((eq action 'auto-update-manual)
- (docstring-auto-update-manual module description)
- (setq auto-updated-manual-list
- (cons (cons module description)
- auto-updated-manual-list))))
-
- (cond ((eq issue 'check-needed)
- (setq check-needed-list
- (cons (cons module description)
- check-needed-list)))
-
- ((eq issue 'update-needed)
- (setq update-needed-list
- (cons (cons module description)
- update-needed-list)))
-
- ((eq issue 'consider-removal)
- (setq consider-removal-list
- (cons (cons module description)
- consider-removal-list)))))))
- (cdr module-list)))))
- alist)
-
- ;; Prepare a buffer describing the results.
- (set-buffer (get-buffer-create "*Docstring Results*"))
- (erase-buffer)
-
- (insert "
-The following items have been automatically added to the manual in
-file `" docstring-manual-directory "/" docstring-new-docstrings-file "'.\n\n")
- (if added-to-manual-list
- (mapcar (function (lambda (moddesc)
- (insert (prin1-to-string (car moddesc))
- ": "
- (cdr moddesc)
- "\n")))
- added-to-manual-list)
- (insert "(none)\n"))
-
- (insert "
-The following items have been automatically updated in the manual.\n\n")
- (if auto-updated-manual-list
- (mapcar (function (lambda (moddesc)
- (insert (prin1-to-string (car moddesc))
- ": "
- (cdr moddesc)
- "\n")))
- auto-updated-manual-list)
- (insert "(none)\n"))
-
- (insert "
-The following items are already documented in the manual but are not
-mentioned in the reference copy of the snarfed docstrings file.
-You should check that the manual documentation matches the docstring
-in the current snarfed docstrings file.\n\n")
- (if check-needed-list
- (mapcar (function (lambda (moddesc)
- (insert (prin1-to-string (car moddesc))
- ": "
- (cdr moddesc)
- "\n")))
- check-needed-list)
- (insert "(none)\n"))
-
- (insert "
-The following items have manual documentation that is different from
-the docstring in the reference copy of the snarfed docstrings file,
-and the snarfed docstring has changed. You need to update the manual
-documentation by hand with reference to the snarfed docstring changes.\n\n")
- (if update-needed-list
- (mapcar (function (lambda (moddesc)
- (insert (prin1-to-string (car moddesc))
- ": "
- (cdr moddesc)
- "\n")))
- update-needed-list)
- (insert "(none)\n"))
-
- (insert "
-The following items are documented in the manual but are no longer
-present in the snarfed docstrings file. You should consider whether
-the existing manual documentation is still pertinent. If it is, its
-docstring module comment may need updating, to connect it with a
-new snarfed docstring file.\n\n")
- (if consider-removal-list
- (mapcar (function (lambda (moddesc)
- (insert (prin1-to-string (car moddesc))
- ": "
- (cdr moddesc)
- "\n")))
- consider-removal-list)
- (insert "(none)\n"))
- (insert "\n")
-
- (goto-char (point-min))
- (local-set-key "d" 'docstring-ediff-this-line)
-
- ;; Popup the issues buffer.
- (let ((pop-up-frames t))
- (set-window-point (display-buffer (current-buffer))
- (point-min)))))
-
-(defun docstring-process-current-buffer ()
- (interactive)
- (docstring-process-alist (make-module-description-list)))
-
-(defun docstring-process-current-region (beg end)
- (interactive "r")
- (narrow-to-region beg end)
- (unwind-protect
- (save-excursion
- (docstring-process-alist (make-module-description-list)))
- (widen)))
-
-(defun docstring-process-module (module)
- (interactive "xModule: ")
- (let ((modpath (module-to-path module))
- (mdlist nil))
- (mapcar (function (lambda (root)
- (let ((fn (concat root
- "/"
- modpath
- ".texi")))
- (if (file-exists-p fn)
- (save-excursion
- (find-file fn)
- (message "Getting docstring list from %s" fn)
- (setq mdlist
- (append mdlist
- (make-module-description-list))))))))
- docstring-snarfed-roots)
- (docstring-process-alist mdlist)))
-
-(defun docstring-ediff-this-line ()
- (interactive)
- (let (module
- description)
- (save-excursion
- (beginning-of-line)
- (setq module (read (current-buffer)))
- (forward-char 2)
- (setq description (buffer-substring (point)
- (progn
- (end-of-line)
- (point)))))
-
- (message "Ediff docstring: %S: %s" module description)
-
- (let ((track-location (or (find-tracking-docstring module description)
- (docstring-temp-location "No docstring in tracking file")))
- (snarf-location (or (find-snarfed-docstring module description)
- (docstring-temp-location "No docstring in snarfed file")))
- (manual-location (or (find-manual-docstring module description)
- (docstring-temp-location "No docstring in manual"))))
-
- (setq docstring-ediff-buffers
- (list (car track-location)
- (car snarf-location)
- (car manual-location)))
-
- (docstring-narrow-to-location track-location)
- (docstring-narrow-to-location snarf-location)
- (docstring-narrow-to-location manual-location)
-
- (add-hook 'ediff-quit-hook 'docstring-widen-ediff-buffers)
-
- (ediff-buffers3 (nth 0 docstring-ediff-buffers)
- (nth 1 docstring-ediff-buffers)
- (nth 2 docstring-ediff-buffers)))))
-
-(defun docstring-narrow-to-location (location)
- (save-excursion
- (set-buffer (car location))
- (narrow-to-region (cadr location) (caddr location))))
-
-(defun docstring-temp-location (str)
- (let ((buf (generate-new-buffer "*Docstring Temp*")))
- (save-excursion
- (set-buffer buf)
- (erase-buffer)
- (insert str "\n")
- (list buf (point-min) (point-max)))))
-
-(require 'ediff)
-
-(defvar docstring-ediff-buffers '())
-
-(defun docstring-widen-ediff-buffers ()
- (remove-hook 'ediff-quit-hook 'docstring-widen-ediff-buffers)
- (save-excursion
- (mapcar (function (lambda (buffer)
- (set-buffer buffer)
- (widen)))
- docstring-ediff-buffers)))
-
-
-;;; Tests:
-
-;(find-docstring "/home/neil/Guile/cvs/guile-core/doc/maint/guile.texi" nil "primitive sloppy-assq")
-;(find-manual-docstring '(guile) "primitive sloppy-assq")
-;(find-tracking-docstring '(guile) "primitive sloppy-assq")
-;(find-snarfed-docstring '(guile) "primitive sloppy-assq")
-
-(defvar docstring-libguile-directory (expand-file-name "libguile"
- guile-core-dir)
- "*The directory containing the C source for libguile.")
-
-(defvar docstring-libguile-build-directory (expand-file-name "libguile"
- guile-build-dir)
- "*The directory containing the libguile build directory.")
-
-(defun docstring-display-location (file line)
- (let ((buffer (find-file-noselect
- (expand-file-name file docstring-libguile-directory))))
- (if buffer
- (let* ((window (or (get-buffer-window buffer)
- (display-buffer buffer)))
- (pos (save-excursion
- (set-buffer buffer)
- (goto-line line)
- (point))))
- (set-window-point window pos)))))
-
-(defun docstring-show-source ()
- "Given that point is sitting in a docstring in one of the Texinfo
-source files for the Guile manual, and that that docstring may be
-snarfed automatically from a libguile C file, determine whether the
-docstring is from libguile and, if it is, display the relevant C file
-at the line from which the docstring was snarfed.
-
-Why? When updating snarfed docstrings, you should usually edit the C
-source rather than the Texinfo source, so that your updates benefit
-Guile's online help as well. This function locates the C source for a
-docstring so that it is easy for you to do this."
- (interactive)
- (let* ((deffn-line
- (save-excursion
- (end-of-line)
- (or (re-search-backward "^@deffn " nil t)
- (error "No docstring here!"))
- (buffer-substring (point)
- (progn
- (end-of-line)
- (point)))))
- (guile-texi-file
- (expand-file-name "guile.texi" docstring-libguile-build-directory))
- (source-location
- (save-excursion
- (set-buffer (find-file-noselect guile-texi-file))
- (save-excursion
- (goto-char (point-min))
- (or (re-search-forward (concat "^"
- (regexp-quote deffn-line)
- "$")
- nil t)
- (error "Docstring not from libguile"))
- (forward-line -1)
- (if (looking-at "^@c snarfed from \\([^:]+\\):\\([0-9]+\\)$")
- (cons (match-string 1)
- (string-to-int (match-string 2)))
- (error "Corrupt docstring entry in guile.texi"))))))
- (docstring-display-location (car source-location)
- (cdr source-location))))
-
-
-(provide 'docstring)
-
-;;; docstring.el ends here