2020
2121from sphinx .domains .python import PythonDomain
2222
23+ from pygments .lexer import RegexLexer , default
24+ from pygments .token import *
25+
26+
2327# -- Spack customizations -----------------------------------------------------
2428# Add the Spack bin directory to the path so that we can use its output in docs.
2529os .environ ["SPACK_ROOT" ] = os .path .abspath ("_spack_root" )
2933os .environ ["COLIFY_SIZE" ] = "25x120"
3034os .environ ["COLUMNS" ] = "120"
3135
36+ sys .path .insert (0 , os .path .abspath ("_spack_root/lib/spack/" ))
37+
3238# Enable todo items
3339todo_include_todos = True
3440
41+ from spack .spec_parser import SpecTokens
42+
43+
44+ class SpecLexer (RegexLexer ):
45+ """A custom lexer for Spack spec strings and spack commands."""
46+
47+ name = "Spack spec"
48+ aliases = ["spec" ]
49+ filenames = []
50+ tokens = {
51+ "root" : [
52+ # Looks for `$ command`, which may need spec highlighting.
53+ (r"^\$\s+" , Generic .Prompt , "command" ),
54+ (r"#.*?\n" , Comment .Single ),
55+ # Alternatively, we just get a literal spec string, so we move to spec mode. We just
56+ # look ahead here, without consuming the spec string.
57+ (r"(?=\S+)" , Generic .Prompt , "spec" ),
58+ ],
59+ "command" : [
60+ # A spack install command is followed by a spec string, which we highlight.
61+ (
62+ r"spack(?:\s+(?:-[eC]\s+\S+|--?\S+))*\s+(?:install|uninstall|spec|load|unload|find|info|list|versions|providers|mark|diff|add|develop)(?: +(?:--?\S+)?)*" ,
63+ Text ,
64+ "spec" ,
65+ ),
66+ # Comment
67+ (r"\s+#.*?\n" , Comment .Single , "command_output" ),
68+ # Escaped newline should leave us in this mode
69+ (r".*?\\\n" , Text ),
70+ # Otherwise, it's the end of the command
71+ (r".*?\n" , Text , "command_output" ),
72+ ],
73+ "command_output" : [
74+ (r"^\$\s+" , Generic .Prompt , "#pop" ), # new command
75+ (r"#.*?\n" , Comment .Single ), # comments
76+ (r".*?\n" , Generic .Output ), # command output
77+ ],
78+ "spec" : [
79+ # New line terminates the spec string
80+ (r"\s*?$" , Text , "#pop" ),
81+ # Dependency, with optional virtual assignment specifier
82+ (SpecTokens .START_EDGE_PROPERTIES .regex , Name .Variable , "edge_properties" ),
83+ (SpecTokens .DEPENDENCY .regex , Name .Variable ),
84+ # versions
85+ (SpecTokens .VERSION_HASH_PAIR .regex , Keyword .Pseudo ),
86+ (SpecTokens .GIT_VERSION .regex , Keyword .Pseudo ),
87+ (SpecTokens .VERSION .regex , Keyword .Pseudo ),
88+ # variants
89+ (SpecTokens .PROPAGATED_BOOL_VARIANT .regex , Name .Function ),
90+ (SpecTokens .BOOL_VARIANT .regex , Name .Function ),
91+ (SpecTokens .PROPAGATED_KEY_VALUE_PAIR .regex , Name .Function ),
92+ (SpecTokens .KEY_VALUE_PAIR .regex , Name .Function ),
93+ # filename
94+ (SpecTokens .FILENAME .regex , Text ),
95+ # Package name
96+ (SpecTokens .FULLY_QUALIFIED_PACKAGE_NAME .regex , Name .Class ),
97+ (SpecTokens .UNQUALIFIED_PACKAGE_NAME .regex , Name .Class ),
98+ # DAG hash
99+ (SpecTokens .DAG_HASH .regex , Text ),
100+ (SpecTokens .WS .regex , Text ),
101+ # Also stop at unrecognized tokens (without consuming them)
102+ default ("#pop" ),
103+ ],
104+ "edge_properties" : [
105+ (SpecTokens .KEY_VALUE_PAIR .regex , Name .Function ),
106+ (SpecTokens .END_EDGE_PROPERTIES .regex , Name .Variable , "#pop" ),
107+ ],
108+ }
109+
35110
36111#
37112# Disable duplicate cross-reference warnings.
@@ -47,6 +122,7 @@ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
47122
48123def setup (sphinx ):
49124 sphinx .add_domain (PatchedPythonDomain , override = True )
125+ sphinx .add_lexer ("spec" , SpecLexer )
50126
51127
52128# -- General configuration -----------------------------------------------------
@@ -143,6 +219,8 @@ def setup(sphinx):
143219# The theme to use for HTML and HTML Help pages. See the documentation for
144220# a list of builtin themes.
145221html_theme = "furo"
222+ pygments_style = "default"
223+ pygments_dark_style = "monokai"
146224
147225# Add any paths that contain custom themes here, relative to this directory.
148226# html_theme_path = ["_themes"]
0 commit comments