Documentation for the SGML major mode.

Written 1994 by Lennart Staflin

PSGML
*****

PSGML is a major mode for editing SGML documents.  It works with GNU Emacs 19.19 and later or with Lucid Emacs 19.9.

This (draft) manual is for PSGML version 0.4.

There are several functions for editing SGML documents.  Indentation according to element nesting depth and identification of structural errors (but it is not a validating SGML parser).  Menus and commands for inserting tags with only the contextually valid tags.  Attribute values can be edited in separate window with information about types and defaults.  Structure based editing includes movement and killing; and also several commands for folding editing.

Limitations
***********

  * Can not handle SHORTREF or variant concrete syntaxes, though it does allow unlimited length names.  I suppose you can say that it accepts the ``Core concrete syntax''.

  * Assumes that general entity references can be treated as data.

  * The features CONCUR, DATATAG, LINK and RANK are not supported.

Installing PSGML
****************

Place the *.el and the *.elc files in a directory where Emacs can find it.  If you obtained PSGML without *.elc files, you can create them by letting Emacs byte compile the *.el files (use M-x byte-compile-file).  Parsing SGML in Emacs Lisp is slow and needs all the speed it can get.

Put the following line in your .emacs:

     (autoload 'sgml-mode "psgml" "Major mode to edit SGML files." t )

Modify search path for external entities
========================================

SGML can refer to external files (really entities) either with public identifiers or with system identifiers.  PSGML uses the variable sgml-public-map to map public identifiers to file names.

A public identifier looks like

     PUBLIC "ISO 8879:1986//ENTITIES Added Latin 1//EN"

where ``ISO 8879:1986'' is the owner, ``ENTITIES'' is the text class and ``Added Latin 1'' is the text description (and ``EN'' is language).  The default path would look for this file in

     /usr/local/lib/sgml/ISO_8879:1986/entities/Added_Latin_1

Note: blanks are transliterated to _ (and also / to %) and the text class is down cased.

The default for sgml-public-map giving the above path is

     ("/usr/local/lib/sgml/%o/%c/%d")

The sgml-public-map variable can contain a list of file name templates where %P will be substituted with the whole public identifier, owner is substituted for %O, public text class for %C, and public text description for %D.  The text class will be converted to lower case and the owner and description will be transliterated according to the variable sgml-public-transliterations.  The templates in the list is tried in order until an existing file is found.  An element can also be a dotted pair (REGEXP . FILENAME), the FILENAME is a string treated as above, but only if the regular expression, REGEXP, matches the public identifier.

A system identifier looks like

     SYSTEM "htmlplus.dtd"

where "htmlplus.dtd" is a system specific identifier. PSGML treats system identifiers as file names and looks for them in the directories listed in the variable sgml-system-path (default is either in current directory or in ~/sgml).

General
*******

Files with extensions .sgml, .sgm or .dtd will automatically be edited in SGML mode.  To edit some other file in sgml mode, type M-x sgml-mode RET after finding the file.

If you can modify the file you can add a Local Variables list (see Local Variables in Files (The Emacs Editor)) to the end of the file.  This can make Emacs automatically set sgml mode and user options when the file is loaded.  The simplest Local Variables list would look like:

     <!--
     Local Variables:
     mode: sgml
     End:
     -->

You can also put a line at the top of the file to tell emacs to use sgml mode:

     <!-- -*- sgml -*- -->

But remember that you can't have a comment before the SGML declaration.

You can use PSGML without specifying a DTD, it will the accept any tags and assume a content model of ANY and no tags can be omitted.

When PSGML needs contextual information it parses the document up to the point. During the parsing, it builds a parse tree.  The parse tree is used to initialise the next parse, to avoid having to parse things already parsed.  Changes to the buffer is supposed to prune the tree of all outdated information.  But if you get strange complaints from the parser, try and back up a bit and use C-c C-o (sgml-next-trouble-spot).

Running an external SGML parser
*******************************

PSGML can not validate a SGML document (see below what it can and can't do).  If you have a validating SGML parser, like sgmls, you can run the parser on your file with the command C-c C-v (sgml-validate).

Some variables control this function:

 -- User Option: sgml-validate-command
     The command to validate an SGML document.  The file name of current buffer file name will be appended to this, separated by a space.  Default is sgml -s.

 -- User Option: sgml-declaration
     If this is a string this will be inserted before the file name when running the sgml-validate-command.

 -- User Option: sgml-offer-save
     If non-nil, C-c C-v (sgml-validate) will ask about saving modified buffers before running the validate command.

The built-in parser can find some markup errors.  The command C-c C-o (sgml-next-trouble-spot) is the best way to use the built-in parser for this.  To check the whole file go to the beginning of the buffer and use C-c C-o.

Some of the markup errors not found are:

  * Errors in the SGML declaration.

  * Errors in attribute specifications.

  * Markup errors in entity replacement text.

Using a SGML declaration
************************

PSGML does not understand the SGML declaration, it accepts one in the file but it is ignored.  If you have the SGML declaration in another file you can make sgmls use it when you use the C-c C-v (sgml-validate) command (see Validating).

PSGML has some options in what features it uses and what markup it creates.  You have to set these options to make PSGMLs behaviour consistent with your SGML declaration and personal preferences.

 -- User Option: sgml-omittag
     Set this to t if the SGML declaration has OMITTAG YES and to nil otherwise.

 -- User Option: sgml-shorttag
     Set this to t if the SGML declaration has SHORTTAG YES and to nil otherwise.

 -- User Option: sgml-always-quote-attributes
     If non-nil, quote all attribute values inserted after finishing edit attributes.  If this variable is nil and sgml-shorttag is non-nil, attribute values that consists of only name characters will not be quoted.

 -- User Option: sgml-minimize-attributes
     Determines minimization of attributes inserted by edit-attributes.  If non-nil, omit attribute name, if attribute value is from a token group. If max, omit attributes with default value.  Minimization will only be done if they produce legal SGML (assuming sgml-omittag and sgml-shorttag are set correctly).

Managing the DTD
****************

PSGML needs to know about the DTD you are using for many of its commands. If you have a DOCTYPE declaration in your file, PSGML will try to parse this.  Either the first time you do something that needs to parse the document or with the command sgml-parse-prolog.  Big DTDs take some time to parse.

You can have the DOCTYPE declaration in another file either by setting sgml-parent-document to the other file or by creating a saved DTD and setting sgml-default-dtd-file to that file.

If parsing the DTD takes long time you can save the parsed DTD in a file using the command M-x sgml-save-dtd.  Next time you can have PSGML load that file instead of parsing the DTD.  For Emacs to find the saved DTD you must either save the DTD using the default name or do a M-x sgml-save-options after saving the DTD.

 -- User Option: sgml-default-dtd-file
     This is the default file name for saved DTD.  This is set by sgml-mode to the buffer file name less extension plus the extension .ced, if that file exists.  Can be changed in the Local variables section of the file.

 -- User Option: sgml-parent-document
     This can be set to a file name (a string) of a file containing the DOCTYPE declaration to use, or a list (FILENAME DOCTYPENAME), where FILENAME is a file name of a file containing then DOCTYPE declaration to use with the modification that the document type name is DOCTYPENAME.

If you change the doctype you must execute sgml-parse-prolog, changes in the doctype are not automatically recognised.

Editing commands
****************

See also the mode documentation (C-h m).

Inserting Markup
================

The commands that insert start-tags works only if the document has an associated DTD.

A list of valid tags is computed for a position in the buffer and is used for a menus and completion.  The list will contain:

 1. The end-tag for the current element unless sgml-balanced-tag-edit is non-nil.  Furthermore it will contain end-tags for enclosing elements if the necessary omissible end-tag declarations has been made in the DTD.

 2. The start-tags of all elements that could occur after point. If sgml-omittag-transparent is nil, the above will be limited to the elements that can occur within the current element.

Another type of computed list is a list of valid element names.  This list is also used for completion.  If sgml-omittag-transparent is nil, the list will only contain the elements that can be in the content of the current element.

The commands are:

C-c <
     Will ask for the tag to insert in the mini-buffer with completion on the the tags that are valid at point (sgml-insert-tag).

     If the option sgml-balanced-tag-edit is non-nil, inserting a start-tag will also insert the corresponding end-tag.  If in addition sgml-auto-insert-required-elements is non-nil, tags for elements required between the inserted tags will also be inserted.

C-c C-e
     Insert start and end-tags for an element (sgml-insert-element). The name of the element is read from the mini-buffer with completion on valid elements.

     Required elements in the content will be automatically inserted if the option sgml-auto-insert-required-elements is non-nil.

C-c C-r
     Makes the region into a new element (sgml-tag-region). Reads element name from mini-buffer with completion.

C-c /
     Inserts an end-tag for the current element (sgml-insert-end-tag).

Menu bar:

Markup
     Selecting from this menu will insert markup.  The menu contains two sub-menus with tags and with entities, some other markup and a user defined section.

     Sub menus:

Insert element
     Will pop-up a menu of valid elements and insert start and end-tags for the selected element.  Selections from the menu works like the C-c C-e command.

Insert start-tag
     Will pop-up a menu of valid start-tags and insert the selected tag.

Insert end-tag
     Will pop-up a menu of valid end-tags and insert the selected tag.

Tag region
     Will pop-up a menu of valid elements and tag the region with the selection.  Selections from the menu works like the C-c C-r command.

Insert entity
     Menu of all general entities defined in the DTD.

A menu is also available directly with a mouse button click in the buffer.  In GNU Emacs it is the first mouse button combined with shift (S-mouse-1).  In Lucid Emacs it is bound to the third mouse button.  The mouse button click will pop-up a menu of valid tags.  The tags list is as described above.  Selections from the menu works like the C-c < command.  With the following exception:

You can tag a region, with start and end-tag.  There are two ways to indicate the region to mark:

 1. Use the normal mouse commands to mark region.

     For this to work you muse either use transient mark mode (see Transient Mark Mode (The Emacs Editor).) or set the option sgml-tag-region-if-active to non-nil (don't set this unless you are sure that you want it).

 2. Alternatively make a secondary selection, this is done by holding down the meta key and using the mouse buttons. See Secondary selection (The Emacs Editor). Some window managers intercepts these events, which make it hard use the secondary selection in Emacs.

User Options:

sgml-balanced-tag-edit
     If non-nil, inserting a start-tag will also insert the corresponding end-tag.

sgml-auto-insert-required-elements
     If non-nil, automatically insert required elements in the content of an inserted element.

sgml-omittag-transparent
     If non-nil, will show legal tags inside elements with omissible start-tags and legal tags beyond omissible end-tags.

sgml-tag-region-if-active
     If non-nil, the Insert tags menu will tag a region if the region is considered active by emacs.  If nil, region must be active and transient-mark-mode must be on for the region to be tagged.

Markup completion
=================

If you are typing in markup directly M-TAB will help you by completing a tag name, an entity name or a markup declaration name.  If you type M-TAB after a plain word, ispell-complete-word will be invoked instead.

If you have typed

     &At-!-

and type M-TAB (assuming you use the ISOLat1 entity set) you get:

     &Atilde-!-

Showing information
===================

Commands for showing information obtained by parsing the buffer.

C-c C-c
     Shows, in the message area, context at point: if in a tag or in mixed content and the open elements (sgml-show-context).

C-c C-w
     Shows what element the character after point (under the cursor) belongs to; also shows context of element (sgml-what-element).

C-c C-t
     List contextually valid tags (sgml-list-tags).

Indentation
===========

You can indent a line according to the depth of element nesting at the beginning of the line.  To indent the current line use TAB you can also use LFD (newline-and-indent) to start a new line with correct indentation.

 -- User Option: sgml-indent-step
     How much to increment indent for every element level.  If nil, no indentation.

     If this is nil, TAB will insert a tab instead of indenting.

 -- User Option: sgml-indent-data
     If non-nil, indent in data/mixed context also.

Moving about
============

These commands move in the element structure.  The commands uses knowledge of SGML syntax, and if available the specific DTD.

C-M-a
     Move to the (content) beginning of the current element (sgml-beginning-of-element).

C-M-e
     Move to the (content) end of the current element (sgml-end-of-element).

C-M-f
     Move forward by element (sgml-forward-element).

C-M-b
     Move backward by element (sgml-backward-element).

C-M-u
     Move up to before current element (sgml-backward-up-element).

C-c C-n
     Move up to after current element (sgml-up-element).

C-M-d
     Move down to the (content) beginning of the next element (sgml-down-element).

C-c C-d
     Move to the next place where data is allowed (sgml-next-data-field).

You can also move to the next place where there is some structural error with C-c C-o (see Validating).

Editing attributes
==================

If you want to change the attributes of start-tag you can simply edit them directly in the buffer.  Or you can place the cursor at or after the start-tag and use the sgml-edit-attributes command, available from the SGML-menu or on C-c C-a.  This will create a new Emacs window with all possible attributes listed in the form

     ATTRIBUTE NAME = CURRENT VALUE.

The CURRENT VALUE may be shown as #DEFAULT if the attribute has not been given a value in the start-tag.  The list also contains the attributes declaration as a comment.  Note also that the CURRENT VALUE is show without eventual quotes.

It is now possible to edit the attribute values.  You can move to the next attribute with TAB.  If you want to let an attribute have its default value use C-c C-d, this will insert a #DEFAULT in the value field.

If Emacs is running in a X window, the #DEFAULT will be underlined to distinguish it from normal values.

Finish the editing with C-c C-c; this will replace the attribute values in the main buffer with those edited.  Note that values will be quoted as needed.

If you want to abort the editing, you can remove the window with C-x 0 or if you want it neat, kill the buffer and remove the window.

Some other keys are:

C-a
     Go to the beginning of the value field. (sgml-edit-attrib-field-end)

C-e
     Go to the end of the value field. (sgml-edit-attrib-field-end)

C-c C-k
     Clear the value field. (sgml-edit-attrib-clear)

Changing and deleting
=====================

C-c =
     Change the name of the current element (sgml-change-element-name). Tries to translate attribute specifications.  An attribute will be translated to an attribute with the same name.  If the new element has no attribute with the same name, the attribute will be ignored.  If there is an attribute with the same name but different declared content, a warning is given.

     ID attributes are handled special, an attribute with declared value ID will always be translated to the attribute with declared value ID.

C-c C-k
     Kill next tag, markup declaration or process instruction (sgml-kill-markup).

C-M-k
     Kill the element following the cursor (sgml-kill-element).

C-c -
     Remove tags from current element (sgml-untag-element).

PSGML has a substitute for the normal fill-paragraph.  The command C-c C-q (sgml-fill-element) uses heuristics to decide what should be a paragraph.

 1. If point is in a element content, recursively fill the sub-elements.

 2. Find the biggest element with mixed content containing point.

 3. If the above element is mixed but contains elements with pure element content then fill what is between the pure elements as paragraphs and fill the pure elements recursively.

The command sgml-normalize will

 1. insert missing tags,

 2. replace minimized tags with full tags,

 3. fix attribute specification lists according to options set.

There is one option for the normalize command.  With its default value, normalize may actually change the data content of some elements.  But only by removing some white-space from the end of elements with omitted end-tags.

 -- User Option: sgml-normalize-trims
     If non-nil, sgml-normalize will trim off white space from end of element when adding end-tag.

     Default: t.

Folding editing
***************

With these commands you can make parts of the text temporarily invisible to make it easier to see the overall structure of your text.

When folding a region all the lines but the first will be invisible. The first line of the region will still be visible with an ellipsis at the end.

See Outline Mode (The Emacs Editor).

C-c C-f C-r
     The region between point and mark will be folded (sgml-fold-region).

C-c C-f C-e
     The region between the start and end of the current element will be folded.  (sgml-fold-element)

C-c C-f C-s
     Fold all the sub elements of the current element (sgml-fold-subelement).

C-c C-s
     Unfold the current line, assuming it is the first line of a folded region (sgml-unfold-line).

C-c C-u C-e
     Make all lines in current element visible (sgml-unfold-element).

C-c C-u C-a
     Make all lines in current buffer visible (sgml-unfold-all).

C-c C-f C-x
     Unfold current element and then fold the subelements (sgml-expand-element).  If the current element is folded this expands what is visible.

Index
*****