-
Notifications
You must be signed in to change notification settings - Fork 0
/
ToggleCommentAndMove.py
104 lines (72 loc) · 3.12 KB
/
ToggleCommentAndMove.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import sublime
import sublime_plugin
import re
def GetCommentSymbol(cmd_ctx):
# self.view.meta_info('block_comment', 0)
syntax_symbols = cmd_ctx.view.meta_info('shellVariables', 0)
# {'value': '#', name: 'TM_COMMENT_START'}
for symbol_entry in syntax_symbols:
name, symbol = symbol_entry.values()
if name == 'TM_COMMENT_START':
return symbol
# get regions that have cursors on them
# [(line_char_start, line_char_end), ...]
def get_lines_with_selections(view) -> list:
selections = view.sel()
line_regions = []
for selection in selections:
lines_in_sel = view.lines(selection)
for region in lines_in_sel:
line_regions.append( region )
return line_regions
def get_soft_start_offset(line_text):
"""
soft line start (if line isn't empty),
0 if the line is empty
"""
whitespace = re.compile(r'(\s|\t)+')
match = re.match(whitespace, line_text)
if match:
return match.end()
return 0
def string_at(needle, haystack, start_pos) -> bool:
return haystack[start_pos:start_pos+len(needle)] == needle
# returns the new state,
# True for commented, False for uncommented
def toggle_line_comment(view, edit, line_region, comment_pattern) -> bool:
line_text = view.substr( line_region )
soft_start_pos = get_soft_start_offset(line_text)
is_comment = string_at(comment_pattern, line_text, soft_start_pos)
comment_pos = line_region.begin()+soft_start_pos
comment_len = len(comment_pattern)
if not is_comment: # line was comment
view.insert(edit, comment_pos, comment_pattern)
else: # erase comment
comment_region = sublime.Region(comment_pos, comment_pos+comment_len)
view.erase(edit, comment_region)
def toggle_line_comments(view, edit, line_regions, comment_pattern):
shift_lines_by = 0 # for shifting line regions when erasing/adding comments
for line_region in line_regions:
line_region = sublime.Region( line_region.begin()+shift_lines_by, line_region.end()+shift_lines_by) # update line region to match
commented = toggle_line_comment(view, edit, line_region, comment_pattern)
if commented:
shift_lines_by += 3
else:
shift_lines_by -= 3
def toggle_comment_fallback(view, cmd_edit, comment_pattern):
lines_with_cursors = get_lines_with_selections(view)
view.run_command("move", {"by": "lines", "forward": True})
toggle_line_comments(view, cmd_edit, lines_with_cursors, comment_pattern)
class ToggleCommentAndMoveCommand(sublime_plugin.TextCommand):
def run(self, edit, forward=True, move=True, fallback_uses_space=True):
comment_symbol = GetCommentSymbol(self)
symbol_missing = (comment_symbol == None)
comment_symbol = comment_symbol or "//"
if fallback_uses_space:
comment_symbol += " "
if symbol_missing:
toggle_comment_fallback(self.view, edit, comment_symbol)
else:
self.view.run_command("toggle_comment", {"block": False})
if move:
self.view.run_command("move", {"by": "lines", "forward": forward})