This is sursis.info, produced by Makeinfo version 3.12f from sursis.texinfo. This is the online manual for Le Sursis (Sane and Usable Response to Scripting Internet Sites) Version 0.1.1 Copyright (C) 2000 Tom Burdick  File: sursis.info, Node: Top, Next: Dist and Copying, Prev: (dir), Up: (dir) Le Sursis is a system to aid in writing CGI scripts in Common Lisp. This manual describes its use. * Menu: * Dist and Copying:: Where to get Le Sursis and your rights regarding it. * Introduction:: Introduction to Le Sursis. * The sursis Package:: Using Le Sursis to retrieve CGI queries. * The sursis-html Package:: Using Le Sursis to generate HTML. * Index:: Detailed index.  File: sursis.info, Node: Dist and Copying, Next: Introduction, Prev: Top, Up: Top Distribution and Copying ************************ This is Version 0.1.1 of Le Sursis by Tom Burdick. The latest version of Le Sursis can always be found on the Sursis web site (http://sursis.sourceforge.net/) . Le Sursis is Free Software licensed to you, the user, under the terms of the GNU General Public License , a copy of which should be in the `COPYING' file included in the Le Sursis distribution. Please read it as it is designed to protect your rights as the user of this software; it also places certain restrictions on the use of this software so as to protect the rights of all users.  File: sursis.info, Node: Introduction, Next: The Name, Prev: Dist and Copying, Up: Top Introduction ************ Le Sursis is an attempt to provide a good environment to write CGI scripts in Common Lisp. It consists of two packages: `sursis' and `sursis-html'. `sursis' contains the functions for retrieving CGI queries, and `sursis-html' contains a set of utility functions to make it easier to compose HTML. Although they are meant to be complimentary, each may be used independently of the other. * Menu: * The Name:: What does Le Sursis mean? * Basic Usage:: Usage for very simple scripts. * Using sursis:: Basic usage of the sursis package. * Using sursis-html:: Basic usage of the sursis-html package.  File: sursis.info, Node: The Name, Next: Basic Usage, Prev: Introduction, Up: Introduction What does Le Sursis mean? ========================= Le Sursis nominally stands for "Sane and Usable Response to Scripting Internet Sites." However, "le sursis" is also French for "the reprieve," meant here in the sense of "a reprieve from Perl." And, alas, while Le Sursis is indeed a reprieve from Perl, it is not a solution. If one has to work on a CGI script with others, it will almost certainly be necessary to use a language other than Lisp. But, when you can use it, what a reprieve! Also, `Le Sursis' is a novel by Jean-Paul Sartre, the second in the three-part series `Les Chemins de la LibertÚ' ("The Paths to Freedom"). It is a great book, M. Sartre was an amazing author and philosopher, and I would encourage everyone to read his work. The remainder of this manual will consider only the software.  File: sursis.info, Node: Basic Usage, Next: Using sursis, Prev: The Name, Up: Introduction Basic Usage =========== All examples given here use the `.lsp' extension for lisp files. In most situations, you would want to compile the lisp files from this distribution. Any references to compiled files will use the `.fas' extension used by CLISP (http://clisp.cons.org/) which is the Common Lisp implementation used by the author. All lisp files intended to be used as CGI scripts are assumed to begin with: #!/usr/local/bin/clisp or the appropriate for the Lisp system being used, and are assumed to have the appropriate executable permissions.  File: sursis.info, Node: Using sursis, Next: Using sursis-html, Prev: Basic Usage, Up: Introduction Basic `sursis' usage -------------------- The `sursis' package provides Le Sursis' interface to CGI queries. For the simplest scripts, the following should suffice: (load "sursis.lsp") (cgi:get-query) => (("name1" . "value1") ... ("nameN" . "valueN")) `get-query''s value is an association list; or, if no input was given to the script, it's value is `nil'. The next most useful function exported is probably `format-query'. `format-query' takes an a-list as an argument and its value is a matching query string. For example: (cgi:get-query) => (("greeting" . "Hello world!") ("tone" . "emphatic")) (cgi:format-query *) => "?greeting=Hello+world!&tone=emphatic" This makes it easy to have a cgi script recur on itself. In fact, it was this behavior of the majority of my cgi scripts that lead me to write this package. For more detail, see *Note The sursis Package::.  File: sursis.info, Node: Using sursis-html, Next: The sursis Package, Prev: Using sursis, Up: Introduction Basic `sursis-html' usage ------------------------- The `sursis-html' package provides utility functions to make it easier to write HTML responses. It exports functions with names corresponding to most common HTML tags. A simple example of its use is: (load "sursis-html.lsp") (use-package 's-html) (http-response (html (head (title "Test page")) (body nil (h1 "Section 1") (p "paragraph 1") (h2 "Subsection 1.1") (p (i "and so on..."))))) => "Content-type: text/html Test page

Section 1

paragraph 1

Subsection 1.1

and so on...

" The resulting html varies in readability, but the assumption is that the user prefers easily readable lisp. All the tag functions take multiple arguments for their bodies and concatenate these to form the text between the two tags (or after the tag in the case of `

', `

  • ', and some others). A typical use could be as follows: (format t (http-response (html (head (title "Thank You!")) (body (h1 "Thank You!") "Thank you for your response.")))) Some tags, for example the `' tag, take attribute values. The functions for these take a required a-list argument before any tag contents. Ex: (img '(("src" . "le-sursis.png") ("alt" . "The Le Sursis banner"))) => "\"The" (table '(("border" . "on")) "...") => "...
    " Also note that some tag functions, like `img', do not accept any arguments for their body, as they don't have one. For more detail, see *Note The sursis-html Package::.  File: sursis.info, Node: The sursis Package, Next: sursis-get-query, Prev: Using sursis-html, Up: Top The `sursis' Package ******************** The `sursis' package (which is also available via the nickname `cgi') is in `sursis.lsp'. It exports functions for retrieving cgi query data and for forming queries. It currently supports only CLISP, but it should be portable to any Common Lisp system with a one or two line change (CL doesn't provide any mechanism for accessing environmental variables). Currently (as of Version 0.1) the `sursis' package only supports GET queries. Version 0.2 will add support for POST queries. Also, the functions in this package have not been optimized to be tail-recursive. Version 0.3--or possibly sooner--should see the re-writing of some functions to be tail-recursive where efficiency or any potential stack overflows could be a concern. * Menu: * sursis-get-query:: Retrieving query data. * sursis-format-query:: Formatting an a-list into a GET query. * sursis-get-environment:: Retrieving CGI-related environmental variables.  File: sursis.info, Node: sursis-get-query, Next: sursis-format-query, Prev: The sursis Package, Up: The sursis Package `sursis:get-query' ================== `get-query &OPTIONAL REGET' `get-query''s value is an association list containing the key-value pairs given to the cgi script, or `nil' if none were given. Normally, `get-query' reads the query data in once and returns the same list every time it is called. This improves efficiency and is necessary for POST queries. If a non-`nil' value is given for the optional argument REGET, `get-query' will behave as if it has not yet been run. This behavior is almost never desired, except under the most pathological circumstances. Sample usage: (cgi:get-query) => (("message" . "Hello World!") ("tone" . "emphatic"))  File: sursis.info, Node: sursis-format-query, Next: sursis-get-environment, Prev: sursis-get-query, Up: The sursis Package `sursis:format-query' ===================== `format-query AL' `format-query' takes an association list AL and returns an appropriately encoded string to be used as a GET query. Note that it ignores repeats of keys, so it is safe to `acons' pairs onto the head of the list returned by `get-query'. Unless you care about order, in which case you'll have to use a more awkward idiom. Sample usage: (cgi:get-query) => (("message" . "Hello World!") ("tone" . "emphatic")) (acons "tone" "blasÚ" *) => (("tone" . "blasÚ") ("message" . "Hello World!") ("tone" . "emphatic")) (cgi:format-query *) => "?tone=blas%e9&message=Hello+World!" (format nil "http://path/to/self~A" *) => "http://path/to/self?tone=blas%e9&message=Hello+World!"  File: sursis.info, Node: sursis-get-environment, Next: The sursis-html Package, Prev: sursis-format-query, Up: The sursis Package `sursis:get-environment' ======================== `get-environment &OPTIONAL REGET TOGET' `get-environment''s value is an association list of environmental variables describing the CGI environment. Under normal circumstances, it reads from the environment once and returns the same list every time it is called. If the optional argument REGET is non-`nil', it will return a newly-constructed list. The optional variable TOGET, which should be a list of strings, specifies the environmental variables to include in the list. As of this writing, TOGET defaults to `("REQUEST_METHOD" "QUERY_STRING" "CONTENT_LENGTH")'. This function will eventually inspect all environmental variables in the CGI specification; the user may wish to inspect the definition of `get-environment' before passing it a custom list, in case the desired variable has been added to the defaults. When specifying a custom list in TOGET, REGET should be set to non-`nil', or the behavior may be other than what was desired. A note on the a-list returned by `get-environment': 1. If an environmental variable is set, the `cdr' of its entry in the a-list will be its value: `( VARIABLE-NAME . VALUE )'. 2. If it is not set, the `cdr' of its entry will be `nil': `( VARIABLE-NAME )'. 3. If is is set to "", the `cdr' of its entry will be `""': `( VARIABLE-NAME . "" )'. Be careful not to mistake the second case for the third. Sample usage: (cgi:get-environment) => (("REQUEST_METHOD" . "GET") ("QUERY_STRING" . "message=Hello+World!&tone=emphatic") ("CONTENT_LENGTH")) (cgi:get-environment nil '("SCI" "WWW_HOME" "USERNAME")) => (("REQUEST_METHOD" . "GET") ("QUERY_STRING" . "message=Hello+World!&tone=emphatic") ("CONTENT_LENGTH")) (cgi:get-environment t '("SCI" "WWW_HOME" "USERNAME")) => (("SCI" . "/usr/lib/scilab-2.4.1/") ("WWW_HOME" . "/home/noc/lynx_bookmarks.html") ("USERNAME" . "")) It is worth noting that `sursis' contains a definition for `getenv', which is a thin wrapper around the current Lisp system's function to retrieve a single environmental variable (this is not a part of Common Lisp, so the function name varies from system to system). It takes a single string as an argument and returns a string, or `nil' if the variable is not set. It is not exported, but it may be useful to call to retrieve a single variable from the environment.  File: sursis.info, Node: The sursis-html Package, Next: sursis-html Overview, Prev: sursis-get-environment, Up: Top The `sursis-html' Package ************************* The `sursis-html' package (which is also available via the nickname `s-html') is in `sursis-html.lsp'. It exports a large number of utility functions to make it easier to form HTML responses to CGI queries. It is written entirely in Common Lisp, using no extensions. Unless one wishes to only use the `sursis-html' functions a few times in a given script, one should import the functions provided by `sursis-html'. So long as one avoids the names of common html tags, this name-space pollution should not be a problem, and the increased readability of the Lisp code should more than make up for it. This package is optimized to be tail-recursive. * Menu: * sursis-html Overview:: Introduction to the sursis-html package. * Simple Tags:: Functions for , , <i>, etc. * Un-closed Tags:: Functions for <li>, <dd>, etc. * Stand-alone Tags:: Functions for <br>, <hr>, etc. * Tags with Attributes:: Functions for <a>, <body>, <img>, etc. * Misc Tags:: Assorted other functions exported by sursis-html, including generic functions for creating arbitrary tags.  File: sursis.info, Node: sursis-html Overview, Next: Simple Tags, Prev: The sursis-html Package, Up: The sursis-html Package `sursis-html' Overview ====================== Nearly every exported function is based on one of the two generic tag functions: `sa-tag' and `tag'. These functions are primitives for creating a stand-alone tag, and a normal tag (with a `<name>' and a `</name>' portion), respectively. All tag functions except those for purely stand-alone tags (i.e., tags like `<br>', as opposed to `<p>', which may be viewed as having contents, even if it need not be closed) have a `&rest' argument for the contents of the tag. The tag functions take the `~D' representations from `format' for all of their `&rest' arguments and concatenate them together for the body of the tag: (html "The" " value of x is" 12) => "<html>The value of x is 12</html>" This allows nesting of the tag functions, as in: (http-response (html (head (title "Example")) (body nil "Hi."))) => "Content-type: text/html <html> <!-- Generated with help from Le Sursis <http://sursis.sourceforge.net/> --> <head><title>Example Hi. " The readability of the Lisp code given above is the point of this package. Although the `http-response' function used in the example above does not produce an HTML tag, it is provided to be consistent with the philosophy of the package. Note that generation of the recognition comment above is controlled by a constant set at the top of `sursis-html.lsp', and may be disabled.  File: sursis.info, Node: Simple Tags, Next: Un-closed Tags, Prev: sursis-html Overview, Up: The sursis-html Package Simple Tags =========== All these functions are of the form: name &REST SL And produce output of the form: `BODY'. The reader should note that some of these functions insert line breaks for readability. * b * big * blockquote * dl * center * h1 * h2 * h3 * h4 * h5 * h6 * head * html * i * ol * p * pre * small * title * tt * ul  File: sursis.info, Node: Un-closed Tags, Next: Stand-alone Tags, Prev: Simple Tags, Up: The sursis-html Package Un-closed Tags ============== All these functions are of the form: name &REST SL And produce output of the form: `BODY'. This is always followed with a newline, except for `dt' which omits the newline to increase readability: (dt "term" (dd "definition of term")) => "
    term
    definition of term " * dd * dt * li  File: sursis.info, Node: Stand-alone Tags, Next: Tags with Attributes, Prev: Un-closed Tags, Up: The sursis-html Package Stand-alone Tags ================ None of the functions in this section accept arguments for a body. They do not have a general form, so they will be addressed one at a time. * `anchor NAME' There is, of course, no `anchor' tag in HTML. This function is meant for establishing anchors within a document, and is intended to be more readable than trying to do the same with the `a' function. (anchor "para1") => " * `br' `br' produces a `
    ' tag, with line breaks before and after the tag. * `hr &OPTIONAL ATRIB' `hr' works the same as `br', except that it accepts an optional list of attributes. * `img &OPTIONAL ATRIB' This produces a stand-alone `' tag exactly how you would expect: (img '(("src" . "pic") ("alt" . "a pic"))) => "\"a"  File: sursis.info, Node: Tags with Attributes, Next: Misc Tags, Prev: Stand-alone Tags, Up: The sursis-html Package Tags with Attributes ==================== Simple ------ These functions are of the form: name ATRIB &REST SL And produce output of the form: `BODY'. As with the simple tag functions, some insert line breaks for readability. * a * body * table * td * tr Un-closed --------- No functions are currently in this section.  File: sursis.info, Node: Misc Tags, Next: Index, Prev: Tags with Attributes, Up: The sursis-html Package Miscellaneous Functions ======================= These functions do not have a general form, so they will be addressed one at a time. * `comment &REST SL' This acts very much like a simple tag except that instead of `BODY', it produces `'. * `http-response &REST SL' This functions simply prepends `"Content-type: text/html"' and two newlines to its body. * `sa-tag NAME ATRIB' `sa-tag' generates an unclosed (stand-alone) tag from the string given as NAME, and the a-list given as ATRIB: (sa-tag "name" nil) => "" (sa-tag "name" '(("a1" . "v1") ("a2" . "v2"))) => "" * `tag NAME ATRIB CONTENTS &OPTIONAL PRETTY1 PRETTY2' Most of the functions exported by `sursis-html' are built on `tag'. Whereas `sa-tag' could be reasonable to use in one's code for tags not provided by `sursis-html', if one is going to use `tag' to produce a given tag more than once, it is probably worthwhile to define a new (inline) function to do this. `tag' is build around `sa-tag'. NAME and ATRIB are used as in `sa-tag', and CONTENTS provides the body. However, note that CONTENTS is a list, which makes `tag' very useful from functions with a &REST argument, but more difficult to use directly. As an example, to create a `' tag using `tag' directly, one could use: (p "Here's " (tag "b" nil '("some bold " "text")) ".") => "

    Here's some bold text.

    " The `defun' for `b': (defun b (&rest sl) (tag "b" nil sl)) makes this much less awkward: (p "Here's " (b "some bold " "text") ".") If PRETTY1 or PRETTY2 are non-`nil', they insert a newline after the `' tag and before the `' tag, respectively. Both are optional, and both default to `nil'.  File: sursis.info, Node: Index, Prev: Misc Tags, Up: Top Index ***** * Menu:  Tag Table: Node: Top226 Node: Dist and Copying768 Node: Introduction1468 Node: The Name2217 Node: Basic Usage3140 Node: Using sursis3806 Node: Using sursis-html4846 Node: The sursis Package6949 Node: sursis-get-query8048 Node: sursis-format-query8846 Node: sursis-get-environment9759 Node: The sursis-html Package12379 Node: sursis-html Overview13725 Node: Simple Tags15372 Node: Un-closed Tags15932 Node: Stand-alone Tags16416 Node: Tags with Attributes17523 Node: Misc Tags18027 Node: Index20217  End Tag Table