Mercurial > hg > xemacs-beta
diff lisp/psgml/psgml-fs.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-fs.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,241 @@ +;;; fs.el --- Format a SGML-file according to a style file +;; Copyright (C) 1995 Lennart Staflin + +;; Author: Lennart Staflin <lenst@lysator.liu.se> +;; Version: $Id: psgml-fs.el,v 1.1.1.1 1996/12/18 03:35:17 steve Exp $ +;; Keywords: +;; Last edited: Mon Jan 8 22:12:00 1996 by lenst@triton.lstaflin.pp.se (Lennart Staflin) + +;;; 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 1, 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. +;;; +;;; A copy of the GNU General Public License can be obtained from this +;;; program's author (send electronic mail to lenst@lysator.liu.se) or from +;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA +;;; 02139, USA. +;;; +;;; Commentary: + +;; The function `style-format' formats the SGML-file in the current buffer +;; according to the style defined in the file `style.el' (or the file given +;; by the variable `fs-style'). + +;; To try it load this file and open the test file example.sgml. Then +;; run the emacs command `M-x style-format'. + +;; The style file should contain a single Lisp list. The elements of +;; this list, are them self lists, describe the style for an element type. +;; The sublists begin with the generic identifier for the element types and +;; the rest of the list are characteristic/value pairs. + +;; E.g. ("p" block t left 4 top 2) + +;; Defines the style for p-elements to be blocks with left margin 4 and +;; at least to blank lines before the block. + + +;;; Code: +(require 'psgml-api) + +;;;; Formatting parameters + +(defvar fs-char + '((left . 0) + (first . nil) + (default-top . 0) + (default-bottom . 0) + (ignore-empty-para . nil) + (literal . nil))) + +(defvar fs-special-styles + '(top bottom before after hang-from text) + "Style attribues that should not be entered in the characteristics table.") + + +;;;; Formatting engine + +(defun fs-char (p) + (cdr (assq p fs-char))) + +(defvar fs-para-acc "" + "Accumulate text of paragraph") + +(defvar fs-hang-from nil + "Hanging indent of current pargraph") + +(defvar fs-first-indent nil) +(defvar fs-left-indent nil) + +(defvar fs-vspace 0 + "Vertical space after last paragraph") + +(defun fs-addvspace (n) + (when (> n fs-vspace) + (princ (make-string (- n fs-vspace) ?\n)) + (setq fs-vspace n))) + + +(defun fs-para () + (when (if (fs-char 'ignore-epmty-para) + (string-match "[^\t\n ]" fs-para-acc) + fs-left-indent) + (assert fs-left-indent) + (fs-output-para fs-para-acc fs-first-indent fs-left-indent + fs-hang-from + (fs-char 'literal)) + (setq fs-vspace 0 + fs-hang-from nil)) + (setq fs-para-acc "" + fs-first-indent nil + fs-left-indent nil)) + +(defun fs-paraform-data (data) + (unless fs-left-indent + (setq fs-left-indent (fs-char 'left) + fs-first-indent (fs-char 'first))) + (setq fs-para-acc (concat fs-para-acc data))) + +(defun fs-output-para (text first-indent indent hang-from literal) + (sgml-push-to-string text) + (let ((indent-tabs-mode nil) + (fill-prefix (make-string indent ? ))) + (cond + (literal + (goto-char (point-max)) + (unless (bolp) + (insert ?\n)) + (goto-char (point-min)) + (while (not (eobp)) + (insert fill-prefix) + (beginning-of-line 2))) + (t + (while (re-search-forward "[ \t\n\r]+" nil t) + (replace-match " ")) + (goto-char (point-min)) + (delete-horizontal-space) + (insert + (if hang-from + hang-from + (make-string (or first-indent indent) ? ))) + (fill-region-as-paragraph (point-min) (point-max)) + )) + (princ (buffer-string))) + (sgml-pop-entity)) + +(defun fs-element-content (e) + (let ((fs-para-acc "")) + (sgml-map-content e + (function fs-paraform-phrase) + (function fs-paraform-data) + nil + (function fs-paraform-entity)) + fs-para-acc)) + +(defun fs-paraform-phrase (e) + (sgml-map-content e + (function fs-paraform-phrase) + (function fs-paraform-data) + nil + (function fs-paraform-entity))) + +(defun fs-paraform-entity (entity) + (let ((entity-map (fs-char 'entity-map)) + (text nil)) + (when entity-map + (setq text + (loop for (name val) on entity-map by 'cddr + thereis (if (equal name (sgml-entity-name entity)) + val)))) + (unless text + (setq text (sgml-entity-text entity))) + (fs-paraform-data text))) + +;;;; Style driven engine + +(defvar fs-style "psgml-style.el" + "*Style sheet to use for `style-format'. +The value can be the style-sheet list, or it can be a file name +\(string) of a file containing the style sheet or it can be the name +\(symbol) of a variable containing the style sheet." ) + +(defvar fs-cached-styles nil) + +(defun fs-get-style (style) + (cond ((stringp style) + (sgml-cache-catalog style + 'fs-cached-styles + (function (lambda () + (read (current-buffer)))))) + ((symbolp style) + (fs-get-style (symbol-value style))) + ((listp style) + style) + (t + (error "Illegal style value: %s" style)))) + +(defun fs-engine (e) + (fs-do-style e + (cdr (or (assoc (sgml-element-gi e) fs-style) + (assq t fs-style))))) + +(defun fs-do-style (e style) + (let ((hang-from (getf style 'hang-from))) + (when hang-from + (setq fs-hang-from + (format "%s%s " + (make-string (fs-char 'left) ? ) + (eval hang-from))))) + (let ((fs-char (nconc + (loop for st on style by 'cddr + unless (memq (car st) fs-special-styles) + collect (cons (car st) + (eval (cadr st)))) + fs-char))) + (when (getf style 'block) + (fs-para) + (fs-addvspace (or (getf style 'top) + (fs-char 'default-top)))) + (let ((before (getf style 'before))) + (when before + (fs-do-style e before))) + (cond ((getf style 'text) + (fs-paraform-data (eval (getf style 'text)))) + (t + (sgml-map-content e + (function fs-engine) + (function fs-paraform-data) + nil + (function fs-paraform-entity)))) + (let ((after (getf style 'after))) + (when after + (fs-do-style e after))) + (when (getf style 'block) + (fs-para) + (fs-addvspace (or (getf style 'bottom) + (fs-char 'default-bottom)))))) + +;;;###autoload +(defun style-format () + (interactive) + (setq fs-para-acc "") + (let ((fs-style (fs-get-style fs-style))) + (with-output-to-temp-buffer "*Formatted*" + (fs-engine (sgml-top-element)) + (fs-para)))) + + + +;;;; Helper functions for use in style sheet + +(defun fs-attval (name) + (sgml-element-attval e name)) + + +;;; fs.el ends here