1414if sphinx .version_info >= (2 ,):
1515 from docutils import io , nodes
1616 from docutils .nodes import Element , Node , TextElement , system_message
17- from docutils .parsers .rst import Directive , directives
17+ from docutils .parsers .rst import directives
1818 from docutils .transforms import Transform
1919 from docutils .utils .code_analyzer import Lexer , LexerError
2020
2121 from sphinx import addnodes
22- from sphinx .directives import ObjectDescription , nl_escape_re
22+ from sphinx .directives import SphinxDirective , ObjectDescription , nl_escape_re
2323 from sphinx .domains import Domain , ObjType
2424 from sphinx .roles import XRefRole
2525 from sphinx .util import logging , ws_re
2626 from sphinx .util .docutils import ReferenceRole
27- from sphinx .util .nodes import make_refnode
27+ from sphinx .util .nodes import make_refnode , nested_parse_with_titles
2828else :
2929 # Sphinx 2.x is required.
3030 assert sphinx .version_info >= (2 ,)
@@ -128,15 +128,16 @@ class ObjectEntry:
128128 name : str
129129
130130
131- class CMakeModule (Directive ):
131+ class CMakeModule (SphinxDirective ):
132132 required_arguments = 1
133133 optional_arguments = 0
134134 final_argument_whitespace = True
135135 option_spec = {'encoding' : directives .encoding }
136136
137137 def __init__ (self , * args , ** keys ):
138- self .re_start = re .compile (r'^#\[(?P<eq>=*)\[\.rst:$' )
139- Directive .__init__ (self , * args , ** keys )
138+ self .re_block_start = re .compile (r'^(?P<prefix>\s*)#\[(?P<eq>=*)\[\.(?:rst|md):$' )
139+ self .re_single = re .compile (r'^(?P<prefix>\s*)#\.(?:rst|md):$' )
140+ super ().__init__ (* args , ** keys )
140141
141142 def run (self ):
142143 settings = self .state .document .settings
@@ -161,41 +162,61 @@ def run(self):
161162 raise self .severe (msg )
162163 raw_lines = f .read ().splitlines ()
163164 f .close ()
164- rst = None
165165 lines = []
166- for line in raw_lines :
167- if rst is not None and rst != '#' :
168- # Bracket mode: check for end bracket
169- pos = line .find (rst )
170- if pos >= 0 :
171- if line [0 ] == '#' :
172- line = ''
173- else :
174- line = line [0 :pos ]
175- rst = None
176- else :
177- # Line mode: check for .rst start (bracket or line)
178- m = self .re_start .match (line )
179- if m :
180- rst = f']{ m .group ("eq" )} ]'
181- line = ''
182- elif line == '#.rst:' :
183- rst = '#'
184- line = ''
185- elif rst == '#' :
186- if line == '#' or line [:2 ] == '# ' :
187- line = line [2 :]
188- else :
189- rst = None
190- line = ''
191- elif rst is None :
192- line = ''
193- lines .append (line )
194- if rst is not None and rst != '#' :
195- raise self .warning (f'{ self .name !r} found unclosed bracket '
196- f'"#[{ rst [1 :- 1 ]} [.rst:" in { path !r} ' )
197- self .state_machine .insert_input (lines , path )
198- return []
166+ block_end = ""
167+ prefix = ""
168+ block_start = - 1
169+ # TODO: Parse nested comments as belonging to specific directive
170+ # Similar to python's documentaiton
171+ for indx , line in enumerate (raw_lines ):
172+ # Check if in block comment mode
173+ if block_end :
174+ # Check for block_end
175+ if line .startswith (block_end ):
176+ # Exit block mode
177+ block_end = ""
178+ prefix = ""
179+ continue
180+ # Check if line is only whitespace, then add an empty line
181+ if not line or line .isspace ():
182+ lines .append ("" )
183+ continue
184+ # Otherwise remove prefix and add the lines
185+ if not line .startswith (prefix ):
186+ raise self .warning (f"{ self .name } found ill-formatted block line in { path } :\n line#{ indx } : { line } " )
187+ lines .append (line .lstrip (prefix ))
188+ continue
189+ # Check if in line comment mode
190+ if prefix :
191+ if line .startswith (prefix ):
192+ # Current line is still part of the comment
193+ lines .append (line .lstrip (prefix ))
194+ continue
195+ # Otherwise we are exiting line-mode
196+ prefix = ""
197+ continue
198+ # Otherwise we are not in comment mode
199+ # Check if we can enter a comment mode
200+ # First check for block-mode
201+ block_mode = self .re_block_start .match (line )
202+ if block_mode :
203+ block_start = indx
204+ prefix = block_mode .group ('prefix' )
205+ block_end = f"{ prefix } ]{ block_mode .group ('eq' )} ]"
206+ continue
207+ # Next check for line-mode
208+ line_mode = self .re_single .match (line )
209+ if line_mode :
210+ prefix = line_mode .group ('prefix' )
211+ continue
212+ # Sanitize exit
213+ if block_end :
214+ raise self .warning (f"{ self .name } found unclosed bracket in { path } :\n "
215+ f"bracket start at:{ block_start } ;bracket end:\" { block_end } \" " )
216+ node = nodes .Element ()
217+ node .document = self .state .document
218+ self .state .nested_parse (lines , self .content_offset , node , match_titles = True )
219+ return node .children
199220
200221
201222class _cmake_index_entry :
0 commit comments