79 lines
1.7 KiB
Python
79 lines
1.7 KiB
Python
import sublime
|
|
import sublime_plugin
|
|
import re
|
|
|
|
|
|
class CycleCommentsCommand(sublime_plugin.TextCommand):
|
|
|
|
def run(self, edit):
|
|
|
|
view = self.view
|
|
syntax_path = view.settings().get("syntax")
|
|
|
|
if not syntax_path:
|
|
return
|
|
|
|
syntax_name = syntax_path.split("/")[-1] \
|
|
.replace(".sublime-syntax", "") \
|
|
.replace(".tmLanguage", "")
|
|
|
|
settings = sublime.load_settings("commentcycle.sublime-settings")
|
|
comment_styles = settings.get(syntax_name)
|
|
|
|
if not comment_styles:
|
|
sublime.status_message("No comment styles for {}".format(syntax_name))
|
|
return
|
|
|
|
# Match longest prefix first (## before #)
|
|
comment_styles = sorted(comment_styles, key=lambda x: len(x[0]), reverse=True)
|
|
|
|
for region in list(view.sel()):
|
|
|
|
if region.empty():
|
|
region = view.line(region)
|
|
|
|
original = view.substr(region)
|
|
|
|
indent_match = re.match(r'^(\s*)', original)
|
|
indent = indent_match.group(1)
|
|
content = original[len(indent):]
|
|
|
|
stripped = content.strip()
|
|
|
|
state = 0
|
|
|
|
for i, pair in enumerate(comment_styles):
|
|
|
|
start, end = pair
|
|
|
|
if stripped.startswith(start):
|
|
if not end or stripped.endswith(end):
|
|
state = i + 1
|
|
break
|
|
|
|
next_state = (state + 1) % (len(comment_styles) + 1)
|
|
|
|
# Remove current comment
|
|
if state > 0:
|
|
|
|
start, end = comment_styles[state - 1]
|
|
|
|
stripped = stripped[len(start):].lstrip()
|
|
|
|
if end:
|
|
stripped = stripped[:-len(end)].rstrip()
|
|
|
|
# Apply next comment
|
|
if next_state > 0:
|
|
|
|
start, end = comment_styles[next_state - 1]
|
|
|
|
if end:
|
|
stripped = "{} {} {}".format(start, stripped, end)
|
|
else:
|
|
stripped = "{} {}".format(start, stripped)
|
|
|
|
new_line = indent + stripped
|
|
|
|
view.replace(edit, region, new_line)
|