]> git.lyx.org Git - lyx.git/blobdiff - development/tools/gen_lfuns.py
Improve autotools support for generating LFUNs.lyx
[lyx.git] / development / tools / gen_lfuns.py
index 4fda0b87c82af240612fbfba6c0541e04c792de1..e8a91062dd7d11b8c52a2b6cfa08d4a31a2c8274 100755 (executable)
@@ -12,8 +12,7 @@
 # Usage:
 # gen_lfuns.py <path/to/LyXAction.cpp> <where/to/save/LFUNs.lyx>
 
-import sys
-import os.path
+import sys,re,os.path
 from datetime import date
 
 def error(message):
@@ -24,7 +23,7 @@ def usage(prog_name):
     return "Usage: %s <path/to/LyXAction.cpp> [<where/to/save/LFUNs.lyx>]" % prog_name
 
 DOXYGEN_START = "/*!"
-DOXYGEN_END = "*/"
+DOXYGEN_END = "},"
 
 LYX_NEWLINE = "\n\\begin_inset Newline newline\n\\end_inset\n\n"
 LYX_BACKSLASH = "\n\\backslash\n"
@@ -44,76 +43,160 @@ 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 345
+\\lyxformat 474
 \\begin_document
 \\begin_header
 \\textclass article
+\\begin_preamble
+\\renewcommand{\\descriptionlabel}[1]{\\hspace\\labelsep\\upshape\\bfseries #1:}
+\\renewenvironment{description}{\\list{}{%
+  \\setlength{\\itemsep}{-2pt}
+  \\advance\\leftmargini6\\p@ \\itemindent-12\\p@
+  \\labelwidth\\z@ \\let\\makelabel\\descriptionlabel}%
+}{
+  \\endlist
+}
+\\end_preamble
 \\use_default_options false
+\\maintain_unincluded_children false
+\\begin_local_layout
+Style Description
+LabelIndent           MM
+LeftMargin            MMMMMxx
+End
+\\end_local_layout
 \\language english
+\\language_package default
 \\inputencoding auto
+\\fontencoding global
 \\font_roman default
 \\font_sans default
 \\font_typewriter default
+\\font_math auto
 \\font_default_family default
+\\use_non_tex_fonts false
 \\font_sc false
 \\font_osf false
 \\font_sf_scale 100
 \\font_tt_scale 100
-
 \\graphics default
+\\default_output_format default
+\\output_sync 0
+\\bibtex_command default
+\\index_command default
 \\paperfontsize default
 \\spacing single
 \\use_hyperref false
 \\papersize default
 \\use_geometry true
-\\use_amsmath 1
-\\use_esint 1
+\\use_package amsmath 1
+\\use_package amssymb 1
+\\use_package cancel 0
+\\use_package esint 1
+\\use_package mathdots 0
+\\use_package mathtools 0
+\\use_package mhchem 1
+\\use_package stackrel 0
+\\use_package stmaryrd 0
+\\use_package undertilde 0
 \\cite_engine basic
+\\cite_engine_type default
+\\biblio_style plain
 \\use_bibtopic false
+\\use_indices false
 \\paperorientation portrait
+\\suppress_date false
+\\justification true
+\\use_refstyle 0
+\\index Index
+\\shortcut idx
+\\color #008000
+\\end_index
 \\leftmargin 2.5cm
 \\topmargin 2cm
 \\rightmargin 3cm
-\\bottommargin 1cm
+\\bottommargin 2.5cm
 \\secnumdepth 3
 \\tocdepth 3
 \\paragraph_separation indent
-\\defskip medskip
+\\paragraph_indentation default
 \\quotes_language english
 \\papercolumns 1
 \\papersides 1
 \\paperpagestyle default
 \\tracking_changes false
 \\output_changes false
-\\author "" 
-\\author "" 
+\\html_math_output 0
+\\html_css_as_file 0
+\\html_be_strict false
 \\end_header
 
 \\begin_body
 
-\\begin_layout Section*""" + "\nLFUNs documentation automatically generated " + str(date.today()) + """
+\\begin_layout Title
+LyX Functions (LFUNs)
 \\end_layout
 
-\\begin_layout Standard
-\\begin_inset ERT
-status collapsed
+\\begin_layout Author
+The LyX Team
+\\end_layout
 
-\\begin_layout Plain Layout
+\\begin_layout Date""" + "\n" + str(date.today()) + """
+\\end_layout
 
+"""
 
-\\backslash
-thispagestyle{empty}
+LFUNS_INTRO ="""\\begin_layout Section*
+About this manual
 \\end_layout
 
+\\begin_layout Standard
+This manual documents the 
+\\begin_inset Quotes eld
+\\end_inset
+
+LyX Functions
+\\begin_inset Quotes erd
 \\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
+ bound to an LFUN.
+\\end_layout
 
-\\begin_inset VSpace 1cm
+\\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{}
+customize the user interface, you need to deal
+ with LFUNs.
+ Furthermore, external programs can use LFUNs to communicate with and 
+\\begin_inset Quotes eld
+\\end_inset
+
+remote-control
+\\begin_inset Quotes erd
+\\end_inset
+
+ LyX.
+ Finally, you can also issue LFUNs directly via the so called mini-buffer
+ which can be opened via 
+\\begin_inset Info
+type  "shortcuts"
+arg   "command-execute"
 \\end_inset
 
+.
+\\end_layout
 
+\\begin_layout Standard
+In the following, all LFUNs are listed, categorized by function.
 \\end_layout
+
 """
+
+
 LFUNS_FOOTER = """\\end_body
 \\end_document
 """
@@ -121,7 +204,7 @@ LFUNS_FOOTER = """\\end_body
 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(name="", action="", notion="", syntax="", params="", sample="", origin="")
+    lfun = dict(action="", notion="", syntax="", params="", sample="", origin="")
     field = ""
     lines = str.splitlines()
     # strip leading whitespace and * from the lines of the comment to get 
@@ -136,11 +219,7 @@ def parse_lfun(str):
         #     nothing as an existing field is being added to
         # if a field id is found, then its the first line of the field so set the pre_space to ""
         #     so that the first line isn't prespaced
-        if lines[i].startswith(LFUN_NAME_ID):
-            field = "name"
-            pre_space = ""
-            skip = len(ID_DICT[field])
-        elif lines[i].startswith(LFUN_ACTION_ID):
+        if lines[i].startswith(LFUN_ACTION_ID):
             field = "action"
             pre_space = ""
             skip = len(ID_DICT[field])
@@ -275,17 +354,37 @@ def write_fields(file, lfun):
         file.write("Origin " + lfun["origin"] + "\n")
         file.write("\\end_layout\n")
         #file.write("\n")
-    file.write("\n")        
+    file.write("\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)"
+        }
+        # write the lfuns to the file
+    for val in sections:
+        file.write("\\begin_layout Section\n")
+        file.write(section_headings[val] + "\n")
+        file.write("\\end_layout\n")
+        for lf in lfuns:
+            if lf["type"] == val:
+                write_fields(file, lf)
     
 def main(argv):
-    # parse command line arguments   
+    # parse command line arguments
     script_path, script_name = os.path.split(argv[0])
     if len(argv) < 2:
         error(usage(script_name))
     # input file
     lyxaction_path = argv[1]
-    if not os.path.exists(lyxaction_path):
-        error(script_name + ": %s is not a valid path" % lyxaction_path, usage(argv[0]))
+    if not os.path.isfile(lyxaction_path):
+        error(script_name + ": %s is not a valid path" % lyxaction_path)
 
     # output file
     if len(argv) == 3:
@@ -301,12 +400,15 @@ def main(argv):
     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_text = lyxaction_file.read()
-       
+
     lfuns_file.write(LFUNS_HEADER)
-       
-       # seek to the important bit of LyXAction.cpp
+    
+    # An introductory section
+    lfuns_file.write(LFUNS_INTRO)
+
+    # seek to the important bit of LyXAction.cpp
     try:
         start = lyxaction_text.index("ev_item const items[] = {")
     except ValueError:
@@ -316,24 +418,42 @@ def main(argv):
 
     done = count = 0
 
+    lfun_list_unsorted = []
+
     while done == 0:
         # look for a doxygen comment
         start = lyxaction_text.find(DOXYGEN_START, start)
         end = lyxaction_text.find(DOXYGEN_END, start) + len(DOXYGEN_END)
+        name = ""
+        atype = ""
+        snippet = lyxaction_text[start:end]
+        defline = snippet.replace("\n", "")
+        match = re.match(r'.*\s*\{\s*(.+),\s*"(.*)",\s*([\w\|\s]+),\s*(\w+)\s*\},.*$', defline)
+        if match:
+            name = match.group(2)
+            atype = match.group(4)
         # parse the lfun if it is found
         if start > 0:
-            count = count + 1
-            lfun = parse_lfun(lyxaction_text[start:end])
-            # write the lfun to the file
-            write_fields(lfuns_file, lfun)
-            # done adding current lfun to LFUNs.lyx so get the next one
+            if name:
+                count = count + 1
+                lfun = parse_lfun(snippet)
+                lfun["name"] = name
+                lfun["type"] = atype
+                # save the lfun (we sort it before writing)
+                lfun_list_unsorted.append(lfun)
+            # get the next one
             start = end
         else:
             # if no more lfuns are found, EOF reached
             done = 1
-            
-    sys.stderr.write(script_name + ": Created documentation for " + str(count) + " LFUNs\n")
+
+    lfun_list = sorted(lfun_list_unsorted, key=lambda k: k['name'])
     
+    # write the lfuns to the file
+    write_sections(lfuns_file, lfun_list)
+
+    sys.stderr.write(script_name + ": Created documentation for " + str(count) + " LFUNs\n")
+
     # write the last part of LFUNs.lyx
     lfuns_file.write(LFUNS_FOOTER)