diff lisp/psgml/psgml-info.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/psgml/psgml-info.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,397 @@
+;;;; psgml-info.el
+;;; Last edited: Mon Aug  7 23:00:54 1995 by lenst@katja.lysator.liu.se (Lennart Staflin)
+;;; $Id: psgml-info.el,v 1.1.1.1 1996/12/18 03:35:21 steve Exp $
+
+;; Copyright (C) 1994, 1995 Lennart Staflin
+
+;; Author: Lennart Staflin <lenst@lysator.liu.se>
+
+;; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;;; Commentary:
+
+;; This file is an addon to the PSGML package.  
+
+;; This file contains some commands to print out information about the
+;; current DTD.
+
+;; sgml-list-elements
+;;    Will list all elements and the attributes declared for the element.
+
+;; sgml-list-attributes
+;;    Will list all attributes declared and the elements that use them.
+
+;; sgml-list-terminals
+;;    Will list all elements that can contain data.
+
+;; sgml-list-occur-in-elements
+;;    Will list all element types and where it can occur.
+
+;; sgml-list-content-elements
+;;    Will list all element types and the element types that can occur
+;;    in its content.
+
+;;;; Code:
+
+(require 'psgml)
+(require 'psgml-parse)
+
+(defconst sgml-attr-col 18)
+
+
+;;;; Utility functions
+
+(defsubst sgml-add-to-table (row-index elem table)
+  (let ((p (assoc row-index table)))
+    (cond ((null p)
+	   (cons (list row-index elem) table))
+	  (t
+	   (nconc p (list elem))
+	   table))))
+
+(defsubst sgml-add-last-unique (x l)
+  (unless (memq x l)
+    (nconc l (list x))))
+
+(defun sgml-map-element-types (func)
+  (sgml-need-dtd)
+  (sgml-map-eltypes func
+		    (sgml-pstate-dtd sgml-buffer-parse-state)
+		    t))
+
+(defun sgml-eltype-refrenced-elements (eltype)
+  "List of element types referenced in the model of ELTYPE."
+  ;; Now with cache. Uses appdata prop re-cache.
+  (or
+   (sgml-eltype-appdata eltype 're-cache)
+   (let* ((res				; result list (eltypes)
+	   nil)
+	  (states			; list of states
+	   (list (sgml-eltype-model eltype)))
+	  (agenda			; point into states
+	   states))
+     (cond
+      ((not (sgml-model-group-p (car states)))
+       nil)
+      (t
+       (while agenda
+	 (cond
+	  ((sgml-normal-state-p (car agenda))
+	   (loop for m in (append (sgml-state-opts (car agenda))
+				  (sgml-state-reqs (car agenda)))
+		 do
+		 (pushnew (sgml-move-token m) res)
+		 (sgml-add-last-unique (sgml-move-dest m) states)))
+       
+	  (t				; &-node
+	   (sgml-add-last-unique (sgml-&node-next (car agenda)) states)
+	   (loop for dfa in (sgml-&node-dfas (car agenda)) do
+		 (sgml-add-last-unique dfa states))))
+	 (setq agenda (cdr agenda)))
+       (setf (sgml-eltype-appdata eltype 're-cache) res)
+       res)))))
+
+
+;;;; List elements
+
+(defun sgml-list-elements ()
+  "List the elements and their attributes in the current DTD."
+  (interactive)
+  (message "Creating table...")
+  (sgml-display-table
+   (sgml-map-element-types
+    (function
+     (lambda (eltype)
+       (cons (sgml-eltype-name eltype)
+	     (mapcar (function sgml-attdecl-name)
+		     (sgml-eltype-attlist eltype))))))
+   "Elements" "Element" "Attribute"))
+
+
+;;;; List attributes
+
+(defun sgml-list-attributes ()
+  "List the attributes and in which elements they occur."
+  (interactive)
+  (let ((attributes nil))
+    (message "Creating table...")
+    (sgml-map-element-types
+     (function
+      (lambda (eltype)
+	(loop for a in (sgml-eltype-attlist eltype) do
+	      (setq attributes
+		    (sgml-add-to-table (sgml-attdecl-name a)
+				       (sgml-eltype-name eltype)
+				       attributes))))))
+    (sgml-display-table attributes
+			"Attributes" "Attribute" "Element")))
+
+
+
+
+;;;; List terminals
+
+(defun sgml-list-terminals ()
+  "List the elements that can have data in their content."
+  (interactive)
+  (message "Creating table...")
+  (let ((data-models (list sgml-cdata sgml-rcdata sgml-any)))
+    (sgml-display-table
+     (delq nil
+	   (sgml-map-element-types
+	    (function
+	     (lambda (eltype)
+	       (if (or (sgml-eltype-mixed eltype)
+		       (memq (sgml-eltype-model eltype) data-models))
+		   (list (sgml-eltype-name eltype)
+			 (symbol-name
+			  (if (sgml-model-group-p (sgml-eltype-model eltype))
+			      'mixed
+			    (sgml-eltype-model eltype)))))))))
+     "Terminals" "Element" "Content")))
+
+
+;;;; Element cross reference list
+
+(defun sgml-list-content-elements ()
+  "List all element types and the element types that can occur in its content."
+  (interactive)
+  (message "Creating table...")
+  (sgml-display-table
+   (sgml-map-element-types
+    (function
+     (lambda (eltype)
+       (cons (sgml-eltype-name eltype)
+	     (mapcar (function sgml-eltype-name)
+		     (sgml-eltype-refrenced-elements eltype))))))
+   "Elements refrenced by elements"
+   "Element" "Content"))
+
+(defun sgml-list-occur-in-elements ()
+  "List all element types and where it can occur."
+  (interactive)
+  (message "Creating table...")
+  (let ((cross nil))
+    (sgml-map-element-types
+     (function
+      (lambda (eltype)
+	(loop for ref in (sgml-eltype-refrenced-elements eltype)
+	      do (setq cross (sgml-add-to-table ref
+						(sgml-eltype-name eltype)
+						cross))))))
+    (sgml-display-table
+     cross
+     "Cross referenced element types" "Element" "Can occur in")))
+
+
+;;;; Display table
+
+(defun sgml-display-table (table title col-title1 col-title2
+				 &optional width nosort)
+  (or width
+      (setq width sgml-attr-col))
+  (let ((buf (get-buffer-create (format "*%s*" title))))
+    (message "Preparing display...")
+    (set-buffer buf)
+    (erase-buffer)
+    (insert col-title1)
+    (indent-to width)
+    (insert col-title2 "\n")
+    (insert-char ?= (length col-title1))
+    (indent-to width)
+    (insert-char ?= (length col-title2))
+    (insert "\n")
+    (unless nosort
+      (setq table (sort table (function (lambda (a b)
+					  (string< (car a) (car b)))))))
+    (loop for e in table do
+	  (insert (format "%s" (car e)))
+	  (loop for name in (if nosort
+				(cdr e)
+			      (sort (cdr e) (function string-lessp)))
+		do
+		(when (> (+ (length name) (current-column))
+			 fill-column)
+		  (insert "\n"))
+		(when (< (current-column) sgml-attr-col)
+		  (indent-to width))
+		(insert  name " "))
+	  (insert "\n"))
+    (goto-char (point-min))
+    (display-buffer buf)
+    (message nil)))
+
+
+;;;; Describe entity
+
+(defun sgml-describe-entity (name)
+  "Describe the properties of an entity as declared in the current DTD."
+  (interactive
+   (let (default input)
+     (sgml-need-dtd)
+     (save-excursion
+       (sgml-with-parser-syntax
+	(unless (sgml-parse-delim "ERO")
+	  (skip-chars-backward "^&\"'= \t\n"))
+	(setq default (or (sgml-parse-name t) ""))))
+     (setq input (completing-read
+		  (format "Entity name (%s): " default)
+		  (sgml-entity-completion-table
+		   (sgml-dtd-entities
+		    (sgml-pstate-dtd sgml-buffer-parse-state)))))
+     (list
+      (if (equal "" input) default input))))
+  
+  (with-output-to-temp-buffer "*Help*"
+    (let ((entity (sgml-lookup-entity name
+				      (sgml-dtd-entities
+				       (sgml-pstate-dtd
+					sgml-buffer-parse-state)))))
+      (or entity (error "Undefined entity"))
+      (princ (format "Entity %s is %s\n"
+		     name
+		     (cond ((null entity)
+			    "undefined")
+			   (t
+			    (format "a %s entity"
+				    (sgml-entity-type entity))))))
+      (when entity
+	(let ((text (sgml-entity-text entity)))
+	  (cond ((stringp text)
+		 (princ "Defined to be:\n")
+		 (princ text))
+		(t
+		 (princ "With external identifier ")
+		 (princ (if (car text) "PUBLIC" "SYSTEM")) 
+		 (when (car text)
+		   (princ (format " '%s'" (car text))))
+		 (when (cdr text)
+		   (princ (format " '%s'" (cdr text)))))))))))
+
+
+
+;;;; Describe element type
+
+(defun sgml-describe-element-type (et-name)
+  "Describe the properties of an element type as declared in the current DTD."
+  (interactive
+   (let (default input)
+     (sgml-need-dtd)
+     (save-excursion
+       (sgml-with-parser-syntax
+	(unless (sgml-parse-delim "STAGO")
+	  (skip-syntax-backward "w_"))
+	(setq default (sgml-parse-name))
+	(unless (and default
+		     (sgml-eltype-defined (sgml-lookup-eltype default)))
+	  (setq default nil))))
+     (setq input (sgml-read-element-type (if default
+					     (format "Element type (%s): "
+						     default)
+					   "Element type: ")
+					 sgml-dtd-info
+					 default))
+
+     (list
+      (sgml-eltype-name input))))
+
+  (sgml-need-dtd)
+  (let ((et (sgml-lookup-eltype et-name)))
+    (with-output-to-temp-buffer "*Help*"
+      (princ (format "ELEMENT: %s\n\n" (sgml-eltype-name et)))
+      (princ (format " Start-tag is %s.\n End-tag is %s.\n"
+		     (if (sgml-eltype-stag-optional et)
+			 "optional" "required")
+		     (if (sgml-eltype-etag-optional et)
+			 "optional" "required")))
+      (princ "\nATTRIBUTES:\n")
+      (loop for attdecl in (sgml-eltype-attlist et) do
+	    (let ((name (sgml-attdecl-name attdecl))
+		  (dval (sgml-attdecl-declared-value attdecl))
+		  (defl (sgml-attdecl-default-value attdecl)))
+	      (when (listp dval)
+		(setq dval (concat (if (eq (first dval)
+					   'notation)
+				       "#NOTATION (" "(")
+				   (mapconcat (function identity)
+					      (second dval)
+					      "|")
+				   ")")))
+	      (cond ((sgml-default-value-type-p 'fixed defl)
+		     (setq defl (format "#FIXED '%s'"
+					(sgml-default-value-attval defl))))
+		    ((symbolp defl)
+		     (setq defl (upcase (format "#%s" defl))))
+		    (t
+		     (setq defl (format "'%s'"
+					(sgml-default-value-attval defl)))))
+	      (princ (format " %-9s %-30s %s\n" name dval defl))))
+      ;; ----
+      (let ((s (sgml-eltype-shortmap et)))
+	(when s
+	  (princ (format "\nUSEMAP: %s\n" s))))
+      ;; ----
+      (princ "\nOCCURS IN:\n\n")
+      (sgml-map-eltypes
+       (function (lambda (cand)
+		   (when (memq et (sgml-eltype-refrenced-elements cand))
+		     (princ (format " %s" (sgml-eltype-name cand))))))
+       (sgml-pstate-dtd sgml-buffer-parse-state)))))
+
+
+;;;; Print general info about the DTD.
+
+(defun sgml-general-dtd-info ()
+  "Display information about the current DTD."
+  (interactive)
+  (sgml-need-dtd)
+  (let ((elements 0)
+	(entities 0)
+	(parameters 0)
+	(fmt "%20s %s\n")
+	(hdr "")
+	)
+    (sgml-map-eltypes (function (lambda (e) (incf elements)))
+		      sgml-dtd-info)
+    (sgml-map-entities (function (lambda (e) (incf entities)))
+		       (sgml-dtd-entities sgml-dtd-info))
+    (sgml-map-entities (function (lambda (e) (incf parameters)))
+		       (sgml-dtd-parameters sgml-dtd-info))
+
+    (with-output-to-temp-buffer "*Help*"
+      (princ (format fmt "Doctype:" (sgml-dtd-doctype sgml-dtd-info)))
+      (when (sgml-dtd-merged sgml-dtd-info)
+	(princ (format fmt "Compiled DTD:"
+		       (car (sgml-dtd-merged sgml-dtd-info)))))
+      (princ (format fmt "Element types:" (format "%d" elements)))
+      (princ (format fmt "Entities:" (format "%d" entities)))
+      (princ (format fmt "Parameter entities:" (format "%d" parameters)))
+
+      (setq hdr "Files used:")
+      (loop for x in (sgml-dtd-dependencies sgml-dtd-info)
+	    if (stringp x)
+	    do (princ (format fmt hdr x))
+	    (setq hdr ""))
+
+      (setq hdr "Undef parameters:")
+      (sgml-map-entities
+       (function (lambda (entity)
+		   (when (sgml-entity-marked-undefined-p entity)
+		     (princ (format fmt hdr (sgml-entity-name entity)))
+		     (setq hdr ""))))
+       (sgml-dtd-parameters sgml-dtd-info)))))
+
+;;; psgml-info.el ends here