Skip to content

Commit cc6dd0e

Browse files
committed
More intuitive default ordering so later built-ins follow earlier
1 parent 69ef283 commit cc6dd0e

File tree

2 files changed

+112
-29
lines changed

2 files changed

+112
-29
lines changed

tests/module_tests.py

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
from vimdoc import error
66
from vimdoc import module
77

8-
class TestVimPlugin(unittest.TestCase):
8+
class TestVimModule(unittest.TestCase):
99

1010
def test_section(self):
1111
plugin = module.VimPlugin('myplugin')
1212
main_module = module.Module('myplugin', plugin)
1313
intro = Block(vimdoc.SECTION)
1414
intro.Local(name='Introduction', id='intro')
1515
main_module.Merge(intro)
16-
self.assertEquals(list(main_module.Chunks()), [intro])
16+
main_module.Close()
17+
self.assertEqual([intro], list(main_module.Chunks()))
1718

1819
def test_duplicate_section(self):
1920
plugin = module.VimPlugin('myplugin')
@@ -25,4 +26,67 @@ def test_duplicate_section(self):
2526
intro2.Local(name='Intro', id='intro')
2627
with self.assertRaises(error.DuplicateSection) as cm:
2728
main_module.Merge(intro2)
28-
self.assertEquals(cm.exception.args, ('Duplicate section intro defined.',))
29+
self.assertEqual(('Duplicate section intro defined.',), cm.exception.args)
30+
31+
def test_default_section_ordering(self):
32+
"""Sections should be ordered according to documented built-in ordering."""
33+
plugin = module.VimPlugin('myplugin')
34+
main_module = module.Module('myplugin', plugin)
35+
intro = Block(vimdoc.SECTION)
36+
intro.Local(name='Introduction', id='intro')
37+
commands = Block(vimdoc.SECTION)
38+
commands.Local(name='Commands', id='commands')
39+
about = Block(vimdoc.SECTION)
40+
about.Local(name='About', id='about')
41+
# Merge in arbitrary order.
42+
main_module.Merge(commands)
43+
main_module.Merge(about)
44+
main_module.Merge(intro)
45+
main_module.Close()
46+
self.assertEqual([intro, commands, about], list(main_module.Chunks()))
47+
48+
def test_manual_section_ordering(self):
49+
"""Sections should be ordered according to explicitly configured order."""
50+
plugin = module.VimPlugin('myplugin')
51+
main_module = module.Module('myplugin', plugin)
52+
intro = Block(vimdoc.SECTION)
53+
intro.Local(name='Introduction', id='intro')
54+
# Configure explicit order.
55+
intro.Global(order=['commands', 'about', 'intro'])
56+
commands = Block(vimdoc.SECTION)
57+
commands.Local(name='Commands', id='commands')
58+
about = Block(vimdoc.SECTION)
59+
about.Local(name='About', id='about')
60+
# Merge in arbitrary order.
61+
main_module.Merge(commands)
62+
main_module.Merge(about)
63+
main_module.Merge(intro)
64+
main_module.Close()
65+
self.assertEqual([commands, about, intro], list(main_module.Chunks()))
66+
67+
def test_partial_ordering(self):
68+
"""Always respect explicit order and prefer built-in ordering.
69+
70+
Undeclared built-in sections will be inserted into explicit order according
71+
to default built-in ordering. The about section should come after custom
72+
sections unless explicitly ordered."""
73+
plugin = module.VimPlugin('myplugin')
74+
main_module = module.Module('myplugin', plugin)
75+
intro = Block(vimdoc.SECTION)
76+
intro.Local(name='Introduction', id='intro')
77+
# Configure explicit order.
78+
intro.Global(order=['custom1', 'intro', 'custom2'])
79+
commands = Block(vimdoc.SECTION)
80+
commands.Local(name='Commands', id='commands')
81+
about = Block(vimdoc.SECTION)
82+
about.Local(name='About', id='about')
83+
custom1 = Block(vimdoc.SECTION)
84+
custom1.Local(name='Custom1', id='custom1')
85+
custom2 = Block(vimdoc.SECTION)
86+
custom2.Local(name='Custom2', id='custom2')
87+
# Merge in arbitrary order.
88+
for section in [commands, custom2, about, intro, custom1]:
89+
main_module.Merge(section)
90+
main_module.Close()
91+
self.assertEqual([custom1, intro, commands, custom2, about],
92+
list(main_module.Chunks()))

vimdoc/module.py

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -146,35 +146,14 @@ def Close(self):
146146
config.Local(id='config', name='Configuration')
147147
self.Merge(config)
148148

149-
# Use explicit order as partial ordering and merge with default section
150-
# ordering. All custom sections must be ordered explicitly.
151-
# Custom sections will be ordered after all sections besides 'about'.
152-
order = self.order or []
153-
builtins_pre = []
154-
for builtin in [
155-
'intro',
156-
'config',
157-
'commands',
158-
'autocmds',
159-
'settings',
160-
'dicts',
161-
'functions',
162-
'exceptions',
163-
'mappings']:
164-
if builtin in self.sections or builtin in self.backmatters:
165-
if builtin not in order:
166-
builtins_pre.append(builtin)
167-
order = builtins_pre + order
168-
for builtin in ['about']:
169-
if builtin in self.sections or builtin in self.backmatters:
170-
if builtin not in order:
171-
order.append(builtin)
172-
self.order = order
173-
174149
for backmatter in self.backmatters:
175150
if backmatter not in self.sections:
176151
raise error.NoSuchSection(backmatter)
177-
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)
178157
neglected = sorted(known.difference(self.order))
179158
if neglected:
180159
raise error.NeglectedSections(neglected, self.order)
@@ -211,6 +190,46 @@ def Chunks(self):
211190
if ident in self.backmatters:
212191
yield self.backmatters[ident]
213192

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
214233

215234
class VimPlugin(object):
216235
"""State for entire plugin (potentially multiple modules)."""

0 commit comments

Comments
 (0)