Skip to content

Commit 7c9a06f

Browse files
committed
Better fold functions command
1 parent e024d85 commit 7c9a06f

2 files changed

Lines changed: 68 additions & 2 deletions

File tree

Default (OSX).sublime-keymap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
// { "keys": ["super+v"], "command": "paste_and_indent" },
99
// { "keys": ["super+shift+v"], "command": "paste" },
1010
// ====== Viewing
11-
{ "keys": ["super+k", "super+b"], "command": "fold_scopes" },
12-
{ "keys": ["ctrl+,"], "command": "fold_scopes" },
11+
{ "keys": ["super+k", "super+b"], "command": "fold_functions" },
12+
{ "keys": ["ctrl+,"], "command": "fold_functions" },
1313
// ====== Editing
1414
// convenience cmd replications for continuous holding
1515
{ "keys": ["ctrl+z"], "command": "undo" },

sublimetect.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,62 @@
11
import sublime, sublime_plugin
2+
import re
3+
4+
INDENT_RE = re.compile('^\s*')
5+
6+
def line_indent(view, row):
7+
pt = view.text_point(row,0)
8+
line = view.full_line(pt)
9+
content = view.substr(line)
10+
if len(content) <= 1:
11+
return 10000 # blank lines have arbitrarily high indent
12+
start,end = INDENT_RE.match(content).span(0)
13+
return end-start
14+
15+
def find_function_bodies(view, decls):
16+
last_row, last_col = view.rowcol(view.size())
17+
fold_regions = []
18+
for decl in decls:
19+
line_region = view.full_line(decl)
20+
start_row, _ = view.rowcol(decl.a)
21+
end_row, _ = view.rowcol(decl.b)
22+
fn_indent = line_indent(view, start_row)
23+
24+
# find lines until closed indent
25+
cur_row = end_row+1
26+
while True:
27+
if cur_row == last_row:
28+
break
29+
indent = line_indent(view, cur_row)
30+
if indent <= fn_indent:
31+
break
32+
cur_row += 1
33+
34+
# compute region
35+
if (cur_row - end_row) > 1:
36+
final_line = view.full_line(view.text_point(cur_row, 0))
37+
if final_line.size() > 4:
38+
# for languages like python, or when the end is otherwise long
39+
# collapse just before the closing bit
40+
end_pt = view.text_point(cur_row-1,0)
41+
else:
42+
final_line_indent = line_indent(view, cur_row)
43+
end_pt = view.text_point(cur_row, final_line_indent)
44+
fold_regions.append(sublime.Region(line_region.b-1, end_pt))
45+
46+
return fold_regions
47+
48+
49+
def find_all_functions(view):
50+
if view.score_selector(0,'source.rust') > 0:
51+
fn_bodies = view.find_by_selector('meta.function meta.block')
52+
folds = [sublime.Region(r.a+1,r.b-1) for r in fn_bodies]
53+
else:
54+
fn_decls = view.find_by_selector('meta.function, entity.name.function')
55+
folds = find_function_bodies(view, fn_decls)
56+
did_fold = view.fold(folds)
57+
if not did_fold: # already folded, toggle off
58+
view.unfold(folds)
59+
260

361
class SelectLineCommand(sublime_plugin.TextCommand):
462
def is_selection_lines(self):
@@ -42,3 +100,11 @@ def run(self, edit, **args):
42100
did_fold = self.view.fold(folds)
43101
if not did_fold: # already folded, toggle off
44102
self.view.unfold(folds)
103+
104+
class FoldFunctionsCommand(sublime_plugin.TextCommand):
105+
def run(self, edit):
106+
folds = find_all_functions(self.view)
107+
# print("folding " + len(folds))
108+
did_fold = self.view.fold(folds)
109+
if not did_fold: # already folded, toggle off
110+
self.view.unfold(folds)

0 commit comments

Comments
 (0)