X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=lib%2Fscripts%2Flayout2layout.py;h=a59dfcfae2afbd3425278d44a4f8ee17edf69e90;hb=897edc10c07f5605584317376d7e909e1eba9319;hp=3d27398ecce1bef0f71f24d0b1f041f6d4a66dd8;hpb=63644744fd6a0decf0fc745814125e1ddeb60220;p=lyx.git diff --git a/lib/scripts/layout2layout.py b/lib/scripts/layout2layout.py index 3d27398ecc..a59dfcfae2 100644 --- a/lib/scripts/layout2layout.py +++ b/lib/scripts/layout2layout.py @@ -9,7 +9,7 @@ # Full author contact details are available in file CREDITS -# This script will update a .layout file to format 6 +# This script will update a .layout file to current format import os, re, string, sys @@ -33,7 +33,103 @@ import os, re, string, sys # Incremented to format 9, 5 October 2008 by rgh # ForcePlain and CustomPars tags added to InsetLayout -currentFormat = 9 +# Incremented to format 10, 6 October 2008 by rgh +# Change format of counters + +# Incremented to format 11, 14 October 2008 by rgh +# Add ProvidesModule, ExcludesModule tags + +# Incremented to format 12, 10 January 2009 by gb +# Add I18NPreamble tag + +# Incremented to format 13, 5 February 2009 by rgh +# Add InToc tag for InsetLayout + +# Incremented to format 14, 14 February 2009 by gb +# Rename I18NPreamble to BabelPreamble and add LangPreamble + +# Incremented to format 15, 28 May 2009 by lasgouttes +# Add new tag OutputFormat; modules can be conditioned on feature +# "from->to". + +# Incremented to format 16, 5 June 2009 by rgh +# Add new tags for Text Class: +# HTMLPreamble, HTMLAddToPreamble +# For Layout: +# HTMLTag, HTMLAttr, HTMLLabel, HTMLLabelAttr, HTMLItem, HTMLItemAttr +# HTMLStyle, and HTMLPreamble +# For InsetLayout: +# HTMLTag, HTMLAttr, HTMLStyle, and HTMLPreamble +# For Floats: +# HTMLType, HTMLClass, HTMLStyle + +# Incremented to format 17, 12 August 2009 by rgh +# Add IfStyle and IfCounter tags for layout. + +# Incremented to format 18, 27 October 2009 by rgh +# Added some new tags for HTML output. + +# Incremented to format 19, 17 November 2009 by rgh +# Added InPreamble tag. + +# Incremented to format 20, 17 December 2009 by rgh +# Added ContentAsLabel tag. + +# Incremented to format 21, 12 January 2010 by rgh +# Added HTMLTocLayout and HTMLTitle tags. + +# Incremented to format 22, 20 January 2010 by rgh +# Added HTMLFormat tag to Counters. + +# Incremented to format 23, 13 February 2010 by spitz +# Added Spellcheck tag. + +# Incremented to format 24, 5 March 2010 by rgh +# Changed LaTeXBuiltin tag to NeedsFloatPkg and +# added new tag ListCommand. + +# Incremented to format 25, 12 March 2010 by rgh +# Added RefPrefix tag for layouts and floats. + +# Incremented to format 26, 29 March 2010 by rgh +# Added CiteFormat. + +# Incremented to format 27, 4 June 2010 by rgh +# Added RequiredArgs tag. + +# Incremented to format 28, 6 August 2010 by lasgouttes +# Added ParbreakIsNewline tag for Layout and InsetLayout. + +# Incremented to format 29, 10 August 2010 by rgh +# Changed Custom:Style, CharStyle:Style, and Element:Style +# uniformly to Flex:Style. + +# Incremented to format 30, 13 August 2010 by rgh +# Introduced ResetsFont tag for InsetLayout. + +# Incremented to format 31, 12 January 2011 by rgh +# Introducted NoCounter tag. + +# Incremented to format 32, 30 January 2011 by forenr +# Added Display tag for InsetLayout + +# Incremented to format 33, 2 February 2011 by rgh +# Changed NeedsFloatPkg to UsesFloatPkg + +# Incremented to format 34, 28 March 2011 by rgh +# Remove obsolete Fill_(Top|Bottom) tags + +# Incremented to format 35, 28 March 2011 by rgh +# Try to add "Flex:" to any flex insets that don't have it. + +# Do not forget to document format change in Customization +# Manual (section "Declaring a new text class"). + +# You might also want to consider running the +# development/tools/updatelayouts.sh script to update all +# layout files to the new format. + +currentFormat = 35 def usage(prog_name): @@ -46,32 +142,24 @@ def error(message): sys.exit(1) -def trim_eol(line): - " Remove end of line char(s)." - if line[-2:-1] == '\r': - return line[:-2] - elif line[-1:] == '\r' or line[-1:] == '\n': - return line[:-1] +def trim_bom(line): + " Remove byte order mark." + if line[0:3] == "\357\273\277": + return line[3:] else: - # file with no EOL in last line return line -def read(input): +def read(source): " Read input file and strip lineendings." - lines = list() - while 1: - line = input.readline() - if not line: - break - lines.append(trim_eol(line)) + lines = source.read().splitlines() + lines[0] = trim_bom(lines[0]) return lines def write(output, lines): " Write output file with native lineendings." - for line in lines: - output.write(line + os.linesep) + output.write(os.linesep.join(lines) + os.linesep) # Concatenates old and new in an intelligent way: @@ -83,14 +171,27 @@ def concatenate_label(old, new): else: return '"' + old + new + '"' +# appends a string to a list unless it's already there +def addstring(s, l): + if l.count(s) > 0: + return + l.append(s) + def convert(lines): " Convert to new format." re_Comment = re.compile(r'^(\s*)#') + re_Counter = re.compile(r'\s*Counter\s*', re.IGNORECASE) + re_Name = re.compile(r'\s*Name\s+(\S+)\s*', re.IGNORECASE) + re_UseMod = re.compile(r'^\s*UseModule\s+(.*)', re.IGNORECASE) re_Empty = re.compile(r'^(\s*)$') re_Format = re.compile(r'^(\s*)(Format)(\s+)(\S+)', re.IGNORECASE) re_Preamble = re.compile(r'^(\s*)Preamble', re.IGNORECASE) re_EndPreamble = re.compile(r'^(\s*)EndPreamble', re.IGNORECASE) + re_LangPreamble = re.compile(r'^(\s*)LangPreamble', re.IGNORECASE) + re_EndLangPreamble = re.compile(r'^(\s*)EndLangPreamble', re.IGNORECASE) + re_BabelPreamble = re.compile(r'^(\s*)BabelPreamble', re.IGNORECASE) + re_EndBabelPreamble = re.compile(r'^(\s*)EndBabelPreamble', re.IGNORECASE) re_MaxCounter = re.compile(r'^(\s*)(MaxCounter)(\s+)(\S+)', re.IGNORECASE) re_LabelType = re.compile(r'^(\s*)(LabelType)(\s+)(\S+)', re.IGNORECASE) re_LabelString = re.compile(r'^(\s*)(LabelString)(\s+)(("[^"]+")|(\S+))', re.IGNORECASE) @@ -102,6 +203,28 @@ def convert(lines): re_End = re.compile(r'^(\s*)(End)(\s*)$', re.IGNORECASE) re_Provides = re.compile(r'^(\s*)Provides(\S+)(\s+)(\S+)', re.IGNORECASE) re_CharStyle = re.compile(r'^(\s*)CharStyle(\s+)(\S+)$', re.IGNORECASE) + re_AMSMaths = re.compile(r'^\s*Input ams(?:math|def)s.inc\s*') + re_AMSMathsPlain = re.compile(r'^\s*Input amsmaths-plain.inc\s*') + re_AMSMathsSeq = re.compile(r'^\s*Input amsmaths-seq.inc\s*') + re_TocLevel = re.compile(r'^(\s*)(TocLevel)(\s+)(\S+)', re.IGNORECASE) + re_I18nPreamble = re.compile(r'^(\s*)I18nPreamble', re.IGNORECASE) + re_EndI18nPreamble = re.compile(r'^(\s*)EndI18nPreamble', re.IGNORECASE) + re_Float = re.compile(r'^\s*Float\s*$', re.IGNORECASE) + re_Type = re.compile(r'\s*Type\s+(\w+)', re.IGNORECASE) + re_Builtin = re.compile(r'^(\s*)LaTeXBuiltin\s+(\w*)', re.IGNORECASE) + re_True = re.compile(r'^\s*(?:true|1)\s*$', re.IGNORECASE) + re_InsetLayout = re.compile(r'^\s*InsetLayout\s+(?:Custom|CharStyle|Element):(\S+)\s*$', re.IGNORECASE) + # with quotes + re_QInsetLayout = re.compile(r'^\s*InsetLayout\s+"(?:Custom|CharStyle|Element):([^"]+)"\s*$', re.IGNORECASE) + re_InsetLayout_CopyStyle = re.compile(r'^\s*CopyStyle\s+(?:Custom|CharStyle|Element):(\S+)\s*$', re.IGNORECASE) + re_QInsetLayout_CopyStyle = re.compile(r'^\s*CopyStyle\s+"(?:Custom|CharStyle|Element):([^"]+)"\s*$', re.IGNORECASE) + re_NeedsFloatPkg = re.compile(r'^(\s*)NeedsFloatPkg\s+(\w+)\s*$', re.IGNORECASE) + re_Fill = re.compile(r'^\s*Fill_(?:Top|Bottom).*$', re.IGNORECASE) + re_InsetLayout2 = re.compile(r'^\s*InsetLayout\s+(\S+)\s*$', re.IGNORECASE) + # with quotes + re_QInsetLayout2 = re.compile(r'^\s*InsetLayout\s+"([^"]+)"\s*$', re.IGNORECASE) + re_IsFlex = re.compile(r'\s*LyXType.*$', re.IGNORECASE) + re_CopyStyle2 = re.compile(r'(\s*CopyStyle\s+)"?([^"]+)"?\s*$') # counters for sectioning styles (hardcoded in 1.3) counters = {"part" : "\\Roman{part}", @@ -132,6 +255,7 @@ def convert(lines): i = 0 only_comment = 1 counter = "" + toclevel = "" label = "" labelstring = "" labelstringappendix = "" @@ -144,6 +268,10 @@ def convert(lines): style = "" maxcounter = 0 format = 1 + formatline = 0 + usemodules = [] + flexstyles = [] + while i < len(lines): # Skip comments and empty lines if re_Comment.match(lines[i]) or re_Empty.match(lines[i]): @@ -154,6 +282,7 @@ def convert(lines): if (only_comment): match = re_Format.match(lines[i]) if match: + formatline = i format = int(match.group(4)) if format > 1 and format < currentFormat: lines[i] = "Format %d" % (format + 1) @@ -174,9 +303,224 @@ def convert(lines): while i < len(lines) and not re_EndPreamble.match(lines[i]): i += 1 continue + if re_LangPreamble.match(lines[i]): + i += 1 + while i < len(lines) and not re_EndLangPreamble.match(lines[i]): + i += 1 + continue + if re_BabelPreamble.match(lines[i]): + i += 1 + while i < len(lines) and not re_EndBabelPreamble.match(lines[i]): + i += 1 + continue + + if format == 34: + match = re_InsetLayout2.match(lines[i]) + if not match: + match = re_QInsetLayout2.match(lines[i]) + if not match: + match = re_CopyStyle2.match(lines[i]) + if not match: + i += 1 + continue + style = match.group(2) + + if flexstyles.count(style): + lines[i] = match.group(1) + "\"Flex:" + style + "\"" + i += 1 + continue + + name = match.group(1) + names = name.split(":", 1) + if len(names) > 1 and names[0] == "Flex": + i += 1 + continue + + isflex = False + for j in range(i + 1, len(lines)): + if re_IsFlex.match(lines[j]): + isflex = True + break + if re_End.match(lines[j]): + break + + if isflex: + flexstyles.append(name) + lines[i] = "InsetLayout \"Flex:" + name + "\"" + + i += 1 + continue + + if format == 33: + m = re_Fill.match(lines[i]) + if m: + lines[i] = "" + i += 1 + continue + + if format == 32: + match = re_NeedsFloatPkg.match(lines[i]) + if match: + space = match.group(1) + val = match.group(2) + lines[i] = space + "UsesFloatPkg " + val + newval = 'true' + if val == '1' or val.lower() == 'true': + newval = 'false' + lines.insert(i, space + "IsPredefined " + newval) + i += 1 + i += 1 + continue + + # Only new features + if format >= 29 and format <= 31: + i += 1 + continue + + if format == 28: + match = re_InsetLayout.match(lines[i]) + if match: + lines[i] = "InsetLayout Flex:" + match.group(1) + else: + match = re_QInsetLayout.match(lines[i]) + if match: + lines[i] = "InsetLayout \"Flex:" + match.group(1) + "\"" + else: + match = re_InsetLayout_CopyStyle.match(lines[i]) + if match: + lines[i] = "\tCopyStyle Flex:" + match.group(1) + else: + match = re_QInsetLayout_CopyStyle.match(lines[i]) + if match: + lines[i] = "\tCopyStyle \"Flex:" + match.group(1) + "\"" + i += 1 + continue + + # Only new features + if format >= 24 and format <= 27: + i += 1 + continue + + if format == 23: + match = re_Float.match(lines[i]) + i += 1 + if not match: + continue + # we need to do two things: + # (i) Convert Builtin to NeedsFloatPkg + # (ii) Write ListCommand lines for the builtin floats table and figure + builtin = False + cmd = "" + while True and i < len(lines): + m1 = re_End.match(lines[i]) + if m1: + if builtin and cmd: + line = " ListCommand " + cmd + lines.insert(i, line) + i += 1 + break + m2 = re_Builtin.match(lines[i]) + if m2: + builtin = True + ws1 = m2.group(1) + arg = m2.group(2) + newarg = "" + if re_True.match(arg): + newarg = "false" + else: + newarg = "true" + lines[i] = ws1 + "NeedsFloatPkg " + newarg + m3 = re_Type.match(lines[i]) + if m3: + fltype = m3.group(1) + fltype = fltype.lower() + if fltype == "table": + cmd = "listoftables" + elif fltype == "figure": + cmd = "listoffigures" + # else unknown, which is why we're doing this + i += 1 + continue + + # This just involved new features, not any changes to old ones + if format >= 14 and format <= 22: + i += 1 + continue + + # Rename I18NPreamble to BabelPreamble + if format == 13: + match = re_I18nPreamble.match(lines[i]) + if match: + lines[i] = match.group(1) + "BabelPreamble" + i += 1 + match = re_EndI18nPreamble.match(lines[i]) + while i < len(lines) and not match: + i += 1 + match = re_EndI18nPreamble.match(lines[i]) + lines[i] = match.group(1) + "EndBabelPreamble" + i += 1 + continue + + # These just involved new features, not any changes to old ones + if format == 11 or format == 12: + i += 1 + continue + + if format == 10: + match = re_UseMod.match(lines[i]) + if match: + module = match.group(1) + lines[i] = "DefaultModule " + module + i += 1 + continue + + if format == 9: + match = re_Counter.match(lines[i]) + if match: + counterline = i + i += 1 + while i < len(lines): + namem = re_Name.match(lines[i]) + if namem: + name = namem.group(1) + lines.pop(i) + lines[counterline] = "Counter %s" % name + # we don't need to increment i + continue + endem = re_End.match(lines[i]) + if endem: + i += 1 + break + i += 1 + i += 1 + continue + + if format == 8: + # We want to scan for ams-type includes and, if we find them, + # add corresponding UseModule tags to the layout. + match = re_AMSMaths.match(lines[i]) + if match: + addstring("theorems-ams", usemodules) + addstring("theorems-ams-extended", usemodules) + addstring("theorems-sec", usemodules) + lines.pop(i) + continue + match = re_AMSMathsPlain.match(lines[i]) + if match: + addstring("theorems-starred", usemodules) + lines.pop(i) + continue + match = re_AMSMathsSeq.match(lines[i]) + if match: + addstring("theorems-ams", usemodules) + addstring("theorems-ams-extended", usemodules) + lines.pop(i) + continue + i += 1 + continue # These just involved new features, not any changes to old ones - if format >= 5 and format <= 8: + if format >= 5 and format <= 7: i += 1 continue @@ -325,11 +669,17 @@ def convert(lines): latextype = string.lower(match.group(4)) latextype_line = i + # Remember the TocLevel line + match = re_TocLevel.match(lines[i]) + if match: + toclevel = string.lower(match.group(4)) + # Reset variables at the beginning of a style definition match = re_Style.match(lines[i]) if match: style = string.lower(match.group(4)) counter = "" + toclevel = "" label = "" space1 = "" labelstring = "" @@ -373,7 +723,7 @@ def convert(lines): # This emulates the hardcoded article style numbering of 1.3 # if counter != "": - if counters.has_key(style): + if style in counters: if labelstring_line < 0: lines.insert(i, '%sLabelString "%s"' % (space1, counters[style])) i += 1 @@ -382,7 +732,7 @@ def convert(lines): lines[labelstring_line] = re_LabelString.sub( r'\1\2\3%s' % new_labelstring.replace("\\", "\\\\"), lines[labelstring_line]) - if appendixcounters.has_key(style): + if style in appendixcounters: if labelstringappendix_line < 0: lines.insert(i, '%sLabelStringAppendix "%s"' % (space1, appendixcounters[style])) i += 1 @@ -397,12 +747,18 @@ def convert(lines): i += 1 # Add the TocLevel setting for sectioning styles - if toclevels.has_key(style) and maxcounter <= toclevels[style]: - lines.insert(i, '%sTocLevel %d' % (space1, toclevels[style])) + if toclevel == "" and style in toclevels and maxcounter <= toclevels[style]: + lines.insert(i, '%s\tTocLevel %d' % (space1, toclevels[style])) i += 1 i += 1 + if usemodules: + i = formatline + 1 + for mod in usemodules: + lines.insert(i, "UseModule " + mod) + i += 1 + return format + 1 @@ -410,16 +766,16 @@ def main(argv): # Open files if len(argv) == 1: - input = sys.stdin + source = sys.stdin output = sys.stdout elif len(argv) == 3: - input = open(argv[1], 'rb') + source = open(argv[1], 'rb') output = open(argv[2], 'wb') else: error(usage(argv[0])) # Do the real work - lines = read(input) + lines = read(source) format = 1 while (format < currentFormat): format = convert(lines) @@ -427,7 +783,7 @@ def main(argv): # Close files if len(argv) == 3: - input.close() + source.close() output.close() return 0