feat(SublimeText2.EditorPackages): cache packages
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
@@ -0,0 +1,41 @@
|
||||
import bh_plugin
|
||||
import re
|
||||
import sublime
|
||||
|
||||
|
||||
class BracketRemove(bh_plugin.BracketPluginCommand):
|
||||
def decrease_indent_level(self, edit, row_first, row_last):
|
||||
tab_size = self.view.settings().get("tab_size", 4)
|
||||
indents = re.compile(r"^(?:\t| {%d}| *)((?:\t| {%d}| )*)([\s\S]*)" % (tab_size, tab_size))
|
||||
if not self.single_line:
|
||||
for x in reversed(range(row_first, row_last + 1)):
|
||||
line = self.view.full_line(self.view.text_point(x, 0))
|
||||
text = self.view.substr(line)
|
||||
m = indents.match(text)
|
||||
if m:
|
||||
self.view.replace(edit, line, m.group(1) + m.group(2))
|
||||
|
||||
def run(self, edit, name, remove_content=False, remove_indent=False, remove_block=False):
|
||||
if remove_content:
|
||||
self.view.replace(edit, sublime.Region(self.left.begin, self.right.end), "")
|
||||
else:
|
||||
row_first = self.view.rowcol(self.left.end)[0] + 1
|
||||
row_last = self.view.rowcol(self.right.begin)[0] - 1
|
||||
self.single_line = not row_first <= row_last
|
||||
if remove_block and not self.single_line:
|
||||
self.view.replace(edit, self.view.full_line(self.right.toregion()), "")
|
||||
else:
|
||||
self.view.replace(edit, self.right.toregion(), "")
|
||||
if remove_indent:
|
||||
self.decrease_indent_level(edit, row_first, row_last)
|
||||
if remove_block and not self.single_line:
|
||||
self.view.replace(edit, self.view.full_line(self.left.toregion()), "")
|
||||
else:
|
||||
self.view.replace(edit, self.left.toregion(), "")
|
||||
|
||||
self.left = None
|
||||
self.right = None
|
||||
|
||||
|
||||
def plugin():
|
||||
return BracketRemove
|
@@ -0,0 +1,33 @@
|
||||
import bh_plugin
|
||||
import sublime
|
||||
|
||||
DEFAULT_TAGS = ["cfml", "html", "angle"]
|
||||
|
||||
|
||||
class SelectBracket(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name, select='', tags=DEFAULT_TAGS):
|
||||
left, right = self.left, self.right
|
||||
first, last = left.end, right.begin
|
||||
if select == 'left':
|
||||
if name in tags and left.size() > 1:
|
||||
first, last = left.begin + 1, left.begin + 1
|
||||
else:
|
||||
first, last = left.end, left.end
|
||||
elif select == 'right':
|
||||
if left.end != right.end:
|
||||
if name in tags and left.size() > 1:
|
||||
first, last = right.begin + 1, right.begin + 1
|
||||
else:
|
||||
first, last = right.begin, right.begin
|
||||
else:
|
||||
# There is no second bracket, so just select the first
|
||||
if name in tags and left.size() > 1:
|
||||
first, last = left.begin + 1, left.begin + 1
|
||||
else:
|
||||
first, last = right.end, right.end
|
||||
|
||||
self.selection = [sublime.Region(first, last)]
|
||||
|
||||
|
||||
def plugin():
|
||||
return SelectBracket
|
@@ -0,0 +1,16 @@
|
||||
import bh_plugin
|
||||
import sublime
|
||||
|
||||
|
||||
class FoldBrackets(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name):
|
||||
content = sublime.Region(self.left.end, self.right.begin)
|
||||
new_content = [content]
|
||||
if content.size > 0:
|
||||
if self.view.fold(content) == False:
|
||||
new_content = self.view.unfold(content)
|
||||
self.selection = new_content
|
||||
|
||||
|
||||
def plugin():
|
||||
return FoldBrackets
|
@@ -0,0 +1,2 @@
|
||||
def compare(name, first, second, bfr):
|
||||
return "end" + bfr[first.begin:first.end].lower() == bfr[second.begin:second.end].lower()
|
@@ -0,0 +1,12 @@
|
||||
import re
|
||||
|
||||
|
||||
def post_match(view, name, style, first, second, center, bfr, threshold):
|
||||
if first is not None:
|
||||
# Strip whitespace from the beginning of first bracket
|
||||
open_bracket = bfr[first.begin:first.end]
|
||||
if open_bracket != "do":
|
||||
m = re.match(r"^(\s*\b)[\w\W]*", open_bracket)
|
||||
if m:
|
||||
first = first.move(first.begin + m.end(1), first.end)
|
||||
return first, second, style
|
@@ -0,0 +1,14 @@
|
||||
import sublime
|
||||
from bh_plugin import ImportModule as ImpMod
|
||||
BracketRemove = ImpMod.import_from("bh_modules.bracketremove", "BracketRemove")
|
||||
|
||||
|
||||
class SwapBrackets(BracketRemove):
|
||||
def run(self, edit, name, remove_content=False, remove_indent=False, remove_block=False):
|
||||
offset = self.left.toregion().size()
|
||||
self.selection = [sublime.Region(self.left.begin, self.right.begin - offset)]
|
||||
super(SwapBrackets, self).run(edit, name)
|
||||
|
||||
|
||||
def plugin():
|
||||
return SwapBrackets
|
@@ -0,0 +1,46 @@
|
||||
import bh_plugin
|
||||
import sublime
|
||||
|
||||
|
||||
class SwapQuotes(bh_plugin.BracketPluginCommand):
|
||||
def escaped(self, idx):
|
||||
view = self.view
|
||||
escaped = False
|
||||
while idx >= 0 and view.substr(idx) == '\\':
|
||||
escaped = ~escaped
|
||||
idx -= 1
|
||||
return escaped
|
||||
|
||||
def run(self, edit, name):
|
||||
view = self.view
|
||||
quote = view.substr(self.left.begin)
|
||||
if quote != "'" and quote != '"':
|
||||
return
|
||||
new = "'" if (quote == '"') else '"'
|
||||
old = quote
|
||||
begin = self.left.end
|
||||
end = self.right.begin
|
||||
content_end = self.right.begin
|
||||
|
||||
view.replace(edit, self.left.toregion(), view.substr(self.left.toregion()).replace(old, new))
|
||||
view.replace(edit, self.right.toregion(), view.substr(self.right.toregion()).replace(old, new))
|
||||
|
||||
offset = 0
|
||||
while begin < end + offset:
|
||||
char = view.substr(begin)
|
||||
if char == old and self.escaped(begin - 1):
|
||||
view.replace(edit, sublime.Region(begin - 1, begin), '')
|
||||
offset -= 1
|
||||
content_end -= 1
|
||||
elif char == new and not self.escaped(begin - 1):
|
||||
view.insert(edit, begin, "\\")
|
||||
offset += 1
|
||||
content_end += 1
|
||||
begin += 1
|
||||
|
||||
self.right = self.right.move(content_end, end + offset)
|
||||
self.selection = [sublime.Region(content_end)]
|
||||
|
||||
|
||||
def plugin():
|
||||
return SwapQuotes
|
@@ -0,0 +1,54 @@
|
||||
import bh_plugin
|
||||
|
||||
|
||||
class SelectAttr(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name, direction='right'):
|
||||
if self.left.size() <= 1:
|
||||
return
|
||||
tag_name = r'[\w\:\-]+'
|
||||
attr_name = r'''([\w\-\.:]+)(?:\s*=\s*(?:(?:"((?:\.|[^"])*)")|(?:'((?:\.|[^'])*)')|([^>\s]+)))?'''
|
||||
tname = self.view.find(tag_name, self.left.begin)
|
||||
current = self.selection[0].b
|
||||
region = self.view.find(attr_name, tname.b)
|
||||
selection = self.selection
|
||||
|
||||
if direction == 'left':
|
||||
last = None
|
||||
|
||||
# Keep track of last attr
|
||||
if region != None and current <= region.b and region.b < self.left.end:
|
||||
last = region
|
||||
|
||||
while region != None and region.b < self.left.end:
|
||||
# Select attribute until you have closest to the left of selection
|
||||
if current > region.b:
|
||||
selection = [region]
|
||||
last = None
|
||||
# Update last attr
|
||||
elif last != None:
|
||||
last = region
|
||||
region = self.view.find(attr_name, region.b)
|
||||
# Wrap right
|
||||
if last != None:
|
||||
selection = [last]
|
||||
else:
|
||||
first = None
|
||||
# Keep track of first attr
|
||||
if region != None and region.b < self.left.end:
|
||||
first = region
|
||||
|
||||
while region != None and region.b < self.left.end:
|
||||
# Select closest attr to the right of the selection
|
||||
if current < region.b:
|
||||
selection = [region]
|
||||
first = None
|
||||
break
|
||||
region = self.view.find(attr_name, region.b)
|
||||
# Wrap left
|
||||
if first != None:
|
||||
selection = [first]
|
||||
self.selection = selection
|
||||
|
||||
|
||||
def plugin():
|
||||
return SelectAttr
|
@@ -0,0 +1,14 @@
|
||||
import bh_plugin
|
||||
|
||||
|
||||
class TagNameSelect(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name):
|
||||
if self.left.size() > 1:
|
||||
tag_name = '[\w\:\-]+'
|
||||
region1 = self.view.find(tag_name, self.left.begin)
|
||||
region2 = self.view.find(tag_name, self.right.begin)
|
||||
self.selection = [region1, region2]
|
||||
|
||||
|
||||
def plugin():
|
||||
return TagNameSelect
|
@@ -0,0 +1,243 @@
|
||||
import re
|
||||
from collections import namedtuple
|
||||
import sublime
|
||||
from os.path import basename
|
||||
|
||||
FLAGS = re.MULTILINE | re.IGNORECASE
|
||||
HTML_START = re.compile(r'''<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^>\s]+))?)*)\s*(\/?)>''', FLAGS)
|
||||
CFML_START = re.compile(r'''<([\w\:\-]+)((?:\s+[\w\-\.:]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^>\s]+))?)*|(?:(?<=cfif)|(?<=cfelseif))[^>]+)\s*(\/?)>''', FLAGS)
|
||||
START_TAG = {
|
||||
"html": HTML_START,
|
||||
"xhtml": HTML_START,
|
||||
"cfml": CFML_START
|
||||
}
|
||||
END_TAG = re.compile(r'<\/([\w\:\-]+)[^>]*>', FLAGS)
|
||||
|
||||
self_closing_tags = set("colgroup dd dt li options p td tfoot th thead tr".split())
|
||||
single_tags = set("area base basefont br col frame hr img input isindex link meta param embed".split())
|
||||
|
||||
|
||||
class TagEntry(namedtuple('TagEntry', ['begin', 'end', 'name', 'self_closing', 'single'], verbose=False)):
|
||||
def move(self, begin, end):
|
||||
return self._replace(begin=begin, end=end)
|
||||
|
||||
|
||||
def compare_languge(language, lang_list):
|
||||
found = False
|
||||
for l in lang_list:
|
||||
if language == l.lower():
|
||||
found = True
|
||||
break
|
||||
return found
|
||||
|
||||
|
||||
def get_tag_mode(view, tag_mode_config):
|
||||
default_mode = None
|
||||
syntax = view.settings().get('syntax')
|
||||
language = basename(syntax).replace('.tmLanguage', '').lower() if syntax != None else "plain text"
|
||||
for mode in ["html", "xhtml", "cfml"]:
|
||||
if compare_languge(language, tag_mode_config.get(mode, [])):
|
||||
return mode
|
||||
return default_mode
|
||||
|
||||
|
||||
def post_match(view, name, style, first, second, center, bfr, threshold):
|
||||
left, right = first, second
|
||||
threshold = [0, len(bfr)] if threshold is None else threshold
|
||||
tag_settings = sublime.load_settings("bh_core.sublime-settings")
|
||||
tag_mode = get_tag_mode(view, tag_settings.get("tag_mode", {}))
|
||||
tag_style = tag_settings.get("tag_style", "angle")
|
||||
bracket_style = style
|
||||
|
||||
if first is not None and tag_mode is not None:
|
||||
matcher = TagMatch(view, bfr, threshold, first, second, center, tag_mode)
|
||||
left, right = matcher.match()
|
||||
if not matcher.no_tag:
|
||||
bracket_style = tag_style
|
||||
|
||||
return left, right, bracket_style
|
||||
|
||||
|
||||
class TagSearch(object):
|
||||
def __init__(self, view, bfr, window, center, pattern, match_type):
|
||||
self.start = window[0]
|
||||
self.end = window[1]
|
||||
self.center = center
|
||||
self.pattern = pattern
|
||||
self.match_type = match_type
|
||||
self.bfr = bfr
|
||||
self.prev_match = None
|
||||
self.return_prev = False
|
||||
self.done = False
|
||||
self.view = view
|
||||
self.scope_exclude = sublime.load_settings("bh_core.sublime-settings").get("tag_scope_exclude")
|
||||
|
||||
def scope_check(self, pt):
|
||||
illegal_scope = False
|
||||
for exclude in self.scope_exclude:
|
||||
illegal_scope |= bool(self.view.score_selector(pt, exclude))
|
||||
return illegal_scope
|
||||
|
||||
def reset_end_state(self):
|
||||
self.done = False
|
||||
self.prev_match = None
|
||||
self.return_prev = False
|
||||
|
||||
def remember(self):
|
||||
self.return_prev = True
|
||||
self.done = False
|
||||
|
||||
def get_tags(self, bracket_code):
|
||||
if self.done:
|
||||
return
|
||||
if self.return_prev:
|
||||
self.return_prev = False
|
||||
yield self.prev_match
|
||||
for m in self.pattern.finditer(self.bfr, self.start, self.end):
|
||||
name = m.group(1).lower()
|
||||
if not self.match_type:
|
||||
single = bool(m.group(3) != "" or name in single_tags)
|
||||
self_closing = name in self_closing_tags or name.startswith("cf")
|
||||
else:
|
||||
single = False
|
||||
self_closing = False
|
||||
start = m.start(0)
|
||||
end = m.end(0)
|
||||
if not self.scope_check(start):
|
||||
self.prev_match = TagEntry(start, end, name, self_closing, single)
|
||||
self.start = end
|
||||
yield self.prev_match
|
||||
self.done = True
|
||||
|
||||
|
||||
class TagMatch(object):
|
||||
def __init__(self, view, bfr, threshold, first, second, center, mode):
|
||||
self.view = view
|
||||
self.bfr = bfr
|
||||
self.mode = mode
|
||||
tag, tag_type, tag_end = self.get_first_tag(first[0])
|
||||
self.left, self.right = None, None
|
||||
self.window = None
|
||||
self.no_tag = False
|
||||
if tag and first[0] < center < tag_end:
|
||||
if tag.single:
|
||||
self.left = tag
|
||||
self.right = tag
|
||||
else:
|
||||
if tag_type == "open":
|
||||
self.left = tag
|
||||
self.window = (tag_end, len(bfr) if threshold is None else threshold[1])
|
||||
else:
|
||||
self.right = tag
|
||||
self.window = (0 if threshold is None else threshold[0], first[0])
|
||||
else:
|
||||
self.left = first
|
||||
self.right = second
|
||||
self.no_tag = True
|
||||
|
||||
def get_first_tag(self, offset):
|
||||
tag = None
|
||||
tag_type = None
|
||||
self_closing = False
|
||||
single = False
|
||||
m = START_TAG[self.mode].match(self.bfr[offset:])
|
||||
end = None
|
||||
if m:
|
||||
name = m.group(1).lower()
|
||||
single = bool(m.group(3) != "" or name in single_tags)
|
||||
if self.mode == "html":
|
||||
self_closing = name in self_closing_tags
|
||||
elif self.mode == "cfml":
|
||||
self_closing = name in self_closing_tags or name.startswith("cf")
|
||||
start = m.start(0) + offset
|
||||
end = m.end(0) + offset
|
||||
tag = TagEntry(start, end, name, self_closing, single)
|
||||
tag_type = "open"
|
||||
self.center = end
|
||||
else:
|
||||
m = END_TAG.match(self.bfr[offset:])
|
||||
if m:
|
||||
name = m.group(1).lower()
|
||||
start = m.start(0) + offset
|
||||
end = m.end(0) + offset
|
||||
tag = TagEntry(start, end, name, self_closing, single)
|
||||
tag_type = "close"
|
||||
self.center = offset
|
||||
return tag, tag_type, end
|
||||
|
||||
def compare_tags(self, left, right):
|
||||
return left.name == right.name
|
||||
|
||||
def resolve_self_closing(self, stack, c):
|
||||
found_tag = None
|
||||
b = stack[-1]
|
||||
if self.compare_tags(b, c):
|
||||
found_tag = b
|
||||
stack.pop()
|
||||
else:
|
||||
while b is not None and b.self_closing:
|
||||
stack.pop()
|
||||
if len(stack):
|
||||
b = stack[-1]
|
||||
if self.compare_tags(b, c):
|
||||
found_tag = b
|
||||
stack.pop()
|
||||
break
|
||||
else:
|
||||
b = None
|
||||
return found_tag
|
||||
|
||||
def match(self):
|
||||
stack = []
|
||||
|
||||
# No tags to search for
|
||||
if self.no_tag or (self.left and self.right):
|
||||
return self.left, self.right
|
||||
|
||||
# Init tag matching objects
|
||||
osearch = TagSearch(self.view, self.bfr, self.window, self.center, START_TAG[self.mode], 0)
|
||||
csearch = TagSearch(self.view, self.bfr, self.window, self.center, END_TAG, 1)
|
||||
|
||||
# Searching for opening or closing tag to match
|
||||
match_type = 0 if self.right else 1
|
||||
|
||||
# Match the tags
|
||||
for c in csearch.get_tags(match_type):
|
||||
if len(stack) and osearch.done:
|
||||
if self.resolve_self_closing(stack, c):
|
||||
continue
|
||||
for o in osearch.get_tags(match_type):
|
||||
if o.end <= c.begin:
|
||||
if not o.single:
|
||||
stack.append(o)
|
||||
continue
|
||||
else:
|
||||
osearch.remember()
|
||||
break
|
||||
|
||||
if len(stack):
|
||||
if self.resolve_self_closing(stack, c):
|
||||
continue
|
||||
elif match_type == 0 and not osearch.done:
|
||||
continue
|
||||
if match_type == 1:
|
||||
if self.left is None or self.compare_tags(self.left, c):
|
||||
self.right = c
|
||||
elif self.left.self_closing:
|
||||
self.right = self.left
|
||||
break
|
||||
|
||||
if match_type == 0:
|
||||
# Find the rest of the the unmatched left side open brackets
|
||||
# approaching the cursor if all closing brackets were matched
|
||||
# Select the most recent open bracket on the stack.
|
||||
for o in osearch.get_tags(0):
|
||||
if not o.single:
|
||||
stack.append(o)
|
||||
if len(stack):
|
||||
self.left = self.resolve_self_closing(stack, self.right)
|
||||
elif self.right is None and self.left is not None and self.left.self_closing:
|
||||
# Account for the opening tag that was found being a self closing
|
||||
self.right = self.left
|
||||
|
||||
return self.left, self.right
|
Reference in New Issue
Block a user