@@ -60,11 +60,17 @@ def Merge(self, block, namespace=None):
60
60
# Overwrite existing section if it's a default.
61
61
if block_id not in self .sections or self .sections [block_id ].IsDefault ():
62
62
self .sections [block_id ] = block
63
+ elif not block .IsDefault ():
64
+ # Tried to overwrite explicit section with explicit section.
65
+ raise error .DuplicateSection (block_id )
63
66
elif typ == vimdoc .BACKMATTER :
64
67
# Overwrite existing section backmatter if it's a default.
65
68
if (block_id not in self .backmatters
66
69
or self .backmatters [block_id ].IsDefault ()):
67
70
self .backmatters [block_id ] = block
71
+ elif not block .IsDefault ():
72
+ # Tried to overwrite explicit backmatter with explicit backmatter.
73
+ raise error .DuplicateBackmatter (block_id )
68
74
else :
69
75
collection_type = self .plugin .GetCollectionType (block )
70
76
if collection_type is not None :
@@ -107,31 +113,26 @@ def Close(self):
107
113
All default sections that have not been overridden will be created.
108
114
"""
109
115
if self .GetCollection (vimdoc .FUNCTION ) and 'functions' not in self .sections :
110
- functions = Block ()
111
- functions .SetType (vimdoc .SECTION )
116
+ functions = Block (vimdoc .SECTION )
112
117
functions .Local (id = 'functions' , name = 'Functions' )
113
118
self .Merge (functions )
114
119
if (self .GetCollection (vimdoc .EXCEPTION )
115
120
and 'exceptions' not in self .sections ):
116
- exceptions = Block ()
117
- exceptions .SetType (vimdoc .SECTION )
121
+ exceptions = Block (vimdoc .SECTION )
118
122
exceptions .Local (id = 'exceptions' , name = 'Exceptions' )
119
123
self .Merge (exceptions )
120
124
if self .GetCollection (vimdoc .COMMAND ) and 'commands' not in self .sections :
121
- commands = Block ()
122
- commands .SetType (vimdoc .SECTION )
125
+ commands = Block (vimdoc .SECTION )
123
126
commands .Local (id = 'commands' , name = 'Commands' )
124
127
self .Merge (commands )
125
128
if self .GetCollection (vimdoc .DICTIONARY ) and 'dicts' not in self .sections :
126
- dicts = Block ()
127
- dicts .SetType (vimdoc .SECTION )
129
+ dicts = Block (vimdoc .SECTION )
128
130
dicts .Local (id = 'dicts' , name = 'Dictionaries' )
129
131
self .Merge (dicts )
130
132
if self .GetCollection (vimdoc .FLAG ):
131
133
# If any maktaba flags were documented, add a default configuration
132
134
# section to explain how to use them.
133
- config = Block (is_default = True )
134
- config .SetType (vimdoc .SECTION )
135
+ config = Block (vimdoc .SECTION , is_default = True )
135
136
config .Local (id = 'config' , name = 'Configuration' )
136
137
config .AddLine (
137
138
'This plugin uses maktaba flags for configuration. Install Glaive'
@@ -141,29 +142,18 @@ def Close(self):
141
142
if ((self .GetCollection (vimdoc .FLAG ) or
142
143
self .GetCollection (vimdoc .SETTING )) and
143
144
'config' not in self .sections ):
144
- config = Block ()
145
- config .SetType (vimdoc .SECTION )
145
+ config = Block (vimdoc .SECTION )
146
146
config .Local (id = 'config' , name = 'Configuration' )
147
147
self .Merge (config )
148
- if not self .order :
149
- self .order = []
150
- for builtin in [
151
- 'intro' ,
152
- 'config' ,
153
- 'commands' ,
154
- 'autocmds' ,
155
- 'settings' ,
156
- 'dicts' ,
157
- 'functions' ,
158
- 'exceptions' ,
159
- 'mappings' ,
160
- 'about' ]:
161
- if builtin in self .sections or builtin in self .backmatters :
162
- self .order .append (builtin )
148
+
163
149
for backmatter in self .backmatters :
164
150
if backmatter not in self .sections :
165
151
raise error .NoSuchSection (backmatter )
166
- known = set (self .sections ) | set (self .backmatters )
152
+ # Use explicit order as partial ordering and merge with default section
153
+ # ordering. All custom sections must be ordered explicitly.
154
+ self .order = self ._GetSectionOrder (self .order , self .sections )
155
+
156
+ known = set (self .sections )
167
157
neglected = sorted (known .difference (self .order ))
168
158
if neglected :
169
159
raise error .NeglectedSections (neglected , self .order )
@@ -200,6 +190,46 @@ def Chunks(self):
200
190
if ident in self .backmatters :
201
191
yield self .backmatters [ident ]
202
192
193
+ @staticmethod
194
+ def _GetSectionOrder (explicit_order , sections ):
195
+ """Gets final section order from explicit_order and actual sections present.
196
+
197
+ Built-in sections with no explicit order come before custom sections, with
198
+ two exceptions:
199
+ * The "about" section comes last by default.
200
+ * If a built-in section is explicitly ordered, it "resets" the ordering so
201
+ so that subsequent built-in sections come directly after it.
202
+ This yields the order you would intuitively expect in cases like ordering
203
+ "intro" after other sections.
204
+ """
205
+ order = explicit_order or []
206
+ default_order = [
207
+ 'intro' ,
208
+ 'config' ,
209
+ 'commands' ,
210
+ 'autocmds' ,
211
+ 'settings' ,
212
+ 'dicts' ,
213
+ 'functions' ,
214
+ 'exceptions' ,
215
+ 'mappings' ]
216
+ # Add any undeclared sections before custom sections, except 'about' which
217
+ # comes at the end by default.
218
+ section_insertion_idx = 0
219
+ order = order [:]
220
+ for builtin in default_order :
221
+ if builtin in order :
222
+ # Section already present. Skip and continue later sections after it.
223
+ section_insertion_idx = order .index (builtin ) + 1
224
+ continue
225
+ else :
226
+ # If section present, insert into order at logical index.
227
+ if builtin in sections :
228
+ order .insert (section_insertion_idx , builtin )
229
+ section_insertion_idx += 1
230
+ if 'about' in sections and 'about' not in order :
231
+ order .append ('about' )
232
+ return order
203
233
204
234
class VimPlugin (object ):
205
235
"""State for entire plugin (potentially multiple modules)."""
@@ -249,8 +279,7 @@ def LookupTag(self, typ, name):
249
279
block = candidates [0 ]
250
280
if block is None :
251
281
# Create a dummy block to get default tag.
252
- block = Block ()
253
- block .SetType (typ )
282
+ block = Block (typ )
254
283
block .Local (name = fullname )
255
284
return block .TagName ()
256
285
@@ -353,8 +382,7 @@ def Modules(directory):
353
382
flagpath = relative_path
354
383
if flagpath .startswith ('after' + os .path .sep ):
355
384
flagpath = os .path .relpath (flagpath , 'after' )
356
- flagblock = Block (is_default = True )
357
- flagblock .SetType (vimdoc .FLAG )
385
+ flagblock = Block (vimdoc .FLAG , is_default = True )
358
386
name_parts = os .path .splitext (flagpath )[0 ].split (os .path .sep )
359
387
flagname = name_parts .pop (0 )
360
388
flagname += '' .join ('[' + p + ']' for p in name_parts )
0 commit comments