# Copyright (C) 2002, Rene Rivera. Permission to copy, use, modify, sell and # distribute this software is granted provided this copyright notice appears in # all copies. This software is provided "as is" without express or implied # warranty, and with no claim as to its suitability for any purpose. # Utilities for generating format independent output. Using these # will help in generation of documentation in at minimum plain/console # and html. import modules ; import numbers ; import string ; # The current output target. Defaults to console. output-target = console ; # The current output type. Defaults to plain. output-type = plain ; # Set the target and type of output to generate. This sets both # the destination output and the type of docs to generate to that # output. The target can be either a file or "console" for echoing # to the console. If the type of output is not specified it defaults # to plain text. # rule output ( target # The target file or device; file or "console". type ? # The type of output; "plain", or "html". ) { type ?= plain ; output-target = $(target) ; output-type = $(type) ; } # Generate a section with a description. The type of output can be # controlled by the value of the 'output-type' variable. If not set # it defaults to 'console' indicating immediate display to the console. # Other possible values are: 'html-file'. # rule section ( name # The name of the section. description * # A number of description lines. ) { if $(output-type) = plain { lines $(name): ; lines ; if $(description) { lines [ split-at-words " " $(description) ] : " " ; lines ; } } } # Generate the start of a list of items. The type of output can be # controlled by the value of the 'output-type' variable. If not set # it defaults to 'console' indicating immediate display to the console. # Other possible values are: 'html-file'. # rule list-start ( ) { if $(output-type) = plain { } } # Generate an item in a list. The type of output can be # controlled by the value of the 'output-type' variable. If not set # it defaults to 'console' indicating immediate display to the console. # Other possible values are: 'html-file'. # rule list-item ( item + # The item to list. ) { if $(output-type) = plain { lines [ split-at-words "*" $(item) ] : " " ; } } # Generate the end of a list of items. The type of output can be # controlled by the value of the 'output-type' variable. If not set # it defaults to 'console' indicating immediate display to the console. # Other possible values are: 'html-file'. # rule list-end ( ) { if $(output-type) = plain { lines ; } } # Split the given text into separate lines, word-wrapping to a margin. # The default margin is 78 characters. # rule split-at-words ( text + # The text to split. : margin ? # An optional margin, default is 78. ) { local lines = ; text = $(text:J=" ") ; margin ?= 78 ; local char-match-1 = ".?" ; local char-match = "" ; while $(margin) != 0 { char-match = $(char-match)$(char-match-1) ; margin = [ numbers.decrement $(margin) ] ; } while $(text) { local s = "" ; local t = "" ; # divide s into the first X characters and the rest s = [ MATCH "^($(char-match))(.*)" : $(text) ] ; if $(s[2]) { # split the first half at a space t = [ MATCH "^(.*)[\\ ]([^\\ ]*)$" : $(s[1]) ] ; } else { t = $(s) ; } if ! $(t[2]) { t += "" ; } text = $(t[2])$(s[2]) ; lines += $(t[1]) ; } return $(lines) ; } # Generate a set of fixed lines. Each single item passed in is # output on a separate line. For console this just echos each line, # but for html this will split them with
. # rule lines ( text * # The lines of text. : indent ? # Optional indentation prepended to each line after the first one. ) { text ?= "" ; indent ?= "" ; if $(output-type) = plain { text $(text[1]) $(indent)$(text[2-]) ; } else if $(output-type) = html { local indent-chars = [ string.chars $(indent) ] ; indent = "" ; for local c in $(indent-chars) { if $(c) = " " { c =   ; } else if $(c) = " " { c =      ; } indent = $(indent)$(c) ; } text $(text[1])
$(indent)$(text[2-])
; } } # Output text directly to the current target. # rule text ( strings * # The strings of text to output. ) { if $(output-target) = console { if ! $(strings) { ECHO ; } else { while $(strings) { ECHO $(strings[1]) ; strings = $(strings[2-]) ; } } } else if $(output-target) { $(output-target).line ?= 0 ; while $(strings) { local line-v = $(output-target).line.$($(output-target).line) ; $(line-v) on $(output-target) = $(strings[1]) ; NOCARE $(line-v) ; NOTFILE $(line-v) ; text-action $(output-target) : $(line-v) ; strings = $(strings[2-]) ; $(output-target).line = [ numbers.increment $($(output-target).line) ] ; } } } # Outputs the text to the current targets, after word-wrapping it rule wrapped-text ( text + ) { local lines = [ split-at-words $(text) ] ; text $(lines) ; } # Append single line to target file. # actions quietly text-action { echo '$($(>))' >> $(<) } local rule __test__ ( ) { import assert ; assert.result one two three : split-at-words one two three : 5 ; assert.result "one two" three : split-at-words one two three : 8 ; assert.result "one two" three : split-at-words one two three : 9 ; assert.result "one two three" : split-at-words one two three ; }