diff options
| -rw-r--r-- | scripts/FileGenerator.py | 44 | ||||
| -rw-r--r-- | scripts/LexGen.py | 70 | ||||
| -rw-r--r-- | scripts/ScintillaData.py | 28 | 
3 files changed, 141 insertions, 1 deletions
diff --git a/scripts/FileGenerator.py b/scripts/FileGenerator.py index 11d6d70ba..3d488ef13 100644 --- a/scripts/FileGenerator.py +++ b/scripts/FileGenerator.py @@ -170,6 +170,50 @@ def UpdateLineInFile(path, linePrefix, lineReplace):      contents = lineEnd.join(lines) + lineEnd      UpdateFile(path, contents) +def ReadFileAsList(path): +    """Read all the lnes in the file and return as a list of strings without line ends. +    """ +    with codecs.open(path, "rU", "utf-8") as f: +        return [l.rstrip('\n') for l in f] +     +def UpdateFileFromLines(path, lines, lineEndToUse): +    """Join the lines with the lineEndToUse then update file if the result is different. +    """ +    contents = lineEndToUse.join(lines) + lineEndToUse +    UpdateFile(path, contents) +     +def FindSectionInList(lines, markers): +    """Find a section defined by an initial start marker, an optional secondary +    marker and an end marker. +    The section is between the secondary/initial start and the end. +    Report as a slice object so the section can be extracted or replaced. +    Raises an exception if the markers can't be found. +    """ +    start = -1 +    end = -1 +    state = 0 +    for i, l in enumerate(lines): +        if markers[0] in l: +            if markers[1]: +                state = 1 +            else: +                start = i+1 +                state = 2 +        elif state == 1: +            if markers[1] in l: +                start = i+1 +                state = 2 +        elif state == 2: +            if markers[2] in l: +                end = i +                state = 3 +    # Check that section was found +    if start == -1: +        raise Exception("Could not find start marker(s) |" + markers[0] + "|" + markers[1] + "|") +    if end == -1: +        raise Exception("Could not find end marker " + markers[2]) +    return slice(start, end) +  def ReplaceREInFile(path, match, replace):      with codecs.open(path, "r", "utf-8") as f:          contents = f.read() diff --git a/scripts/LexGen.py b/scripts/LexGen.py index ba179eee0..ae7ae99d5 100644 --- a/scripts/LexGen.py +++ b/scripts/LexGen.py @@ -8,9 +8,12 @@  # Files are regenerated in place with templates stored in comments.  # The format of generation comments is documented in FileGenerator.py. -from FileGenerator import Regenerate, UpdateLineInFile, ReplaceREInFile, UpdateLineInPlistFile +from FileGenerator import Regenerate, UpdateLineInFile, \ +    ReplaceREInFile, UpdateLineInPlistFile, ReadFileAsList, UpdateFileFromLines, \ +    FindSectionInList  import ScintillaData  import HFacer +import uuid  def UpdateVersionNumbers(sci, root):      UpdateLineInFile(root + "win32/ScintRes.rc", "#define VERSION_SCINTILLA", @@ -43,6 +46,68 @@ def UpdateVersionNumbers(sci, root):      UpdateLineInPlistFile(root + "cocoa/ScintillaFramework/Info.plist",          "CFBundleShortVersionString", sci.versionDotted) +# Last 24 digits of UUID, used for item IDs in Xcode +def uid24(): +    return str(uuid.uuid4()).replace("-", "").upper()[-24:] + +def ciLexerKey(a): +    return a.split()[2].lower() + +""" +		11F35FDB12AEFAF100F0236D /* LexA68k.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11F35FDA12AEFAF100F0236D /* LexA68k.cxx */; }; +		11F35FDA12AEFAF100F0236D /* LexA68k.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexA68k.cxx; path = ../../lexers/LexA68k.cxx; sourceTree = SOURCE_ROOT; }; +				11F35FDA12AEFAF100F0236D /* LexA68k.cxx */, +				11F35FDB12AEFAF100F0236D /* LexA68k.cxx in Sources */, +""" +def RegenerateXcodeProject(path, lexers, lexerReferences): +    # Build 4 blocks for insertion: +    # Each markers contains a unique section start, an optional wait string, and a section end + +    markersPBXBuildFile = ["Begin PBXBuildFile section", "", "End PBXBuildFile section"] +    sectionPBXBuildFile = [] + +    markersPBXFileReference = ["Begin PBXFileReference section", "", "End PBXFileReference section"] +    sectionPBXFileReference = [] + +    markersLexers = ["/* Lexers */ =", "children", ");"] +    sectionLexers = [] + +    markersPBXSourcesBuildPhase = ["Begin PBXSourcesBuildPhase section", "files", ");"] +    sectionPBXSourcesBuildPhase = [] + +    for lexer in lexers: +        if lexer not in lexerReferences: +            uid1 = uid24() +            uid2 = uid24() +            print("Lexer", lexer, "is not in Xcode project. Use IDs", uid1, uid2) +            lexerReferences[lexer] = [uid1, uid2] +            linePBXBuildFile = "\t\t{} /* {}.cxx in Sources */ = {{isa = PBXBuildFile; fileRef = {} /* {}.cxx */; }};".format(uid1, lexer, uid2, lexer) +            linePBXFileReference = "\t\t{} /* {}.cxx */ = {{isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = {}.cxx; path = ../../lexers/{}.cxx; sourceTree = SOURCE_ROOT; }};".format(uid2, lexer, lexer, lexer) +            lineLexers = "\t\t\t\t{} /* {}.cxx */,".format(uid2, lexer) +            linePBXSourcesBuildPhase = "\t\t\t\t{} /* {}.cxx in Sources */,".format(uid1, lexer) +            sectionPBXBuildFile.append(linePBXBuildFile) +            sectionPBXFileReference.append(linePBXFileReference) +            sectionLexers.append(lineLexers) +            sectionPBXSourcesBuildPhase.append(linePBXSourcesBuildPhase) + +    lines = ReadFileAsList(path) + +    sli = FindSectionInList(lines, markersPBXBuildFile) +    lines[sli.stop:sli.stop] = sectionPBXBuildFile + +    sli = FindSectionInList(lines, markersPBXFileReference) +    lines[sli.stop:sli.stop] = sectionPBXFileReference + +    sli = FindSectionInList(lines, markersLexers) +    # This section is shown in the project outline so sort it to make it easier to navigate. +    allLexers = sorted(lines[sli.start:sli.stop] + sectionLexers, key=ciLexerKey) +    lines[sli] = allLexers + +    sli = FindSectionInList(lines, markersPBXSourcesBuildPhase) +    lines[sli.stop:sli.stop] = sectionPBXSourcesBuildPhase + +    UpdateFileFromLines(path, lines, "\n") +  def RegenerateAll(root):      sci = ScintillaData.ScintillaData(root) @@ -50,6 +115,9 @@ def RegenerateAll(root):      Regenerate(root + "src/Catalogue.cxx", "//", sci.lexerModules)      Regenerate(root + "win32/scintilla.mak", "#", sci.lexFiles) +    RegenerateXcodeProject(root + "cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj", +        sci.lexFiles, sci.lexersXcode) +      UpdateVersionNumbers(sci, root)      HFacer.RegenerateAll(root, False) diff --git a/scripts/ScintillaData.py b/scripts/ScintillaData.py index 7aeee4f62..0ac1eddfa 100644 --- a/scripts/ScintillaData.py +++ b/scripts/ScintillaData.py @@ -57,6 +57,31 @@ def FindModules(lexFile):                      partLine = partLine + l      return modules +def FindLexersInXcode(xCodeProject): +    lines = FileGenerator.ReadFileAsList(xCodeProject) + +    uidsOfBuild = {} +    markersPBXBuildFile = ["Begin PBXBuildFile section", "", "End PBXBuildFile section"] +    for buildLine in lines[FileGenerator.FindSectionInList(lines, markersPBXBuildFile)]: +        # Occurs for each file in the build. Find the UIDs used for the file. +        #\t\t[0-9A-F]+ /* [a-zA-Z]+.cxx in sources */ = {isa = PBXBuildFile; fileRef = [0-9A-F]+ /* [a-zA-Z]+ */; }; +        pieces = buildLine.split() +        uid1 = pieces[0] +        filename = pieces[2].split(".")[0] +        uid2 = pieces[12] +        uidsOfBuild[filename] = [uid1, uid2] + +    lexers = {} +    markersLexers = ["/* Lexers */ =", "children", ");"] +    for lexerLine in lines[FileGenerator.FindSectionInList(lines, markersLexers)]: +        #\t\t\t\t[0-9A-F]+ /* [a-zA-Z]+.cxx */, +        uid, _, rest = lexerLine.partition("/* ") +        uid = uid.strip() +        lexer, _, _ = rest.partition(".") +        lexers[lexer] = uidsOfBuild[lexer] + +    return lexers +  # Properties that start with lexer. or fold. are automatically found but there are some  # older properties that don't follow this pattern so must be explicitly listed.  knownIrregularProperties = [ @@ -217,6 +242,7 @@ class ScintillaData:          self.lexerProperties = list(lexerProperties)          SortListInsensitive(self.lexerProperties) +        self.lexersXcode = FindLexersInXcode(scintillaRoot + "cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj")          self.credits = FindCredits(scintillaRoot + "doc/ScintillaHistory.html")  def printWrapped(text): @@ -229,6 +255,8 @@ if __name__=="__main__":          sci.dateModified, sci.yearModified, sci.mdyModified, sci.dmyModified, sci.myModified))      printWrapped(str(len(sci.lexFiles)) + " lexer files: " + ", ".join(sci.lexFiles))      printWrapped(str(len(sci.lexerModules)) + " lexer modules: " + ", ".join(sci.lexerModules)) +    #~ printWrapped(str(len(sci.lexersXcode)) + " Xcode lexer references: " + ", ".join( +        #~ [lex+":"+uids[0]+","+uids[1] for lex, uids in sci.lexersXcode.items()]))      print("Lexer name to ID:")      lexNames = sorted(sci.sclexFromName.keys())      for lexName in lexNames:  | 
