From: Trevor Daniels Date: Wed, 18 Aug 2010 11:59:43 +0000 (+0100) Subject: Docs: add py script to check cross-references X-Git-Tag: release/2.13.31-1~48 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=c3b4cf23e16259037dde8eed3ba559fc294b8206;p=lilypond.git Docs: add py script to check cross-references - for use by doc editors to check cross-references in the doc tree are correct - run at top level of git repository - see comments for known issues - files to be checked/excluded are in ref_check.tely --- diff --git a/scripts/auxiliar/ref_check.py b/scripts/auxiliar/ref_check.py new file mode 100644 index 0000000000..8050272d9f --- /dev/null +++ b/scripts/auxiliar/ref_check.py @@ -0,0 +1,184 @@ + +""" +*** RefCheck + +Flow + Read files + On @defManual manual refManual eg @defManual LM rlearning + Associate manual name 'manual' with reference @'refManual'{ ... } + Add 'refManual' to list of keywords + On @setManual manual set current manual name to 'manual' + On @include open and process new file + On @node add node to Nodes list with current manual name and current file name + On @ref add contents to References list with refManual, current manual name and current file name + On one of refManual keywords add contents to References list with ditto + Match refs and nodes + Process References list: + Check reference is contained in Nodes list with refManual in Nodes = refManual in References + Print results + +Known issues + Node names containing commas are only checked up to the comma + Spurious warnings "Xref should be internal" for files in /included + +""" + + +################################################## +class CrossRefs: + """ Holds References and Nodes """ + def __init__(self): + self.Manuals = {} + self.Nodes = {} + self.nodeNames = {} # used to check for duplicates only + self.Refs = [] + self.nodeCount = 0 + + def addManual(self, manualName, refManual): + self.Manuals[refManual] = manualName + + def getRefManuals(self): + return self.Manuals.keys() + + def getManualName(self, refManual): + return self.Manuals[refManual] + + def addNode(self, nodeName, manualName, fileName): + global returnCode +# print "Node: ", nodeName, " in ", manualName, " found in ", fileName + if manualName+"/"+nodeName in self.Nodes.keys(): + print "Error: Duplicate nodename ",nodeName, " in ", fileName, " and ", self.Nodes[manualName+nodeName] + returnCode=1 + self.Nodes[manualName + "/" + nodeName] = [manualName, fileName] + self.nodeNames[nodeName] = fileName + + def addRef(self, toManualName, toHeading, inFileName): +# if inFileName == "notation/vocal.itely": +# print "Ref to ", toManualName, "/",toHeading, " found in ", inFileName + self.Refs.append([toManualName + "/" + toHeading, inFileName]) + + def check(self): + noErrors = True + for [refHeading, refFileName] in self.Refs: + try: + targetFileName = self.Nodes[refHeading] +# if refFileName == "notation/vocal.itely": +# print "ref to: ", refHeading, " in ", refFileName, " found in ", targetFileName + except KeyError: + noErrors = False + print "ref to: ", refHeading, " in ", refFileName, " not found" + if noErrors: + print " All references satisfied" + else: + returnCode=1 + +################################################## +class File: + """ Process an included file """ + + # Class variables + CurrentManualName = "" + DefaultPath = "" + Excludes = [] + Paths = {} + + # Methods + def __init__(self, fileName): + self.fileName = fileName + try: + self.fullFileName = File.Paths[fileName] + fileName + except KeyError: + self.fullFileName = File.DefaultPath + fileName + + def read(self, crossRefs): + """ Process File """ + + skip = False + myfile = open(self.fullFileName, 'r') + remainderLine = "" + lineNo = 0 + for line in myfile: + lineNo += 1 + words = line.split() + if len(words) > 0: + if words[0] == "@ignore" or words[0] == "@macro": + skip = True + if skip and len(words) > 1: + if words[0] == "@end" and (words[1].find("ignore") >= 0 or words[1].find("macro") >= 0): + skip = False + + if not skip and words[0].find("@c") < 0: + if words[0].find("@defManual") >= 0: + # Manual definition found - extract manual name and refManual string + manualName = words[1] + refManual = words[2] + crossRefs.addManual(manualName, refManual) +# print manualName, refManual + + elif words[0].find("@defaultPath") >=0: + File.DefaultPath = words[1] + + elif words[0].find("@path") >=0: + File.Paths[words[1]] = words[2] + + elif words[0].find("@setManual") >= 0: + File.CurrentManualName = words[1] +# print " Checking ", File.CurrentManualName + + elif words[0].find("@exclude") >=0: + File.Excludes.append(words[1]) + + elif words[0].find("@include") >= 0: + if words[1] not in File.Excludes: + currentFileName = words[1] +# print " File: ", currentFileName + currentFile = File(currentFileName) + currentFile.read(crossRefs) + + elif words[0] == "@node": + nodeName = line[6:-1] + crossRefs.addNode(nodeName, File.CurrentManualName, self.fileName) + + # Find references + + twoLines = remainderLine + ' ' + line.strip() + manualRefStrings = crossRefs.getRefManuals() + refFound = False + for manualRefString in manualRefStrings: + toManualName = crossRefs.getManualName(manualRefString) + actualToManualName = toManualName + if toManualName == "this": + toManualName = File.CurrentManualName + refString = "@" + manualRefString + "{" + refStart = twoLines.find(refString) + if refStart >= 0: + refFound = True + if actualToManualName == File.CurrentManualName: + print "Warning: xref should be internal around line ", lineNo, " in ", self.fileName + twoLines = twoLines[refStart:] + refNodeStart = twoLines.find("{") + 1 + # TODO Need to check here for nested {} + refNodeEnd = twoLines.find("}") + refNodeEndComma = twoLines.find(",") + if refNodeEndComma > 0: + refNodeEnd = min(refNodeEnd, refNodeEndComma) + if refNodeEnd >= 0: + crossRefs.addRef(toManualName, twoLines[refNodeStart:refNodeEnd], self.fileName) + remainderLine=twoLines[refNodeEnd+1:] + if refFound: + refFound = False + break + if not refFound: + remainderLine = "" + + myfile.close() + return + +topFile = File("scripts/auxiliar/ref_check.tely") # TODO get from input params +print "RefCheck ver 0.1" +returnCode=0 +crossRefs = CrossRefs() +topFile.read(crossRefs) +crossRefs.check() +if returnCode > 0: + print "Errors found: status code: ",returnCode \ No newline at end of file diff --git a/scripts/auxiliar/ref_check.tely b/scripts/auxiliar/ref_check.tely new file mode 100644 index 0000000000..960f092d99 --- /dev/null +++ b/scripts/auxiliar/ref_check.tely @@ -0,0 +1,71 @@ + +Manual names and reference keywords: +(refs to IR not checked) +@defManual this ref +@defManual CH rchanges +@defManual EL rextend +@defManual WE rgeneral +@defManual ES ressay +@defManual LM rlearning +@defManual MG rgloss +@defManual NR ruser +@defManual AU rprogram +@defManual CG rcontrib + +Files to be excluded (not available in git): +@exclude colorado.itexi +@exclude computer-notation.itexi +@exclude context-properties.tely +@exclude engravingbib.itexi +@exclude identifiers.tely +@exclude layout-properties.tely +@exclude macros.itexi +@exclude markup-commands.tely +@exclude markup-list-commands.tely +@exclude scheme-functions.tely +@exclude type-predicates.tely +@exclude version.itexi +@exclude weblinks.itexi + +@defaultPath Documentation/ + +Learning Manual +@setManual LM +@include learning.tely + +Music Glossary +@setManual MG +@include music-glossary.tely + +Notation Reference +@setManual NR +@include notation.tely +Dummy nodes to satisfy refs to text markup +@node Text markup commands +@node Font +@node Align +@node Graphic +@node Instrument Specific Markup +@node Music +@node Text markup list commands + +Application Usage +@setManual AU +@include usage.tely + +Contributors Guide +@setManual CG +@include contributor.texi + +Extending Lilypond +@setManual EL +@include extending.tely + +Essay +@setManual ES +@include essay.tely + +General (web) +@setManual WE +@include web.texi +