Selaa lähdekoodia

Apply Black to doc utils in man (#1366)

This applies Black 20.8b1 formatting to Python doc utils in man and adds the directory to checks.
Vaclav Petras 4 vuotta sitten
vanhempi
commit
7e03dcd6a8

+ 4 - 3
.github/workflows/black.yml

@@ -12,9 +12,10 @@ jobs:
     strategy:
     strategy:
       matrix:
       matrix:
         directory:
         directory:
-        - lib/init
-        - scripts
-        - utils
+          - lib/init
+          - man
+          - scripts
+          - utils
       fail-fast: false
       fail-fast: false
 
 
     steps:
     steps:

+ 6 - 4
man/build_check.py

@@ -11,12 +11,14 @@ from build_html import *
 
 
 os.chdir(html_dir)
 os.chdir(html_dir)
 
 
-sys.stdout.write(message_tmpl.substitute(html_dir = html_dir))
+sys.stdout.write(message_tmpl.substitute(html_dir=html_dir))
 
 
-for cmd in html_files('*'):
+for cmd in html_files("*"):
     if "DESCRIPTION" not in read_file(cmd):
     if "DESCRIPTION" not in read_file(cmd):
         sys.stdout.write("%s\n" % cmd[:-5])
         sys.stdout.write("%s\n" % cmd[:-5])
 
 
-sys.stdout.write(r"""
+sys.stdout.write(
+    r"""
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
-""")
+"""
+)

+ 6 - 4
man/build_check_rest.py

@@ -11,12 +11,14 @@ from build_rest import *
 
 
 os.chdir(rest_dir)
 os.chdir(rest_dir)
 
 
-sys.stdout.write(message_tmpl.substitute(rest_dir = rest_dir))
+sys.stdout.write(message_tmpl.substitute(rest_dir=rest_dir))
 
 
-for cmd in rest_files('*'):
+for cmd in rest_files("*"):
     if "DESCRIPTION" not in read_file(cmd):
     if "DESCRIPTION" not in read_file(cmd):
         sys.stdout.write("%s\n" % cmd[:-5])
         sys.stdout.write("%s\n" % cmd[:-5])
 
 
-sys.stdout.write(r"""
+sys.stdout.write(
+    r"""
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
-""")
+"""
+)

+ 18 - 12
man/build_class.py

@@ -10,13 +10,13 @@ import string
 from build_html import *
 from build_html import *
 
 
 
 
-no_intro_page_classes = ['display', 'general', 'miscellaneous', 'postscript']
+no_intro_page_classes = ["display", "general", "miscellaneous", "postscript"]
 
 
 os.chdir(html_dir)
 os.chdir(html_dir)
 
 
-#write separate module pages:
+# write separate module pages:
 
 
-#for all module groups:
+# for all module groups:
 cls = sys.argv[1]
 cls = sys.argv[1]
 modclass = sys.argv[2]
 modclass = sys.argv[2]
 year = None
 year = None
@@ -25,27 +25,33 @@ if len(sys.argv) > 3:
 
 
 filename = modclass + ".html"
 filename = modclass + ".html"
 
 
-f = open(filename + ".tmp", 'w')
+f = open(filename + ".tmp", "w")
 
 
-write_html_header(f, "%s modules - GRASS GIS %s Reference Manual" % (modclass.capitalize(), grass_version))
+write_html_header(
+    f,
+    "%s modules - GRASS GIS %s Reference Manual"
+    % (modclass.capitalize(), grass_version),
+)
 modclass_lower = modclass.lower()
 modclass_lower = modclass.lower()
 modclass_visible = modclass
 modclass_visible = modclass
 if modclass_lower not in no_intro_page_classes:
 if modclass_lower not in no_intro_page_classes:
-    if modclass_visible == 'raster3d':
+    if modclass_visible == "raster3d":
         # covert keyword to nice form
         # covert keyword to nice form
-        modclass_visible = '3D raster'
-    f.write(modclass_intro_tmpl.substitute(modclass=modclass_visible, modclass_lower=modclass_lower))
+        modclass_visible = "3D raster"
+    f.write(
+        modclass_intro_tmpl.substitute(
+            modclass=modclass_visible, modclass_lower=modclass_lower
+        )
+    )
 f.write(modclass_tmpl.substitute(modclass=to_title(modclass_visible)))
 f.write(modclass_tmpl.substitute(modclass=to_title(modclass_visible)))
 
 
-#for all modules:
+# for all modules:
 for cmd in html_files(cls):
 for cmd in html_files(cls):
     basename = os.path.splitext(cmd)[0]
     basename = os.path.splitext(cmd)[0]
     desc = check_for_desc_override(basename)
     desc = check_for_desc_override(basename)
     if desc is None:
     if desc is None:
         desc = get_desc(cmd)
         desc = get_desc(cmd)
-    f.write(desc2_tmpl.substitute(cmd = cmd,
-                                  basename = basename,
-                                  desc = desc))
+    f.write(desc2_tmpl.substitute(cmd=cmd, basename=basename, desc=desc))
 f.write("</table>\n")
 f.write("</table>\n")
 
 
 write_html_footer(f, "index.html", year)
 write_html_footer(f, "index.html", year)

+ 67 - 51
man/build_class_graphical.py

@@ -18,11 +18,18 @@ import sys
 import os
 import os
 import fnmatch
 import fnmatch
 
 
-#from build_html import *
+# from build_html import *
 from build_html import (
 from build_html import (
-    default_year, header1_tmpl, grass_version,
-    modclass_intro_tmpl, to_title, html_files,
-    check_for_desc_override, get_desc, write_html_footer, replace_file,
+    default_year,
+    header1_tmpl,
+    grass_version,
+    modclass_intro_tmpl,
+    to_title,
+    html_files,
+    check_for_desc_override,
+    get_desc,
+    write_html_footer,
+    replace_file,
 )
 )
 
 
 
 
@@ -95,9 +102,9 @@ def starts_with_module(string, module):
     # not solving:
     # not solving:
     # module = module.replace('wxGUI.', 'g.gui.')
     # module = module.replace('wxGUI.', 'g.gui.')
     # TODO: matches g.mapsets images for g.mapset and d.rast.num for d.rast
     # TODO: matches g.mapsets images for g.mapset and d.rast.num for d.rast
-    if string.startswith(module.replace('.', '_')):
+    if string.startswith(module.replace(".", "_")):
         return True
         return True
-    if string.startswith(module.replace('.', '')):
+    if string.startswith(module.replace(".", "")):
         return True
         return True
     if string.startswith(module):
     if string.startswith(module):
         return True
         return True
@@ -115,68 +122,75 @@ def get_module_image(module, images):
     if not candidates:
     if not candidates:
         return None
         return None
     for image in candidates:
     for image in candidates:
-        basename, unused = image.rsplit('.', 1)
-        if basename == module.replace('.', '_'):
+        basename, unused = image.rsplit(".", 1)
+        if basename == module.replace(".", "_"):
             return image
             return image
-        if basename == module.replace('.', ''):
+        if basename == module.replace(".", ""):
             return image
             return image
         if basename == module:
         if basename == module:
             return image
             return image
     return sorted(candidates, key=len)[0]
     return sorted(candidates, key=len)[0]
 
 
 
 
-def generate_page_for_category(short_family, module_family, imgs, year,
-                               skip_no_image=False):
+def generate_page_for_category(
+    short_family, module_family, imgs, year, skip_no_image=False
+):
     filename = module_family + "_graphical.html"
     filename = module_family + "_graphical.html"
 
 
-    output = open(filename + ".tmp", 'w')
+    output = open(filename + ".tmp", "w")
 
 
-    output.write(header1_tmpl.substitute(
-        title="GRASS GIS %s Reference "
-              "Manual: Graphical index" % grass_version))
+    output.write(
+        header1_tmpl.substitute(
+            title="GRASS GIS %s Reference " "Manual: Graphical index" % grass_version
+        )
+    )
     output.write(header_graphical_index_tmpl)
     output.write(header_graphical_index_tmpl)
 
 
-    if module_family.lower() not in ['general', 'postscript']:
-        if module_family == 'raster3d':
+    if module_family.lower() not in ["general", "postscript"]:
+        if module_family == "raster3d":
             # covert keyword to nice form
             # covert keyword to nice form
-            module_family = '3D raster'
-        output.write(modclass_intro_tmpl.substitute(
-            modclass=module_family, modclass_lower=module_family.lower()))
-    if module_family == 'wxGUI':
+            module_family = "3D raster"
+        output.write(
+            modclass_intro_tmpl.substitute(
+                modclass=module_family, modclass_lower=module_family.lower()
+            )
+        )
+    if module_family == "wxGUI":
         output.write("<h3>wxGUI components:</h3>")
         output.write("<h3>wxGUI components:</h3>")
-    elif module_family == 'guimodules':
+    elif module_family == "guimodules":
         output.write("<h3>g.gui.* modules:</h3>")
         output.write("<h3>g.gui.* modules:</h3>")
     else:
     else:
         output.write("<h3>{0} modules:</h3>".format(to_title(module_family)))
         output.write("<h3>{0} modules:</h3>".format(to_title(module_family)))
     output.write('<ul class="img-list">')
     output.write('<ul class="img-list">')
 
 
-    #for all modules:
+    # for all modules:
     for cmd in html_files(short_family, ignore_gui=False):
     for cmd in html_files(short_family, ignore_gui=False):
         basename = os.path.splitext(cmd)[0]
         basename = os.path.splitext(cmd)[0]
         desc = check_for_desc_override(basename)
         desc = check_for_desc_override(basename)
         if desc is None:
         if desc is None:
             desc = get_desc(cmd)
             desc = get_desc(cmd)
         img = get_module_image(basename, imgs)
         img = get_module_image(basename, imgs)
-        img_class = 'linkimg'
+        img_class = "linkimg"
         if skip_no_image and not img:
         if skip_no_image and not img:
             continue
             continue
         elif not img:
         elif not img:
-            img = 'grass_logo.png'
-            img_class = 'default-img'
-        if basename.startswith('wxGUI'):
-            basename = basename.replace('.', ' ')
+            img = "grass_logo.png"
+            img_class = "default-img"
+        if basename.startswith("wxGUI"):
+            basename = basename.replace(".", " ")
         output.write(
         output.write(
-            '<li>'
+            "<li>"
             '<a href="{html}">'
             '<a href="{html}">'
             '<img class="{img_class}" src="{img}">'
             '<img class="{img_class}" src="{img}">'
             '<span class="name">{name}</span> '
             '<span class="name">{name}</span> '
             '<span class="desc">{desc}</span>'
             '<span class="desc">{desc}</span>'
-            '</a>'
-            '</li>'
-            .format(html=cmd, img=img, name=basename,
-                    desc=desc, img_class=img_class))
+            "</a>"
+            "</li>".format(
+                html=cmd, img=img, name=basename, desc=desc, img_class=img_class
+            )
+        )
 
 
-    output.write('</ul>')
+    output.write("</ul>")
 
 
     write_html_footer(output, "index.html", year)
     write_html_footer(output, "index.html", year)
 
 
@@ -187,13 +201,14 @@ def generate_page_for_category(short_family, module_family, imgs, year,
 # TODO: dependencies in makefile for this have to be fixed
 # TODO: dependencies in makefile for this have to be fixed
 # TODO: there is a potential overlap with other scripts (-> refactoring)
 # TODO: there is a potential overlap with other scripts (-> refactoring)
 
 
+
 def main():
 def main():
     year = default_year
     year = default_year
     html_dir = sys.argv[1]
     html_dir = sys.argv[1]
     os.chdir(html_dir)
     os.chdir(html_dir)
 
 
-    img_extensions = ['png', 'jpg', 'gif']
-    img_patterns = ['*.' + extension for extension in img_extensions]
+    img_extensions = ["png", "jpg", "gif"]
+    img_patterns = ["*." + extension for extension in img_extensions]
     imgs = []
     imgs = []
     for filename in sorted(os.listdir(html_dir)):
     for filename in sorted(os.listdir(html_dir)):
         if file_matches(filename, img_patterns):
         if file_matches(filename, img_patterns):
@@ -204,18 +219,18 @@ def main():
     # class has its meaning in Python, plus it is a synonym for category
     # class has its meaning in Python, plus it is a synonym for category
     # TODO: what would be user friendly is unclear
     # TODO: what would be user friendly is unclear
     families = [
     families = [
-        ('d', 'display'),
-        ('db', 'database'),
-        ('g', 'general'),
-        ('i', 'imagery'),
-        ('m', 'miscellaneous'),
-        ('ps', 'postscript'),
-        ('r', 'raster'),
-        ('r3', 'raster3d'),
-        ('t', 'temporal'),
-        ('v', 'vector'),
-        ('wxGUI', 'wxGUI'),
-        ('g.gui', 'guimodules'),
+        ("d", "display"),
+        ("db", "database"),
+        ("g", "general"),
+        ("i", "imagery"),
+        ("m", "miscellaneous"),
+        ("ps", "postscript"),
+        ("r", "raster"),
+        ("r3", "raster3d"),
+        ("t", "temporal"),
+        ("v", "vector"),
+        ("wxGUI", "wxGUI"),
+        ("g.gui", "guimodules"),
     ]
     ]
 
 
     # partial compatibility with build_class.py
     # partial compatibility with build_class.py
@@ -228,9 +243,10 @@ def main():
             year = sys.argv[4]
             year = sys.argv[4]
 
 
     for short_family, module_family in families:
     for short_family, module_family in families:
-        generate_page_for_category(short_family, module_family, imgs,
-                                   year=year, skip_no_image=False)
+        generate_page_for_category(
+            short_family, module_family, imgs, year=year, skip_no_image=False
+        )
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
     main()

+ 13 - 10
man/build_class_rest.py

@@ -11,29 +11,32 @@ from build_rest import *
 
 
 os.chdir(rest_dir)
 os.chdir(rest_dir)
 
 
-#write separate module pages:
+# write separate module pages:
 
 
-#for all module groups:
+# for all module groups:
 cls = sys.argv[1]
 cls = sys.argv[1]
 modclass = sys.argv[2]
 modclass = sys.argv[2]
 
 
 filename = modclass + ".txt"
 filename = modclass + ".txt"
 
 
-f = open(filename + ".tmp", 'wb')
+f = open(filename + ".tmp", "wb")
 
 
 write_rest_header(f, "GRASS GIS %s Reference Manual: %s" % (grass_version, modclass))
 write_rest_header(f, "GRASS GIS %s Reference Manual: %s" % (grass_version, modclass))
-if modclass.lower() not in ['general', 'miscellaneous', 'postscript']:
-    f.write(modclass_intro_tmpl.substitute(modclass = modclass, modclass_lower = modclass.lower()))
-f.write(modclass_tmpl.substitute(modclass = modclass))
-
-#for all modules:
+if modclass.lower() not in ["general", "miscellaneous", "postscript"]:
+    f.write(
+        modclass_intro_tmpl.substitute(
+            modclass=modclass, modclass_lower=modclass.lower()
+        )
+    )
+f.write(modclass_tmpl.substitute(modclass=modclass))
+
+# for all modules:
 for cmd in rest_files(cls):
 for cmd in rest_files(cls):
     basename = os.path.splitext(cmd)[0]
     basename = os.path.splitext(cmd)[0]
     desc = check_for_desc_override(basename)
     desc = check_for_desc_override(basename)
     if desc is None:
     if desc is None:
         desc = get_desc(cmd)
         desc = get_desc(cmd)
-    f.write(desc2_tmpl.substitute(basename = basename,
-                                  desc = desc))
+    f.write(desc2_tmpl.substitute(basename=basename, desc=desc))
 
 
 write_rest_footer(f, "index.txt")
 write_rest_footer(f, "index.txt")
 
 

+ 21 - 21
man/build_full_index.py

@@ -17,48 +17,48 @@ os.chdir(html_dir)
 
 
 # TODO: create some master function/dict somewhere
 # TODO: create some master function/dict somewhere
 class_labels = {
 class_labels = {
-    'd': 'display',
-    'db': 'database',
-    'g': 'general',
-    'i': 'imagery',
-    'm': 'miscellaneous',
-    'ps': 'PostScript',
-    'r': 'raster',
-    'r3': '3D raster',
-    't': 'temporal',
-    'v': 'vector'
+    "d": "display",
+    "db": "database",
+    "g": "general",
+    "i": "imagery",
+    "m": "miscellaneous",
+    "ps": "PostScript",
+    "r": "raster",
+    "r3": "3D raster",
+    "t": "temporal",
+    "v": "vector",
 }
 }
 
 
 classes = []
 classes = []
-for cmd in html_files('*'):
-    prefix = cmd.split('.')[0]
+for cmd in html_files("*"):
+    prefix = cmd.split(".")[0]
     if prefix not in [item[0] for item in classes]:
     if prefix not in [item[0] for item in classes]:
         classes.append((prefix, class_labels.get(prefix, prefix)))
         classes.append((prefix, class_labels.get(prefix, prefix)))
 classes.sort(key=lambda tup: tup[0])
 classes.sort(key=lambda tup: tup[0])
 
 
-#begin full index:
+# begin full index:
 filename = "full_index.html"
 filename = "full_index.html"
-f = open(filename + ".tmp", 'w')
+f = open(filename + ".tmp", "w")
 
 
-write_html_header(f, "GRASS GIS %s Reference Manual: Full index" % grass_version, body_width="80%")
+write_html_header(
+    f, "GRASS GIS %s Reference Manual: Full index" % grass_version, body_width="80%"
+)
 
 
-#generate main index of all modules:
+# generate main index of all modules:
 f.write(full_index_header)
 f.write(full_index_header)
 
 
 f.write(toc)
 f.write(toc)
 
 
-#for all module groups:
+# for all module groups:
 for cls, cls_label in classes:
 for cls, cls_label in classes:
     f.write(cmd2_tmpl.substitute(cmd_label=to_title(cls_label), cmd=cls))
     f.write(cmd2_tmpl.substitute(cmd_label=to_title(cls_label), cmd=cls))
-    #for all modules:
+    # for all modules:
     for cmd in html_files(cls):
     for cmd in html_files(cls):
         basename = os.path.splitext(cmd)[0]
         basename = os.path.splitext(cmd)[0]
         desc = check_for_desc_override(basename)
         desc = check_for_desc_override(basename)
         if desc is None:
         if desc is None:
             desc = get_desc(cmd)
             desc = get_desc(cmd)
-        f.write(desc1_tmpl.substitute(cmd = cmd,
-                                      basename = basename,
-                                      desc = desc))
+        f.write(desc1_tmpl.substitute(cmd=cmd, basename=basename, desc=desc))
     f.write("</table>\n")
     f.write("</table>\n")
 
 
 write_html_footer(f, "index.html", year)
 write_html_footer(f, "index.html", year)

+ 14 - 15
man/build_full_index_rest.py

@@ -12,40 +12,39 @@ from build_rest import *
 os.chdir(rest_dir)
 os.chdir(rest_dir)
 
 
 classes = []
 classes = []
-for cmd in rest_files('*'):
-    prefix = cmd.split('.')[0]
+for cmd in rest_files("*"):
+    prefix = cmd.split(".")[0]
     if prefix not in classes:
     if prefix not in classes:
         classes.append(prefix)
         classes.append(prefix)
 classes.sort()
 classes.sort()
 
 
-#begin full index:
+# begin full index:
 filename = "full_index.txt"
 filename = "full_index.txt"
-f = open(filename + ".tmp", 'wb')
+f = open(filename + ".tmp", "wb")
 
 
 write_rest_header(f, "GRASS GIS %s Reference Manual: Full index" % grass_version)
 write_rest_header(f, "GRASS GIS %s Reference Manual: Full index" % grass_version)
 
 
-#generate main index of all modules:
+# generate main index of all modules:
 f.write(full_index_header)
 f.write(full_index_header)
-#"
+# "
 
 
-#for cls in classes:
-#f.write(cmd1_tmpl.substitute(cmd = cls))
-#if cls != classes[-1]:
-#f.write(" | ")
+# for cls in classes:
+# f.write(cmd1_tmpl.substitute(cmd = cls))
+# if cls != classes[-1]:
+# f.write(" | ")
 
 
 f.write(sections)
 f.write(sections)
 
 
-#for all module groups:
+# for all module groups:
 for cls in classes:
 for cls in classes:
-    f.write(cmd2_tmpl.substitute(cmd = cls))
-    #for all modules:
+    f.write(cmd2_tmpl.substitute(cmd=cls))
+    # for all modules:
     for cmd in rest_files(cls):
     for cmd in rest_files(cls):
         basename = os.path.splitext(cmd)[0]
         basename = os.path.splitext(cmd)[0]
         desc = check_for_desc_override(basename)
         desc = check_for_desc_override(basename)
         if desc is None:
         if desc is None:
             desc = get_desc(cmd)
             desc = get_desc(cmd)
-        f.write(desc1_tmpl.substitute(basename = basename,
-                                      desc = desc))
+        f.write(desc1_tmpl.substitute(basename=basename, desc=desc))
     f.write("\n")
     f.write("\n")
 
 
 write_rest_footer(f, "index.txt")
 write_rest_footer(f, "index.txt")

+ 38 - 26
man/build_graphical_index.py

@@ -22,7 +22,7 @@ import re
 from build_html import write_html_footer, grass_version, header1_tmpl
 from build_html import write_html_footer, grass_version, header1_tmpl
 
 
 
 
-output_name = 'graphical_index.html'
+output_name = "graphical_index.html"
 
 
 year = os.getenv("VERSION_DATE")
 year = os.getenv("VERSION_DATE")
 
 
@@ -90,45 +90,57 @@ def std_img_name(name):
 
 
 
 
 index_items = [
 index_items = [
-    ('raster_graphical.html', std_img_name('raster'), 'Raster'),
-    ('vector_graphical.html', std_img_name('vector'), 'Vector'),
-    ('database_graphical.html', std_img_name('database'), 'Database'),
-    ('general_graphical.html', std_img_name('general'), 'General'),
-    ('display_graphical.html', std_img_name('display'), 'Display'),
-    ('imagery_graphical.html', std_img_name('imagery'), 'Imagery'),
-    ('raster3d_graphical.html', std_img_name('raster3d'), '3D raster'),
-    ('temporal_graphical.html', std_img_name('temporal'), 'Temporal'),
-    ('miscellaneous_graphical.html', std_img_name('miscellaneous'), 'Miscellaneous'),
-    ('postscript_graphical.html', std_img_name('cartography'), 'Cartography'),
-    ('wxGUI_graphical.html', std_img_name('gui'), 'GUI'),
-    ('wxGUI.nviz.html', std_img_name('3dview'), '3D view'),
-    ('https://grass.osgeo.org/grass79/manuals/libpython/index.html', std_img_name('python'), 'Python'),
-    ('https://grass.osgeo.org/programming7/', std_img_name('c'), 'C library'),
-    ('manual_gallery.html', std_img_name('gallery'), 'Gallery'),
-    ('https://grass.osgeo.org/grass7/manuals/addons/', std_img_name('addons'), 'Addons'),
+    ("raster_graphical.html", std_img_name("raster"), "Raster"),
+    ("vector_graphical.html", std_img_name("vector"), "Vector"),
+    ("database_graphical.html", std_img_name("database"), "Database"),
+    ("general_graphical.html", std_img_name("general"), "General"),
+    ("display_graphical.html", std_img_name("display"), "Display"),
+    ("imagery_graphical.html", std_img_name("imagery"), "Imagery"),
+    ("raster3d_graphical.html", std_img_name("raster3d"), "3D raster"),
+    ("temporal_graphical.html", std_img_name("temporal"), "Temporal"),
+    ("miscellaneous_graphical.html", std_img_name("miscellaneous"), "Miscellaneous"),
+    ("postscript_graphical.html", std_img_name("cartography"), "Cartography"),
+    ("wxGUI_graphical.html", std_img_name("gui"), "GUI"),
+    ("wxGUI.nviz.html", std_img_name("3dview"), "3D view"),
+    (
+        "https://grass.osgeo.org/grass79/manuals/libpython/index.html",
+        std_img_name("python"),
+        "Python",
+    ),
+    ("https://grass.osgeo.org/programming7/", std_img_name("c"), "C library"),
+    ("manual_gallery.html", std_img_name("gallery"), "Gallery"),
+    (
+        "https://grass.osgeo.org/grass7/manuals/addons/",
+        std_img_name("addons"),
+        "Addons",
+    ),
 ]
 ]
 
 
 
 
 def main():
 def main():
     html_dir = sys.argv[1]
     html_dir = sys.argv[1]
 
 
-    with open(os.path.join(html_dir, output_name), 'w') as output:
-        output.write(header1_tmpl.substitute(title="GRASS GIS %s Reference "
-                                               "Manual: Graphical index" % grass_version))
+    with open(os.path.join(html_dir, output_name), "w") as output:
+        output.write(
+            header1_tmpl.substitute(
+                title="GRASS GIS %s Reference "
+                "Manual: Graphical index" % grass_version
+            )
+        )
         output.write(header_graphical_index_tmpl)
         output.write(header_graphical_index_tmpl)
         output.write('<ul class="img-list">\n')
         output.write('<ul class="img-list">\n')
         for html_file, image, label in index_items:
         for html_file, image, label in index_items:
             output.write(
             output.write(
-                '<li>'
+                "<li>"
                 '<a href="{html}">'
                 '<a href="{html}">'
                 '<img src="{img}">'
                 '<img src="{img}">'
                 '<span class="name">{name}</span>'
                 '<span class="name">{name}</span>'
-                '</a>'
-                '</li>\n'
-                .format(html=html_file, img=image, name=label))
-        output.write('</ul>')
+                "</a>"
+                "</li>\n".format(html=html_file, img=image, name=label)
+            )
+        output.write("</ul>")
         write_html_footer(output, "index.html", year)
         write_html_footer(output, "index.html", year)
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
     main()

+ 128 - 94
man/build_html.py

@@ -18,13 +18,14 @@ exclude_mods = [
     "r.watershed.ram",
     "r.watershed.ram",
     "r.watershed.seg",
     "r.watershed.seg",
     "v.topo.check",
     "v.topo.check",
-    "helptext.html"]
+    "helptext.html",
+]
 
 
 # these modules don't use G_parser()
 # these modules don't use G_parser()
 
 
 desc_override = {
 desc_override = {
     "g.parser": "Provides automated parser, GUI, and help support for GRASS scipts.",
     "g.parser": "Provides automated parser, GUI, and help support for GRASS scipts.",
-    "r.li.daemon": "Support module for r.li landscape index calculations."
+    "r.li.daemon": "Support module for r.li landscape index calculations.",
 }
 }
 
 
 ############################################################################
 ############################################################################
@@ -36,14 +37,16 @@ header1_tmpl = string.Template(
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <title>${title} - GRASS GIS Manual</title>
  <title>${title} - GRASS GIS Manual</title>
  <meta name="Author" content="GRASS Development Team">
  <meta name="Author" content="GRASS Development Team">
-""")
+"""
+)
 
 
 macosx_tmpl = string.Template(
 macosx_tmpl = string.Template(
     r"""
     r"""
  <meta name="AppleTitle" content="GRASS GIS ${grass_version} Help">
  <meta name="AppleTitle" content="GRASS GIS ${grass_version} Help">
  <meta name="AppleIcon" content="GRASS-${grass_mmver}/grass_icon.png">
  <meta name="AppleIcon" content="GRASS-${grass_mmver}/grass_icon.png">
  <meta name="robots" content="anchors">
  <meta name="robots" content="anchors">
-""")
+"""
+)
 
 
 header2_tmpl = string.Template(
 header2_tmpl = string.Template(
     r""" <link rel="stylesheet" href="grassdocs.css" type="text/css">
     r""" <link rel="stylesheet" href="grassdocs.css" type="text/css">
@@ -71,8 +74,9 @@ Geographic Resources Analysis Support System (GRASS), an open source
 (<a href="https://www.gnu.org/licenses/gpl.html">GNU GPLed</a>), image
 (<a href="https://www.gnu.org/licenses/gpl.html">GNU GPLed</a>), image
 processing and geographic information system (GIS).</p>
 processing and geographic information system (GIS).</p>
 
 
-""")
-#"
+"""
+)
+# "
 
 
 overview_tmpl = string.Template(
 overview_tmpl = string.Template(
     r"""<!-- the files grass${grass_version_major}.html & helptext.html file live in lib/init/ -->
     r"""<!-- the files grass${grass_version_major}.html & helptext.html file live in lib/init/ -->
@@ -190,35 +194,35 @@ overview_tmpl = string.Template(
     </tr>
     </tr>
   </tbody>
   </tbody>
 </table>
 </table>
-""")
-#"
-
-footer_tmpl = string.Template(\
-    ## TODO: https://trac.osgeo.org/grass/ticket/3987
-    #r"""<a name="wxGUI"></a>
-    #<h3>wxGUI: Graphical user interface</h3>
-    #<table><tbody>
-    #<tr><td valign="top"><a href="wxGUI.html">wxGUI Graphical User Interface</a></td> <td>wxGUI Graphical User Interface</td></tr>
-    #<tr><td valign="top"><a href="wxGUI.nviz.html">3D visualization suite</a></td>    <td>wxGUI.nviz 3D visualization suite</td></tr>
-    #</tbody></table>
-    #<p>
-    #<a name="further"></a>
-    #<h3>Further pages</h3>
-    #<table><tbody>
-    #<tr><td valign="top"><a href="databaseintro.html">database intro</a></td> <td>database intro</td></tr>
-    #<tr><td valign="top"><a href="imageryintro.html">imagery intro</a></td> <td>imagery intro</td></tr>
-    #<tr><td valign="top"><a href="projectionintro.html">projection intro</a></td> <td>projection intro</td></tr>
-    #<tr><td valign="top"><a href="raster3dintro.html">raster3D intro</a></td> <td>raster3D intro</td></tr>
-    #<tr><td valign="top"><a href="rasterintro.html">raster intro</a></td> <td>raster intro</td></tr>
-    #<tr><td valign="top"><a href="temporalintro.html">temporal intro</a></td> <td>temporal intro</td></tr>
-    #<tr><td valign="top"><a href="vectorintro.html">vector intro</a></td> <td>vector intro</td></tr>
-    #<tr><td valign="top"> </td> <td> </td></tr>
-    #<tr><td valign="top"><a href="sql.html">SQL</a></td> <td>SQL</td></tr>
-    #<tr><td valign="top"><a href="variables.html">Variables</a></td> <td>Variables</td></tr>
-    #</tbody></table>
+"""
+)
+# "
+
+footer_tmpl = string.Template(  ## TODO: https://trac.osgeo.org/grass/ticket/3987
+    # r"""<a name="wxGUI"></a>
+    # <h3>wxGUI: Graphical user interface</h3>
+    # <table><tbody>
+    # <tr><td valign="top"><a href="wxGUI.html">wxGUI Graphical User Interface</a></td> <td>wxGUI Graphical User Interface</td></tr>
+    # <tr><td valign="top"><a href="wxGUI.nviz.html">3D visualization suite</a></td>    <td>wxGUI.nviz 3D visualization suite</td></tr>
+    # </tbody></table>
+    # <p>
+    # <a name="further"></a>
+    # <h3>Further pages</h3>
+    # <table><tbody>
+    # <tr><td valign="top"><a href="databaseintro.html">database intro</a></td> <td>database intro</td></tr>
+    # <tr><td valign="top"><a href="imageryintro.html">imagery intro</a></td> <td>imagery intro</td></tr>
+    # <tr><td valign="top"><a href="projectionintro.html">projection intro</a></td> <td>projection intro</td></tr>
+    # <tr><td valign="top"><a href="raster3dintro.html">raster3D intro</a></td> <td>raster3D intro</td></tr>
+    # <tr><td valign="top"><a href="rasterintro.html">raster intro</a></td> <td>raster intro</td></tr>
+    # <tr><td valign="top"><a href="temporalintro.html">temporal intro</a></td> <td>temporal intro</td></tr>
+    # <tr><td valign="top"><a href="vectorintro.html">vector intro</a></td> <td>vector intro</td></tr>
+    # <tr><td valign="top"> </td> <td> </td></tr>
+    # <tr><td valign="top"><a href="sql.html">SQL</a></td> <td>SQL</td></tr>
+    # <tr><td valign="top"><a href="variables.html">Variables</a></td> <td>Variables</td></tr>
+    # </tbody></table>
     #
     #
-    #<p>
-    #<hr class="header">
+    # <p>
+    # <hr class="header">
     r"""<hr class="header">
     r"""<hr class="header">
 <p>
 <p>
 <a href="${index_url}">Main index</a> |
 <a href="${index_url}">Main index</a> |
@@ -236,23 +240,25 @@ GRASS GIS ${grass_version} Reference Manual
 </div>
 </div>
 </body>
 </body>
 </html>
 </html>
-""")
-#"
+"""
+)
+# "
 
 
 cmd2_tmpl = string.Template(
 cmd2_tmpl = string.Template(
     r"""<a name="${cmd}"></a>
     r"""<a name="${cmd}"></a>
 <h3>${cmd_label} commands (${cmd}.*)</h3>
 <h3>${cmd_label} commands (${cmd}.*)</h3>
 <table>
 <table>
-""")
-#"
+"""
+)
+# "
 
 
 desc1_tmpl = string.Template(
 desc1_tmpl = string.Template(
     r"""<tr><td valign="top"><a href="${cmd}">${basename}</a></td> <td>${desc}</td></tr>
     r"""<tr><td valign="top"><a href="${cmd}">${basename}</a></td> <td>${desc}</td></tr>
-""")
-#"
+"""
+)
+# "
 
 
-toc = \
-    r"""
+toc = r"""
 <div class="toc">
 <div class="toc">
 <h4 class="toc">Table of contents</h4>
 <h4 class="toc">Table of contents</h4>
 <ul class="toc">
 <ul class="toc">
@@ -271,49 +277,51 @@ toc = \
 </ul>
 </ul>
 </div>
 </div>
 """
 """
-#"
+# "
 
 
 modclass_intro_tmpl = string.Template(
 modclass_intro_tmpl = string.Template(
     r"""Go to <a href="${modclass_lower}intro.html">${modclass} introduction</a> | <a href="topics.html">topics</a> <p>
     r"""Go to <a href="${modclass_lower}intro.html">${modclass} introduction</a> | <a href="topics.html">topics</a> <p>
-""")
-#"
+"""
+)
+# "
 
 
 modclass_tmpl = string.Template(
 modclass_tmpl = string.Template(
     r"""Go <a href="index.html">back to help overview</a>
     r"""Go <a href="index.html">back to help overview</a>
 <h3>${modclass} commands:</h3>
 <h3>${modclass} commands:</h3>
 <table>
 <table>
-""")
-#"
+"""
+)
+# "
 
 
 desc2_tmpl = string.Template(
 desc2_tmpl = string.Template(
     r"""<tr><td valign="top"><a href="${cmd}">${basename}</a></td> <td>${desc}</td></tr>
     r"""<tr><td valign="top"><a href="${cmd}">${basename}</a></td> <td>${desc}</td></tr>
-""")
-#"
+"""
+)
+# "
 
 
 
 
-full_index_header = \
-    r"""
+full_index_header = r"""
 Go <a href="index.html">back to help overview</a>
 Go <a href="index.html">back to help overview</a>
 """
 """
-#"
+# "
 
 
 
 
 message_tmpl = string.Template(
 message_tmpl = string.Template(
     r"""Generated HTML docs in ${html_dir}/index.html
     r"""Generated HTML docs in ${html_dir}/index.html
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 Following modules are missing the 'modulename.html' file in src code:
 Following modules are missing the 'modulename.html' file in src code:
-""")
-#"
+"""
+)
+# "
 
 
 moduletopics_tmpl = string.Template(
 moduletopics_tmpl = string.Template(
     r"""
     r"""
 <li> <a href="topic_${key}.html">${name}</a></li>
 <li> <a href="topic_${key}.html">${name}</a></li>
 """
 """
 )
 )
-#"
+# "
 
 
-headertopics_tmpl = \
-    r"""
+headertopics_tmpl = r"""
 <link rel="stylesheet" href="grassdocs.css" type="text/css">
 <link rel="stylesheet" href="grassdocs.css" type="text/css">
 </head>
 </head>
 <body style="width: 99%">
 <body style="width: 99%">
@@ -324,10 +332,9 @@ headertopics_tmpl = \
 <h2>Topics</h2>
 <h2>Topics</h2>
 <ul>
 <ul>
 """
 """
-#"
+# "
 
 
-headerkeywords_tmpl = \
-    r"""
+headerkeywords_tmpl = r"""
 <link rel="stylesheet" href="grassdocs.css" type="text/css">
 <link rel="stylesheet" href="grassdocs.css" type="text/css">
 </head>
 </head>
 <body style="width: 99%">
 <body style="width: 99%">
@@ -337,7 +344,7 @@ headerkeywords_tmpl = \
 <hr class="header">
 <hr class="header">
 <h2>Keywords - Index of GRASS GIS modules</h2>
 <h2>Keywords - Index of GRASS GIS modules</h2>
 """
 """
-#"
+# "
 
 
 headerkey_tmpl = string.Template(
 headerkey_tmpl = string.Template(
     r"""
     r"""
@@ -352,11 +359,11 @@ headerkey_tmpl = string.Template(
 <h2>Topic: ${keyword}</h2>
 <h2>Topic: ${keyword}</h2>
 
 
 <table>
 <table>
-""")
-#"
+"""
+)
+# "
 
 
-headerpso_tmpl = \
-    r"""
+headerpso_tmpl = r"""
 <link rel="stylesheet" href="grassdocs.css" type="text/css">
 <link rel="stylesheet" href="grassdocs.css" type="text/css">
 <link rel="stylesheet" href="parser_standard_options.css" type="text/css">
 <link rel="stylesheet" href="parser_standard_options.css" type="text/css">
 <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
 <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
@@ -371,33 +378,42 @@ headerpso_tmpl = \
 <h2>Parser standard options</h2>
 <h2>Parser standard options</h2>
 <ul>
 <ul>
 """
 """
-#"
+# "
 
 
 ############################################################################
 ############################################################################
 
 
+
 def check_for_desc_override(basename):
 def check_for_desc_override(basename):
     return desc_override.get(basename)
     return desc_override.get(basename)
 
 
+
 def read_file(name):
 def read_file(name):
-    f = open(name, 'r')
+    f = open(name, "r")
     s = f.read()
     s = f.read()
     f.close()
     f.close()
     return s
     return s
 
 
+
 def write_file(name, contents):
 def write_file(name, contents):
-    f = open(name, 'w')
+    f = open(name, "w")
     f.write(contents)
     f.write(contents)
     f.close()
     f.close()
 
 
+
 def try_mkdir(path):
 def try_mkdir(path):
     try:
     try:
         os.mkdir(path)
         os.mkdir(path)
     except OSError as e:
     except OSError as e:
         pass
         pass
 
 
+
 def replace_file(name):
 def replace_file(name):
     temp = name + ".tmp"
     temp = name + ".tmp"
-    if os.path.exists(name) and os.path.exists(temp) and read_file(name) == read_file(temp):
+    if (
+        os.path.exists(name)
+        and os.path.exists(temp)
+        and read_file(name) == read_file(temp)
+    ):
         os.remove(temp)
         os.remove(temp)
     else:
     else:
         try:
         try:
@@ -406,40 +422,56 @@ def replace_file(name):
             pass
             pass
         os.rename(temp, name)
         os.rename(temp, name)
 
 
+
 def copy_file(src, dst):
 def copy_file(src, dst):
     write_file(dst, read_file(src))
     write_file(dst, read_file(src))
 
 
+
 def html_files(cls=None, ignore_gui=True):
 def html_files(cls=None, ignore_gui=True):
     for cmd in sorted(os.listdir(html_dir)):
     for cmd in sorted(os.listdir(html_dir)):
-        if cmd.endswith(".html") and \
-           (cls in [None, '*'] or cmd.startswith(cls + ".")) and \
-           (cls != '*' or len(cmd.split('.')) >= 3) and \
-           cmd not in ["full_index.html", "index.html"] and \
-           cmd not in exclude_mods and \
-           (ignore_gui and not cmd.startswith("wxGUI.") or not ignore_gui):
+        if (
+            cmd.endswith(".html")
+            and (cls in [None, "*"] or cmd.startswith(cls + "."))
+            and (cls != "*" or len(cmd.split(".")) >= 3)
+            and cmd not in ["full_index.html", "index.html"]
+            and cmd not in exclude_mods
+            and (ignore_gui and not cmd.startswith("wxGUI.") or not ignore_gui)
+        ):
             yield cmd
             yield cmd
 
 
-def write_html_header(f, title, ismain = False, body_width = "99%"):
-    f.write(header1_tmpl.substitute(title = title))
+
+def write_html_header(f, title, ismain=False, body_width="99%"):
+    f.write(header1_tmpl.substitute(title=title))
     if ismain and macosx:
     if ismain and macosx:
-        f.write(macosx_tmpl.substitute(grass_version = grass_version,
-                                       grass_mmver = grass_mmver))
-    f.write(header2_tmpl.substitute(grass_version = grass_version, body_width = body_width))
+        f.write(
+            macosx_tmpl.substitute(grass_version=grass_version, grass_mmver=grass_mmver)
+        )
+    f.write(header2_tmpl.substitute(grass_version=grass_version, body_width=body_width))
+
 
 
 def write_html_cmd_overview(f):
 def write_html_cmd_overview(f):
-    f.write(overview_tmpl.substitute(grass_version_major = grass_version_major,
-                                     grass_version_minor = grass_version_minor))
+    f.write(
+        overview_tmpl.substitute(
+            grass_version_major=grass_version_major,
+            grass_version_minor=grass_version_minor,
+        )
+    )
+
 
 
-def write_html_footer(f, index_url, year = None):
+def write_html_footer(f, index_url, year=None):
     if year is None:
     if year is None:
         cur_year = default_year
         cur_year = default_year
     else:
     else:
         cur_year = year
         cur_year = year
-    f.write(footer_tmpl.substitute(grass_version = grass_version,
-                                   index_url = index_url, year = cur_year))
+    f.write(
+        footer_tmpl.substitute(
+            grass_version=grass_version, index_url=index_url, year=cur_year
+        )
+    )
+
 
 
 def get_desc(cmd):
 def get_desc(cmd):
-    f = open(cmd, 'r')
+    f = open(cmd, "r")
     while True:
     while True:
         line = f.readline()
         line = f.readline()
         if not line:
         if not line:
@@ -454,7 +486,7 @@ def get_desc(cmd):
         if "SYNOPSIS" in line:
         if "SYNOPSIS" in line:
             break
             break
         if "<em>" in line:
         if "<em>" in line:
-            sp = line.split('-',1)
+            sp = line.split("-", 1)
             if len(sp) > 1:
             if len(sp) > 1:
                 return sp[1].strip()
                 return sp[1].strip()
             else:
             else:
@@ -462,22 +494,24 @@ def get_desc(cmd):
 
 
     return ""
     return ""
 
 
+
 def to_title(name):
 def to_title(name):
     """Convert name of command class/family to form suitable for title"""
     """Convert name of command class/family to form suitable for title"""
-    if name == 'PostScript':
+    if name == "PostScript":
         return name
         return name
     return name.capitalize()
     return name.capitalize()
 
 
+
 ############################################################################
 ############################################################################
 
 
-arch_dist_dir = os.environ['ARCH_DISTDIR']
+arch_dist_dir = os.environ["ARCH_DISTDIR"]
 html_dir = os.path.join(arch_dist_dir, "docs", "html")
 html_dir = os.path.join(arch_dist_dir, "docs", "html")
-gisbase = os.environ['GISBASE']
+gisbase = os.environ["GISBASE"]
 grass_version = os.getenv("VERSION_NUMBER", "unknown")
 grass_version = os.getenv("VERSION_NUMBER", "unknown")
-grass_version_major = grass_version.split('.')[0]
-grass_version_minor = grass_version.split('.')[1]
-grass_mmver = '.'.join(grass_version.split('.')[0:2])
-macosx = "darwin" in os.environ['ARCH'].lower()
+grass_version_major = grass_version.split(".")[0]
+grass_version_minor = grass_version.split(".")[1]
+grass_mmver = ".".join(grass_version.split(".")[0:2])
+macosx = "darwin" in os.environ["ARCH"].lower()
 default_year = os.getenv("VERSION_DATE")
 default_year = os.getenv("VERSION_DATE")
 if not default_year:
 if not default_year:
     default_year = str(datetime.now().year)
     default_year = str(datetime.now().year)

+ 1 - 1
man/build_index.py

@@ -12,7 +12,7 @@ from build_html import *
 os.chdir(html_dir)
 os.chdir(html_dir)
 
 
 filename = "index.html"
 filename = "index.html"
-f = open(filename + ".tmp", 'w')
+f = open(filename + ".tmp", "w")
 
 
 year = None
 year = None
 if len(sys.argv) > 1:
 if len(sys.argv) > 1:

+ 1 - 1
man/build_index_rest.py

@@ -12,7 +12,7 @@ from build_rest import *
 os.chdir(rest_dir)
 os.chdir(rest_dir)
 
 
 filename = "index.txt"
 filename = "index.txt"
-f = open(filename + ".tmp", 'w')
+f = open(filename + ".tmp", "w")
 
 
 write_rest_header(f, "GRASS GIS %s Reference Manual" % grass_version, True)
 write_rest_header(f, "GRASS GIS %s Reference Manual" % grass_version, True)
 write_rest_cmd_overview(f)
 write_rest_cmd_overview(f)

+ 35 - 22
man/build_keywords.py

@@ -9,15 +9,25 @@ import sys
 import glob
 import glob
 from build_html import *
 from build_html import *
 
 
-blacklist = ['Display', 'Database', 'General', 'Imagery', 'Misc', 'Postscript',
-             'Raster', 'Raster3D', 'Temporal', 'Vector']
+blacklist = [
+    "Display",
+    "Database",
+    "General",
+    "Imagery",
+    "Misc",
+    "Postscript",
+    "Raster",
+    "Raster3D",
+    "Temporal",
+    "Vector",
+]
 
 
 path = sys.argv[1]
 path = sys.argv[1]
 year = os.getenv("VERSION_DATE")
 year = os.getenv("VERSION_DATE")
 
 
 keywords = {}
 keywords = {}
 
 
-htmlfiles = glob.glob1(path, '*.html')
+htmlfiles = glob.glob1(path, "*.html")
 
 
 char_list = {}
 char_list = {}
 
 
@@ -26,25 +36,24 @@ for fname in htmlfiles:
     # TODO maybe move to Python re (regex)
     # TODO maybe move to Python re (regex)
     lines = fil.readlines()
     lines = fil.readlines()
     # remove empty lines
     # remove empty lines
-    lines = [x for x in lines if x != '\n']
+    lines = [x for x in lines if x != "\n"]
     try:
     try:
-        index_keys = lines.index('<h2>KEYWORDS</h2>\n') + 1
-        index_desc = lines.index('<h2>NAME</h2>\n') + 1
+        index_keys = lines.index("<h2>KEYWORDS</h2>\n") + 1
+        index_desc = lines.index("<h2>NAME</h2>\n") + 1
     except:
     except:
         continue
         continue
     try:
     try:
-        keys = lines[index_keys].split(',')
+        keys = lines[index_keys].split(",")
     except:
     except:
         continue
         continue
     for key in keys:
     for key in keys:
         key = key.strip()
         key = key.strip()
         try:
         try:
-            key = key.split('>')[1].split('<')[0]
+            key = key.split(">")[1].split("<")[0]
         except:
         except:
             pass
             pass
         if not key:
         if not key:
-            exit("Empty keyword from file %s line: %s"
-                 % (fname, lines[index_keys]))
+            exit("Empty keyword from file %s line: %s" % (fname, lines[index_keys]))
         if key not in keywords.keys():
         if key not in keywords.keys():
             keywords[key] = []
             keywords[key] = []
             keywords[key].append(fname)
             keywords[key].append(fname)
@@ -70,22 +79,26 @@ for key in sorted(keywords.keys()):
         if key.lower() < char_list[str(firstchar)].lower():
         if key.lower() < char_list[str(firstchar)].lower():
             char_list[str(firstchar.lower())] = key
             char_list[str(firstchar.lower())] = key
 
 
-keywordsfile = open(os.path.join(path, 'keywords.html'), 'w')
-keywordsfile.write(header1_tmpl.substitute(title="GRASS GIS %s Reference "
-                                           "Manual: Keywords index" % grass_version))
+keywordsfile = open(os.path.join(path, "keywords.html"), "w")
+keywordsfile.write(
+    header1_tmpl.substitute(
+        title="GRASS GIS %s Reference " "Manual: Keywords index" % grass_version
+    )
+)
 keywordsfile.write(headerkeywords_tmpl)
 keywordsfile.write(headerkeywords_tmpl)
-keywordsfile.write('<dl>')
+keywordsfile.write("<dl>")
 
 
 sortedKeys = sorted(keywords.keys(), key=lambda s: s.lower())
 sortedKeys = sorted(keywords.keys(), key=lambda s: s.lower())
 
 
 for key in sortedKeys:
 for key in sortedKeys:
-    keyword_line = '<dt><b><a name="%s" class="urlblack">%s</a></b></dt>' \
-                   '<dd>' % (key, key)
+    keyword_line = '<dt><b><a name="%s" class="urlblack">%s</a></b></dt>' "<dd>" % (
+        key,
+        key,
+    )
     for value in sorted(keywords[key]):
     for value in sorted(keywords[key]):
-        keyword_line += ' <a href="%s">%s</a>,' % (value,
-                                                   value.replace('.html', ''))
-    keyword_line = keyword_line.rstrip(',')
-    keyword_line += '</dd>\n'
+        keyword_line += ' <a href="%s">%s</a>,' % (value, value.replace(".html", ""))
+    keyword_line = keyword_line.rstrip(",")
+    keyword_line += "</dd>\n"
     keywordsfile.write(keyword_line)
     keywordsfile.write(keyword_line)
 keywordsfile.write("</dl>\n")
 keywordsfile.write("</dl>\n")
 # create toc
 # create toc
@@ -94,7 +107,7 @@ test_length = 0
 all_keys = len(char_list.keys())
 all_keys = len(char_list.keys())
 for k in sorted(char_list.keys()):
 for k in sorted(char_list.keys()):
     test_length += 1
     test_length += 1
-#    toc += '<li><a href="#%s" class="toc">%s</a></li>' % (char_list[k], k)
+    #    toc += '<li><a href="#%s" class="toc">%s</a></li>' % (char_list[k], k)
     if test_length % 4 == 0 and not test_length == all_keys:
     if test_length % 4 == 0 and not test_length == all_keys:
         toc += '\n<a href="#%s" class="toc">%s</a>, ' % (char_list[k], k)
         toc += '\n<a href="#%s" class="toc">%s</a>, ' % (char_list[k], k)
     elif test_length % 4 == 0 and test_length == all_keys:
     elif test_length % 4 == 0 and test_length == all_keys:
@@ -103,7 +116,7 @@ for k in sorted(char_list.keys()):
         toc += '<a href="#%s" class="toc">%s</a>' % (char_list[k], k)
         toc += '<a href="#%s" class="toc">%s</a>' % (char_list[k], k)
     else:
     else:
         toc += '<a href="#%s" class="toc">%s</a>, ' % (char_list[k], k)
         toc += '<a href="#%s" class="toc">%s</a>, ' % (char_list[k], k)
-toc += '</p></div>\n'
+toc += "</p></div>\n"
 keywordsfile.write(toc)
 keywordsfile.write(toc)
 
 
 write_html_footer(keywordsfile, "index.html", year)
 write_html_footer(keywordsfile, "index.html", year)

+ 30 - 24
man/build_manual_gallery.py

@@ -22,17 +22,17 @@ import re
 from build_html import write_html_footer, grass_version, header1_tmpl
 from build_html import write_html_footer, grass_version, header1_tmpl
 
 
 
 
-output_name = 'manual_gallery.html'
+output_name = "manual_gallery.html"
 
 
-img_extensions = ['png', 'jpg', 'gif']
-img_patterns = ['*.' + extension for extension in img_extensions]
+img_extensions = ["png", "jpg", "gif"]
+img_patterns = ["*." + extension for extension in img_extensions]
 
 
 # we don't want some images to show up
 # we don't want some images to show up
 # logos
 # logos
-img_blacklist = ['grass_logo.png', 'grass_icon.png']
+img_blacklist = ["grass_logo.png", "grass_icon.png"]
 # circles with numbers from helptext.html (unfortunate we have to list it here)
 # circles with numbers from helptext.html (unfortunate we have to list it here)
 # perhaps some general name ending would be good, like *_noindex.png
 # perhaps some general name ending would be good, like *_noindex.png
-img_blacklist.extend(['circle_{0}.png'.format(num) for num in range(1, 6)])
+img_blacklist.extend(["circle_{0}.png".format(num) for num in range(1, 6)])
 
 
 year = os.getenv("VERSION_DATE")
 year = os.getenv("VERSION_DATE")
 
 
@@ -97,7 +97,7 @@ header_graphical_index_tmpl = """\
 def img_in_html(filename, imagename):
 def img_in_html(filename, imagename):
     # for some reason, calling search just once is much faster
     # for some reason, calling search just once is much faster
     # than calling it on every line (time is spent in _compile)
     # than calling it on every line (time is spent in _compile)
-    pattern = re.compile('<img .*src=.{0}.*>'.format(imagename))
+    pattern = re.compile("<img .*src=.{0}.*>".format(imagename))
     with open(filename) as file:
     with open(filename) as file:
         if re.search(pattern, file.read()):
         if re.search(pattern, file.read()):
             return True
             return True
@@ -121,10 +121,10 @@ def get_files(directory, patterns, exclude_patterns):
 
 
 
 
 def remove_module_name(string, module):
 def remove_module_name(string, module):
-    string = string.replace(module.replace('wxGUI.', 'g.gui.'), '')
-    string = string.replace(module.replace('.', '_'), '')  # using _
-    string = string.replace(module.replace('.', ''), '')  # using nothing
-    string = string.replace(module, '')  # using original dots
+    string = string.replace(module.replace("wxGUI.", "g.gui."), "")
+    string = string.replace(module.replace(".", "_"), "")  # using _
+    string = string.replace(module.replace(".", ""), "")  # using nothing
+    string = string.replace(module, "")  # using original dots
     return string
     return string
 
 
 
 
@@ -133,9 +133,9 @@ def title_from_names(module_name, img_name):
     # so possibly r.out.png fails but image name should use _ anyway
     # so possibly r.out.png fails but image name should use _ anyway
     # strictly speaking, it could be also, e.g., index name
     # strictly speaking, it could be also, e.g., index name
     for extension in img_extensions:
     for extension in img_extensions:
-        img_name = img_name.replace('.' + extension, '')
+        img_name = img_name.replace("." + extension, "")
     img_name = remove_module_name(img_name, module_name)
     img_name = remove_module_name(img_name, module_name)
-    img_name = img_name.replace('_', ' ')
+    img_name = img_name.replace("_", " ")
     img_name = img_name.strip()
     img_name = img_name.strip()
     if img_name:
     if img_name:
         return "{name} ({desc})".format(name=module_name, desc=img_name)
         return "{name} ({desc})".format(name=module_name, desc=img_name)
@@ -144,14 +144,17 @@ def title_from_names(module_name, img_name):
 
 
 
 
 def get_module_name(filename):
 def get_module_name(filename):
-    return filename.replace('.html', '')
+    return filename.replace(".html", "")
 
 
 
 
 def main():
 def main():
     html_dir = sys.argv[1]
     html_dir = sys.argv[1]
 
 
-    html_files = get_files(html_dir, ['*.html'],
-                           exclude_patterns=[output_name, '*_graphical.html', 'graphical_index.html'])
+    html_files = get_files(
+        html_dir,
+        ["*.html"],
+        exclude_patterns=[output_name, "*_graphical.html", "graphical_index.html"],
+    )
     img_html_files = {}
     img_html_files = {}
 
 
     for filename in os.listdir(html_dir):
     for filename in os.listdir(html_dir):
@@ -163,25 +166,28 @@ def main():
                     img_html_files[filename] = html_file
                     img_html_files[filename] = html_file
                     # for now suppose one image per html
                     # for now suppose one image per html
 
 
-    with open(os.path.join(html_dir, output_name), 'w') as output:
-        output.write(header1_tmpl.substitute(title="GRASS GIS %s Reference "
-                                               "Manual: Manual gallery" % grass_version))
+    with open(os.path.join(html_dir, output_name), "w") as output:
+        output.write(
+            header1_tmpl.substitute(
+                title="GRASS GIS %s Reference " "Manual: Manual gallery" % grass_version
+            )
+        )
         output.write(header_graphical_index_tmpl)
         output.write(header_graphical_index_tmpl)
         output.write('<ul class="img-list">\n')
         output.write('<ul class="img-list">\n')
         for image, html_file in sorted(img_html_files.items()):
         for image, html_file in sorted(img_html_files.items()):
             name = get_module_name(html_file)
             name = get_module_name(html_file)
             title = title_from_names(name, image)
             title = title_from_names(name, image)
             output.write(
             output.write(
-                '<li>'
+                "<li>"
                 '<a href="{html}" title="{title}">'
                 '<a href="{html}" title="{title}">'
                 '<img src="{img}">'
                 '<img src="{img}">'
                 '<span class="name">{name}</span>'
                 '<span class="name">{name}</span>'
-                '</a>'
-                '</li>\n'
-                .format(html=html_file, img=image, title=title, name=name))
-        output.write('</ul>')
+                "</a>"
+                "</li>\n".format(html=html_file, img=image, title=title, name=name)
+            )
+        output.write("</ul>")
         write_html_footer(output, "index.html", year)
         write_html_footer(output, "index.html", year)
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
     main()

+ 65 - 41
man/build_rest.py

@@ -22,13 +22,14 @@ exclude_mods = [
     "r.watershed.ram",
     "r.watershed.ram",
     "r.watershed.seg",
     "r.watershed.seg",
     "v.topo.check",
     "v.topo.check",
-    "helptext.html"]
+    "helptext.html",
+]
 
 
 # these modules don't use G_parser()
 # these modules don't use G_parser()
 
 
 desc_override = {
 desc_override = {
     "g.parser": "Provides automated parser, GUI, and help support for GRASS scipts.",
     "g.parser": "Provides automated parser, GUI, and help support for GRASS scipts.",
-    "r.li.daemon": "Support module for r.li landscape index calculations."
+    "r.li.daemon": "Support module for r.li landscape index calculations.",
 }
 }
 
 
 ############################################################################
 ############################################################################
@@ -57,7 +58,8 @@ This reference manual details the use of modules distributed with
 Geographic Resources Analysis Support System (GRASS), an open source
 Geographic Resources Analysis Support System (GRASS), an open source
 (`GNU GPLed <https://www.gnu.org/licenses/gpl.html>`_), image
 (`GNU GPLed <https://www.gnu.org/licenses/gpl.html>`_), image
 processing and geographic information system (GIS).
 processing and geographic information system (GIS).
-""")
+"""
+)
 
 
 overview_tmpl = string.Template(
 overview_tmpl = string.Template(
     r"""
     r"""
@@ -158,9 +160,10 @@ Printing
     
     
         PostScript commands manual <postscript>
         PostScript commands manual <postscript>
 
 
-""")
+"""
+)
 
 
-#TODO add copyright symbol
+# TODO add copyright symbol
 footer_tmpl = string.Template(
 footer_tmpl = string.Template(
     r"""
     r"""
 
 
@@ -168,10 +171,10 @@ footer_tmpl = string.Template(
 
 
 :doc:`Manual main page <index>` \| :doc:`Full Index <full_index>`
 :doc:`Manual main page <index>` \| :doc:`Full Index <full_index>`
  2003-2021 `GRASS Development Team <https://grass.osgeo.org>`_, GRASS GIS ${grass_version} Reference Manual
  2003-2021 `GRASS Development Team <https://grass.osgeo.org>`_, GRASS GIS ${grass_version} Reference Manual
-""")
+"""
+)
 
 
-cmd1_tmpl = string.Template(
-    r"""*`$cmd.\* <${cmd}>` *""")
+cmd1_tmpl = string.Template(r"""*`$cmd.\* <${cmd}>` *""")
 
 
 cmd2_tmpl = string.Template(
 cmd2_tmpl = string.Template(
     r"""
     r"""
@@ -183,14 +186,15 @@ ${cmd}.* commands:
     :maxdepth: 1
     :maxdepth: 1
     
     
 
 
-""")
+"""
+)
 
 
 desc1_tmpl = string.Template(
 desc1_tmpl = string.Template(
     r"""        ${basename} - ${desc} <${basename}>
     r"""        ${basename} - ${desc} <${basename}>
-""")
+"""
+)
 
 
-sections = \
-    r"""
+sections = r"""
 
 
 +-----------------------------+-------------------------------+
 +-----------------------------+-------------------------------+
 |`d.* <full_index.html#d>`_   | `display commands`            |
 |`d.* <full_index.html#d>`_   | `display commands`            |
@@ -222,8 +226,9 @@ sections = \
 
 
 modclass_intro_tmpl = string.Template(
 modclass_intro_tmpl = string.Template(
     r"""Go to :doc:`${modclass} introduction <${modclass_lower}intro>`
     r"""Go to :doc:`${modclass} introduction <${modclass_lower}intro>`
-""")
-#"
+"""
+)
+# "
 
 
 modclass_tmpl = string.Template(
 modclass_tmpl = string.Template(
     r"""Go :doc:`back to help overview<index>`
     r"""Go :doc:`back to help overview<index>`
@@ -236,54 +241,65 @@ modclass_tmpl = string.Template(
     :maxdepth: 1
     :maxdepth: 1
     
     
 
 
-""")
-#"
+"""
+)
+# "
 
 
 desc2_tmpl = string.Template(
 desc2_tmpl = string.Template(
     r"""        ${basename} - ${desc} <${basename}>
     r"""        ${basename} - ${desc} <${basename}>
-""")
-#"
+"""
+)
+# "
 
 
 
 
-full_index_header = \
-    r"""Go :doc:`back to help overview<index>`
+full_index_header = r"""Go :doc:`back to help overview<index>`
 
 
 
 
 Full command index:
 Full command index:
 ~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~
 """
 """
-#"
+# "
 
 
 
 
 message_tmpl = string.Template(
 message_tmpl = string.Template(
     r"""Generated HTML docs in ${rest_dir}/index.txt
     r"""Generated HTML docs in ${rest_dir}/index.txt
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 Following modules are missing the 'modulename.txt' file in src code:
 Following modules are missing the 'modulename.txt' file in src code:
-""")
+"""
+)
+
 
 
 def check_for_desc_override(basename):
 def check_for_desc_override(basename):
     return desc_override.get(basename)
     return desc_override.get(basename)
 
 
+
 def read_file(name):
 def read_file(name):
-    f = open(name, 'r')
+    f = open(name, "r")
     s = f.read()
     s = f.read()
     f.close()
     f.close()
     return s
     return s
 
 
+
 def write_file(name, contents):
 def write_file(name, contents):
-    f = open(name, 'w')
+    f = open(name, "w")
     f.write(contents)
     f.write(contents)
     f.close()
     f.close()
 
 
+
 def try_mkdir(path):
 def try_mkdir(path):
     try:
     try:
         os.mkdir(path)
         os.mkdir(path)
     except OSError as e:
     except OSError as e:
         pass
         pass
 
 
+
 def replace_file(name):
 def replace_file(name):
     temp = name + ".tmp"
     temp = name + ".tmp"
-    if os.path.exists(name) and os.path.exists(temp) and read_file(name) == read_file(temp):
+    if (
+        os.path.exists(name)
+        and os.path.exists(temp)
+        and read_file(name) == read_file(temp)
+    ):
         os.remove(temp)
         os.remove(temp)
     else:
     else:
         try:
         try:
@@ -292,32 +308,39 @@ def replace_file(name):
             pass
             pass
         os.rename(temp, name)
         os.rename(temp, name)
 
 
+
 def copy_file(src, dst):
 def copy_file(src, dst):
     write_file(dst, read_file(src))
     write_file(dst, read_file(src))
 
 
-def rest_files(cls = None):
+
+def rest_files(cls=None):
     for cmd in sorted(os.listdir(rest_dir)):
     for cmd in sorted(os.listdir(rest_dir)):
-        if cmd.endswith(".txt") and \
-           (cls in [None, '*'] or cmd.startswith(cls + ".")) and \
-           (cls != '*' or len(cmd.split('.')) >= 3) and \
-           cmd not in ["full_index.txt", "index.txt"] and \
-           cmd not in exclude_mods and \
-           not cmd.startswith("wxGUI."):
+        if (
+            cmd.endswith(".txt")
+            and (cls in [None, "*"] or cmd.startswith(cls + "."))
+            and (cls != "*" or len(cmd.split(".")) >= 3)
+            and cmd not in ["full_index.txt", "index.txt"]
+            and cmd not in exclude_mods
+            and not cmd.startswith("wxGUI.")
+        ):
             yield cmd
             yield cmd
 
 
-def write_rest_header(f, title, ismain = False):
-    f.write(header2_tmpl.substitute(grass_version = grass_version))
+
+def write_rest_header(f, title, ismain=False):
+    f.write(header2_tmpl.substitute(grass_version=grass_version))
+
 
 
 def write_rest_cmd_overview(f):
 def write_rest_cmd_overview(f):
     box_color = "#e1ecd0"
     box_color = "#e1ecd0"
-    f.write(overview_tmpl.substitute(box_color = box_color))
+    f.write(overview_tmpl.substitute(box_color=box_color))
+
 
 
 def write_rest_footer(f, index_url):
 def write_rest_footer(f, index_url):
-    f.write(footer_tmpl.substitute(grass_version = grass_version,
-                                   index_url = index_url))
+    f.write(footer_tmpl.substitute(grass_version=grass_version, index_url=index_url))
+
 
 
 def get_desc(cmd):
 def get_desc(cmd):
-    f = open(cmd, 'r')
+    f = open(cmd, "r")
     while True:
     while True:
         line = f.readline()
         line = f.readline()
         if not line:
         if not line:
@@ -332,7 +355,7 @@ def get_desc(cmd):
         if "SYNOPSIS" in line:
         if "SYNOPSIS" in line:
             break
             break
         if "*" in line:
         if "*" in line:
-            sp = line.split('-',1)
+            sp = line.split("-", 1)
             if len(sp) > 1:
             if len(sp) > 1:
                 return sp[1].strip()
                 return sp[1].strip()
             else:
             else:
@@ -340,11 +363,12 @@ def get_desc(cmd):
 
 
     return ""
     return ""
 
 
+
 ############################################################################
 ############################################################################
 
 
-arch_dist_dir = os.environ['ARCH_DISTDIR']
+arch_dist_dir = os.environ["ARCH_DISTDIR"]
 rest_dir = os.path.join(arch_dist_dir, "docs", "rest")
 rest_dir = os.path.join(arch_dist_dir, "docs", "rest")
-gisbase = os.environ['GISBASE']
+gisbase = os.environ["GISBASE"]
 ver = read_file(os.path.join(gisbase, "etc", "VERSIONNUMBER"))
 ver = read_file(os.path.join(gisbase, "etc", "VERSIONNUMBER"))
 try:
 try:
     grass_version = ver.split()[0].strip()
     grass_version = ver.split()[0].strip()

+ 29 - 20
man/build_topics.py

@@ -16,24 +16,24 @@ min_num_modules_for_topic = 3
 
 
 keywords = {}
 keywords = {}
 
 
-htmlfiles = glob.glob1(path, '*.html')
+htmlfiles = glob.glob1(path, "*.html")
 
 
 for fname in htmlfiles:
 for fname in htmlfiles:
     fil = open(os.path.join(path, fname))
     fil = open(os.path.join(path, fname))
     # TODO maybe move to Python re (regex)
     # TODO maybe move to Python re (regex)
     lines = fil.readlines()
     lines = fil.readlines()
     try:
     try:
-        index_keys = lines.index('<h2>KEYWORDS</h2>\n')+1
-        index_desc = lines.index('<h2>NAME</h2>\n')+1
+        index_keys = lines.index("<h2>KEYWORDS</h2>\n") + 1
+        index_desc = lines.index("<h2>NAME</h2>\n") + 1
     except:
     except:
         continue
         continue
     try:
     try:
-        key = lines[index_keys].split(',')[1].strip().replace(' ', '_')
-        key = key.split('>')[1].split('<')[0]
+        key = lines[index_keys].split(",")[1].strip().replace(" ", "_")
+        key = key.split(">")[1].split("<")[0]
     except:
     except:
         continue
         continue
     try:
     try:
-        desc = lines[index_desc].split('-', 1)[1].strip()
+        desc = lines[index_desc].split("-", 1)[1].strip()
     except:
     except:
         desc.strip()
         desc.strip()
     if key not in keywords.keys():
     if key not in keywords.keys():
@@ -42,33 +42,42 @@ for fname in htmlfiles:
     elif fname not in keywords[key]:
     elif fname not in keywords[key]:
         keywords[key][fname] = desc
         keywords[key][fname] = desc
 
 
-topicsfile = open(os.path.join(path, 'topics.html'), 'w')
-topicsfile.write(header1_tmpl.substitute(title = "GRASS GIS "
-                        "%s Reference Manual: Topics index" % grass_version))
+topicsfile = open(os.path.join(path, "topics.html"), "w")
+topicsfile.write(
+    header1_tmpl.substitute(
+        title="GRASS GIS " "%s Reference Manual: Topics index" % grass_version
+    )
+)
 topicsfile.write(headertopics_tmpl)
 topicsfile.write(headertopics_tmpl)
 
 
 for key, values in sorted(keywords.items(), key=lambda s: s[0].lower()):
 for key, values in sorted(keywords.items(), key=lambda s: s[0].lower()):
-    keyfile = open(os.path.join(path, 'topic_%s.html' % key), 'w')
-    keyfile.write(header1_tmpl.substitute(title = "GRASS GIS "
-                        "%s Reference Manual: Topic %s" % (grass_version,
-                                                    key.replace('_', ' '))))
-    keyfile.write(headerkey_tmpl.substitute(keyword=key.replace('_', ' ')))
+    keyfile = open(os.path.join(path, "topic_%s.html" % key), "w")
+    keyfile.write(
+        header1_tmpl.substitute(
+            title="GRASS GIS "
+            "%s Reference Manual: Topic %s" % (grass_version, key.replace("_", " "))
+        )
+    )
+    keyfile.write(headerkey_tmpl.substitute(keyword=key.replace("_", " ")))
     num_modules = 0
     num_modules = 0
     for mod, desc in sorted(values.items()):
     for mod, desc in sorted(values.items()):
         num_modules += 1
         num_modules += 1
-        keyfile.write(desc1_tmpl.substitute(cmd=mod, desc=desc,
-                                            basename=mod.replace('.html', '')))
+        keyfile.write(
+            desc1_tmpl.substitute(cmd=mod, desc=desc, basename=mod.replace(".html", ""))
+        )
     if num_modules >= min_num_modules_for_topic:
     if num_modules >= min_num_modules_for_topic:
-        topicsfile.writelines([moduletopics_tmpl.substitute(
-            key=key, name=key.replace('_', ' '))])
+        topicsfile.writelines(
+            [moduletopics_tmpl.substitute(key=key, name=key.replace("_", " "))]
+        )
     keyfile.write("</table>\n")
     keyfile.write("</table>\n")
     # link to the keywords index
     # link to the keywords index
     # TODO: the labels in keywords index are with spaces and capitals
     # TODO: the labels in keywords index are with spaces and capitals
     # this should be probably changed to lowercase with underscores
     # this should be probably changed to lowercase with underscores
     keyfile.write(
     keyfile.write(
-        '<p><em>See also the corresponding keyword'
+        "<p><em>See also the corresponding keyword"
         ' <a href="keywords.html#{key}">{key}</a>'
         ' <a href="keywords.html#{key}">{key}</a>'
-        ' for additional references.</em>'.format(key=key.replace('_', ' ')))
+        " for additional references.</em>".format(key=key.replace("_", " "))
+    )
     write_html_footer(keyfile, "index.html", year)
     write_html_footer(keyfile, "index.html", year)
 topicsfile.write("</ul>\n")
 topicsfile.write("</ul>\n")
 write_html_footer(topicsfile, "index.html", year)
 write_html_footer(topicsfile, "index.html", year)

+ 109 - 57
man/parser_standard_options.py

@@ -15,24 +15,26 @@ except ImportError:
 
 
 from build_html import *
 from build_html import *
 
 
-def parse_options(lines, startswith='Opt'):
+
+def parse_options(lines, startswith="Opt"):
     def split_in_groups(lines):
     def split_in_groups(lines):
         def count_par_diff(line):
         def count_par_diff(line):
-            open_par = line.count('(')
-            close_par = line.count(')')
+            open_par = line.count("(")
+            close_par = line.count(")")
             return open_par - close_par
             return open_par - close_par
+
         res = None
         res = None
         diff = 0
         diff = 0
         for line in lines:
         for line in lines:
-            if line.startswith('case'):
+            if line.startswith("case"):
                 optname = line.split()[1][:-1]
                 optname = line.split()[1][:-1]
                 res = []
                 res = []
-#                if optname == 'G_OPT_R_BASENAME_INPUT':
-#                    import ipdb; ipdb.set_trace()
-            elif line == 'break;':
+            #                if optname == 'G_OPT_R_BASENAME_INPUT':
+            #                    import ipdb; ipdb.set_trace()
+            elif line == "break;":
                 diff = 0
                 diff = 0
                 yield optname, res
                 yield optname, res
-            elif line.startswith('G_'):
+            elif line.startswith("G_"):
                 diff = count_par_diff(line)
                 diff = count_par_diff(line)
             elif diff > 0:
             elif diff > 0:
                 diff -= count_par_diff(line)
                 diff -= count_par_diff(line)
@@ -40,10 +42,10 @@ def parse_options(lines, startswith='Opt'):
                 res.append(line) if res is not None else None
                 res.append(line) if res is not None else None
 
 
     def split_opt_line(line):
     def split_opt_line(line):
-        index = line.index('=')
+        index = line.index("=")
         key = line[:index].strip()
         key = line[:index].strip()
-        default = line[index + 1:].strip()
-        if default.startswith('_('):
+        default = line[index + 1 :].strip()
+        if default.startswith("_("):
             default = default[2:]
             default = default[2:]
         return key, default
         return key, default
 
 
@@ -56,26 +58,28 @@ def parse_options(lines, startswith='Opt'):
                 dynamic_answer = True
                 dynamic_answer = True
             if line.strip() == "/* end dynamic answer */":
             if line.strip() == "/* end dynamic answer */":
                 dynamic_answer = False
                 dynamic_answer = False
-            if dynamic_answer or line.startswith('/*'):
+            if dynamic_answer or line.startswith("/*"):
                 continue
                 continue
-            if line.startswith('/*'):
+            if line.startswith("/*"):
                 continue
                 continue
-            if line.startswith(startswith) and line.endswith(';'):
+            if line.startswith(startswith) and line.endswith(";"):
                 key, default = [w.strip() for w in split_opt_line(line[5:])]
                 key, default = [w.strip() for w in split_opt_line(line[5:])]
                 res[key] = default
                 res[key] = default
             elif line.startswith(startswith):
             elif line.startswith(startswith):
                 key, default = split_opt_line(line[5:])
                 key, default = split_opt_line(line[5:])
-                res[key] = [default, ]
+                res[key] = [
+                    default,
+                ]
             else:
             else:
                 if key is not None:
                 if key is not None:
                     if key not in res:
                     if key not in res:
                         res[key] = []
                         res[key] = []
                     start, end = 0, -1
                     start, end = 0, -1
-                    if line.startswith('_('):
+                    if line.startswith("_("):
                         start = 2
                         start = 2
-                    if line.endswith(');'):
+                    if line.endswith(");"):
                         end = -3
                         end = -3
-                    elif line.endswith(';'):
+                    elif line.endswith(";"):
                         end = -2
                         end = -2
                     res[key].append(line[start:end])
                     res[key].append(line[start:end])
         # pprint(glines)
         # pprint(glines)
@@ -84,9 +88,15 @@ def parse_options(lines, startswith='Opt'):
 
 
     def clean_value(val):
     def clean_value(val):
         if isinstance(val, list):
         if isinstance(val, list):
-            val = ' '.join(val)
-        return (val.replace('"', '').replace("\'", "'").strip().strip(';')
-                ).strip().strip('_(').strip().strip(')').strip()
+            val = " ".join(val)
+        return (
+            (val.replace('"', "").replace("'", "'").strip().strip(";"))
+            .strip()
+            .strip("_(")
+            .strip()
+            .strip(")")
+            .strip()
+        )
 
 
     # with open(optionfile, mode='r') as optfile:
     # with open(optionfile, mode='r') as optfile:
     lines = [line.strip() for line in lines]
     lines = [line.strip() for line in lines]
@@ -106,25 +116,31 @@ class OptTable(object):
 
 
     def __init__(self, list_of_dict):
     def __init__(self, list_of_dict):
         self.options = list_of_dict
         self.options = list_of_dict
-        self.columns = sorted(set([key for _, d in self.options
-                                   for key in d.keys()]))
+        self.columns = sorted(set([key for _, d in self.options for key in d.keys()]))
 
 
-    def csv(self, delimiter=';', endline='\n'):
+    def csv(self, delimiter=";", endline="\n"):
         """Return a CSV string with the options"""
         """Return a CSV string with the options"""
         csv = []
         csv = []
         csv.append(delimiter.join(self.columns))
         csv.append(delimiter.join(self.columns))
         for optname, options in self.options:
         for optname, options in self.options:
-            opts = [options.get(col, '') for col in self.columns]
-            csv.append(delimiter.join([optname, ] + opts))
+            opts = [options.get(col, "") for col in self.columns]
+            csv.append(
+                delimiter.join(
+                    [
+                        optname,
+                    ]
+                    + opts
+                )
+            )
         return endline.join(csv)
         return endline.join(csv)
 
 
-    def html(self, endline='\n', indent='  ', toptions='border=1'):
+    def html(self, endline="\n", indent="  ", toptions="border=1"):
         """Return a HTML table with the options"""
         """Return a HTML table with the options"""
-        html = ['<table{0}>'.format(' ' + toptions if toptions else '')]
+        html = ["<table{0}>".format(" " + toptions if toptions else "")]
         # write headers
         # write headers
         html.append(indent + "<thead>")
         html.append(indent + "<thead>")
         html.append(indent + "<tr>")
         html.append(indent + "<tr>")
-        html.append(indent * 2 + "<th>{0}</th>".format('option'))
+        html.append(indent * 2 + "<th>{0}</th>".format("option"))
         for col in self.columns:
         for col in self.columns:
             html.append(indent * 2 + "<th>{0}</th>".format(col))
             html.append(indent * 2 + "<th>{0}</th>".format(col))
         html.append(indent + "</tr>")
         html.append(indent + "</tr>")
@@ -134,8 +150,7 @@ class OptTable(object):
             html.append(indent + "<tr>")
             html.append(indent + "<tr>")
             html.append(indent * 2 + "<td>{0}</td>".format(optname))
             html.append(indent * 2 + "<td>{0}</td>".format(optname))
             for col in self.columns:
             for col in self.columns:
-                html.append(indent * 2 +
-                            "<td>{0}</td>".format(options.get(col, '')))
+                html.append(indent * 2 + "<td>{0}</td>".format(options.get(col, "")))
             html.append(indent + "</tr>")
             html.append(indent + "</tr>")
         html.append(indent + "</tbody>")
         html.append(indent + "</tbody>")
         html.append("</table>")
         html.append("</table>")
@@ -147,43 +162,80 @@ class OptTable(object):
 
 
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
-    URL = ('https://trac.osgeo.org/grass/browser/grass/'
-           'trunk/lib/gis/parser_standard_options.c?format=txt')
-    parser = argparse.ArgumentParser(description='Extract GRASS default '
-                                                 'options from link.')
-    parser.add_argument('-f', '--format', default='html', dest='format',
-                        choices=['html', 'csv', 'grass'],
-                        help='Define the output format')
-    parser.add_argument('-l', '--link', default=URL, dest='url', type=str,
-                        help='Provide the url with the file to parse')
-    parser.add_argument('-t', '--text', dest='text',
-                        type=argparse.FileType('r'),
-                        help='Provide the file to parse')
-    parser.add_argument('-o', '--output', default=sys.stdout, dest='output',
-                        type=argparse.FileType('w'),
-                        help='Provide the url with the file to parse')
-    parser.add_argument('-s', '--starts-with', default='Opt',
-                        dest='startswith', type=str,
-                        help='Extract only the options that starts with this')
-    parser.add_argument('-p', '--html_params', default='border=1', type=str,
-                        dest='htmlparmas', help="Options for the HTML table")
+    URL = (
+        "https://trac.osgeo.org/grass/browser/grass/"
+        "trunk/lib/gis/parser_standard_options.c?format=txt"
+    )
+    parser = argparse.ArgumentParser(
+        description="Extract GRASS default " "options from link."
+    )
+    parser.add_argument(
+        "-f",
+        "--format",
+        default="html",
+        dest="format",
+        choices=["html", "csv", "grass"],
+        help="Define the output format",
+    )
+    parser.add_argument(
+        "-l",
+        "--link",
+        default=URL,
+        dest="url",
+        type=str,
+        help="Provide the url with the file to parse",
+    )
+    parser.add_argument(
+        "-t",
+        "--text",
+        dest="text",
+        type=argparse.FileType("r"),
+        help="Provide the file to parse",
+    )
+    parser.add_argument(
+        "-o",
+        "--output",
+        default=sys.stdout,
+        dest="output",
+        type=argparse.FileType("w"),
+        help="Provide the url with the file to parse",
+    )
+    parser.add_argument(
+        "-s",
+        "--starts-with",
+        default="Opt",
+        dest="startswith",
+        type=str,
+        help="Extract only the options that starts with this",
+    )
+    parser.add_argument(
+        "-p",
+        "--html_params",
+        default="border=1",
+        type=str,
+        dest="htmlparmas",
+        help="Options for the HTML table",
+    )
     args = parser.parse_args()
     args = parser.parse_args()
 
 
     cfile = args.text if args.text else urlopen(args.url, proxies=None)
     cfile = args.text if args.text else urlopen(args.url, proxies=None)
 
 
-    options = OptTable(parse_options(cfile.readlines(),
-                                     startswith=args.startswith))
+    options = OptTable(parse_options(cfile.readlines(), startswith=args.startswith))
     outform = args.format
     outform = args.format
-    if outform in ['csv', 'html']:
+    if outform in ["csv", "html"]:
         print(getattr(options, outform)(), file=args.output)
         print(getattr(options, outform)(), file=args.output)
         args.output.close()
         args.output.close()
     else:
     else:
         year = os.getenv("VERSION_DATE")
         year = os.getenv("VERSION_DATE")
         name = args.output.name
         name = args.output.name
         args.output.close()
         args.output.close()
-        topicsfile = open(name, 'w')
-        topicsfile.write(header1_tmpl.substitute(title="GRASS GIS "
-                        "%s Reference Manual: Parser standard options index" % grass_version))
+        topicsfile = open(name, "w")
+        topicsfile.write(
+            header1_tmpl.substitute(
+                title="GRASS GIS "
+                "%s Reference Manual: Parser standard options index" % grass_version
+            )
+        )
         topicsfile.write(headerpso_tmpl)
         topicsfile.write(headerpso_tmpl)
         topicsfile.write(options.html(toptions=args.htmlparmas))
         topicsfile.write(options.html(toptions=args.htmlparmas))
         write_html_footer(topicsfile, "index.html", year)
         write_html_footer(topicsfile, "index.html", year)

+ 88 - 74
man/sphinx/conf.py

@@ -17,155 +17,155 @@ import os
 # If extensions (or modules to document with autodoc) are in another directory,
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath('.'))
 
 
 # -- General configuration -----------------------------------------------------
 # -- General configuration -----------------------------------------------------
 
 
 # If your documentation needs a minimal Sphinx version, state it here.
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.todo', 'sphinx.ext.pngmath']
+extensions = ["sphinx.ext.todo", "sphinx.ext.pngmath"]
 
 
 # Add any paths that contain templates here, relative to this directory.
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 
 # The suffix of source filenames.
 # The suffix of source filenames.
-source_suffix = '.txt'
+source_suffix = ".txt"
 
 
 # The encoding of source files.
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 
 # The master toctree document.
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 
 # General information about the project.
 # General information about the project.
-project = u'GRASS 7.9 Documentation'
-copyright = u'2019, GRASS Development Team'
+project = u"GRASS 7.9 Documentation"
+copyright = u"2019, GRASS Development Team"
 
 
 # The version info for the project you're documenting, acts as replacement for
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 # built documents.
 #
 #
 # The short X.Y version.
 # The short X.Y version.
-version = '7.9'
+version = "7.9"
 # The full version, including alpha/beta/rc tags.
 # The full version, including alpha/beta/rc tags.
-release = 'dev'
+release = "dev"
 
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
 # for a list of supported languages.
-#language = None
+# language = None
 
 
 # There are two options for replacing |today|: either, you set today to some
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 
 # List of patterns, relative to source directory, that match files and
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
 
 
 # The reST default role (used for this markup: `text`) to use for all documents.
 # The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
+# default_role = None
 
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 
 # If true, the current module name will be prepended to all description
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 
 # The name of the Pygments (syntax highlighting) style to use.
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 
 # A list of ignored prefixes for module index sorting.
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 
 
 
 # -- Options for HTML output ---------------------------------------------------
 # -- Options for HTML output ---------------------------------------------------
 
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
 # a list of builtin themes.
-html_theme = 'default'
+html_theme = "default"
 
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # further.  For a list of options available for each theme, see the
 # documentation.
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 
 # Add any paths that contain custom themes here, relative to this directory.
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 
 # The name of an image file (relative to this directory) to place at the top
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 
 # The name of an image file (within the static path) to use as favicon of the
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
 
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 
 # Custom sidebar templates, maps document names to template names.
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
 
 
 # Additional templates that should be rendered to pages, maps page names to
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 
 # If false, no module index is generated.
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 
 # If false, no index is generated.
 # If false, no index is generated.
 html_use_index = False
 html_use_index = False
 
 
 # If true, the index is split into individual pages for each letter.
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 
 # If true, links to the reST sources are added to the pages.
 # If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
 
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 
 # If true, an OpenSearch description file will be output, and all pages will
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 
 # Output file base name for HTML help builder.
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'grass79Documentationdoc'
+htmlhelp_basename = "grass79Documentationdoc"
 
 
 
 
 # -- Options for LaTeX output --------------------------------------------------
 # -- Options for LaTeX output --------------------------------------------------
@@ -173,10 +173,8 @@ htmlhelp_basename = 'grass79Documentationdoc'
 latex_elements = {
 latex_elements = {
     # The paper size ('letterpaper' or 'a4paper').
     # The paper size ('letterpaper' or 'a4paper').
     #'papersize': 'letterpaper',
     #'papersize': 'letterpaper',
-
     # The font size ('10pt', '11pt' or '12pt').
     # The font size ('10pt', '11pt' or '12pt').
     #'pointsize': '10pt',
     #'pointsize': '10pt',
-
     # Additional stuff for the LaTeX preamble.
     # Additional stuff for the LaTeX preamble.
     #'preamble': '',
     #'preamble': '',
 }
 }
@@ -184,29 +182,34 @@ latex_elements = {
 # Grouping the document tree into LaTeX files. List of tuples
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
 latex_documents = [
-  ('content', 'grass79Documentation.tex', u'GRASS 7.9 Documentation',
-   u'GRASS Development Team', 'manual'),
+    (
+        "content",
+        "grass79Documentation.tex",
+        u"GRASS 7.9 Documentation",
+        u"GRASS Development Team",
+        "manual",
+    ),
 ]
 ]
 
 
 # The name of an image file (relative to this directory) to place at the top of
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 
 # If true, show page references after internal links.
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 
 # If true, show URL addresses after external links.
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 
 # Documents to append as an appendix to all manuals.
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 
 # If false, no module index is generated.
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 
 
 # -- Options for manual page output --------------------------------------------
 # -- Options for manual page output --------------------------------------------
@@ -214,12 +217,17 @@ latex_documents = [
 # One entry per manual page. List of tuples
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 # (source start file, name, description, authors, manual section).
 man_pages = [
 man_pages = [
-    ('content', 'grass79documentation', u'GRASS 7.9 Documentation',
-     [u'GRASS Development Team'], 1)
+    (
+        "content",
+        "grass79documentation",
+        u"GRASS 7.9 Documentation",
+        [u"GRASS Development Team"],
+        1,
+    )
 ]
 ]
 
 
 # If true, show URL addresses after external links.
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 
 
 # -- Options for Texinfo output ------------------------------------------------
 # -- Options for Texinfo output ------------------------------------------------
@@ -228,59 +236,65 @@ man_pages = [
 # (source start file, target name, title, author,
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 #  dir menu entry, description, category)
 texinfo_documents = [
 texinfo_documents = [
-  ('content', 'grass79Documentation', u'GRASS 7.9 Documentation',
-   u'GRASS Development Team', 'grass79Documentation', 'One line description of project.',
-   'Miscellaneous'),
+    (
+        "content",
+        "grass79Documentation",
+        u"GRASS 7.9 Documentation",
+        u"GRASS Development Team",
+        "grass79Documentation",
+        "One line description of project.",
+        "Miscellaneous",
+    ),
 ]
 ]
 
 
 # Documents to append as an appendix to all manuals.
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 
 # If false, no module index is generated.
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
 
 
 
 
 # -- Options for Epub output ---------------------------------------------------
 # -- Options for Epub output ---------------------------------------------------
 
 
 # Bibliographic Dublin Core info.
 # Bibliographic Dublin Core info.
-epub_title = u'GRASS 7.9 Documentation'
-epub_author = u'GRASS Development Team'
-epub_publisher = u'GRASS Development Team'
-epub_copyright = u'2017, GRASS Development Team'
+epub_title = u"GRASS 7.9 Documentation"
+epub_author = u"GRASS Development Team"
+epub_publisher = u"GRASS Development Team"
+epub_copyright = u"2017, GRASS Development Team"
 
 
 # The language of the text. It defaults to the language option
 # The language of the text. It defaults to the language option
 # or en if the language is not set.
 # or en if the language is not set.
-#epub_language = ''
+# epub_language = ''
 
 
 # The scheme of the identifier. Typical schemes are ISBN or URL.
 # The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
+# epub_scheme = ''
 
 
 # The unique identifier of the text. This can be a ISBN number
 # The unique identifier of the text. This can be a ISBN number
 # or the project homepage.
 # or the project homepage.
-#epub_identifier = ''
+# epub_identifier = ''
 
 
 # A unique identification for the text.
 # A unique identification for the text.
-#epub_uid = ''
+# epub_uid = ''
 
 
 # A tuple containing the cover image and cover page html template filenames.
 # A tuple containing the cover image and cover page html template filenames.
-#epub_cover = ()
+# epub_cover = ()
 
 
 # HTML files that should be inserted before the pages created by sphinx.
 # HTML files that should be inserted before the pages created by sphinx.
 # The format is a list of tuples containing the path and title.
 # The format is a list of tuples containing the path and title.
-#epub_pre_files = []
+# epub_pre_files = []
 
 
 # HTML files shat should be inserted after the pages created by sphinx.
 # HTML files shat should be inserted after the pages created by sphinx.
 # The format is a list of tuples containing the path and title.
 # The format is a list of tuples containing the path and title.
-#epub_post_files = []
+# epub_post_files = []
 
 
 # A list of files that should not be packed into the epub file.
 # A list of files that should not be packed into the epub file.
-#epub_exclude_files = []
+# epub_exclude_files = []
 
 
 # The depth of the table of contents in toc.ncx.
 # The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
+# epub_tocdepth = 3
 
 
 # Allow duplicate toc entries.
 # Allow duplicate toc entries.
-#epub_tocdup = True
+# epub_tocdup = True