feat(SublimeText2.EditorPackages): cache packages
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
import sublime
|
||||
import sublime_plugin
|
||||
from os.path import basename
|
||||
import re
|
||||
|
||||
|
||||
BH_TABSTOPS = re.compile(r"(\$\{BH_(SEL|TAB)(?:\:([^\}]+))?\})")
|
||||
TAB_REGION = "bh_plugin_wrapping_tabstop"
|
||||
SEL_REGION = "bh_plugin_wrapping_select"
|
||||
OUT_REGION = "bh_plugin_wrapping_outlier"
|
||||
|
||||
VALID_INSERT_STYLES = (
|
||||
("inline", "Inline Insert"),
|
||||
("block", "Block Insert"),
|
||||
("indent_block", "Indented Block Insert")
|
||||
)
|
||||
|
||||
|
||||
def exclude_entry(enabled, filter_type, language_list, language):
|
||||
"""
|
||||
Exclude bracket wrapping entry by filter
|
||||
"""
|
||||
|
||||
exclude = True
|
||||
if enabled:
|
||||
# Black list languages
|
||||
if filter_type == 'blacklist':
|
||||
exclude = False
|
||||
if language != None:
|
||||
for item in language_list:
|
||||
if language == item.lower():
|
||||
exclude = True
|
||||
break
|
||||
#White list languages
|
||||
elif filter_type == 'whitelist':
|
||||
if language != None:
|
||||
for item in language_list:
|
||||
if language == item.lower():
|
||||
exclude = False
|
||||
break
|
||||
return exclude
|
||||
|
||||
|
||||
class TextInsertion(object):
|
||||
"""
|
||||
Wrapper class for inserting text
|
||||
"""
|
||||
|
||||
def __init__(self, view, edit):
|
||||
"""
|
||||
Store view and edit objects
|
||||
"""
|
||||
|
||||
self.view = view
|
||||
self.edit = edit
|
||||
|
||||
def insert(self, pt, text):
|
||||
"""
|
||||
Peform insertion
|
||||
"""
|
||||
|
||||
return self.view.insert(self.edit, pt, text)
|
||||
|
||||
|
||||
class WrapBrackets(object):
|
||||
"""
|
||||
Wrap the current selection(s) with the defined wrapping options
|
||||
"""
|
||||
|
||||
def __init__(self, view, setting_file, attribute):
|
||||
self.view = view
|
||||
self._menu = []
|
||||
self._brackets = []
|
||||
self._insert = []
|
||||
self._style = []
|
||||
self.read_wrap_entries(setting_file, attribute)
|
||||
|
||||
def inline(self, edit, sel):
|
||||
"""
|
||||
Inline wrap
|
||||
"""
|
||||
|
||||
ti = TextInsertion(self.view, edit)
|
||||
|
||||
offset1 = ti.insert(sel.begin(), self.brackets[0])
|
||||
self.insert_regions.append(sublime.Region(sel.begin(), sel.begin() + offset1))
|
||||
offset2 = ti.insert(sel.end() + offset1, self.brackets[1])
|
||||
self.insert_regions.append(sublime.Region(sel.end() + offset1, sel.end() + offset1 + offset2))
|
||||
|
||||
def block(self, edit, sel, indent=False):
|
||||
"""
|
||||
Wrap brackets around selection and block off the content
|
||||
"""
|
||||
|
||||
# Calculate number of lines between brackets
|
||||
self.calculate_lines(sel)
|
||||
# Calculate the current indentation of first bracket
|
||||
self.calculate_indentation(sel)
|
||||
|
||||
ti = TextInsertion(self.view, edit)
|
||||
|
||||
line_offset = 0
|
||||
first_end = 0
|
||||
second_end = 0
|
||||
second_start = sel.end()
|
||||
|
||||
for b in reversed(self.brackets[1].split('\n')):
|
||||
second_end += ti.insert(sel.end(), "\n" + self.indent_to_col + b)
|
||||
num_open_lines = self.brackets[0].count('\n')
|
||||
for b in reversed(self.brackets[0].split('\n')):
|
||||
if line_offset == num_open_lines:
|
||||
line = b + "\n"
|
||||
else:
|
||||
line = self.indent_to_col + b + "\n"
|
||||
first_end += ti.insert(sel.begin(), line)
|
||||
line_offset += 1
|
||||
self.insert_regions.append(sublime.Region(sel.begin(), sel.begin() + first_end))
|
||||
|
||||
if indent:
|
||||
second_start += self.indent_content(ti, line_offset)
|
||||
else:
|
||||
pt = self.view.text_point(self.first_line + line_offset, 0)
|
||||
second_start += ti.insert(pt, self.indent_to_col)
|
||||
|
||||
self.insert_regions.append(sublime.Region(first_end + second_start, first_end + second_start + second_end))
|
||||
|
||||
def indent_content(self, ti, line_offset):
|
||||
"""
|
||||
Indent the block content
|
||||
"""
|
||||
|
||||
first = True
|
||||
offset = 0
|
||||
for l in range(line_offset, self.total_lines + line_offset):
|
||||
pt = self.view.text_point(self.first_line + l, 0)
|
||||
if first:
|
||||
offset += ti.insert(pt, self.indent_to_col + "\t")
|
||||
first = False
|
||||
else:
|
||||
offset += ti.insert(pt, "\t")
|
||||
return offset
|
||||
|
||||
def calculate_lines(self, sel):
|
||||
"""
|
||||
Calculate lines between brackets
|
||||
"""
|
||||
|
||||
self.first_line, self.col_position = self.view.rowcol(sel.begin())
|
||||
last_line = self.view.rowcol(sel.end())[0]
|
||||
self.total_lines = last_line - self.first_line + 1
|
||||
|
||||
def calculate_indentation(self, sel):
|
||||
"""
|
||||
Calculate how much lines should be indented
|
||||
"""
|
||||
|
||||
tab_size = self.view.settings().get("tab_size", 4)
|
||||
tab_count = self.view.substr(sublime.Region(sel.begin() - self.col_position, sel.begin())).count('\t')
|
||||
spaces = self.col_position - tab_count
|
||||
self.indent_to_col = "\t" * tab_count + "\t" * (spaces / tab_size) + " " * (spaces % tab_size if spaces >= tab_size else spaces)
|
||||
|
||||
def select(self, edit):
|
||||
"""
|
||||
Select defined regions after wrapping
|
||||
"""
|
||||
|
||||
self.view.sel().clear()
|
||||
map(lambda x: self.view.sel().add(x), self.insert_regions)
|
||||
|
||||
final_sel = []
|
||||
initial_sel = []
|
||||
for s in self.view.sel():
|
||||
string = self.view.substr(s)
|
||||
matches = [m for m in BH_TABSTOPS.finditer(string)]
|
||||
multi_offset = 0
|
||||
if matches:
|
||||
for m in matches:
|
||||
r = sublime.Region(s.begin() + multi_offset + m.start(1), s.begin() + multi_offset + m.end(1))
|
||||
if m.group(3):
|
||||
replace = m.group(3)
|
||||
self.view.erase(edit, r)
|
||||
added = self.view.insert(edit, r.begin(), replace)
|
||||
final_sel.append(sublime.Region(s.begin() + multi_offset + m.start(1), s.begin() + multi_offset + m.start(1) + added))
|
||||
multi_offset += added - r.size()
|
||||
else:
|
||||
self.view.erase(edit, r)
|
||||
final_sel.append(sublime.Region(s.begin() + multi_offset + m.start(1)))
|
||||
multi_offset -= r.size()
|
||||
if m.group(2) == "SEL":
|
||||
initial_sel.append(final_sel[-1])
|
||||
|
||||
if len(initial_sel) != len(final_sel):
|
||||
self.view.add_regions(TAB_REGION, final_sel, "", "", sublime.HIDDEN)
|
||||
|
||||
# Re-position cursor
|
||||
self.view.sel().clear()
|
||||
if len(initial_sel):
|
||||
map(lambda x: self.view.sel().add(x), initial_sel)
|
||||
elif len(final_sel):
|
||||
self.view.sel().add(final_sel[0])
|
||||
|
||||
def read_wrap_entries(self, setting_file, attribute):
|
||||
"""
|
||||
Read wrap entries from the settings file
|
||||
"""
|
||||
|
||||
settings = sublime.load_settings(setting_file)
|
||||
syntax = self.view.settings().get('syntax')
|
||||
language = basename(syntax).replace('.tmLanguage', '').lower() if syntax != None else "plain text"
|
||||
wrapping = settings.get(attribute, [])
|
||||
for i in wrapping:
|
||||
if not exclude_entry(i["enabled"], i["language_filter"], i["language_list"], language):
|
||||
for j in i.get("entries", []):
|
||||
try:
|
||||
menu_entry = j["name"]
|
||||
bracket_entry = j["brackets"]
|
||||
insert_style = j.get("insert_style", ["inline"])
|
||||
self._menu.append(menu_entry)
|
||||
self._brackets.append(bracket_entry)
|
||||
self._insert.append(insert_style)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def wrap_brackets(self, value):
|
||||
"""
|
||||
Wrap selection(s) with defined brackets
|
||||
"""
|
||||
|
||||
if value < 0:
|
||||
return
|
||||
|
||||
# Use new edit object since the main run has already exited
|
||||
# and the old edit is more than likely closed now
|
||||
edit = self.view.begin_edit()
|
||||
|
||||
# Wrap selections with brackets
|
||||
style = self._style[value]
|
||||
self.insert_regions = []
|
||||
|
||||
for sel in self.view.sel():
|
||||
# Determine indentation style
|
||||
if style == "indent_block":
|
||||
self.block(edit, sel, True)
|
||||
elif style == "block":
|
||||
self.block(edit, sel)
|
||||
else:
|
||||
self.inline(edit, sel)
|
||||
|
||||
self.select(edit)
|
||||
|
||||
self.view.end_edit(edit)
|
||||
|
||||
def wrap_style(self, value):
|
||||
"""
|
||||
Choose insert style for wrapping.
|
||||
"""
|
||||
|
||||
if value < 0:
|
||||
return
|
||||
|
||||
style = []
|
||||
|
||||
self.brackets = self._brackets[value]
|
||||
for s in VALID_INSERT_STYLES:
|
||||
if s[0] in self._insert[value]:
|
||||
self._style.append(s[0])
|
||||
style.append(s[1])
|
||||
|
||||
if len(style) > 1:
|
||||
self.view.window().show_quick_panel(
|
||||
style,
|
||||
self.wrap_brackets
|
||||
)
|
||||
else:
|
||||
self.wrap_brackets(0)
|
||||
|
||||
|
||||
class WrapBracketsCommand(sublime_plugin.TextCommand, WrapBrackets):
|
||||
def run(self, edit):
|
||||
"""
|
||||
Display the wrapping menu
|
||||
"""
|
||||
|
||||
self._menu = []
|
||||
self._brackets = []
|
||||
self._insert = []
|
||||
self._style = []
|
||||
self.read_wrap_entries("bh_wrapping.sublime-settings", "wrapping")
|
||||
|
||||
if len(self._menu):
|
||||
self.view.window().show_quick_panel(
|
||||
self._menu,
|
||||
self.wrap_style
|
||||
)
|
||||
|
||||
|
||||
class BhNextWrapSelCommand(sublime_plugin.TextCommand):
|
||||
"""
|
||||
Navigate wrapping tab stop regions
|
||||
"""
|
||||
|
||||
def run(self, edit):
|
||||
"""
|
||||
Look for the next wrapping tab stop region
|
||||
"""
|
||||
|
||||
regions = self.view.get_regions(SEL_REGION) + self.view.get_regions(OUT_REGION)
|
||||
if len(regions):
|
||||
self.view.sel().clear()
|
||||
map(lambda x: self.view.sel().add(x), regions)
|
||||
|
||||
# Clean up unneed sections
|
||||
self.view.erase_regions(SEL_REGION)
|
||||
self.view.erase_regions(OUT_REGION)
|
||||
|
||||
|
||||
class BhWrapListener(sublime_plugin.EventListener):
|
||||
"""
|
||||
Listen for wrapping tab stop tabbing
|
||||
"""
|
||||
|
||||
def on_query_context(self, view, key, operator, operand, match_all):
|
||||
"""
|
||||
Mark the next regions to navigate to.
|
||||
"""
|
||||
|
||||
accept_query = False
|
||||
if key == "bh_wrapping":
|
||||
select = []
|
||||
outlier = []
|
||||
regions = view.get_regions(TAB_REGION)
|
||||
tabstop = []
|
||||
sels = view.sel()
|
||||
|
||||
if len(regions) == 0:
|
||||
return False
|
||||
|
||||
for s in sels:
|
||||
count = 0
|
||||
found = False
|
||||
for r in regions[:]:
|
||||
if found:
|
||||
select.append(r)
|
||||
tabstop.append(r)
|
||||
del regions[count]
|
||||
break
|
||||
if r.begin() <= s.begin() <= r.end():
|
||||
del regions[count]
|
||||
found = True
|
||||
continue
|
||||
count += 1
|
||||
if not found:
|
||||
outlier.append(s)
|
||||
tabstop += regions
|
||||
|
||||
if len(tabstop) == len(select):
|
||||
if len(tabstop):
|
||||
tabstop = []
|
||||
accept_query = True
|
||||
elif len(tabstop) != 0:
|
||||
accept_query = True
|
||||
|
||||
# Mark regions to make the "next" command aware of what to do
|
||||
view.add_regions(SEL_REGION, select, "", "", sublime.HIDDEN)
|
||||
view.add_regions(OUT_REGION, outlier, "", "", sublime.HIDDEN)
|
||||
view.add_regions(TAB_REGION, tabstop, "", "", sublime.HIDDEN)
|
||||
|
||||
return accept_query
|
Reference in New Issue
Block a user