#!/usr/local/bin/python #-- # stylindex: Index builder for PyStyler # $Revision: 1.7 $ $Date: 2007/12/02 03:58:09 $ #-- from __future__ import generators # Allow generators EXTERNAL_NAME = "StylIndex" # Product name EXTERNAL_VERSION = "2.0" # External major.minor version number #================================================================ # CONTENTS #---------------------------------------------------------------- # 1. Imports # 2. Manifest constants # 3. Specification functions (for Cleanroom verification) # 4. Classes and functions # # Args: Object to represent the command line arguments. # writeIndices(): Write all output files. # buildIndex(): Index titles with a KwicIndex object. # addTopics(): Recursively index titles in a topic subtree. # writeStartPage(): Write the base page for the index. # writePrologue(): Write the fixed content of a Web page. # writeGHeader(): Write PyStyler .g file heading. # writeBoilerPlate(): Append contents of boilerplate file. # writeSearchForm(): Write form allowing search for a term. # writeThumbIndex(): Write the links for each letter. # writeLetterPage(): Write one letter's worth of the index. # writePermutedReport(): Write report in permuted style. # writePermutedEntry(): Write one permuted index entry. # linkify(): Make a link to a topic. # writeBookReport(): Write report in book style. # writeBookEntry(): Write one entry in book style. # writeKeywordFile(): Write a file of all keywords used. # # 5. Main #---------------------------------------------------------------- #================================================================ # IMPORTS #---------------------------------------------------------------- import sys # Usual system services #-- # Stuff from /u/john/tcc/python/lib (copied to PyStyler directory) #-- sys.path.insert(0, "/u/www/docs/tcc/projects/pystyler") from cset import * # Cset, character set type from log import * # Log, error logging object from scan import * # Scan, stream scanning object from sysargs import * # Command line argument checker from set import * # Mathematical set type import time # Date and time stuff #-- # Stuff from the PyStyler development tree #-- from pathmap import * # Represents PathMap file from plan import * # Represents Plan file from kwic import * #================================================================ # MANIFEST CONSTANTS #---------------------------------------------------------------- PATH_MAP_FILE = "PathMap" # Name of PathMap file PLAN_FILE = "Plan" # Name of Plan file KEYWORD_FILE = "keywords" # Name of keywords file to be built LOG_FILE = "stylindex.log" # Error logging file OUTPUT_EXTENSION = ".g" # Extension for PyStyler input files DEFAULT_DIR = "./" # Default working directory #-- # KEYWORD_CSET defines which characters are considered part of keywords. # DOC_URL is the documentation for this project, and an actual link # appears on every generated Web page. #-- KEYWORD_CSET = Cset ( string.letters + string.digits + "_" ) DOC_URL = "http://www.nmt.edu/tcc/help/pubs/pystyler/pystyler.pdf" #================================================================ # SPECIFICATION FUNCTIONS #---------------------------------------------------------------- # Blanket preconditions: # * We have write access to the KEYWORD_FILE and all the generated # files. # * If the user specifies a boilerplate file, it's readable. #---------------------------------------------------------------- # boiler-plate(args) == # if args specifies a boiler-plate file -> # the contents of that file # else -> nothing #---------------------------------------------------------------- # g-header == # the usual header for a .g file, with the tag # identifying this program as the author, and an # time with the build time #---------------------------------------------------------------- # index-shortname(args) == # the short name of the index from the command line arguments #---------------------------------------------------------------- # keyword-file == a file named KEYWORD_FILE #---------------------------------------------------------------- # keyword-file-contents ( plan ) == # list of all keywords from plan, one per line, in ascending # order #-- # The set of keywords is written to a file so that the # web maintainer can look for potential candidates to be # added to the exclusion list. For example, if you see the # word `of' in the keywords file, it should clearly be added # to the exclusion list; we don't want to index on the word `of'. #---------------------------------------------------------------- # letter-contents(args, plan, L) == # ( g-header + boiler-plate(args) + search-form + thumb-index + # letter-entries(args, plan, L) + thumb-index ) #-- # The page for a given letter of the alphabet L starts with # the usual .g header, the boilerplate file if there is one, # the search form and thumb index as on the start-page, # all the index entries from plan that start with that letter, # and another copy of the thumb index (heck, it's short). #---------------------------------------------------------------- # letter-entries(args, plan, L) == # all the KWIC entries for keywords from plan that start with # letter L, formatted according to args #---------------------------------------------------------------- # letter-page(args,L) == # a file whose name is (index-shortname(args) + "_" + L) #-- # The index entries for each letter of the alphabet are placed # on a separate page. We could put it all on one page, which # allow one to see more context, but some pages might be large # and slow to load. #---------------------------------------------------------------- # search-form == # a form that allows the user to type in a search term, and # calls search.cgi #---------------------------------------------------------------- # start-page(args) == # a file whose name is (index-shortname(args) + OUTPUT_EXTENSION) #-- # This will be the start page for the index structure. #---------------------------------------------------------------- # start-page-contents(args, plan) == # ( g-header + boiler-plate(args) + search-form + thumb-index ) #-- # The start page has four main sections: # - g-header is the usual WebStyler header section for .g files # - boiler-plate is the contents of the boilerplate file if any # - search-form contains the `To find an index term...' form # - thumb-index is 26 links to pages for each letter #---------------------------------------------------------------- # thumb-index == # the alphabet, with each letter a link to letter-page(args,L) #---------------------------------------------------------------- # - - - - - c l a s s A r g s - - - - - - class Args: """Represents the command line arguments of this program. Exports: Args(): [ if the command line arguments are valid for this program -> return a new Args object representing those arguments else -> sys.stderr +:= (usage message) + (error message) stop execution ] .indexDirName: [ if an index directory was given -> that directory name as a string, ending with "/" else -> "" ] .exclusion: [ if an exclusion file name was given -> that file name as a string else -> the default exclusion file name ] .isPermuted: [ true iff permuted format desired ] .rotationPoint: [ effective rotation point ] .indexBase: [ start page short reference ] .boilerFileName: [ if a boilerplate file was specified -> its name as a string else -> None ] """ DEFAULT_EXCLUSION = "exclusion" # Default exclusion file name INDEX_DIR_OPTION = "D" # Option for indexDirName EXCLUSION_OPTION = "x" # Option for exclusion file PERMUTED_OPTION = "p" # Option for permuted format ROTATION_OPTION = "r" # Option for rotation point INDEX_BASE_KEY = "indexBase" # Positional key for index name BOILER_FILE_KEY = "boilerFile" # Positional key for boiler file switchSpecs = [ # Switch options SwitchArg ( INDEX_DIR_OPTION, [ "index directory name" ], takesValue=1 ), SwitchArg ( EXCLUSION_OPTION, [ "exclusion file name" ], takesValue=1 ), SwitchArg ( PERMUTED_OPTION, [ "use permuted list format (default is", "book format)" ] ), SwitchArg ( ROTATION_OPTION, [ "rotation point: 0 for flush left, 0.5 for", "mid-page, and so forth." ], takesValue=1 ) ] posSpecs = [ # Positional arguments PosArg ( INDEX_BASE_KEY, [ "short reference of the starting page of", "the generated index" ] ), PosArg ( BOILER_FILE_KEY, [ "name of the boilerplate file to be appended", "to the generated pages" ], optional=1 ) ] # - - - A r g s . _ _ i n i t _ _ - - - def __init__ ( self ): "Constructor for Args" #-- 1 -- # [ if the command line arguments have the right syntax -> # sysArgs := a SysArgs object representing those arguments # else -> # sys.stderr +:= (usage message) + (error message) # stop execution ] sysArgs = SysArgs ( self.switchSpecs, self.posSpecs ) #-- 2 -- # [ if sysArgs has an INDEX_DIR_OPTION -> # self.indexDirName := the value of that option, with # "/" appended if not there already # else -> # self.indexDirName := None ] self.indexDirName = sysArgs.switchMap[self.INDEX_DIR_OPTION] if self.indexDirName is 0: self.indexDirName = "" else: if ( ( len ( self.indexDirName ) > 0 ) and ( self.indexDirName[-1] != "/" ) ): self.indexDirName += "/" #-- 3 -- # [ if sysArgs has an EXCLUSION_OPTION -> # self.exclusion := that option's value # else -> # self.exclusion := the default exclusion file name ] self.exclusion = sysArgs.switchMap[self.EXCLUSION_OPTION] if self.exclusion == 0: self.exclusion = self.DEFAULT_EXCLUSION #-- 4 -- # [ self.isPermuted := the PERMUTED_OPTION from sysArgs # self.rotationPoint := the ROTATION_OPTION from sysArgs ] self.isPermuted = sysArgs.switchMap[self.PERMUTED_OPTION] self.rotationPoint = sysArgs.switchMap[self.ROTATION_OPTION] #-- 5 -- # [ self.indexBase := the INDEX_BASE_KEY positional argument # from sysArgs ] self.indexBase = sysArgs.posMap[self.INDEX_BASE_KEY] #-- 6 -- # [ if sysArgs has a BOILER_FILE_KEY positional argument -> # self.boilerFileName := that argument # else -> # self.boilerFileName := None ] self.boilerFileName = sysArgs.posMap[self.BOILER_FILE_KEY] # - - - w r i t e I n d i c e s - - - def writeIndices ( args, plan, indexTopic ): """Write all output files. [ (args is the Args object) and (plan is a Plan object) and (indexTopic is a Topic in plan) -> start-page(args) := start-page-contents(args) letter-page(args,L) := letter-contents(args,plan,L) for L = "a", "b", ..., "z" keyword-file := keyword-file-contents(plan) ] """ #-- 1 -- # [ kwic := a new KwicIndex object indexing all the keywords # from titles in plan, using KEYWORD_CSET to define which # characters are keywords, excluding words from the file named # by args.exclusion, and formatting as specified in args ] kwic = buildIndex ( args, plan ) #-- 2 -- # [ start-page(args) := start-page-contents(args) writeStartPage ( args, indexTopic ) #-- 3 -- # [ letter-page(args,L) := letter-contents(args,kwic,L) # for L = "a", "b", ..., "z" ] for L in string.uppercase: #-- 3 body -- # [ letter-page(args, L) := letter-contents(args,kwic,L) ] writeLetterPage ( args, indexTopic, kwic, L ) #-- 4 -- # [ keyword-file := keyword-file-contents(kwic) ] writeKeywordFile ( args, kwic ) # - - - b u i l d I n d e x - - - def buildIndex ( args, plan ): """Index the titles in plan using a KwicIndex object [ (args is the Args object) and (plan is a Plan object) -> return a new KwicIndex object indexing all the keywords from titles in plan, using KEYWORD_CSET to define which characters are keywords, excluding words from the file named by args.exclusion, and formatting as specified in args ] """ #-- 1 -- if args.isPermuted: # If it's a permuted index ... startTag = "=" # ...mark the start of each title else: startTag = "" # For book-style, don't. #-- 2 -- # [ kwic := a new, empty KwicIndex object ] kwic = KwicIndex ( keyCset=KEYWORD_CSET, exclusionFileName=args.exclusion, permutePoint=args.rotationPoint, startMark=startTag ) #-- 3 -- # [ kwic := kwic with all titles from plan indexed ] addTopics ( kwic, plan.root ) #-- 4 -- return kwic # - - - a d d T o p i c s - - - def addTopics ( kwic, topic ): """Recursively add topic's title, and its descendants', to kwic. [ (kwic is a KwicIndex object) and (topic is a Topic object) -> kwic := kwic with all titles from topic and its descendants added ] """ #-- 1 -- # [ kwic := kwic with topic's title indexed and value=topic ] kwic.add ( topic.title, topic ) #-- 2 -- # [ kwic := kwic with topic's descendants indexed and value-topic ] for subtopic in topic.childList(): addTopics ( kwic, subtopic ) # - - - w r i t e S t a r t P a g e - - - def writeStartPage ( args, indexTopic ): """Write the index's start page. [ (args is the Args object) and (indexTopic is the Topic object for the index root) -> start-page(args) := start-page-contents(args,indexTopic) ] """ #-- 1 -- # [ startPageName := (indexTopic's path) + OUTPUT_EXTENSION ] startPageName = indexTopic.path + OUTPUT_EXTENSION #-- 2-- # [ startPageName can be opened for writing -> # startPage := that file so opened ] try: startPage = open ( startPageName, "w" ) except IOError: Log().fatal ( "Can't open the index start page, `%s'." % startPageName ) #-- 3 -- # [ startPage +:= g-header + boiler-plate(args) + # search-form + thumb-index ] writePrologue ( startPage, args, indexTopic ) #-- 4 -- startPage.close() # - - - w r i t e P r o l o g u e - - - def writePrologue ( page, args, indexTopic ): """Write the fixed content that starts each web page. [ (page is a writeable file handle) and (args is the Args object) and (indexTopic is the Topic object for the index base page) -> page +:= g-header + boiler-plate(args) + search-form + thumb-index ] """ #-- 1 -- # [ page +:= g-header ] writeGHeader ( page ) #-- 2 -- # [ page +:= boiler-plate(args) ] writeBoilerPlate ( args, page ) #-- 3 -- # [ page +:= search-form ] writeSearchForm ( page ) #-- 4 -- # [ page +:= thumb-index from indexTopic as the base page ] writeThumbIndex ( page, indexTopic ) # - - - w r i t e G H e a d e r - - - def writeGHeader ( page ): """Writes the usual PyStyler header block. [ page is a writeable file -> page +:= g-header ] """ #-- 1 -- # [ timestamp := current time as "YYYY-MM-DD HH:MM:SS z" # where z is the zone correction ] timestamp = time.strftime ( "%Y/%m/%d %H:%M:%S %Z", time.localtime ( time.time() ) ) #-- 2 -- # [ page +:= g-header with timestame as the time ] page.write ( '\n' ' This file generated automatically by\n' ' the stylindex program. See the\n' ' PyStyler project documentation.\n' ' \n' #-- # The breaks after the dollar signs below prevent RCS # from writing over them as RCS tags. #-- ' \n' '\n' % ( DOC_URL, timestamp ) ) # - - - w r i t e B o i l e r P l a t e - - - def writeBoilerPlate ( args, page ): """Add the boilerplate text file contents, if any. [ (args is the Args object) and (page is a writeable file) -> page +:= boiler-plate(args) ] """ #-- 1 -- if args.boilerFileName is None: return #-- 2 -- # [ args.boilerFileName names a readable file -> # boilerFile := that file, so opened ] try: boilerFile = open ( args.boilerFileName ) except IOError: Log().fatal ( "Can't open the boilerplate file `%s' " "for reading." % args.boilerFileName ) #-- 3 -- # [ page +:= contents of boilerFile ] for line in boilerFile: page.write ( line ) #-- 4 -- boilerFile.close() # - - - w r i t e S e a r c h F o r m - - - def writeSearchForm ( page ): """Write the HTLM form that allows users to search for keywords. [ page is a writeable file -> page +:= search-form ] """ page.write ( '
\n' '

To find an index term, type it into this field,\n' ' or click on its initial letter below.\n' ' \n' ' \n' ' \n' '

\n' ) # - - - w r i t e T h u m b I n d e x - - - def writeThumbIndex ( page, indexTopic ): """Write the alphabet, each a link to the page for that letter. [ page is a writeable file -> page +:= thumb-index ] """ #-- 1 -- page.write ( '

\n' ) #-- 2 -- # [ page +:= the uppercase letters, with each letter L an # link to topic letter-page(L) ] #-- # Note: ' ' is the HTML entity for a non-breaking space. #-- for L in string.uppercase: #-- 2 body -- # [ page +:= (letter L, as an link to topic # letter-page(L)) + " " ] page.write ( ' %s \n' % ( indexTopic.shortName, L.lower(), L ) ) #-- 3 -- page.write ( '

\n' ) # - - - w r i t e L e t t e r P a g e - - - def writeLetterPage ( args, indexTopic, kwic, L ): """Write the page with all index entries whose keywords start with L. [ (args is the Args object) and (indexTopic is the Topic for the start page) and (kwic is the KwicIndex indexing the plan file) and (L is one uppercase letter) -> letter-page(args, L) := letter-contents(args,kwic,L) ] """ #-- 1 -- # [ if letter-page(L) can be opened for writing -> # page := that file, so opened ] letterPageName = ( "%s_%s%s" % ( indexTopic.path, L.lower(), OUTPUT_EXTENSION ) ) try: page = open ( letterPageName, "w" ) except IOError: Log().fatal ( "Can't open index page for letter `%s' " "for writing." % letterPageName ) #-- 2 -- # [ page +:= g_header + boiler-plate ( args ) + # search_form + thumb_index ( indexTopic ) ] writePrologue ( page, args, indexTopic ) #-- 3 -- # [ if args.isPermuted -> # page +:= index entries in the half-open range [L,stopKey) # formatted in permuted style # else -> # page +:= index entries in the half-open range [L,stopKey) # formatted in book style ] page.write ( '
\n' ) if args.isPermuted: writePermutedReport ( page, kwic, L ) else: writeBookReport ( page, kwic, L ) page.write ( '\n' ) #-- 4 -- # [ page +:= (another thumb-index) ] writeThumbIndex ( page, indexTopic ) page.close() # - - - w r i t e P e r m u t e d R e p o r t - - - def writePermutedReport ( page, kwic, L ): """Write entries for one letter in the permuted style. [ (page is a writeable file) and (kwic is a KwicIndex object) and (L is a single uppercase letter) and (stopKey is a string) -> page +:= index entries in the half-open range [L,L+1) formatted in permuted style ] """ #-- 1 -- page.write ( '
\n' )        # Start preformatted section

    #-- 2 --
    oldKey  =  ""

    #-- 3 --
    # [ page    +:=  index entries in the half-open range [L,L+1)
    #                formatted in the permuted style
    #   oldKey  :=   last keyword in the range, lowercased,
    #                or "" if the range is empty ]
    for  ref in kwic.genRefs ( L, chr ( ord ( L ) + 1 ) ):
        #-- 3 body --
        # [ if (ref.title.lower() != oldKey) ->
        #     page  +:=  (an 

heading containing ref's keyword, # defining an anchor with name=keyword) + # (ref, displayed in permuted style, with a link # to ref.topic) # else -> # page +:= (ref, displayed in permuted style, with a link # to ref.topic) # In any case -> # oldKey := ref's keyword, lowercased ] oldKey = writePermutedEntry ( page, kwic, ref, oldKey ) #-- n -- page.write ( '

\n' ) # End preformatted section # - - - w r i t e P e r m u t e d E n t r y - - - def writePermutedEntry ( page, kwic, ref, oldKey ): """Write one index entry in the permuted style. [ (page is a writeable file) and (kwic is a KwicIndex object) and (ref is a KwicRef object) and (oldKey is a string) -> if (ref.keyword().lower() != oldKey) -> page +:= (an

heading containing ref's keyword, defining an anchor with name=keyword) + (ref, displayed in permuted style according to kwic, with a link to ref.topic) else -> page +:= (ref, displayed in permuted style, with a link to ref.topic) In any case -> return ref's keyword, lowercased ] """ #-- 1 -- # [ keyword := ref's keyword, lowercased ] keyword = ref.keyword().lower() #-- 2 -- # [ if keyword != oldKey -> # page +:= an

containing keyword, defining an anchor # with name=keyword # else -> I ] if keyword != oldKey: page.write ( '\n

%s

\n' % ( keyword, keyword ) ) #-- 3 -- # [ page +:= ref, shown in permuted style as per kwic's arguments, # with the keyword a link to its value as a target ] page.write ( '%s\n' % kwic.permuteLink ( ref, linkify ) ) #-- 4 -- return keyword # - - - l i n k i f y - - - def linkify ( ref, text ): """Makes `text' into a link to ref's topic. [ (ref is a KwicRef object) and (text is a string) -> return a string containin a hyperlink whose link text=(text) and whose href attribute is derived from ref ] Note: This function's calling sequence is required by the KwicIndex.permuteLink() method. Note that ref.value is the Topic object of the page associated with the reference. """ return ( '%s' % ( ref.value.shortName, text ) ) # - - - w r i t e B o o k R e p o r t - - - def writeBookReport ( page, kwic, L ): """Write the index entries for one letter, in the book-index style. [ (page is a writeable file) and (kwic is a KwicIndex object) and (L is a single uppercase letter) -> page +:= index entries in the half-open range [L,L+1) formatted in book style ] """ #-- 1 -- oldKey = "" #-- 2 -- # [ page +:= index entries in the half-open range [L,L+1) # formatted in book-index style # oldKey := last keyword in the range, lowercased, # or "" if the range is empty ] for ref in kwic.genRefs ( L, chr ( ord ( L ) + 1 ) ): #-- 2 body -- # [ if ref.title.lower() != oldKey -> # page +:= an

heading containing ref's keyword, # defining an anchor with name=keyword) + # (ref, displayed in book style, with a link # to ref's topic) # else -> # page +:= (ref, displayed in book style, with a link # to ref's topic) # In any case -> # oldKey := ref's keyword, lowercased ] oldKey = writeBookEntry ( page, ref, oldKey ) # - - - w r i t e B o o k E n t r y - - - def writeBookEntry ( page, ref, oldKey ): """Write one index entry in the book style. [ (page is a writeable file) and (ref is a KwicRef object) and (oldKey is a string) -> if ref.title.lower() != oldKey -> page +:= an

heading containing ref's keyword, defining an anchor with name=keyword) + (ref, displayed in book style, with a link to ref's topic) else -> page +:= (ref, displayed in book style, with a link to ref's topic) In any case -> return ref's keyword, lowercased ] """ #-- 1 -- # [ keyword := ref's keyword, lowercased ] keyword = ref.keyword().lower() #-- 2 -- # [ if keyword != oldKey -> # page +:= an

containing keyword, defining an anchor # with name=keyword # else -> I ] if keyword != oldKey: page.write ( '\n

%s

\n' % ( keyword, keyword ) ) #-- 3 -- # [ page +:= the keyword from ref, wrapped in an element # linking it to ref's value as a topic ] page.write ( '%s' % ( ref.value.shortName, ref.keyword() ) ) #-- 4 -- # [ page +:= the suffix from ref ] page.write ( ref.suffix() ) #-- 5 -- # [ if ref's prefix is empty -> # I # else -> # page +:= "," + (ref's prefix) ] prefixText = ref.prefix() if len(prefixText) > 0: page.write ( ', %s' % prefixText ) #-- 6 -- page.write ( '
\n' ) #-- 7 -- return keyword # - - - w r i t e K e y w o r d F i l e - - - def writeKeywordFile ( args, kwic ): """Write a list of the unique keywords in the index. [ kwic is a KwicIndex object -> keyword-file := keyword-file-contents(kwic) ] """ #-- 1 -- # [ if keywordFile can be opened new for writing -> # keywordFile := that file, so opened ] try: keywordFile = open ( KEYWORD_FILE, "w" ) except IOError: Log().fatal ( "Cannot open file keyword file `%s' " "new for writing." % KEYWORD_FILE ) #-- 2 -- # [ keySet := a new, empty Set object ] keySet = Set() #-- 3 -- # [ keySet := union ( keySet, {keywords from kwic, lowercased} ) ] for ref in kwic.genRefs(): #-- 3 body -- # [ keySet := union ( keySet, keyword from ref, lowercased ) ] keySet.add ( ref.keyword().lower() ) #-- 4 -- # [ keywordFile +:= words from keySet, one per line ] for keyword in keySet.genSorted(): keywordFile.write ( "%s\n" % keyword ) #-- 5 -- keywordFile.close() # - - - - - m a i n - - - - - #================================================================ # Overall intended function #---------------------------------------------------------------- # [ if (command line options are valid) and # else if all input files are readable and valid -> # start-page(args) := start-page-contents(args,plan) # letter-page(args,L) := letter-contents(args,plan,L) # for L = "a", "b", ..., "z" # keyword-file := keyword-file-contents(plan) # else if (command line options are invalid) -> # sys.stderr +:= (usage message) + (error message) # else if (not all input files are readable and valid) -> # sys.stderr +:= (error message) ] #---------------------------------------------------------------- #-- 1 - # [ Log() +:= a Log singleton logging to LOG_FILE ] Log().addLogFile(LOG_FILE) # Keep a disk copy of all error messages Log().write ( "=== %s %s ===" % ( EXTERNAL_NAME, EXTERNAL_VERSION ) ) #-- 2 -- # [ if command line options are valid -> # args := an Args object representing those options # else -> # sys.stderr +:= (usage message) + (error message) ] args = Args() #-- 3 -- # [ if PATH_MAP_FILE names a readable, valid PathMap file -> # pathMap := a new PathMap object representing that file # else -> # Log() +:= error message(s) # stop execution ] try: pathMap = PathMap ( PATH_MAP_FILE ) except IOError: sys.exit(1) #-- 4 -- # [ if PLAN_FILE names a readable, valid Plan file in the context # of pathMap -> # plan := a new Plan object representing that file # else -> # Log() +:= error message(s) # stop execution ] try: plan = Plan ( pathMap, PLAN_FILE ) except IOError: sys.exit(2) #-- 5 -- # [ if args.indexBase is a valid short name in plan -> # indexTarget := a new Target representing the topic for # that short name # indexTopic := the Topic representing the topic for that # short name ] # else -> # sys.stderr +:= (usage message) + (error message) # stop execution ] try: indexTarget = plan.lookupShortName ( args.indexBase ) indexTopic = indexTarget.topic except KeyError: Log().fatal ( "Short name '%s' is not define in the %s file." % ( args.indexBase, PLAN_FILE ) ) #-- 6 -- # [ start-page(args) := start-page-contents(args,plan) # letter-page(args,L) := letter-contents(args,plan,L) # for L = "a", "b", ..., "z" # keyword-file := keyword-file-contents(plan) ] writeIndices ( args, plan, indexTopic ) #-- 7 -- Log().write ( "stylindex complete." )