Commit 62445630 authored by David Byers's avatar David Byers
Browse files

Added files for the manual

parent 7fc74d04
CHAPTERS=texts.xml \
# Generate the manual from DocBook XML using Jade wrappers
# I really don't know if the jw command is standard in installations
# of Jade, but it works fine in Debian/Gnu Linux. $(INCFILES) manual.xml chp.xml
jw -f docbook -b ps manual.xml
# These files are generated from the source code.
fnc.ent var.ent commands.xml: $(SRC)/lyskom.el
emacs -batch -l $(SRC)/lyskom.el -l ./docgen.el -f lyskom-docgen
# This file is generated from the Makefile and contains references
# to all the chapters.
chp.xml: Makefile
echo > $@
for i in $(INCFILES) ; do \
echo "<!ENTITY $$i SYSTEM \"$$i\">" >> $@ ; \
echo "<!ENTITY chapters \"" \
`echo $(INCFILES) | sed 's/\([-A-Za-z0-9.][-A-Za-z0-9.]*\)/\&\1; /g'` \
"\">" >> $@
# Build lyskom.el if necessary
cd $(SRC) && make lyskom.el
# The files are the chapter files without the surrounding
# book element. They are built using the xml2inc script. %.xml
./xml2inc < $< > $@
;;;;; -*-coding: iso-8859-1;-*-
;;;;; $Id$
;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association.
;;;;; This file is part of the LysKOM Emacs LISP client.
;;;;; LysKOM 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.
;;;;; LysKOM 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 LysKOM; see the file COPYING. If not, write to
;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
;;;;; MA 02139, USA.
;;;;; Please mail bug reports to
;;;; ================================================================
;;;; ================================================================
;;;; File: docgen.el
;;;; Generate documentation data for inclusion in the user manual
;;; TO DO
;;; Variable documentation requires considerably more flexibility
;;; than command documentation:
;;; * Generate segmentedlist elements. Look for two-column
;;; indented parts in the documentation.
;;; * Highlight code (e.g. `t', `nil', `other' usw. Handle
;;; references to elisp functions and elisp variables.
;;; * Format examples. I don't think we can do this consistently
;;; without any markup. MAybe by looking for indented blocks
;;; where some line in a block does not match a segmentedlist
;;; format.
;;; In variables, warn for undocumented (no **) def-kom-vared
;;; variables that start with kom-
;;; Generate DTD fragments so we can use entities for command and
;;; variable references (e.g. &fn:kom-mark-text;) in XML.
;;; Read templates from a file, so we don't hard-code the
;;; format here.
;;; Specify output file on the command line.
;;; Specify lyskom.elc on the command line.
;;; Read a list of external references from a file. Ideally we'd read
;;; and parse the actual XML, but that is probably too much work. We
;;; need to map references like lyskom-read-text-no-prefix-arg to the
;;; actual ID to link to. Specify this file on the command line too.
;;; Do variable documentation.
;;; Write or find a stylesheed that doesn't suck. Mainly paragraph
;;; spacing is way too big, and the period after section numbers is
;;; just plain wrong. Maybe this can be fixed by setting parameters to
;;; the DSSSL processor -- see
;;; /usr/share/sgml/docbook/stylesheet/dsssl/modular/print/dbparam.dsl
;;; for all available parameters. %para-sep% is interesting.
(require 'cl)
(defvar lyskom-docgen-external-refs
'((lyskom-read-text-no-prefix-arg . lyskom-read-text-no-prefix-arg)))
(defvar lyskom-docgen-errors nil)
(defvar lyskom-docgen-found-variables nil)
(defvar lyskom-docgen-found-functions nil)
(defvar lyskom-docgen-xrefd-variables nil)
(defvar lyskom-docgen-xrefd-functions nil)
(defun lyskom-docgen-error (fmt &rest args)
(apply 'message fmt args)
(setq lyskom-docgen-errors (cons (apply 'format fmt args)
(defun lyskom-docgen-report-errors (stage)
(when nil
(lyskom-traverse msg (nreverse lyskom-docgen-errors)
(message "%s: %s" stage msg))))
(defun lyskom-docgen-princ (str)
(insert str))
(defun lyskom-docgen-fixup-sgml (str)
(when str
(let ((s str))
(setq s (replace-in-string s "&" "&amp;"))
(setq s (replace-in-string s "<" "&lt;"))
(setq s (replace-in-string s ">" "&gt;"))
(defun lyskom-docgen-get-name (fn lang)
(let ((lyskom-language lang))
(lyskom-command-name fn)))
(defun lyskom-docgen-get-doc (fn)
(let ((doc (documentation fn)))
(when (and doc (string-match "Lisp documentation:" doc))
(setq doc (substring doc 0 (match-beginning 0))))
(lyskom-docgen-transform-refs fn (lyskom-docgen-fixup-sgml doc))))
(defun lyskom-docgen-transform-refs (fn doc)
(if doc
(let ((result "")
(start 0))
(while (string-match "`\\(.*?\\)'" doc start)
(setq result (concat result (substring doc start (match-beginning 0))))
(let ((sym (intern (match-string 1 doc))))
((assq sym lyskom-docgen-external-refs)
(setq result
(concat result
(format "<xref linkend=\"%s\" />"
(cdr (assq sym lyskom-docgen-external-refs))))))
((fboundp sym)
(unless (memq sym lyskom-commands)
(lyskom-docgen-error "%s: reference to non-command %s" fn sym))
(setq result
(concat result
(format "<link linkend=\"fn:%s\"><command>%s</command></link> [<link linkend=\"fn:%s\"><function>%s</function></link>]"
(lyskom-docgen-get-name fn 'en)
(setq lyskom-docgen-xrefd-functions
(add-to-list 'lyskom-docgen-xrefd-functions sym)))
((boundp sym)
(setq result
(concat result
(format "<link linkend=\"var:%s\">%s</link>"
sym sym)))
(setq lyskom-docgen-xrefd-variables
(add-to-list 'lyskom-docgen-xrefd-variables sym)))
(t (lyskom-docgen-error "%s: undefined reference to %s" fn sym)
(setq result (concat result
(match-string 1 doc)
(setq start (match-end 0))))
(setq result (concat result (substring doc start)))
(concat " <para>\n"
(replace-in-string result "\n\n+" "\n </para>\n <para>\n")
"\n </para>\n")
(lyskom-docgen-error "%s: No documentation!" fn)
(defun lyskom-docgen-format-key-sequence (binding)
(lambda (x)
(format "<keycap>%s</keycap>"
(lyskom-docgen-fixup-sgml (key-description x))))
binding "; "))
(defun lyskom-docgen-generate-commands-chapter-2 ()
(lyskom-traverse command lyskom-commands
(let* ((name-sv (lyskom-docgen-get-name command 'sv))
(name-en (lyskom-docgen-get-name command 'en))
(bind-sv (where-is-internal command lyskom-sv-mode-map))
(bind-en (where-is-internal command lyskom-en-mode-map))
(doc-en (lyskom-docgen-get-doc command)))
(format "\
<section id=\"fn:%s\"><title>%s [%s]</title>
<informaltable frame=\"topbot\">
<tgroup cols=\"2\">
<tbody valign=\"top\">
<entry>English name</entry>
<entry>English binding</entry>
<entry>Swedish name</entry>
<entry>Swedish binding</entry>
(lyskom-docgen-format-key-sequence bind-en)
(lyskom-docgen-format-key-sequence bind-sv)
(setq lyskom-docgen-found-functions
(cons command lyskom-docgen-found-functions)))))
(defun lyskom-docgen-generate-missing-anchors ()
(lyskom-docgen-princ "<section><title>Dummy anchors</title><para>\n")
(lyskom-traverse fn (set-difference lyskom-docgen-xrefd-functions
(format "<anchor id=\"fn:%s\" />Missing target: %s; \n" fn fn)))
(lyskom-traverse var (set-difference lyskom-docgen-xrefd-variables
(format "<anchor id=\"var:%s\" />Missing target: %s; \n" var var)))
(lyskom-docgen-princ "</para></section>\n"))
(defun lyskom-docgen-open-file (fname)
(set-buffer (get-buffer-create (format "*LysKOM DOCGEN* %s" fname)))
(set-language-environment 'latin-1)
(set-buffer-multibyte nil)
(make-local-variable 'lyskom-docgen-fname)
(make-local-variable 'lyskom-docgen-errors)
(setq lyskom-docgen-errors nil)
(setq lyskom-docgen-fname fname))
(defun lyskom-docgen-close-file ()
(write-file lyskom-docgen-fname))
(defun lyskom-docgen-generate-fnc-ent ()
(message "Generating fnc.ent")
(lyskom-docgen-open-file "fnc.ent")
(lambda (x)
(when (and (fboundp x)
(commandp x)
(or (string-match "^kom-" (symbol-name x))
(string-match "^lyskom-" (symbol-name x))))
(format "<!ENTITY fn:%s \"<function>%s</function>\">\n" x x)))))
(defun lyskom-docgen-generate-var-ent ()
(message "Generating var.ent")
(lyskom-docgen-open-file "var.ent")
(lambda (x)
(when (and (boundp x)
(or (string-match "^kom-" (symbol-name x))
(string-match "^lyskom-" (symbol-name x)))
(string-match "^\\*\\*"
(or (documentation-property x 'variable-documentation) "")))
(format "<!ENTITY var:%s \"<varname>%s</varname>\">\n" x x)))))
(defun lyskom-docgen-generate-commands-chapter ()
(message "Generating commands.xml")
(lyskom-docgen-open-file "commands.xml")
(lyskom-docgen-princ "
<?xml version='1.0' encoding='iso-8859-1' ?>
<!DOCTYPE book PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"
<book lang=\"en\">
<title>Command Reference</title>
This chapter describes all commands in LysKOM. Commands are
listed in alphabetical order by english name.
(lyskom-docgen-princ "\
<section id=\"lyskom-read-text-no-prefix-arg\">
(lyskom-docgen-princ "</chapter>
(defmacro lyskom-docgen-run (stage fn)
(funcall ,fn)
(lyskom-docgen-report-errors ,stage)))
(defun lyskom-docgen ()
(lyskom-docgen-run "commands.xml" 'lyskom-docgen-generate-commands-chapter)
(lyskom-docgen-run "fnc.ent" 'lyskom-docgen-generate-fnc-ent)
(lyskom-docgen-run "var.ent" 'lyskom-docgen-generate-var-ent)
<?xml version='1.0' encoding='iso-8859-1' ?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"docbook/dtd/xml/4.2/docbookx.dtd" [
<!ENTITY % chp SYSTEM "chp.xml">
<!ENTITY % fnc SYSTEM "fnc.ent">
<!ENTITY % var SYSTEM "var.ent">
%fnc; <!-- LysKOM functions -->
%var; <!-- LysKOM variables -->
%chp; <!-- Book chapters -->
<!-- There is a bit of magic going on here. Each chapter is a -->
<!-- self-contained DocBook file with one and only one chapter. -->
<!-- The makefile will take care of extracting that chapter to -->
<!-- a file with the same name, but suffixed with .inc. The -->
<!-- makefile will also create chp.xml, which defines entities -->
<!-- for all chapters, and defines the chapter entity to expand -->
<!-- to all chapters. The fnc.ent and var.ent files are created -->
<!-- by docgen.el, also from the makefile. You should only have -->
<!-- to concern yourself with writing DocBook. -->
<title>The LysKOM Elisp Client</title>
<subtitle>User's Manual</subtitle>
<ulink url="">
<holder>Lysator Academic Computing Society</holder>
<?xml version='1.0' encoding='iso-8859-1' ?>
<!DOCTYPE book SYSTEM "manual.dtd">
<book lang="en">
<title>Texts in LysKOM</title>
<section id="texts:special">
<title>Special Texts</title>
<section id="texts:presentations">
Every conference and person can and should have a
presentation. A conference presentation should contain
information about the conference, such as what topics are
appropriate, related conferences and possibly external
links. Do not confuse presentations with FAQs; there is
support for FAQ texts as well (<xref linkend="texts:faqs"
Keeping with the tradition of openness, presentations of
persons in LysKOM are fairly detailed, almost always
including the real name and location of the person, and
frequently including telephone number, address, interests,
job details and more.
You can see the presentation for any conference or person
using &fn:kom-review-presentation;. To change or create a
presentation for a person or conference, use
&fn:kom-change-presentation;. You can remove a presentation
using &fn:kom-remove-presentation;. To make an existing text
the presentation of a conference, use
When you use &fn:kom-change-presentation; to create the
presentation for a conference or person, the recipient of
that text will be a special conference (there is one for
conferences and one for persons). If the conference is
secret, the recipient will be the conference itself since
there is no point in presenting a secret conference.
When you use &fn:kom-change-presentation; to change a
presentation the new presentation will be a comment to the
old one. This is a convention that helps people see what
differs from one presentation to the next.
Presentations are protected from automatic deletion, but can
be deleted manually. Don't do that.
<section id="texts:notices">
A notice is a text containing important information about
the server, a person or a conference. Each object can have
at most one notice. Notices are sent to a special
conference. Check the recipient of your notice if it is
applied to a secret conference; the conference will be less
secret if its notice is in a public conference.
Notices are protected from automatic deletion but can be
deleted manually. Don't do that. If you want to remove a
notice, use the appropriate command (see below).
<simplesect id="texts:notices:server">
<title>Server notices</title>
The server notice (sometimes called "message of the day")
is shown on login and can be reviewed by using the
&fn:kom-status-server;; the text number of the server
notice will be listed.
The server notice is set using the &fn:kom-set-motd; and
removed with &fn:kom-remove-motd; These commands are only
available in administrative mode.
<simplesect id="texts:notices:conf">
<title>Conference notices</title>
Conference notices are not used in this client. They can
be set and removed by the conference supervisor using
&fn:kom-change-conf-motd; and &fn:kom-unset-conf-motd;,
<simplesect id="texts:notices:pers">
<title>Person notices</title>
Notices may be attached to letterboxes. In a strictly
technical sense, these notices are conference notices, but
from the perspective of the user they are different. When
writing a text with a lettterbox as a recipient, any
notice on that letterbox will be shown, and confirmation
is required to submit the text.
Person notices are set and removed by the conference
supervisor using &fn:kom-change-conf-motd; and
&fn:kom-unset-conf-motd;, respectively.
<section id="texts:faqs">
A FAQ is a regular text that is linked to one or more
conferences through a FAQ link. The purpose of a FAQ is to
answer questions that are frequently asked in the
conference. If the list of questions is small, it is not
uncommon to use the conference presentation instead. It is
also possible to attach a FAQ to the server itself.
A FAQ is considered unread as a FAQ until you read it using
one of the special FAQ-related commands in the context of a
particular conference. If a text you have read is added as a
FAQ to a conference, it will become an unread FAQ for that
conference, and will be shown the next time you enter the
conference. If it is later added as a FAQ to another
conference, it will become an unread FAQ for
<emphasis>that</emphasis> conference, despite the face that
you have read it twice.
With default settings, unread FAQs are listed and shown each
time you enter a conference or log on to the server. When
you enter a conference, FAQs that are unread in that
conference are listed and shown. When you log on to the
server, unread FAQs that are attached to the server are
To list all FAQs that are attached to a conference, use
&fn:kom-status-conf; (FAQs are listed as part of the status)
or &fn:kom-review-presentation; (in which case FAQs are
listed after the conference presentation). To list all
conferences attached to the server, use
&fn:kom-status-server; (FAQs are listed as part of the
To view FAQs for a particular conference, use
&fn:kom-review-faq;. To view FAQs for the server, use
In the elisp client the link is created with one of the
commands &fn:kom-add-faq; or &fn:kom-change-conf-faq;, and is
removed using &fn:kom-del-faq;. There are similar commands
for manipulating server FAQs; these can only be used by
users with administrative rights to the LysKOM server.
There are a number of settings that affect FAQs.
&var:kom-auto-list-faqs; controls automatic listing of FAQs
when entering conferences. &var:kom-auto-review-faqs;
controls automatic reviewing of FAQs when entering
# This script is really simple and someone can probably write a much
# better version of it. I wanted to do a sed version, but advanced sed