summaryrefslogtreecommitdiff
path: root/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/Sphinx/cmake.py129
1 files changed, 87 insertions, 42 deletions
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index a98898060d..2ccaf9a7fe 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -1,89 +1,123 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+# BEGIN imports
+
import os
import re
from dataclasses import dataclass
from typing import Any, List, Tuple, Type, cast
+import sphinx
+
+from docutils.utils.code_analyzer import Lexer, LexerError
+from docutils.parsers.rst import Directive, directives
+from docutils.transforms import Transform
+from docutils.nodes import Element, Node, TextElement, system_message
+from docutils import io, nodes
+
+from sphinx.directives import ObjectDescription, nl_escape_re
+from sphinx.domains import Domain, ObjType
+from sphinx.roles import XRefRole
+from sphinx.util.docutils import ReferenceRole
+from sphinx.util.nodes import make_refnode
+from sphinx.util import logging, ws_re
+from sphinx import addnodes
+
+# END imports
+
+# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+# BEGIN pygments tweaks
+
# Override much of pygments' CMakeLexer.
# We need to parse CMake syntax definitions, not CMake code.
# For hard test cases that use much of the syntax below, see
-# - module/FindPkgConfig.html (with "glib-2.0>=2.10 gtk+-2.0" and similar)
-# - module/ExternalProject.html (with http:// https:// git@; also has command options -E --build)
-# - manual/cmake-buildsystem.7.html (with nested $<..>; relative and absolute paths, "::")
+# - module/FindPkgConfig.html
+# (with "glib-2.0>=2.10 gtk+-2.0" and similar)
+# - module/ExternalProject.html
+# (with http:// https:// git@; also has command options -E --build)
+# - manual/cmake-buildsystem.7.html
+# (with nested $<..>; relative and absolute paths, "::")
from pygments.lexers import CMakeLexer
-from pygments.token import Name, Operator, Punctuation, String, Text, Comment, Generic, Whitespace, Number
+from pygments.token import (Comment, Name, Number, Operator, Punctuation,
+ String, Text, Whitespace)
from pygments.lexer import bygroups
-# RE to split multiple command signatures
-sig_end_re = re.compile(r'(?<=[)])\n')
-
# Notes on regular expressions below:
# - [\.\+-] are needed for string constants like gtk+-2.0
-# - Unix paths are recognized by '/'; support for Windows paths may be added if needed
+# - Unix paths are recognized by '/'; support for Windows paths may be added
+# if needed
# - (\\.) allows for \-escapes (used in manual/cmake-language.7)
# - $<..$<..$>..> nested occurrence in cmake-buildsystem
-# - Nested variable evaluations are only supported in a limited capacity. Only
-# one level of nesting is supported and at most one nested variable can be present.
+# - Nested variable evaluations are only supported in a limited capacity.
+# Only one level of nesting is supported and at most one nested variable can
+# be present.
CMakeLexer.tokens["root"] = [
- (r'\b(\w+)([ \t]*)(\()', bygroups(Name.Function, Text, Name.Function), '#push'), # fctn(
+ # fctn(
+ (r'\b(\w+)([ \t]*)(\()',
+ bygroups(Name.Function, Text, Name.Function), '#push'),
(r'\(', Name.Function, '#push'),
(r'\)', Name.Function, '#pop'),
(r'\[', Punctuation, '#push'),
(r'\]', Punctuation, '#pop'),
(r'[|;,.=*\-]', Punctuation),
- (r'\\\\', Punctuation), # used in commands/source_group
+ # used in commands/source_group
+ (r'\\\\', Punctuation),
(r'[:]', Operator),
- (r'[<>]=', Punctuation), # used in FindPkgConfig.cmake
- (r'\$<', Operator, '#push'), # $<...>
- (r'<[^<|]+?>(\w*\.\.\.)?', Name.Variable), # <expr>
- (r'(\$\w*\{)([^\}\$]*)?(?:(\$\w*\{)([^\}]+?)(\}))?([^\}]*?)(\})', # ${..} $ENV{..}, possibly nested
- bygroups(Operator, Name.Tag, Operator, Name.Tag, Operator, Name.Tag, Operator)),
- (r'([A-Z]+\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)), # DATA{ ...}
- (r'[a-z]+(@|(://))((\\.)|[\w.+-:/\\])+', Name.Attribute), # URL, git@, ...
- (r'/\w[\w\.\+-/\\]*', Name.Attribute), # absolute path
+ # used in FindPkgConfig.cmake
+ (r'[<>]=', Punctuation),
+ # $<...>
+ (r'\$<', Operator, '#push'),
+ # <expr>
+ (r'<[^<|]+?>(\w*\.\.\.)?', Name.Variable),
+ # ${..} $ENV{..}, possibly nested
+ (r'(\$\w*\{)([^\}\$]*)?(?:(\$\w*\{)([^\}]+?)(\}))?([^\}]*?)(\})',
+ bygroups(Operator, Name.Tag, Operator, Name.Tag, Operator, Name.Tag,
+ Operator)),
+ # DATA{ ...}
+ (r'([A-Z]+\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)),
+ # URL, git@, ...
+ (r'[a-z]+(@|(://))((\\.)|[\w.+-:/\\])+', Name.Attribute),
+ # absolute path
+ (r'/\w[\w\.\+-/\\]*', Name.Attribute),
(r'/', Name.Attribute),
- (r'\w[\w\.\+-]*/[\w.+-/\\]*', Name.Attribute), # relative path
- (r'[A-Z]((\\.)|[\w.+-])*[a-z]((\\.)|[\w.+-])*', Name.Builtin), # initial A-Z, contains a-z
+ # relative path
+ (r'\w[\w\.\+-]*/[\w.+-/\\]*', Name.Attribute),
+ # initial A-Z, contains a-z
+ (r'[A-Z]((\\.)|[\w.+-])*[a-z]((\\.)|[\w.+-])*', Name.Builtin),
(r'@?[A-Z][A-Z0-9_]*', Name.Constant),
(r'[a-z_]((\\;)|(\\ )|[\w.+-])*', Name.Builtin),
(r'[0-9][0-9\.]*', Number),
- (r'(?s)"(\\"|[^"])*"', String), # "string"
+ # "string"
+ (r'(?s)"(\\"|[^"])*"', String),
(r'\.\.\.', Name.Variable),
- (r'<', Operator, '#push'), # <..|..> is different from <expr>
+ # <..|..> is different from <expr>
+ (r'<', Operator, '#push'),
(r'>', Operator, '#pop'),
(r'\n', Whitespace),
(r'[ \t]+', Whitespace),
(r'#.*\n', Comment),
- # (r'[^<>\])\}\|$"# \t\n]+', Name.Exception), # fallback, for debugging only
+ # fallback, for debugging only
+ # (r'[^<>\])\}\|$"# \t\n]+', Name.Exception),
]
-from docutils.utils.code_analyzer import Lexer, LexerError
-from docutils.parsers.rst import Directive, directives
-from docutils.transforms import Transform
-from docutils.nodes import Element, Node, TextElement, system_message
-from docutils import io, nodes
-
-from sphinx.directives import ObjectDescription, nl_escape_re
-from sphinx.domains import Domain, ObjType
-from sphinx.roles import XRefRole
-from sphinx.util.docutils import ReferenceRole
-from sphinx.util.nodes import make_refnode
-from sphinx.util import logging, ws_re
-from sphinx import addnodes
+# END pygments tweaks
-import sphinx
+# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Require at least Sphinx 2.x.
assert sphinx.version_info >= (2,)
logger = logging.getLogger(__name__)
+# RE to split multiple command signatures.
+sig_end_re = re.compile(r'(?<=[)])\n')
+
@dataclass
class ObjectEntry:
@@ -162,13 +196,15 @@ class CMakeModule(Directive):
self.state_machine.insert_input(lines, path)
return []
+
class _cmake_index_entry:
def __init__(self, desc):
self.desc = desc
- def __call__(self, title, targetid, main = 'main'):
+ def __call__(self, title, targetid, main='main'):
return ('pair', f'{self.desc} ; {title}', targetid, main, None)
+
_cmake_index_objs = {
'command': _cmake_index_entry('command'),
'cpack_gen': _cmake_index_entry('cpack generator'),
@@ -189,6 +225,7 @@ _cmake_index_objs = {
'variable': _cmake_index_entry('variable'),
}
+
class CMakeTransform(Transform):
# Run this transform early since we insert nodes we want
@@ -215,7 +252,8 @@ class CMakeTransform(Transform):
title = False
else:
for line in f:
- if len(line) > 0 and (line[0].isalnum() or line[0] == '<' or line[0] == '$'):
+ if len(line) > 0 and (line[0].isalnum() or
+ line[0] == '<' or line[0] == '$'):
title = line.rstrip()
break
f.close()
@@ -256,6 +294,7 @@ class CMakeTransform(Transform):
domain = cast(CMakeDomain, env.get_domain('cmake'))
domain.note_object(objtype, targetname, targetid, targetid)
+
class CMakeObject(ObjectDescription):
def __init__(self, *args, **kwargs):
self.targetname = None
@@ -453,6 +492,7 @@ class CMakeSignatureObject(CMakeObject):
return super().run()
+
class CMakeReferenceRole:
# See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
_re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
@@ -478,6 +518,7 @@ class CMakeReferenceRole:
return super().__call__(name, rawtext, text, *args, **kwargs)
return Class
+
class CMakeCRefRole(CMakeReferenceRole[ReferenceRole]):
nodeclass: Type[Element] = nodes.reference
innernodeclass: Type[TextElement] = nodes.literal
@@ -493,6 +534,7 @@ class CMakeCRefRole(CMakeReferenceRole[ReferenceRole]):
return [refnode], []
+
class CMakeXRefRole(CMakeReferenceRole[XRefRole]):
_re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL)
@@ -530,6 +572,7 @@ class CMakeXRefRole(CMakeReferenceRole[XRefRole]):
# def result_nodes(self, document, env, node, is_ref):
# pass
+
class CMakeXRefTransform(Transform):
# Run this transform early since we insert nodes we want
@@ -570,6 +613,7 @@ class CMakeXRefTransform(Transform):
indexnode['entries'] = [make_index_entry(objname, targetid, '')]
ref.replace_self([indexnode, targetnode, ref])
+
class CMakeDomain(Domain):
"""CMake domain."""
name = 'cmake'
@@ -603,7 +647,7 @@ class CMakeDomain(Domain):
}
roles = {
'cref': CMakeCRefRole(),
- 'command': CMakeXRefRole(fix_parens = True, lowercase = True),
+ 'command': CMakeXRefRole(fix_parens=True, lowercase=True),
'cpack_gen': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
@@ -668,6 +712,7 @@ class CMakeDomain(Domain):
for refname, obj in self.data['objects'].items():
yield (refname, obj.name, obj.objtype, obj.docname, obj.node_id, 1)
+
def setup(app):
app.add_directive('cmake-module', CMakeModule)
app.add_transform(CMakeTransform)