Skip to content

Commit 8637180

Browse files
committed
Plugins: Improve Fold/Unfold section key bindings
This commit replaces "Toggle Folding Current Section" via `shift+tab` by separate fold/unfold commands bound to default key combinations. - `primary+shift+[` => `mde_fold_section` => fold current section - `primary+shift+]` => `mde_unfold_section` => unfold current section Fixes conflicts with `shift+tab` being also used to unindent text, which caused unexpected folding in various situations.
1 parent 91cc587 commit 8637180

10 files changed

Lines changed: 112 additions & 109 deletions

Context.sublime-menu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
},
1010
{
1111
"caption": "Fold Section",
12-
"command": "mde_fold_section_context"
12+
"command": "mde_fold_section"
1313
},
1414
{
1515
"caption": "Unfold Section",
16-
"command": "mde_unfold_section_context"
16+
"command": "mde_unfold_section"
1717
},
1818
{
1919
"caption": "-",

Default (Linux).sublime-keymap

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -678,24 +678,20 @@
678678
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }
679679
]
680680
},
681-
{ "keys": ["shift+tab"], "command": "mde_fold_section", "context":
681+
{ "keys": ["ctrl+shift+["], "command": "mde_fold_section", "context":
682682
[
683683
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true },
684684
{ "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true },
685-
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
686685
{ "key": "has_prev_field", "operator": "equal", "operand": false },
687-
{ "key": "overlay_visible", "operator": "equal", "operand": false },
688-
{ "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }
686+
{ "key": "overlay_visible", "operator": "equal", "operand": false }
689687
]
690688
},
691-
{ "keys": ["shift+tab"], "command": "mde_fold_section", "context":
689+
{ "keys": ["ctrl+shift+]"], "command": "mde_unfold_section", "context":
692690
[
693-
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true },
691+
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true },
694692
{ "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true },
695-
{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true },
696693
{ "key": "has_prev_field", "operator": "equal", "operand": false },
697-
{ "key": "overlay_visible", "operator": "equal", "operand": false },
698-
{ "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"}
694+
{ "key": "overlay_visible", "operator": "equal", "operand": false }
699695
]
700696
},
701697
{ "keys": ["ctrl+shift+tab"], "command": "mde_show_fold_all_sections", "context":

Default (OSX).sublime-keymap

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -678,24 +678,20 @@
678678
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }
679679
]
680680
},
681-
{ "keys": ["shift+tab"], "command": "mde_fold_section", "context":
681+
{ "keys": ["super+shift+["], "command": "mde_fold_section", "context":
682682
[
683683
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true },
684684
{ "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true },
685-
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
686685
{ "key": "has_prev_field", "operator": "equal", "operand": false },
687-
{ "key": "overlay_visible", "operator": "equal", "operand": false },
688-
{ "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }
686+
{ "key": "overlay_visible", "operator": "equal", "operand": false }
689687
]
690688
},
691-
{ "keys": ["shift+tab"], "command": "mde_fold_section", "context":
689+
{ "keys": ["super+shift+]"], "command": "mde_unfold_section", "context":
692690
[
693-
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true },
691+
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true },
694692
{ "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true },
695-
{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true },
696693
{ "key": "has_prev_field", "operator": "equal", "operand": false },
697-
{ "key": "overlay_visible", "operator": "equal", "operand": false },
698-
{ "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"}
694+
{ "key": "overlay_visible", "operator": "equal", "operand": false }
699695
]
700696
},
701697
{ "keys": ["ctrl+shift+tab"], "command": "mde_show_fold_all_sections", "context":

Default (Windows).sublime-keymap

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -678,24 +678,20 @@
678678
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }
679679
]
680680
},
681-
{ "keys": ["shift+tab"], "command": "mde_fold_section", "context":
681+
{ "keys": ["ctrl+shift+["], "command": "mde_fold_section", "context":
682682
[
683683
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true },
684684
{ "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true },
685-
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
686685
{ "key": "has_prev_field", "operator": "equal", "operand": false },
687-
{ "key": "overlay_visible", "operator": "equal", "operand": false },
688-
{ "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }
686+
{ "key": "overlay_visible", "operator": "equal", "operand": false }
689687
]
690688
},
691-
{ "keys": ["shift+tab"], "command": "mde_fold_section", "context":
689+
{ "keys": ["ctrl+shift+]"], "command": "mde_unfold_section", "context":
692690
[
693-
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true },
691+
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true },
694692
{ "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true },
695-
{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true },
696693
{ "key": "has_prev_field", "operator": "equal", "operand": false },
697-
{ "key": "overlay_visible", "operator": "equal", "operand": false },
698-
{ "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"}
694+
{ "key": "overlay_visible", "operator": "equal", "operand": false }
699695
]
700696
},
701697
{ "keys": ["ctrl+shift+tab"], "command": "mde_show_fold_all_sections", "context":

Default.sublime-commands

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,13 @@
146146
//
147147

148148
{
149-
"caption": "MarkdownEditing: Toggle Folding Current Section",
149+
"caption": "MarkdownEditing: Fold Current Section",
150150
"command": "mde_fold_section"
151151
},
152+
{
153+
"caption": "MarkdownEditing: Unold Current Section",
154+
"command": "mde_unfold_section"
155+
},
152156
{
153157
"caption": "MarkdownEditing: Fold Level 1 Sections",
154158
"command": "mde_fold_all_sections",

docs/usage.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,21 @@ Adding or removing `#` at the beginning of lines also modifies heading levels im
133133
134134
Irrelevant sections of documents can be folded/collapsed via Command Palette:
135135
136-
* **MarkdownEditing: Toggle Folding Current Section**
137-
Whether child sections are folded or unfolded as well depends on folding level defined by calling one of the following commands.
136+
* **MarkdownEditing: Fold Current Section**
137+
Whether child sections are folded depends on folding level defined by calling one of the following commands.
138138
139-
If `Fold All Sections` was called before _("outline mode" is active)_, the region between current and following sibling or child heading is (un)folded only.
139+
If `Fold All Sections` was called before _("outline mode" is active)_, the region between current and following sibling or child heading is folded only.
140+
141+
If `Unfold All Sections` was called before, all child sections are folded.
142+
143+
* **MarkdownEditing: Unfold Current Section**
144+
Whether child sections are unfolded depends on folding level defined by calling one of the following commands.
145+
146+
If `Fold All Sections` was called before _("outline mode" is active)_, the region between current and following sibling or child heading is unfolded only.
140147
141148
If `Fold Level 1-6 Sections` was called before, all child sections with lower level keep folded when unfolding their parent section.
142149
143-
If `Unfold All Sections` was called before, all child sections are (un)folded.
150+
If `Unfold All Sections` was called before, all child sections are unfolded.
144151
145152
* **MarkdownEditing: Fold Level 1-6 Sections**
146153
Folds all sections of headings of specific level. Also hides lower level headings.
@@ -158,7 +165,8 @@ Folding is bound to following keys by default:
158165
| <kbd>Ctrl</kbd> + <kbd>k</kbd>, <kbd>Ctrl</kbd> + <kbd>0</kbd> | <kbd>⌥</kbd> + <kbd>k</kbd>, <kbd>⌥</kbd> + <kbd>0</kbd> | Unfold all sections
159166
| <kbd>Ctrl</kbd> + <kbd>k</kbd>, <kbd>Ctrl</kbd> + <kbd>1..6</kbd> | <kbd>⌥</kbd> + <kbd>k</kbd>, <kbd>⌥</kbd> + <kbd>1..6</kbd> | Fold sections by level 1..6
160167
| <kbd>Ctrl</kbd> + <kbd>k</kbd>, <kbd>Ctrl</kbd> + <kbd>9</kbd> | <kbd>⌥</kbd> + <kbd>k</kbd>, <kbd>⌥</kbd> + <kbd>9</kbd> | Fold all sections, but keep headings of any level visible
161-
| <kbd>Shift</kbd> + <kbd>Tab</kbd> | <kbd>⇧</kbd> + <kbd>Tab</kbd> | Fold/Unfold current section.
168+
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>[</kbd> | <kbd>^</kbd> + <kbd>⇧</kbd> + <kbd>Tab</kbd> | Fold current section.
169+
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>]</kbd> | <kbd>^</kbd> + <kbd>⇧</kbd> + <kbd>Tab</kbd> | Unfold current section.
162170
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Tab</kbd> | <kbd>^</kbd> + <kbd>⇧</kbd> + <kbd>Tab</kbd> | Fold all sections under headings of a certain level.
163171
164172
## Automatic Link Url Folding

messages/3.1.9.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,8 @@ feedback you can use [GitHub issues][issues].
1717
This change is required to properly support 3rd-party packages which
1818
extend default Markdown syntax in ST4.
1919

20+
* Replace "Toggle Folding Current Section" via <kbd>shift+tab</kbd> by
21+
- "Fold Current Section" via <kbd>ctrl+shift+[</kbd>
22+
- "Unfold Current Section" via <kbd>ctrl+shift+]</kbd>
23+
2024
[issues]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues

plugin.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,9 @@
3232
MdeFoldLinksCommand,
3333
MdeFoldLinksListener,
3434
MdeFoldSectionCommand,
35-
MdeFoldSectionContextCommand,
3635
MdeShowFoldAllSectionsCommand,
3736
MdeUnfoldAllSectionsCommand,
38-
MdeUnfoldSectionContextCommand,
37+
MdeUnfoldSectionCommand,
3938
)
4039
from .plugins.footnotes import (
4140
MdeGatherMissingFootnotesCommand,

plugins/folding.py

Lines changed: 63 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ class MdeFoldSectionCommand(MdeTextCommand):
208208
"""
209209
This class describes a `mde_fold_section` command.
210210
211-
The command folds or unfolds sections at least one caret is within.
211+
The command folds sections at least one caret is within.
212212
213213
It's behavior depends on former call of `mde_fold_all_secitons` command and
214214
the active `mde.folding.target_level` setting respectively.
@@ -222,98 +222,98 @@ class MdeFoldSectionCommand(MdeTextCommand):
222222
keep folded if their parent section is unfolded.
223223
"""
224224

225-
def description(self):
226-
return "Toggle fold/unfold on current section"
225+
def is_enabled(self):
226+
view = self.view
227+
target_level = folding_target_level(view)
228+
for sel in view.sel():
229+
section, _ = section_region_and_level(view, sel.a, target_level)
230+
if section:
231+
return not bool(folded_region(view, section))
232+
return False
227233

228234
def run(self, edit):
229235
view = self.view
230236
target_level = folding_target_level(view)
231237
sections = []
232-
levels = []
233-
unfold = False
234238
for sel in view.sel():
235239
if any(s.contains(sel) for s in sections):
236240
continue
237-
section, level = section_region_and_level(view, sel.begin(), target_level)
241+
section, _ = section_region_and_level(view, sel.begin(), target_level)
238242
if not section:
239243
continue
240244
folded_section = folded_region(view, section)
241-
if folded_section:
242-
if folded_section != section:
243-
level = section_level(view, folded_section.begin())
244-
sections.append(folded_section)
245-
unfold = True
246-
else:
245+
if not folded_section:
247246
sections.append(section)
248-
levels.append(level)
249-
250-
if unfold:
251-
regions_to_fold = []
252-
if target_level > -1:
253-
# keep all child sections folded
254-
for section, level in zip(sections, levels):
255-
regions_to_fold.extend(
256-
sections_to_fold(view, section, max(target_level, level + 1))
257-
)
258-
else:
259-
for section in sections:
260-
regions_to_fold.extend(sections_to_fold(view, section, -1))
261-
262-
view.unfold(sections)
263-
view.fold(regions_to_fold + urls_to_fold(view))
264247

265-
else:
266-
view.fold(sections)
248+
view.fold(sections)
267249

268250
sublime.status_message(
269-
"{} region{} {}folded".format(
270-
len(sections), "s" if len(sections) > 1 else "", "un" if unfold else ""
271-
)
251+
"{} region{} folded".format(len(sections), "s" if len(sections) > 1 else "")
272252
)
273253

274254

275-
class MdeFoldSectionContextCommand(MdeFoldSectionCommand):
255+
class MdeUnfoldSectionCommand(MdeTextCommand):
276256
"""
277-
This class describes a `mde_fold_section_context` command.
257+
This class describes a `mde_unfold_section` command.
258+
259+
The command unfolds sections at least one caret is within.
260+
261+
It's behavior depends on former call of `mde_fold_all_secitons` command and
262+
the active `mde.folding.target_level` setting respectively.
263+
264+
-1: The whole section, including all child sections is folded and unfolded.
265+
The folded region begins after the nearest heading found before a caret's
266+
position and ends with the next heading of same level after the caret.
267+
0: The region between two the headings enclosing the caret's position
268+
is folded or unfolded. That's the so called outline mode.
269+
>0: Like (-1) but all child sections of higher level then `target_level`
270+
keep folded if their parent section is unfolded.
278271
"""
279272

280-
def is_visible(self):
281-
if not super().is_visible():
282-
return False
273+
def is_enabled(self):
283274
view = self.view
284275
target_level = folding_target_level(view)
285-
hasSection = False
286276
for sel in view.sel():
287277
section, _ = section_region_and_level(view, sel.a, target_level)
288278
if section:
289-
folded = folded_region(view, section)
290-
if folded:
291-
return False
292-
else:
293-
hasSection = True
294-
return hasSection
279+
return bool(folded_region(view, section))
280+
return False
295281

296-
297-
class MdeUnfoldSectionContextCommand(MdeFoldSectionCommand):
298-
"""
299-
This class describes a `mde_unfold_section_context` command.
300-
"""
301-
302-
def is_visible(self):
303-
if not super().is_visible():
304-
return False
282+
def run(self, edit):
305283
view = self.view
306284
target_level = folding_target_level(view)
307-
hasSection = False
285+
sections = []
286+
levels = []
308287
for sel in view.sel():
309-
section, _ = section_region_and_level(view, sel.a, target_level)
310-
if section:
311-
folded = folded_region(view, section)
312-
if folded:
313-
hasSection = True
314-
else:
315-
return False
316-
return hasSection
288+
if any(s.contains(sel) for s in sections):
289+
continue
290+
section, level = section_region_and_level(view, sel.begin(), target_level)
291+
if not section:
292+
continue
293+
folded_section = folded_region(view, section)
294+
if folded_section:
295+
if folded_section != section:
296+
level = section_level(view, folded_section.begin())
297+
sections.append(folded_section)
298+
levels.append(level)
299+
300+
regions_to_fold = []
301+
if target_level > -1:
302+
# keep all child sections folded
303+
for section, level in zip(sections, levels):
304+
regions_to_fold.extend(
305+
sections_to_fold(view, section, max(target_level, level + 1))
306+
)
307+
else:
308+
for section in sections:
309+
regions_to_fold.extend(sections_to_fold(view, section, -1))
310+
311+
view.unfold(sections)
312+
view.fold(regions_to_fold + urls_to_fold(view))
313+
314+
sublime.status_message(
315+
"{} region{} unfolded".format(len(sections), "s" if len(sections) > 1 else "")
316+
)
317317

318318

319319
class MdeShowFoldAllSectionsCommand(MdeTextCommand):

0 commit comments

Comments
 (0)