]> git.lyx.org Git - lyx.git/blobdiff - development/tools/gen_lfuns.py
Add support for mixed-encoded biblatex files
[lyx.git] / development / tools / gen_lfuns.py
index e8a91062dd7d11b8c52a2b6cfa08d4a31a2c8274..6162bbb3dfca39ea9cea99ec56792d14d07091a0 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#! /usr/bin/python3
 # -*- coding: utf-8 -*-
 
 # file gen_lfuns.py
@@ -13,7 +13,7 @@
 # gen_lfuns.py <path/to/LyXAction.cpp> <where/to/save/LFUNs.lyx>
 
 import sys,re,os.path
-from datetime import date
+import io
 
 def error(message):
     sys.stderr.write(message + '\n')
@@ -25,27 +25,29 @@ def usage(prog_name):
 DOXYGEN_START = "/*!"
 DOXYGEN_END = "},"
 
-LYX_NEWLINE = "\n\\begin_inset Newline newline\n\\end_inset\n\n"
-LYX_BACKSLASH = "\n\\backslash\n"
-
-HTMLONLY_START = "\\htmlonly"
-HTMLONLY_END = "\\endhtmlonly"
-LFUN_NAME_ID = "\\var lyx::FuncCode lyx::"
-LFUN_ACTION_ID = "\\li Action: "
-LFUN_NOTION_ID = "\\li Notion: "
-LFUN_SYNTAX_ID = "\\li Syntax: "
-LFUN_PARAMS_ID = "\\li Params: "
-LFUN_SAMPLE_ID = "\\li Sample: "
-LFUN_ORIGIN_ID = "\\li Origin: "
-LFUN_ENDVAR = "\\endvar"
-
-ID_DICT = dict(name=LFUN_NAME_ID, action=LFUN_ACTION_ID, notion=LFUN_NOTION_ID, 
+LYX_NEWLINE = u"\n\\begin_inset Newline newline\n\\end_inset\n\n"
+LYX_BACKSLASH = u"\n\\backslash\n"
+
+HTMLONLY_START = u"\\htmlonly"
+HTMLONLY_END = u"\\endhtmlonly"
+LFUN_NAME_ID = u"\\var lyx::FuncCode lyx::"
+LFUN_ACTION_ID = u"\\li Action: "
+LFUN_NOTION_ID = u"\\li Notion: "
+LFUN_SYNTAX_ID = u"\\li Syntax: "
+LFUN_PARAMS_ID = u"\\li Params: "
+LFUN_SAMPLE_ID = u"\\li Sample: "
+LFUN_ORIGIN_ID = u"\\li Origin: "
+LFUN_ENDVAR = u"\\endvar"
+
+ID_DICT = dict(name=LFUN_NAME_ID, action=LFUN_ACTION_ID, notion=LFUN_NOTION_ID,
                 syntax=LFUN_SYNTAX_ID, params=LFUN_PARAMS_ID, sample=LFUN_SAMPLE_ID, origin=LFUN_ORIGIN_ID)
 
-LFUNS_HEADER = """# gen_lfuns.py generated this file. For more info see http://www.lyx.org/
-\\lyxformat 474
+LFUNS_HEADER = u"""# gen_lfuns.py generated this file. For more info see http://www.lyx.org/
+\\lyxformat 509
 \\begin_document
 \\begin_header
+\\save_transient_properties true
+\\origin /systemlyxdir/doc/
 \\textclass article
 \\begin_preamble
 \\renewcommand{\\descriptionlabel}[1]{\\hspace\\labelsep\\upshape\\bfseries #1:}
@@ -69,16 +71,17 @@ End
 \\language_package default
 \\inputencoding auto
 \\fontencoding global
-\\font_roman default
-\\font_sans default
-\\font_typewriter default
-\\font_math auto
+\\font_roman "default" "default"
+\\font_sans "default" "default"
+\\font_typewriter "default" "default"
+\\font_math "auto" "auto"
 \\font_default_family default
 \\use_non_tex_fonts false
 \\font_sc false
 \\font_osf false
-\\font_sf_scale 100
-\\font_tt_scale 100
+\\font_sf_scale 100 100
+\\font_tt_scale 100 100
+\\use_microtype 0
 \\graphics default
 \\default_output_format default
 \\output_sync 0
@@ -134,24 +137,23 @@ End
 \\begin_body
 
 \\begin_layout Title
-LyX Functions (LFUNs)
+\\SpecialChar LyX
+ Functions (LFUNs)
 \\end_layout
 
 \\begin_layout Author
-The LyX Team
-\\end_layout
-
-\\begin_layout Date""" + "\n" + str(date.today()) + """
+The \\SpecialChar LyX
+ Team
 \\end_layout
 
 """
 
-LFUNS_INTRO ="""\\begin_layout Section*
+LFUNS_INTRO = u"""\\begin_layout Section*
 About this manual
 \\end_layout
 
 \\begin_layout Standard
-This manual documents the 
+This manual documents the
 \\begin_inset Quotes eld
 \\end_inset
 
@@ -160,18 +162,20 @@ LyX Functions
 \\end_inset
 
  (abbreviated LFUNs).
- These are commands that are used to make LyX perform specific actions.
- LyX itself uses these functions internally, and every internal action is
+ These are commands that are used to make \\SpecialChar LyX
+ perform specific actions.
+ \\SpecialChar LyX
+ itself uses these functions internally, and every internal action is
  bound to an LFUN.
 \\end_layout
 
 \\begin_layout Standard
 LFUNs are also used in the files that define keyboard shortcuts, menu or
  toolbar items.
- So if you want to change\\SpecialChar \\slash{}
+ So if you want to change\\SpecialChar breakableslash
 customize the user interface, you need to deal
  with LFUNs.
- Furthermore, external programs can use LFUNs to communicate with and 
+ Furthermore, external programs can use LFUNs to communicate with and
 \\begin_inset Quotes eld
 \\end_inset
 
@@ -179,9 +183,10 @@ remote-control
 \\begin_inset Quotes erd
 \\end_inset
 
- LyX.
+ \\SpecialChar LyX
+ .
  Finally, you can also issue LFUNs directly via the so called mini-buffer
- which can be opened via 
+ which can be opened via
 \\begin_inset Info
 type  "shortcuts"
 arg   "command-execute"
@@ -197,21 +202,21 @@ In the following, all LFUNs are listed, categorized by function.
 """
 
 
-LFUNS_FOOTER = """\\end_body
+LFUNS_FOOTER = u"""\\end_body
 \\end_document
 """
 
 def parse_lfun(str):
     """Takes a comment block (str) and parses it for fields describing the LFUN. Returns a dict containing the fields."""
-    
+
     lfun = dict(action="", notion="", syntax="", params="", sample="", origin="")
     field = ""
     lines = str.splitlines()
-    # strip leading whitespace and * from the lines of the comment to get 
+    # strip leading whitespace and * from the lines of the comment to get
     # rid of unimportant characters
     for i in range(0, len(lines)):
         lines[i] = lines[i].strip(" *")
-    
+
     for i in range(0, len(lines) - 1):
         # work out what field is being read if none of these is found, the line will be added
         #     to the last field edited
@@ -252,11 +257,11 @@ def parse_lfun(str):
                 pre_space = ""
             else:
                 pre_space = " "
-        
+
         # add the line to the field, processing it for \ characters and \n
         # which, if occurring at the end of a line, must become a LYX_NEWLINE
         line = lines[i][skip:]
-        
+
         # deal with \htmlonly
         # TODO: convert chars found in htmlonly to unicode
         start = line.find(HTMLONLY_START)
@@ -271,7 +276,7 @@ def parse_lfun(str):
             #else:
             # TODO: if HTMLONLY_END is not found, look on the next line
             # TODO: in the current LyXAction.cpp there are no htmlonly fields which go over a line break
-        
+
         # deal with \ but leave \n if at the end of the line
         slash_idx = line.find("\\")
         while slash_idx >= 0:
@@ -279,7 +284,7 @@ def parse_lfun(str):
             or slash_idx == len(line)-1:
                 # true when the \ is not the last or second last char
                 #      or when the slash is the last char of the line
-                
+
                 # slash must be interpreted literaly so swap it for a LYX_BACKSLASH
                 line = line[:slash_idx] + LYX_BACKSLASH + line[slash_idx+1:]
                 # skip the index ahead beyond the added text
@@ -287,10 +292,10 @@ def parse_lfun(str):
             elif line[slash_idx+1] != "n": # only evaluated if the line ends "\x" where 'x' != 'n'
                 line = line[:slash_idx] + LYX_BACKSLASH + line[slash_idx+1:]
                 # skip the index ahead beyond the added text
-                slash_idx = slash_idx + len(LYX_BACKSLASH) 
+                slash_idx = slash_idx + len(LYX_BACKSLASH)
             # look for the next \
             slash_idx = line.find("\\", slash_idx+1)
-            
+
         # \n at the end of lines will not be processed by the above while loop
         # so sort those out now
         # sometime lines end " \n" so chop the space if its there
@@ -298,11 +303,11 @@ def parse_lfun(str):
             line = line[:len(line)-3] + LYX_NEWLINE
         elif line.endswith("\\n"):
             line = line[:len(line)-2] + LYX_NEWLINE
-        
+
         # any references to other LFUNs need the # removing
         # TODO: actually insert a cross-reference here
         line = line.replace("#LFUN", "LFUN")
-        
+
         # handle the few #lyx:: cases
         line = line.replace("#lyx::", "lyx::")
 
@@ -311,71 +316,70 @@ def parse_lfun(str):
         # to avoid an error
         if field != "":
             lfun[field] = lfun[field] + pre_space + line
-        
+
         # TODO: sort out chopping lines of more that 80 chars in length
-        
+
     return lfun
 
 def write_fields(file, lfun):
     """Writes the LFUN contained in the dict lfun to the file. Does not write a the file header or footer"""
     # add lfun to LFUNs.lyx
-    file.write("\\begin_layout Subsection*\n")
+    file.write(u"\\begin_layout Subsection*\n")
     file.write(lfun["name"] + "\n")
-    file.write("\\end_layout\n")
-    #file.write("\n")
+    file.write(u"\\end_layout\n")
+    file.write(u"\n")
     if lfun["action"] != "":
-        file.write("\\begin_layout Description\n")
+        file.write(u"\\begin_layout Description\n")
         file.write("Action " + lfun["action"] + "\n")
-        #file.write("\n")
-        file.write("\\end_layout\n")
-        #file.write("\n")
+        file.write(u"\\end_layout\n")
+        file.write(u"\n")
     if lfun["notion"] != "":
-        file.write("\\begin_layout Description\n")
+        file.write(u"\\begin_layout Description\n")
         file.write("Notion " + lfun["notion"] + "\n")
-        file.write("\\end_layout\n")
-        #file.write("\n")
+        file.write(u"\\end_layout\n")
+        file.write(u"\n")
     if lfun["syntax"] != "":
-        file.write("\\begin_layout Description\n")
+        file.write(u"\\begin_layout Description\n")
         file.write("Syntax " + lfun["syntax"] + "\n")
-        file.write("\\end_layout\n")
-        #file.write("\n")
+        file.write(u"\\end_layout\n")
+        file.write(u"\n")
     if lfun["params"] != "":
-        file.write("\\begin_layout Description\n")
+        file.write(u"\\begin_layout Description\n")
         file.write("Params " + lfun["params"] + "\n")
-        file.write("\\end_layout\n")
-        #file.write("\n")
+        file.write(u"\\end_layout\n")
+        file.write(u"\n")
     if lfun["sample"] != "":
-        file.write("\\begin_layout Description\n")
+        file.write(u"\\begin_layout Description\n")
         file.write("Sample " + lfun["sample"] + "\n")
-        file.write("\\end_layout\n")
-        #file.write("\n")
+        file.write(u"\\end_layout\n")
+        file.write(u"\n")
     if lfun["origin"] != "":
-        file.write("\\begin_layout Description\n")
+        file.write(u"\\begin_layout Description\n")
         file.write("Origin " + lfun["origin"] + "\n")
-        file.write("\\end_layout\n")
-        #file.write("\n")
-    file.write("\n")
+        file.write(u"\\end_layout\n")
+        file.write(u"\n")
 
 def write_sections(file,lfuns):
     """Write sections of LFUNs"""
     sections = ["Layout", "Edit", "Math", "Buffer", "System", "Hidden"]
     section_headings = {
-        "Layout":  "Layout Functions (Font, Layout and Textclass related)",
-        "Edit":  "Editing Functions (Cursor and Mouse Movement, Copy/Paste etc.)",
-        "Math":  "Math Editor Functions",
-        "Buffer":  "Buffer Fuctions (File and Window related)",
-        "System":  "System Funtions (Preferences, LyX Server etc.)",
-        "Hidden":  "Hidden Functions (not listed for configuration)"
+        "Layout":  u"Layout Functions (Font, Layout and Textclass related)",
+        "Edit":    u"Editing Functions (Cursor and Mouse Movement, Copy/Paste etc.)",
+        "Math":    u"Math Editor Functions",
+        "Buffer":  u"Buffer Fuctions (File and Window related)",
+        "System":  u"System Functions (Preferences, LyX Server etc.)",
+        "Hidden":  u"Hidden Functions (not listed for configuration)"
         }
         # write the lfuns to the file
     for val in sections:
-        file.write("\\begin_layout Section\n")
+        file.write(u"\\begin_layout Section\n")
         file.write(section_headings[val] + "\n")
-        file.write("\\end_layout\n")
+        file.write(u"\\end_layout\n")
+        file.write(u"\n")
         for lf in lfuns:
             if lf["type"] == val:
                 write_fields(file, lf)
-    
+
 def main(argv):
     # parse command line arguments
     script_path, script_name = os.path.split(argv[0])
@@ -393,18 +397,18 @@ def main(argv):
             lfuns_path = lfuns_path + "LFUNs.lyx"
         elif os.path.exists(lfuns_path):
             error(script_name + ": %s already exists, delete it and rerun the script" % lfuns_path)
-        lfuns_file = open(lfuns_path, 'wb')
+        lfuns_file = io.open(lfuns_path, 'w', encoding='utf_8')
     else:
         lfuns_file = sys.stdout
 
     sys.stderr.write(script_name + ": Start processing " + argv[1] + '\n')
     # Read the input file and write the output file
-    lyxaction_file = open(lyxaction_path, 'rb')
+    lyxaction_file = io.open(lyxaction_path, 'r', encoding='utf_8')
 
     lyxaction_text = lyxaction_file.read()
 
     lfuns_file.write(LFUNS_HEADER)
-    
+
     # An introductory section
     lfuns_file.write(LFUNS_INTRO)
 
@@ -448,7 +452,7 @@ def main(argv):
             done = 1
 
     lfun_list = sorted(lfun_list_unsorted, key=lambda k: k['name'])
-    
+
     # write the lfuns to the file
     write_sections(lfuns_file, lfun_list)
 
@@ -456,11 +460,11 @@ def main(argv):
 
     # write the last part of LFUNs.lyx
     lfuns_file.write(LFUNS_FOOTER)
-    
+
     lyxaction_file.close()
     lfuns_file.close()
-    
+
     sys.stderr.write(script_name + ": Finished\n")
-    
+
 if __name__ == "__main__":
     main(sys.argv)