home *** CD-ROM | disk | FTP | other *** search
- ;;; sdoc.el
- ;;;
- ;;; Find information from structured ASCII-files such as Amiga Autodocs,
- ;;; Unix man pages and programming language header and include files. It is
- ;;; possible to create match entries for any file format really, using the
- ;;; appropriate filter function.
- ;;;
- ;;; Copyright © 1995 Torbjörn Axelsson
- ;;;
- ;;; This file is NOT part of the GNU Emacs.
- ;;;
- ;;; Verbatim copies of this file may be freely redistributed together with
- ;;; its documentation file.
- ;;;
- ;;; Modified versions of this file may be redistributed provided that this
- ;;; notice remains unchanged, the file contains prominent notice of author
- ;;; and time of modifications, and redistribution of the file is not
- ;;; further restricted in any way.
- ;;;
- ;;; This file is distributed `as is', without warranties of any kind.
- ;;;
- ;;; To contact the author, send email to torax@ctrl-c.liu.se.
- ;;;
- ;;; History:
- ;;; v1.00 1995-01-14: Developed using GNU Emacs 18.58, Amiga port1.26DG
- ;;; Features searching, adding matches and merging
- ;;; databases.
- ;;;
- ;;; Future:
- ;;; Pri Project
- ;;; top (Semi)automatic scripts for creating multiple database entries from
- ;;; documentation files.
- ;;; top Implementing the filter function. (Such as stripping formatting
- ;;; codes from hypertext documents, should work on a region.)
- ;;; low Use techinfo for the doc file.
-
- (provide 'sdoc)
-
- (defvar sdoc-buffer "*Sdoc*" "*Name of the Sdoc output buffer.")
- (defvar sdoc-database "/users/torax/sdoc/sdoc.database" "*Full path to the Sdoc database file.")
-
- ;;; These buffer local variables are used for narrowing search and editing of the database file.
- (make-variable-buffer-local 'sdoc-eofiles) ; End of file list.
- (make-variable-buffer-local 'sdoc-botypes) ; Beginning of type list.
- (make-variable-buffer-local 'sdoc-eotypes) ; End of type list.
- (make-variable-buffer-local 'sdoc-bomatches) ; Beginning of matchlist.
-
- ;;; Basic search function
-
- (defun sdoc (about)
- "Lookup a word using the Sdoc database."
- (interactive "sSearch for: ")
- (save-excursion
- (with-output-to-temp-buffer sdoc-buffer
- (let ((database-buffer (find-file-noselect sdoc-database))
- (work-buffer (get-buffer-create " sdoc-work-buffer"))
- found-match)
- (sdoc-print "Sdoc looking for: " about "\n\n")
- (setq about (concat "^" about "\^L"))
- (if (not (sdoc-databasep database-buffer))
- (error "%s is not a valid Sdoc database" sdoc-database))
- (set-buffer database-buffer)
- (goto-char sdoc-bomatches)
- (while (setq found-match (sdoc-grab-match about database-buffer))
- ;; Find and add the text to the help buffer.
- (set-buffer work-buffer)
- (erase-buffer)
- (insert-file-contents (nth 1 found-match))
- (delete-region (nth 5 found-match) (point-max))
- (delete-region (nth 4 found-match) (point-min))
- (sdoc-print (nth 2 found-match) " found: " (car found-match) "\nData file: "
- (nth 1 found-match) "\n----------S-T-A-R-T----------\n"
- (buffer-string)
- (if (not (equal (buffer-substring (point-max) (1- (point-max))) "\n"))
- "\n" "")
- "----------E-N-D--------------\n\n"))
- (kill-buffer work-buffer)))))
-
- ;;; Database management
-
- (defun sdoc-merge-buffer-to-database (&optional buff)
- "Merges the database in BUFFER with the main Sdoc database file.
- BUFFER defaults to the current buffer."
- (interactive "bMerge Sdoc database with buffer ")
- (save-excursion
- (if (not buff)
- (setq buff (current-buffer)))
- (let ((database-buffer (find-file-noselect sdoc-database))
- (newbase-buffer buff))
- (if (not (sdoc-databasep database-buffer))
- (error "Sdoc default database buffer \"%s\" is corrupt." sdoc-database))
- (if (not (sdoc-databasep newbase-buffer))
- (error "Trying to add an incorrect database buffer."))
- (set-buffer newbase-buffer)
- (goto-char sdoc-bomatches)
- (while
- (sdoc-add-match (sdoc-grab-match "^.*\^L" newbase-buffer) database-buffer)))))
-
- (defun sdoc-add-region-as-match (id matchtype startpos endpos &optional filter)
- "*Add the current region as an entry in the Sdoc database, supply ID and MATCHTYPE.
- When called from other lisp functions, add STARTPOS and ENDPOS and
- optional FILTER"
- (interactive "sid: \nsmatchtype: \nr")
- (if buffer-file-name
- (sdoc-add-match (list id buffer-file-name matchtype filter startpos endpos)
- (find-file-noselect sdoc-database))
- (error "Current buffer not visiting a file, cannot add to Sdoc database")))
-
- (defun sdoc-add-match (match &optional buff)
- "Add a MATCH entry to the (&optional) BUFFER (current). If MATCH is nil return nil, if all ok return t.
- If the buffer is completely empty, will create the database.
- Will fail if it is a non empty non sdoc database buffer.
-
- The format of the match entry is a list:
- matchstring filename matchtype filter startpos endpos
-
- matchstring - string with the id of the match
- filename - string with the complete filename to look up
- matchtype - string saying what type of match this is
- filter - string with the name of the filter function or nil if no filter needed
- startpos, endpos - integers with the start and end of the region to display"
- (and
- match
- (save-excursion
- (if buff
- (set-buffer buff))
- (if (not (sdoc-databasep (current-buffer)))
- (if (or (/= 1 (point-min))
- (/= 1 (point-max)))
- (error "Trying to add a match to a non sdoc database buffer.")
- (insert
- (concat
- (nth 1 match) "\n\^L\n" (nth 2 match)
- (if (nth 3 match) "\^L")
- (nth 3 match) "\n\^L\n"
- (nth 0 match) "\^L1\^L0\^L" (nth 4 match) "\^L" (nth 5 match) "\n"))
- (sdoc-databasep (current-buffer)))
- (let* ((fileno (sdoc-add-filename (nth 1 match)))
- (matchno (sdoc-add-matchtype (nth 2 match) (nth 3 match)))
- (matchstring (concat (nth 0 match) "\^L" fileno "\^L" matchno "\^L" (nth 4 match) "\^L"
- (nth 5 match) "\n")))
- (goto-char sdoc-bomatches)
- (if (not (search-forward matchstring nil 1))
- (let (buffer-read-only)
- (insert matchstring))))
- t))))
-
- (defun sdoc-databasep (buff)
- "Check if BUFFER is a well formed Sdoc database and if so set the sdoc-bo* and sdoc-eo* variables.."
- (save-excursion
- (set-buffer buff)
- (if (and
- (markerp sdoc-eofiles)
- (markerp sdoc-botypes)
- (markerp sdoc-eotypes)
- (markerp sdoc-bomatches))
- t
- (goto-char (point-min))
- (and
- (looking-at
- (concat "\\`" ; Start of buffer
- "\\(^[^\^L\n]+\n\\)+\^L\n" ;Filenames
- "\\(\\([^\^L\n]+\^L\\)?[^\^L\n]+\n\\)+\^L\n" ; Types (w filter functions)
- "\\(^[^\^L\n]+\^L[0-9]+\^L[0-9]+\^L[0-9]+\^L[0-9]+\n\\)+\\'"))
- (let ((md (match-data)))
- (setq sdoc-eofiles (make-marker))
- (setq sdoc-botypes (make-marker))
- (setq sdoc-eotypes (make-marker))
- (setq sdoc-bomatches (make-marker))
- (set-marker sdoc-eofiles (nth 3 md))
- (set-marker sdoc-botypes (nth 4 md))
- (set-marker sdoc-eotypes (nth 5 md))
- (set-marker sdoc-bomatches (nth (- (length md) 2) md))
- (setq mode-line-buffer-identification '("Sdoc: %18b"))
- (setq buffer-read-only t)
- t)))))
-
- ;;; Support functions
-
- (defun sdoc-print (&rest l)
- "Print multiple objects to stdout"
- (mapcar 'princ l))
-
- (defun sdoc-add-filename (filename)
- "Add FILENAME to the files section of current buffer. Returns the filenumber."
- (if filename
- (save-excursion
- (goto-char (point-min))
- (if (search-forward (concat filename "\n") sdoc-eofiles t)
- (count-lines (point) (point-min))
- (goto-char (1- sdoc-eofiles))
- (let (buffer-read-only)
- (insert "\n" filename))
- (count-lines (point) (point-min))))))
-
- (defun sdoc-add-matchtype (type &optional filter)
- "Add a match named TYPE with optional FILTER to database. Return matchno of the TYPE/FILTER pair."
- (save-excursion
- (goto-char sdoc-botypes)
- (let (buffer-read-only (typeline (concat type (if filter "\^L") filter)))
- (if (search-forward (concat typeline "\n") sdoc-eotypes t)
- (1- (count-lines (point) sdoc-botypes))
- (goto-char (1- sdoc-eotypes))
- (let (buffer-read-only)
- (insert "\n" typeline))
- (1- (count-lines (point) sdoc-botypes))))))
-
- (defun sdoc-grab-match (regexp &optional buff)
- "Find the next match matching REGEXP in (optional) BUFFER.
- Will return a list (match filename matchtype filter startpos endpos)"
- (let ((cbuff (current-buffer)) result)
- (if buff
- (set-buffer buff))
- (if (not (sdoc-databasep (current-buffer)))
- (progn
- (set-buffer cbuff)
- (error "Trying to extract matchdata from non-database buffer.")))
- (cond
- ((re-search-forward regexp nil t)
- (beginning-of-line)
- (if (not (looking-at "^\\([^\^L\n]+\\)\^L\\([0-9]+\\)\^L\\([0-9]+\\)\^L\\([0-9]+\\)\^L\\([0-9]+\\)\n"))
- (error "Bad database entry"))
- (let ((tmp (list (buffer-substring (match-beginning 1) (match-end 1))
- (string-to-int (buffer-substring (match-beginning 2) (match-end 2)))
- (string-to-int (buffer-substring (match-beginning 3) (match-end 3)))
- (string-to-int (buffer-substring (match-beginning 3) (match-end 3)))
- (string-to-int (buffer-substring (match-beginning 4) (match-end 4)))
- (string-to-int (buffer-substring (match-beginning 5) (match-end 5))))))
- (setcar (cdr tmp) (sdoc-grab-filename (nth 1 tmp)))
- (setcar (nthcdr 2 tmp) (sdoc-grab-matchtype (nth 2 tmp)))
- (setcar (nthcdr 3 tmp) (sdoc-grab-filter (nth 3 tmp)))
- (forward-line)
- (setq result tmp))))
- (set-buffer cbuff)
- result))
-
- (defun sdoc-grab-filename (fileno &optional buff)
- "Return the filename of FILENO in optional BUFFER."
- (save-excursion
- (if buff
- (set-buffer buff))
- (goto-line fileno)
- (let ((bol (point)))
- (end-of-line)
- (buffer-substring bol (point)))))
-
- (defun sdoc-grab-matchtype (matchno &optional buff)
- "Return the matchtype for match number MATCHNO in optional BUFFER."
- (save-excursion
- (if buff
- (set-buffer buff))
- (goto-char sdoc-botypes)
- (forward-line matchno)
- (let ((bol (point)))
- (re-search-forward "[^\^L\n]+")
- (buffer-substring bol (point)))))
-
- (defun sdoc-grab-filter (matchno &optional buff)
- "Return the filter for match number MATCHNO in optional BUFFER."
- (save-excursion
- (if buff
- (set-buffer buff))
- (goto-char sdoc-botypes)
- (forward-line matchno)
- (if (looking-at "[^\^L\n]+\^L\\(.+\\)")
- (buffer-substring (match-beginning 1) (match-end 1)))))
-
-