Skip to content

Commit

Permalink
more folding and heading navigation support
Browse files Browse the repository at this point in the history
  • Loading branch information
felixhao28 committed Dec 12, 2016
1 parent e7cd2a8 commit b20fa15
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 13 deletions.
25 changes: 25 additions & 0 deletions Default (Linux).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -599,5 +599,30 @@
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+shift+tab"], "command": "show_fold_all_sections", "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+;"], "command": "goto_previous_heading", "args": {"same_level": true}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+."], "command": "goto_next_heading", "args": {"same_level": true}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+shift+;"], "command": "goto_previous_heading", "args": {"same_level": false}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+shift+."], "command": "goto_next_heading", "args": {"same_level": false}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
}
]
25 changes: 25 additions & 0 deletions Default (OSX).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -604,5 +604,30 @@
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["super+shift+tab"], "command": "show_fold_all_sections", "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["super+;"], "command": "goto_previous_heading", "args": {"same_level": true}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["super+."], "command": "goto_next_heading", "args": {"same_level": true}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["super+shift+;"], "command": "goto_previous_heading", "args": {"same_level": false}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["super+shift+."], "command": "goto_next_heading", "args": {"same_level": false}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
}
]
25 changes: 25 additions & 0 deletions Default (Windows).sublime-keymap
Original file line number Diff line number Diff line change
Expand Up @@ -599,5 +599,30 @@
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+shift+tab"], "command": "show_fold_all_sections", "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+;"], "command": "goto_previous_heading", "args": {"same_level": true}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+."], "command": "goto_next_heading", "args": {"same_level": true}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+shift+;"], "command": "goto_previous_heading", "args": {"same_level": false}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
},
{ "keys": ["ctrl+shift+."], "command": "goto_next_heading", "args": {"same_level": false}, "context":
[
{ "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
]
}
]
56 changes: 56 additions & 0 deletions Default.sublime-commands
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,61 @@
{
"caption": "MarkdownEditing: Toggle Folding Current Section",
"command": "fold_section"
},
{
"caption": "MarkdownEditing: Fold Level 1 Sections",
"command": "fold_all_sections", "args" :
{
"target_level" : 1
}
},
{
"caption": "MarkdownEditing: Fold Level 2 Sections",
"command": "fold_all_sections", "args" :
{
"target_level" : 2
}
},
{
"caption": "MarkdownEditing: Fold Level 3 Sections",
"command": "fold_all_sections", "args" :
{
"target_level" : 3
}
},
{
"caption": "MarkdownEditing: Fold Level 4 Sections",
"command": "fold_all_sections", "args" :
{
"target_level" : 4
}
},
{
"caption": "MarkdownEditing: Find Next Heading (Same or higher level)",
"command": "goto_next_heading", "args" :
{
"same_level" : true
}
},
{
"caption": "MarkdownEditing: Find Next Heading (Any level)",
"command": "goto_next_heading", "args" :
{
"same_level" : false
}
},
{
"caption": "MarkdownEditing: Find Previous Heading (Same or higher level)",
"command": "goto_previous_heading", "args" :
{
"same_level" : true
}
},
{
"caption": "MarkdownEditing: Find Previous Heading (Any level)",
"command": "goto_previous_heading", "args" :
{
"same_level" : false
}
}
]
143 changes: 130 additions & 13 deletions folding.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,42 @@
except ImportError:
from mdeutils import *


def getFoldedRegion(view, reg):
for i in view.folded_regions():
if i.contains(reg):
return i
return None


def all_headings(view):
text = view.substr(sublime.Region(0, view.size()))
it = re.finditer(r'^(#{1,6}(?!#))|^(-{3,}|={3,})', text, re.M)
for m in it:
if re.match(r'^(-{3,}|={3,})$', m.group()):
title_end = m.start() - 1
title_begin = text.rfind('\n', 0, title_end) + 1
title_end = m.end() + 1
level = 2 if text[m.start()] == '-' else 1
else:
title_begin = m.end()
title_end = re.search('(' + m.group() + ')?(\n|$)', text[title_begin:]).start() + title_begin
title_begin = m.start()
level = m.end() - m.start()
yield (title_begin, title_end, level)


class FoldSectionCommand(MDETextCommand):

def run(self, edit):
view = self.view
sections = []
shouldUnfold = False
for sel in view.sel():
text = view.substr(sublime.Region(0, view.size()))
it = re.finditer(r'^(#{1,6}(?!#))|^(-{3,}|={3,})', text, re.M)
section_start = -1
section_end = view.size() - 1
section_level = 0
for m in it:
if re.match(r'^(-{3,}|={3,})$', m.group()):
title_end = m.start() - 1
title_begin = text.rfind('\n', 0, title_end) + 1
title_end = m.end() + 1
level = 2 if text[m.start()] == '-' else 1
else:
title_begin = m.end()
title_end = re.search('(' + m.group() + ')?(\n|$)', text[title_begin:]).start() + title_begin
title_begin = m.start()
level = m.end() - m.start()
for (title_begin, title_end, level) in all_headings(view):
if title_begin <= sel.a:
section_start = title_end
section_level = level
Expand All @@ -55,4 +62,114 @@ def run(self, edit):
view.unfold(reg)
else:
view.fold(reg)
sublime.status_message('%d region%s %sfolded' % (len(sections), 's' if len(sections) > 1 else '', 'un' if shouldUnfold else ''))


class ShowFoldAllSectionsCommand(MDETextCommand):

def run(self, edit):
view = self.view
options = [
'Unfold all',
'Fold Level 1 Sections',
'Fold Level 2 Sections',
'Fold Level 3 Sections',
'Fold Level 4 Sections'
]
view.window().show_quick_panel(options, self.run_command)

def run_command(self, value):
view = self.view
if value >= 1 and value <= 4:
view.run_command('fold_all_sections', {'target_level': value + 1})
elif value == 0:
view.run_command('unfold_all')


class FoldAllSectionsCommand(MDETextCommand):

def run(self, edit, target_level):
view = self.view
view.run_command('unfold_all')
section_start = -1
section_end = view.size() - 1
n_sections = 0
for (title_begin, title_end, level) in all_headings(view):
if level <= target_level:
if section_start > 0:
section_end = title_begin - 1
reg = sublime.Region(section_start, section_end)
view.fold(reg)
n_sections += 1
section_start = -1
if level == target_level:
section_start = title_end
if section_start >= 0:
reg = sublime.Region(section_start, view.size() - 1)
view.fold(reg)
n_sections += 1
sublime.status_message('%d region%s folded' % (n_sections, 's' if n_sections > 1 else ''))


class GotoNextHeadingCommand(MDETextCommand):

def run(self, edit, same_level=True):
view = self.view
new_sel = []
for sel in view.sel():
section_level = 0
found = False
for (title_begin, title_end, level) in all_headings(view):
if title_begin <= sel.a:
section_level = level
elif not same_level or section_level >= level:
found = True
break
if found:
new_sel.append(sublime.Region(title_begin, title_end))
if len(new_sel) == 0:
sublime.status_message('No heading can be found')
else:
view.sel().clear()
for region in new_sel:
view.sel().add(region)
view.show(region)


class GotoPreviousHeadingCommand(MDETextCommand):

def run(self, edit, same_level=True):
view = self.view
new_sel = []
max_level = 0
last_level = 0
found = False
for sel in view.sel():
prev = {}
for (title_begin, title_end, level) in all_headings(view):
max_level = max(max_level, level)
if title_end < sel.a:
for lvl in range(level, max_level + 1):
prev[lvl] = (title_begin, title_end)
last_level = level
else:
found = True
break
if found:
if same_level:
while level not in prev and level > 0:
level -= 1
if level > 0 and level in prev:
new_sel.append(sublime.Region(prev[level][0], prev[level][1]))
else:
if last_level > 0 and last_level in prev:
new_sel.append(sublime.Region(prev[last_level][0], prev[last_level][1]))
elif max_level > 0:
new_sel.append(sublime.Region(title_begin, title_end))
if len(new_sel) == 0:
sublime.status_message('No heading can be found')
else:
view.sel().clear()
for region in new_sel:
view.sel().add(region)
view.show(region)

0 comments on commit b20fa15

Please sign in to comment.