Pretty Printing
===============

The module (ice-9 pretty-print) provides the procedure pretty-print, which provides nicely formatted output of Scheme objects.  This is especially useful for deeply nested or complex data structures, such as lists and vectors.

The module is loaded by simply saying.

     (use-modules (ice-9 pretty-print))

This makes the procedure pretty-print available.  As an example how pretty-print will format the output, see the following:

     (pretty-print '(define (foo) (lambda (x)
     (cond ((zero? x) #t) ((negative? x) -x) (else
     (if (= x 1) 2 (* x x x)))))))
     -|
     (define (foo)
       (lambda (x)
         (cond ((zero? x) #t)
               ((negative? x) -x)
               (else (if (= x 1) 2 (* x x x))))))

 -- Scheme Procedure: pretty-print obj [port] [keyword-options]
     Print the textual representation of the Scheme object OBJ to PORT.  PORT defaults to the current output port, if not given.

     The further KEYWORD-OPTIONS are keywords and parameters as follows,

     #:display? FLAG
          If FLAG is true then print using display.  The default is #f which means use write style.  (see Writing)

     #:per-line-prefix STRING
          Print the given STRING as a prefix on each line.  The default is no prefix.

     #:width COLUMNS
          Print within the given COLUMNS.  The default is 79.

Beware: Since pretty-print uses it's own write procedure, it's output will not be the same as for example the output of write. Consider the following example.

     (write (lambda (x) x))
     -|
     #<procedure #f (x)>

     (pretty-print (lambda (x) x))
     -|
     #[procedure]

The reason is that pretty-print does not know as much about Guile's object types as the builtin procedures.  This is particularly important for smobs, for which a write procedure can be defined and be used by write, but not by pretty-print.

Formatted Output
================

Outputting messages or other texts which are composed of literal strings, variable contents, newlines and other formatting can be cumbersome, when only the standard procedures like display, write and newline are available.  Additionally, one often wants to collect the output in strings.  With the standard routines, the user is required to set up a string port, add this port as a parameter to the output procedure calls and then retrieve the resulting string from the string port.

The format procedure, to be found in module (ice-9 format), can do all this, and even more.  If you are a C programmer, you can think of this procedure as Guile's fprintf.

 -- Scheme Procedure: format destination format-string args ...
     The first parameter is the DESTINATION, it determines where the output of format will go.

     #t
          Send the formatted output to the current output port and return #t.

     #f
          Return the formatted output as a string.

     Any number value
          Send the formatted output to the current error port and return #t.

     A valid output port
          Send the formatted output to the port DESTINATION and return #t.

     The second parameter is the format string.  It has a similar function to the format string in calls to printf or fprintf in C. It is output to the specified destination, but all escape sequences are replaced by the results of formatting the corresponding sequence.

     Note that escape sequences are marked with the character ~ (tilde), and not with a % (percent sign), as in C.

     The escape sequences in the following table are supported.  When there appears ``corresponding ARG', that means any of the additional arguments, after dropping all arguments which have been used up by escape sequences which have been processed earlier.  Some of the format characters (the characters following the tilde) can be prefixed by :, @, or :@, to modify the behaviour of the format character.  How the modified behaviour differs from the default behaviour is described for every character in the table where appropriate.

     ~~
          Output a single ~ (tilde) character.

     ~%
          Output a newline character, thus advancing to the next output line.

     ~&
          Start a new line, that is, output a newline character if not already at the start of a line.

     ~_
          Output a single space character.

     ~/
          Output a single tabulator character.

     ~|
          Output a page separator (formfeed) character.

     ~t
          Advance to the next tabulator position.

     ~y
          Pretty-print the corresponding ARG.

     ~a
          Output the corresponding ARG like display.

     ~s
          Output the corresponding ARG like write.

     ~d
          Output the corresponding ARG as a decimal number.

     ~x
          Output the corresponding ARG as a hexadecimal number.

     ~o
          Output the corresponding ARG as an octal number.

     ~b
          Output the corresponding ARG as a binary number.

     ~r
          Output the corresponding ARG as a number word, e.g. 10 prints as ten.  If prefixed with :, tenth is printed, if prefixed with :@, Roman numbers are printed.

     ~f
          Output the corresponding ARG as a fixed format floating point number, such as 1.34.

     ~e
          Output the corresponding ARG in exponential notation, such as 1.34E+0.

     ~g
          This works either like ~f or like ~e, whichever produces less characters to be written.

     ~$
          Like ~f, but only with two digits after the decimal point.

     ~i
          Output the corresponding ARG as a complex number.

     ~c
          Output the corresponding ARG as a character.  If prefixed with @, it is printed like with write.  If prefixed with :, control characters are treated specially, for example #\newline will be printed as ^J.

     ~p
          ``Plural''.  If the corresponding ARG is 1, nothing is printed (or y if prefixed with @ or :@), otherwise s is printed (or ies if prefixed with @ or :@).

     ~?, ~k
          Take the corresponding argument as a format string, and the following argument as a list of values.  Then format the values with respect to the format string.

     ~!
          Flush the output to the output port.

     ~#\newline (tilde-newline)
          Continuation lines.

     ~*
          Argument jumping. Navigate in the argument list as specified by the corresponding argument.  If prefixed with :, jump backwards in the argument list, if prefixed by :@, jump to the parameter with the absolute index, otherwise jump forward in the argument list.

     ~(
          Case conversion begin.  If prefixed by :, the following output string will be capitalized, if prefixed by @, the first character will be capitalized, if prefixed by :@ it will be upcased and otherwise it will be downcased.  Conversion stops when the ``Case conversion end'' ~)sequence is encountered.

     ~)
          Case conversion end.  Stop any case conversion currently in effect.

     ~[
          Conditional begin.

     ~;
          Conditional separator.

     ~]
          Conditional end.

     ~{
          Iteration begin.

     ~}
          Iteration end.

     ~^
          Up and out.

     ~'
          Character parameter.

     ~0 ... ~9, ~-, ~+
          Numeric parameter.

     ~v
          Variable parameter from next argument.

     ~#
          Parameter is number of remaining args.  The number of the remaining arguments is prepended to the list of unprocessed arguments.

     ~,
          Parameter separators.

     ~q
          Inquiry message.  Insert a copyright message into the output.

     If any type conversions should fail (for example when using an escape sequence for number output, but the argument is a string), an error will be signalled.

You may have noticed that Guile contains a format procedure even when the module (ice-9 format) is not loaded.  The default format procedure does not support all escape sequences documented in this chapter, and will signal an error if you try to use one of them.  The reason for providing two versions of format is that the full-featured module is fairly large and requires some time to get loaded.  So the Guile maintainers decided not to load the large version of format by default, so that the start-up time of the interpreter is not unnecessarily increased.

The Rx Regular Expression Library
=================================

[FIXME: this is taken from Gary and Mark's quick summaries and should be reviewed and expanded.  Rx is pretty stable, so could already be done!]

The guile-lang-allover package provides an interface to Tom Lord's Rx library (currently only to POSIX regular expressions).  Use of the library requires a two step process: compile a regular expression into an efficient structure, then use the structure in any number of string comparisons.

For example, given the regular expression abc. (which matches any string containing abc followed by any single character):

     guile> (define r (regcomp "abc."))
     guile> r
     #<rgx abc.>
     guile> (regexec r "abc")
     #f
     guile> (regexec r "abcd")
     #((0 . 4))
     guile>

The definitions of regcomp and regexec are as follows:

 -- Scheme Procedure: regcomp pattern [flags]
     Compile the regular expression pattern using POSIX rules.  Flags is optional and should be specified using symbolic names:
      -- Variable: REG_EXTENDED
          use extended POSIX syntax

      -- Variable: REG_ICASE
          use case-insensitive matching

      -- Variable: REG_NEWLINE
          allow anchors to match after newline characters in the string and prevents . or [^...] from matching newlines.

     The logior procedure can be used to combine multiple flags. The default is to use POSIX basic syntax, which makes + and ?  literals and \+ and \? operators.  Backslashes in PATTERN must be escaped if specified in a literal string e.g., "\\(a\\)\\?".

 -- Scheme Procedure: regexec regex string [match-pick] [flags]
     Match STRING against the compiled POSIX regular expression REGEX. MATCH-PICK and FLAGS are optional.  Possible flags (which can be combined using the logior procedure) are:

      -- Variable: REG_NOTBOL
          The beginning of line operator won't match the beginning of STRING (presumably because it's not the beginning of a line)

      -- Variable: REG_NOTEOL
          Similar to REG_NOTBOL, but prevents the end of line operator from matching the end of STRING.

     If no match is possible, regexec returns #f.  Otherwise MATCH-PICK determines the return value:

     #t or unspecified: a newly-allocated vector is returned, containing pairs with the indices of the matched part of STRING and any substrings.

     "": a list is returned: the first element contains a nested list with the matched part of STRING surrounded by the the unmatched parts. Remaining elements are matched substrings (if any).  All returned substrings share memory with STRING.

     #f: regexec returns #t if a match is made, otherwise #f.

     vector: the supplied vector is returned, with the first element replaced by a pair containing the indices of the matched portion of STRING and further elements replaced by pairs containing the indices of matched substrings (if any).

     list: a list will be returned, with each member of the list specified by a code in the corresponding position of the supplied list:

     a number: the numbered matching substring (0 for the entire match).

     #\<: the beginning of STRING to the beginning of the part matched by regex.

     #\>: the end of the matched part of STRING to the end of STRING.

     #\c: the "final tag", which seems to be associated with the "cut operator", which doesn't seem to be available through the posix interface.

     e.g., (list #\< 0 1 #\>).  The returned substrings share memory with STRING.

Here are some other procedures that might be used when using regular expressions:

 -- Scheme Procedure: compiled-regexp? obj
     Test whether obj is a compiled regular expression.

 -- Scheme Procedure: regexp->dfa regex [flags]

 -- Scheme Procedure: dfa-fork dfa

 -- Scheme Procedure: reset-dfa! dfa

 -- Scheme Procedure: dfa-final-tag dfa

 -- Scheme Procedure: dfa-continuable? dfa

 -- Scheme Procedure: advance-dfa! dfa string

File Tree Walk
==============

The functions in this section traverse a tree of files and directories, in a fashion similar to the C ftw and nftw routines (see Working with Directory Trees (GNU C Library Reference Manual)).

     (use-modules (ice-9 ftw))

 -- Function: ftw startname proc ['hash-size n]
     Walk the filesystem tree descending from STARTNAME, calling PROC for each file and directory.

     Hard links and symbolic links are followed.  A file or directory is reported to PROC only once, and skipped if seen again in another place.  One consequence of this is that ftw is safe against circularly linked directory structures.

     Each PROC call is (PROC filename statinfo flag) and it should return #t to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path and the name of the item.  STATINFO is the return from stat (see File System) on FILENAME.  FLAG is one of the following symbols,

     regular
          FILENAME is a file, this includes special files like devices, named pipes, etc.

     directory
          FILENAME is a directory.

     invalid-stat
          An error occurred when calling stat, so nothing is known. STATINFO is #f in this case.

     directory-not-readable
          FILENAME is a directory, but one which cannot be read and hence won't be recursed into.

     symlink
          FILENAME is a dangling symbolic link.  Symbolic links are normally followed and their target reported, the link itself is reported if the target does not exist.

     The return value from ftw is #t if it ran to completion, or otherwise the non-#t value from PROC which caused the stop.

     Optional argument symbol hash-size and an integer can be given to set the size of the hash table used to track items already visited. (see Hash Table Reference)

     In the current implementation, returning non-#t from PROC is the only valid way to terminate ftw.  PROC must not use throw or similar to escape.

 -- Function: nftw startname proc ['chdir] ['depth] ['hash-size n] ['mount] ['physical]
     Walk the filesystem tree starting at STARTNAME, calling PROC for each file and directory.  nftw has extra features over the basic ftw described above.

     Hard links and symbolic links are followed, but a file or directory is reported to PROC only once, and skipped if seen again in another place.  One consequence of this is that nftw is safe against circular linked directory structures.

     Each PROC call is (PROC filename statinfo flag basename level) and it should return #t to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path and the name of the item.  STATINFO is the return from stat on FILENAME (see File System). BASENAME it the item name without any path.  LEVEL is an integer giving the directory nesting level, starting from 0 for the contents of STARTNAME (or that item itself if it's a file). FLAG is one of the following symbols,

     regular
          FILENAME is a file, this includes special files like devices, named pipes, etc.

     directory
          FILENAME is a directory.

     directory-processed
          FILENAME is a directory, and its contents have all been visited. This flag is given instead of directory when the depth option below is used.

     invalid-stat
          An error occurred when applying stat to FILENAME, so nothing is known about it.  STATINFO is #f in this case.

     directory-not-readable
          FILENAME is a directory, but one which cannot be read and hence won't be recursed into.

     symlink
          FILENAME is a dangling symbolic link.  Symbolic links are normally followed and their target reported, the link itself is reported if the target does not exist.

          Under the physical option described below, symlink is instead given for symbolic links whose target does exist.

     stale-symlink
          Under the physical option described below, this indicates FILENAME is a dangling symbolic link, meaning its target does not exist.  Without the physical option plain symlink indicates this.

     The following optional arguments can be given to modify the way nftw works.  Each is passed as a symbol (and hash-size takes a following integer value).

     chdir
          Change to the directory containing the item before calling PROC. When nftw returns the original current directory is restored.

          Under this option, generally the BASENAME parameter should be used to access the item in each PROC call.  The FILENAME parameter still has a path as normal and this will only be valid if the STARTNAME directory was absolute.

     depth
          Visit files ``depth first'', meaning PROC is called for the contents of each directory before it's called for the directory itself.  Normally a directory is reported first, then its contents.

          Under this option, the FLAG to PROC for a directory is directory-processed instead of directory.

     hash-size N
          Set the size of the hash table used to track items already visited. (see Hash Table Reference)

     mount
          Don't cross a mount point, meaning only visit items on the same filesystem as STARTNAME.  (Ie. the same stat:dev.)

     physical
          Don't follow symbolic links, instead report them to PROC as symlink, and report dangling links as stale-symlink.

     The return value from nftw is #t if it ran to completion, or otherwise the non-#t value from PROC which caused the stop.

     In the current implementation, returning non-#t from PROC is the only valid way to terminate ftw.  PROC must not use throw or similar to escape.

Queues
======

The functions in this section are provided by

     (use-modules (ice-9 q))

This module implements queues holding arbitrary scheme objects and designed for efficient first-in / first-out operations.

make-q creates a queue, and objects are entered and removed with enq! and deq!.  q-push!  and q-pop! can be used too, treating the front of the queue like a stack.

 -- Scheme Procedure: make-q
     Return a new queue.

 -- Scheme Procedure: q? obj
     Return #t if OBJ is a queue, or #f if not.

     Note that queues are not a distinct class of objects but are implemented with cons cells.  For that reason certain list structures can get #t from q?.

 -- Scheme Procedure: enq! q obj
     Add OBJ to the rear of Q, and return Q.

 -- Scheme Procedure: deq! q
 -- Scheme Procedure: q-pop! q
     Remove and return the front element from Q.  If Q is empty, a q-empty exception is thrown.

     deq! and q-pop! are the same operation, the two names just let an application match enq! with deq!, or q-push! with q-pop!.

 -- Scheme Procedure: q-push! q obj
     Add OBJ to the front of Q, and return Q.

 -- Scheme Procedure: q-length q
     Return the number of elements in Q.

 -- Scheme Procedure: q-empty? q
     Return true if Q is empty.

 -- Scheme Procedure: q-empty-check q
     Throw a q-empty exception if Q is empty.

 -- Scheme Procedure: q-front q
     Return the first element of Q (without removing it).  If Q is empty, a q-empty exception is thrown.

 -- Scheme Procedure: q-rear q
     Return the last element of Q (without removing it).  If Q is empty, a q-empty exception is thrown.

 -- Scheme Procedure: q-remove! q obj
     Remove all occurences of OBJ from Q, and return Q. OBJ is compared to queue elements using eq?.

The q-empty exceptions described above are thrown just as (throw 'q-empty), there's no message etc like an error throw.

A queue is implemented as a cons cell, the car containing a list of queued elements, and the cdr being the last cell in that list (for ease of enqueuing).

     (LIST . LAST-CELL)

If the queue is empty, LIST is the empty list and LAST-CELL is #f.

An application can directly access the queue list if desired, for instance to search the elements or to insert at a specific point.

 -- Scheme Procedure: sync-q! q
     Recompute the LAST-CELL field in Q.

     All the operations above maintain LAST-CELL as described, so normally there's no need for sync-q!.  But if an application modifies the queue LIST then it must either maintain LAST-CELL similarly, or call sync-q! to recompute it.