''' + +FILE_INFO = '''''' + +TABLE_START = ''' %(date_time)s %(file)s\n\n
' + + '%(line)s ' + + ' | ' + + '' +
+ ' %(code)s\n ' +
+ ' | ' +
+ '
' + escape_html.escape(plist.get(name)) + '', + wnd = window.open('', '_blank', "status=1,toolbar=0,scrollbars=1"), + doc = wnd.document; + doc.write(text); + doc.close(); + wnd.focus(); + } +} diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/js/print.js b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/js/print.js new file mode 100644 index 0000000..cf5594d --- /dev/null +++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/js/print.js @@ -0,0 +1,15 @@ +/*jshint globalstrict: true*/ +"use strict"; + +function page_print() { + var element = document.getElementById("toolbarhide"); + if (element != null) { + element.style.display = "none"; + } + if (window.print) { + window.print(); + } + if (element != null) { + element.style.display = "block"; + } +} diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/package-metadata.json new file mode 100644 index 0000000..9887e8e --- /dev/null +++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/package-metadata.json @@ -0,0 +1 @@ +{"url": "https://github.com/facelessuser/ExportHtml", "version": "2013.03.29.23.39.49", "description": "Sublime Text - Export code to HTML for copying/printing/saving. Also, export code to BBCode for forum posts."} \ No newline at end of file diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/readme.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/readme.md new file mode 100644 index 0000000..c9957c1 --- /dev/null +++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ExportHtml/readme.md @@ -0,0 +1,220 @@ +# About +This is a fork of agibsonsw's [PrintHtml](https://github.com/agibsonsw/PrintHtml) plugin. This plugin allows the exporting of a document in ST2 to an HTML file or to BBCode. It duplicates ST2's theme colors and font styles. You can play with the demo page that has actual html pages generated with this plugin [here](http://facelessuser.github.com/ExportHtml). + +
tags.
+ """
+ yield 0, ""
+ for tup in inner:
+ yield tup
+ yield 0, "
"
+
+ def wrap(self, source, outfile):
+ """Return the source with a code, pre, and div."""
+ return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
+
+ formatter_opts.setdefault("cssclass", "codehilite")
+ formatter = HtmlCodeFormatter(**formatter_opts)
+ return pygments.highlight(codeblock, lexer, formatter)
+
+ def _code_block_sub(self, match, is_fenced_code_block=False):
+ lexer_name = None
+ if is_fenced_code_block:
+ lexer_name = match.group(1)
+ if lexer_name:
+ formatter_opts = self.extras['fenced-code-blocks'] or {}
+ codeblock = match.group(2)
+ codeblock = codeblock[:-1] # drop one trailing newline
+ else:
+ codeblock = match.group(1)
+ codeblock = self._outdent(codeblock)
+ codeblock = self._detab(codeblock)
+ codeblock = codeblock.lstrip('\n') # trim leading newlines
+ codeblock = codeblock.rstrip() # trim trailing whitespace
+
+ # Note: "code-color" extra is DEPRECATED.
+ if "code-color" in self.extras and codeblock.startswith(":::"):
+ lexer_name, rest = codeblock.split('\n', 1)
+ lexer_name = lexer_name[3:].strip()
+ codeblock = rest.lstrip("\n") # Remove lexer declaration line.
+ formatter_opts = self.extras['code-color'] or {}
+
+ if lexer_name:
+ lexer = self._get_pygments_lexer(lexer_name)
+ if lexer:
+ colored = self._color_with_pygments(codeblock, lexer,
+ **formatter_opts)
+ return "\n\n%s\n\n" % colored
+
+ codeblock = self._encode_code(codeblock)
+ pre_class_str = self._html_class_str_from_tag("pre")
+ code_class_str = self._html_class_str_from_tag("code")
+ return "\n\n%s\n
\n\n" % (
+ pre_class_str, code_class_str, codeblock)
+
+ def _html_class_str_from_tag(self, tag):
+ """Get the appropriate ' class="..."' string (note the leading
+ space), if any, for the given tag.
+ """
+ if "html-classes" not in self.extras:
+ return ""
+ try:
+ html_classes_from_tag = self.extras["html-classes"]
+ except TypeError:
+ return ""
+ else:
+ if tag in html_classes_from_tag:
+ return ' class="%s"' % html_classes_from_tag[tag]
+ return ""
+
+ def _do_code_blocks(self, text):
+ """Process Markdown `` blocks."""
+ code_block_re = re.compile(r'''
+ (?:\n\n|\A\n?)
+ ( # $1 = the code block -- one or more lines, starting with a space/tab
+ (?:
+ (?:[ ]{%d} | \t) # Lines must start with a tab or a tab-width of spaces
+ .*\n+
+ )+
+ )
+ ((?=^[ ]{0,%d}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
+ ''' % (self.tab_width, self.tab_width),
+ re.M | re.X)
+ return code_block_re.sub(self._code_block_sub, text)
+
+ _fenced_code_block_re = re.compile(r'''
+ (?:\n\n|\A\n?)
+ ^```([\w+-]+)?[ \t]*\n # opening fence, $1 = optional lang
+ (.*?) # $2 = code block content
+ ^```[ \t]*\n # closing fence
+ ''', re.M | re.X | re.S)
+
+ def _fenced_code_block_sub(self, match):
+ return self._code_block_sub(match, is_fenced_code_block=True);
+
+ def _do_fenced_code_blocks(self, text):
+ """Process ```-fenced unindented code blocks ('fenced-code-blocks' extra)."""
+ return self._fenced_code_block_re.sub(self._fenced_code_block_sub, text)
+
+ # Rules for a code span:
+ # - backslash escapes are not interpreted in a code span
+ # - to include one or or a run of more backticks the delimiters must
+ # be a longer run of backticks
+ # - cannot start or end a code span with a backtick; pad with a
+ # space and that space will be removed in the emitted HTML
+ # See `test/tm-cases/escapes.text` for a number of edge-case
+ # examples.
+ _code_span_re = re.compile(r'''
+ (?%s
" % c
+
+ def _do_code_spans(self, text):
+ # * Backtick quotes are used for
spans.
+ #
+ # * You can use multiple backticks as the delimiters if you want to
+ # include literal backticks in the code span. So, this input:
+ #
+ # Just type ``foo `bar` baz`` at the prompt.
+ #
+ # Will translate to:
+ #
+ # Just type foo `bar` baz
at the prompt.
+ #
+ # There's no arbitrary limit to the number of backticks you
+ # can use as delimters. If you need three consecutive backticks
+ # in your code, use four for delimiters, etc.
+ #
+ # * You can use spaces to get literal backticks at the edges:
+ #
+ # ... type `` `bar` `` ...
+ #
+ # Turns to:
+ #
+ # ... type `bar`
...
+ return self._code_span_re.sub(self._code_span_sub, text)
+
+ def _encode_code(self, text):
+ """Encode/escape certain characters inside Markdown code runs.
+ The point is that in code, these characters are literals,
+ and lose their special Markdown meanings.
+ """
+ replacements = [
+ # Encode all ampersands; HTML entities are not
+ # entities within a Markdown code span.
+ ('&', '&'),
+ # Do the angle bracket song and dance:
+ ('<', '<'),
+ ('>', '>'),
+ ]
+ for before, after in replacements:
+ text = text.replace(before, after)
+ hashed = _hash_text(text)
+ self._escape_table[text] = hashed
+ return hashed
+
+ _strong_re = re.compile(r"(\*\*|__)(?=\S)(.+?[*_]*)(?<=\S)\1", re.S)
+ _em_re = re.compile(r"(\*|_)(?=\S)(.+?)(?<=\S)\1", re.S)
+ _code_friendly_strong_re = re.compile(r"\*\*(?=\S)(.+?[*_]*)(?<=\S)\*\*", re.S)
+ _code_friendly_em_re = re.compile(r"\*(?=\S)(.+?)(?<=\S)\*", re.S)
+ def _do_italics_and_bold(self, text):
+ # must go first:
+ if "code-friendly" in self.extras:
+ text = self._code_friendly_strong_re.sub(r"\1", text)
+ text = self._code_friendly_em_re.sub(r"\1", text)
+ else:
+ text = self._strong_re.sub(r"\2", text)
+ text = self._em_re.sub(r"\2", text)
+ return text
+
+ # "smarty-pants" extra: Very liberal in interpreting a single prime as an
+ # apostrophe; e.g. ignores the fact that "round", "bout", "twer", and
+ # "twixt" can be written without an initial apostrophe. This is fine because
+ # using scare quotes (single quotation marks) is rare.
+ _apostrophe_year_re = re.compile(r"'(\d\d)(?=(\s|,|;|\.|\?|!|$))")
+ _contractions = ["tis", "twas", "twer", "neath", "o", "n",
+ "round", "bout", "twixt", "nuff", "fraid", "sup"]
+ def _do_smart_contractions(self, text):
+ text = self._apostrophe_year_re.sub(r"’\1", text)
+ for c in self._contractions:
+ text = text.replace("'%s" % c, "’%s" % c)
+ text = text.replace("'%s" % c.capitalize(),
+ "’%s" % c.capitalize())
+ return text
+
+ # Substitute double-quotes before single-quotes.
+ _opening_single_quote_re = re.compile(r"(?
+ See "test/tm-cases/smarty_pants.text" for a full discussion of the
+ support here and
+ for a
+ discussion of some diversion from the original SmartyPants.
+ """
+ if "'" in text: # guard for perf
+ text = self._do_smart_contractions(text)
+ text = self._opening_single_quote_re.sub("‘", text)
+ text = self._closing_single_quote_re.sub("’", text)
+
+ if '"' in text: # guard for perf
+ text = self._opening_double_quote_re.sub("“", text)
+ text = self._closing_double_quote_re.sub("”", text)
+
+ text = text.replace("---", "—")
+ text = text.replace("--", "–")
+ text = text.replace("...", "…")
+ text = text.replace(" . . . ", "…")
+ text = text.replace(". . .", "…")
+ return text
+
+ _block_quote_re = re.compile(r'''
+ ( # Wrap whole match in \1
+ (
+ ^[ \t]*>[ \t]? # '>' at the start of a line
+ .+\n # rest of the first line
+ (.+\n)* # subsequent consecutive lines
+ \n* # blanks
+ )+
+ )
+ ''', re.M | re.X)
+ _bq_one_level_re = re.compile('^[ \t]*>[ \t]?', re.M);
+
+ _html_pre_block_re = re.compile(r'(\s*.+?
)', re.S)
+ def _dedent_two_spaces_sub(self, match):
+ return re.sub(r'(?m)^ ', '', match.group(1))
+
+ def _block_quote_sub(self, match):
+ bq = match.group(1)
+ bq = self._bq_one_level_re.sub('', bq) # trim one level of quoting
+ bq = self._ws_only_line_re.sub('', bq) # trim whitespace-only lines
+ bq = self._run_block_gamut(bq) # recurse
+
+ bq = re.sub('(?m)^', ' ', bq)
+ # These leading spaces screw with content, so we need to fix that:
+ bq = self._html_pre_block_re.sub(self._dedent_two_spaces_sub, bq)
+
+ return "\n%s\n
\n\n" % bq
+
+ def _do_block_quotes(self, text):
+ if '>' not in text:
+ return text
+ return self._block_quote_re.sub(self._block_quote_sub, text)
+
+ def _form_paragraphs(self, text):
+ # Strip leading and trailing lines:
+ text = text.strip('\n')
+
+ # Wrap tags.
+ grafs = []
+ for i, graf in enumerate(re.split(r"\n{2,}", text)):
+ if graf in self.html_blocks:
+ # Unhashify HTML blocks
+ grafs.append(self.html_blocks[graf])
+ else:
+ cuddled_list = None
+ if "cuddled-lists" in self.extras:
+ # Need to put back trailing '\n' for `_list_item_re`
+ # match at the end of the paragraph.
+ li = self._list_item_re.search(graf + '\n')
+ # Two of the same list marker in this paragraph: a likely
+ # candidate for a list cuddled to preceding paragraph
+ # text (issue 33). Note the `[-1]` is a quick way to
+ # consider numeric bullets (e.g. "1." and "2.") to be
+ # equal.
+ if (li and len(li.group(2)) <= 3 and li.group("next_marker")
+ and li.group("marker")[-1] == li.group("next_marker")[-1]):
+ start = li.start()
+ cuddled_list = self._do_lists(graf[start:]).rstrip("\n")
+ assert cuddled_list.startswith("
") or cuddled_list.startswith("")
+ graf = graf[:start]
+
+ # Wrap tags.
+ graf = self._run_span_gamut(graf)
+ grafs.append("
" + graf.lstrip(" \t") + "
")
+
+ if cuddled_list:
+ grafs.append(cuddled_list)
+
+ return "\n\n".join(grafs)
+
+ def _add_footnotes(self, text):
+ if self.footnotes:
+ footer = [
+ '',
+ '
',
+ ]
+ for i, id in enumerate(self.footnote_ids):
+ if i != 0:
+ footer.append('')
+ footer.append('- ' % id)
+ footer.append(self._run_block_gamut(self.footnotes[id]))
+ backlink = (''
+ '↩' % (id, i+1))
+ if footer[-1].endswith(""):
+ footer[-1] = footer[-1][:-len("")] \
+ + ' ' + backlink + ""
+ else:
+ footer.append("\n
%s
" % backlink)
+ footer.append(' ')
+ footer.append('')
+ footer.append('')
+ return text + '\n\n' + '\n'.join(footer)
+ else:
+ return text
+
+ # Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
+ # http://bumppo.net/projects/amputator/
+ _ampersand_re = re.compile(r'&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)')
+ _naked_lt_re = re.compile(r'<(?![a-z/?\$!])', re.I)
+ _naked_gt_re = re.compile(r'''(?''', re.I)
+
+ def _encode_amps_and_angles(self, text):
+ # Smart processing for ampersands and angle brackets that need
+ # to be encoded.
+ text = self._ampersand_re.sub('&', text)
+
+ # Encode naked <'s
+ text = self._naked_lt_re.sub('<', text)
+
+ # Encode naked >'s
+ # Note: Other markdown implementations (e.g. Markdown.pl, PHP
+ # Markdown) don't do this.
+ text = self._naked_gt_re.sub('>', text)
+ return text
+
+ def _encode_backslash_escapes(self, text):
+ for ch, escape in list(self._escape_table.items()):
+ text = text.replace("\\"+ch, escape)
+ return text
+
+ _auto_link_re = re.compile(r'<((https?|ftp):[^\'">\s]+)>', re.I)
+ def _auto_link_sub(self, match):
+ g1 = match.group(1)
+ return '%s' % (g1, g1)
+
+ _auto_email_link_re = re.compile(r"""
+ <
+ (?:mailto:)?
+ (
+ [-.\w]+
+ \@
+ [-\w]+(\.[-\w]+)*\.[a-z]+
+ )
+ >
+ """, re.I | re.X | re.U)
+ def _auto_email_link_sub(self, match):
+ return self._encode_email_address(
+ self._unescape_special_chars(match.group(1)))
+
+ def _do_auto_links(self, text):
+ text = self._auto_link_re.sub(self._auto_link_sub, text)
+ text = self._auto_email_link_re.sub(self._auto_email_link_sub, text)
+ return text
+
+ def _encode_email_address(self, addr):
+ # Input: an email address, e.g. "foo@example.com"
+ #
+ # Output: the email address as a mailto link, with each character
+ # of the address encoded as either a decimal or hex entity, in
+ # the hopes of foiling most address harvesting spam bots. E.g.:
+ #
+ # foo
+ # @example.com
+ #
+ # Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
+ # mailing list:
+ chars = [_xml_encode_email_char_at_random(ch)
+ for ch in "mailto:" + addr]
+ # Strip the mailto: from the visible part.
+ addr = '%s' \
+ % (''.join(chars), ''.join(chars[7:]))
+ return addr
+
+ def _do_link_patterns(self, text):
+ """Caveat emptor: there isn't much guarding against link
+ patterns being formed inside other standard Markdown links, e.g.
+ inside a [link def][like this].
+
+ Dev Notes: *Could* consider prefixing regexes with a negative
+ lookbehind assertion to attempt to guard against this.
+ """
+ link_from_hash = {}
+ for regex, repl in self.link_patterns:
+ replacements = []
+ for match in regex.finditer(text):
+ if hasattr(repl, "__call__"):
+ href = repl(match)
+ else:
+ href = match.expand(repl)
+ replacements.append((match.span(), href))
+ for (start, end), href in reversed(replacements):
+ escaped_href = (
+ href.replace('"', '"') # b/c of attr quote
+ # To avoid markdown and :
+ .replace('*', self._escape_table['*'])
+ .replace('_', self._escape_table['_']))
+ link = '%s' % (escaped_href, text[start:end])
+ hash = _hash_text(link)
+ link_from_hash[hash] = link
+ text = text[:start] + hash + text[end:]
+ for hash, link in list(link_from_hash.items()):
+ text = text.replace(hash, link)
+ return text
+
+ def _unescape_special_chars(self, text):
+ # Swap back in all the special characters we've hidden.
+ for ch, hash in list(self._escape_table.items()):
+ text = text.replace(hash, ch)
+ return text
+
+ def _outdent(self, text):
+ # Remove one level of line-leading tabs or spaces
+ return self._outdent_re.sub('', text)
+
+
+class MarkdownWithExtras(Markdown):
+ """A markdowner class that enables most extras:
+
+ - footnotes
+ - code-color (only has effect if 'pygments' Python module on path)
+
+ These are not included:
+ - pyshell (specific to Python-related documenting)
+ - code-friendly (because it *disables* part of the syntax)
+ - link-patterns (because you need to specify some actual
+ link-patterns anyway)
+ """
+ extras = ["footnotes", "code-color"]
+
+
+#---- internal support functions
+
+class UnicodeWithAttrs(unicode):
+ """A subclass of unicode used for the return value of conversion to
+ possibly attach some attributes. E.g. the "toc_html" attribute when
+ the "toc" extra is used.
+ """
+ metadata = None
+ _toc = None
+ def toc_html(self):
+ """Return the HTML for the current TOC.
+
+ This expects the `_toc` attribute to have been set on this instance.
+ """
+ if self._toc is None:
+ return None
+
+ def indent():
+ return ' ' * (len(h_stack) - 1)
+ lines = []
+ h_stack = [0] # stack of header-level numbers
+ for level, id, name in self._toc:
+ if level > h_stack[-1]:
+ lines.append("%s" % indent())
+ h_stack.append(level)
+ elif level == h_stack[-1]:
+ lines[-1] += ""
+ else:
+ while level < h_stack[-1]:
+ h_stack.pop()
+ if not lines[-1].endswith(""):
+ lines[-1] += ""
+ lines.append("%s
" % indent())
+ lines.append('%s- %s' % (
+ indent(), id, name))
+ while len(h_stack) > 1:
+ h_stack.pop()
+ if not lines[-1].endswith("
"):
+ lines[-1] += ""
+ lines.append("%s
" % indent())
+ return '\n'.join(lines) + '\n'
+ toc_html = property(toc_html)
+
+## {{{ http://code.activestate.com/recipes/577257/ (r1)
+_slugify_strip_re = re.compile(r'[^\w\s-]')
+_slugify_hyphenate_re = re.compile(r'[-\s]+')
+def _slugify(value):
+ """
+ Normalizes string, converts to lowercase, removes non-alpha characters,
+ and converts spaces to hyphens.
+
+ From Django's "django/template/defaultfilters.py".
+ """
+
+ try:
+ import unicodedata
+ value = unicodedata.normalize('NFKD', value)
+ except ImportError:
+ pass
+ value = value.encode('ascii', 'ignore').decode()
+ value = _slugify_strip_re.sub('', value).strip().lower()
+ return _slugify_hyphenate_re.sub('-', value)
+## end of http://code.activestate.com/recipes/577257/ }}}
+
+
+# From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
+def _curry(*args, **kwargs):
+ function, args = args[0], args[1:]
+ def result(*rest, **kwrest):
+ combined = kwargs.copy()
+ combined.update(kwrest)
+ return function(*args + rest, **combined)
+ return result
+
+# Recipe: regex_from_encoded_pattern (1.0)
+def _regex_from_encoded_pattern(s):
+ """'foo' -> re.compile(re.escape('foo'))
+ '/foo/' -> re.compile('foo')
+ '/foo/i' -> re.compile('foo', re.I)
+ """
+ if s.startswith('/') and s.rfind('/') != 0:
+ # Parse it: /PATTERN/FLAGS
+ idx = s.rfind('/')
+ pattern, flags_str = s[1:idx], s[idx+1:]
+ flag_from_char = {
+ "i": re.IGNORECASE,
+ "l": re.LOCALE,
+ "s": re.DOTALL,
+ "m": re.MULTILINE,
+ "u": re.UNICODE,
+ }
+ flags = 0
+ for char in flags_str:
+ try:
+ flags |= flag_from_char[char]
+ except KeyError:
+ raise ValueError("unsupported regex flag: '%s' in '%s' "
+ "(must be one of '%s')"
+ % (char, s, ''.join(list(flag_from_char.keys()))))
+ return re.compile(s[1:idx], flags)
+ else: # not an encoded regex
+ return re.compile(re.escape(s))
+
+# Recipe: dedent (0.1.2)
+def _dedentlines(lines, tabsize=8, skip_first_line=False):
+ """_dedentlines(lines, tabsize=8, skip_first_line=False) -> dedented lines
+
+ "lines" is a list of lines to dedent.
+ "tabsize" is the tab width to use for indent width calculations.
+ "skip_first_line" is a boolean indicating if the first line should
+ be skipped for calculating the indent width and for dedenting.
+ This is sometimes useful for docstrings and similar.
+
+ Same as dedent() except operates on a sequence of lines. Note: the
+ lines list is modified **in-place**.
+ """
+ DEBUG = False
+ if DEBUG:
+ print("dedent: dedent(..., tabsize=%d, skip_first_line=%r)"\
+ % (tabsize, skip_first_line))
+ indents = []
+ margin = None
+ for i, line in enumerate(lines):
+ if i == 0 and skip_first_line: continue
+ indent = 0
+ for ch in line:
+ if ch == ' ':
+ indent += 1
+ elif ch == '\t':
+ indent += tabsize - (indent % tabsize)
+ elif ch in '\r\n':
+ continue # skip all-whitespace lines
+ else:
+ break
+ else:
+ continue # skip all-whitespace lines
+ if DEBUG: print("dedent: indent=%d: %r" % (indent, line))
+ if margin is None:
+ margin = indent
+ else:
+ margin = min(margin, indent)
+ if DEBUG: print("dedent: margin=%r" % margin)
+
+ if margin is not None and margin > 0:
+ for i, line in enumerate(lines):
+ if i == 0 and skip_first_line: continue
+ removed = 0
+ for j, ch in enumerate(line):
+ if ch == ' ':
+ removed += 1
+ elif ch == '\t':
+ removed += tabsize - (removed % tabsize)
+ elif ch in '\r\n':
+ if DEBUG: print("dedent: %r: EOL -> strip up to EOL" % line)
+ lines[i] = lines[i][j:]
+ break
+ else:
+ raise ValueError("unexpected non-whitespace char %r in "
+ "line %r while removing %d-space margin"
+ % (ch, line, margin))
+ if DEBUG:
+ print("dedent: %r: %r -> removed %d/%d"\
+ % (line, ch, removed, margin))
+ if removed == margin:
+ lines[i] = lines[i][j+1:]
+ break
+ elif removed > margin:
+ lines[i] = ' '*(removed-margin) + lines[i][j+1:]
+ break
+ else:
+ if removed:
+ lines[i] = lines[i][removed:]
+ return lines
+
+def _dedent(text, tabsize=8, skip_first_line=False):
+ """_dedent(text, tabsize=8, skip_first_line=False) -> dedented text
+
+ "text" is the text to dedent.
+ "tabsize" is the tab width to use for indent width calculations.
+ "skip_first_line" is a boolean indicating if the first line should
+ be skipped for calculating the indent width and for dedenting.
+ This is sometimes useful for docstrings and similar.
+
+ textwrap.dedent(s), but don't expand tabs to spaces
+ """
+ lines = text.splitlines(1)
+ _dedentlines(lines, tabsize=tabsize, skip_first_line=skip_first_line)
+ return ''.join(lines)
+
+
+class _memoized(object):
+ """Decorator that caches a function's return value each time it is called.
+ If called later with the same arguments, the cached value is returned, and
+ not re-evaluated.
+
+ http://wiki.python.org/moin/PythonDecoratorLibrary
+ """
+ def __init__(self, func):
+ self.func = func
+ self.cache = {}
+ def __call__(self, *args):
+ try:
+ return self.cache[args]
+ except KeyError:
+ self.cache[args] = value = self.func(*args)
+ return value
+ except TypeError:
+ # uncachable -- for instance, passing a list as an argument.
+ # Better to not cache than to blow up entirely.
+ return self.func(*args)
+ def __repr__(self):
+ """Return the function's docstring."""
+ return self.func.__doc__
+
+
+def _xml_oneliner_re_from_tab_width(tab_width):
+ """Standalone XML processing instruction regex."""
+ return re.compile(r"""
+ (?:
+ (?<=\n\n) # Starting after a blank line
+ | # or
+ \A\n? # the beginning of the doc
+ )
+ ( # save in $1
+ [ ]{0,%d}
+ (?:
+ <\?\w+\b\s+.*?\?> # XML processing instruction
+ |
+ <\w+:\w+\b\s+.*?/> # namespaced single tag
+ )
+ [ \t]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+ )
+ """ % (tab_width - 1), re.X)
+_xml_oneliner_re_from_tab_width = _memoized(_xml_oneliner_re_from_tab_width)
+
+def _hr_tag_re_from_tab_width(tab_width):
+ return re.compile(r"""
+ (?:
+ (?<=\n\n) # Starting after a blank line
+ | # or
+ \A\n? # the beginning of the doc
+ )
+ ( # save in \1
+ [ ]{0,%d}
+ <(hr) # start tag = \2
+ \b # word break
+ ([^<>])*? #
+ /?> # the matching end tag
+ [ \t]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+ )
+ """ % (tab_width - 1), re.X)
+_hr_tag_re_from_tab_width = _memoized(_hr_tag_re_from_tab_width)
+
+
+def _xml_escape_attr(attr, skip_single_quote=True):
+ """Escape the given string for use in an HTML/XML tag attribute.
+
+ By default this doesn't bother with escaping `'` to `'`, presuming that
+ the tag attribute is surrounded by double quotes.
+ """
+ escaped = (attr
+ .replace('&', '&')
+ .replace('"', '"')
+ .replace('<', '<')
+ .replace('>', '>'))
+ if not skip_single_quote:
+ escaped = escaped.replace("'", "'")
+ return escaped
+
+
+def _xml_encode_email_char_at_random(ch):
+ r = random()
+ # Roughly 10% raw, 45% hex, 45% dec.
+ # '@' *must* be encoded. I [John Gruber] insist.
+ # Issue 26: '_' must be encoded.
+ if r > 0.9 and ch not in "@_":
+ return ch
+ elif r < 0.45:
+ # The [1:] is to drop leading '0': 0x63 -> x63
+ return '%s;' % hex(ord(ch))[1:]
+ else:
+ return '%s;' % ord(ch)
+
+
+
+#---- mainline
+
+class _NoReflowFormatter(optparse.IndentedHelpFormatter):
+ """An optparse formatter that does NOT reflow the description."""
+ def format_description(self, description):
+ return description or ""
+
+def _test():
+ import doctest
+ doctest.testmod()
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv
+ if not logging.root.handlers:
+ logging.basicConfig()
+
+ usage = "usage: %prog [PATHS...]"
+ version = "%prog "+__version__
+ parser = optparse.OptionParser(prog="markdown2", usage=usage,
+ version=version, description=cmdln_desc,
+ formatter=_NoReflowFormatter())
+ parser.add_option("-v", "--verbose", dest="log_level",
+ action="store_const", const=logging.DEBUG,
+ help="more verbose output")
+ parser.add_option("--encoding",
+ help="specify encoding of text content")
+ parser.add_option("--html4tags", action="store_true", default=False,
+ help="use HTML 4 style for empty element tags")
+ parser.add_option("-s", "--safe", metavar="MODE", dest="safe_mode",
+ help="sanitize literal HTML: 'escape' escapes "
+ "HTML meta chars, 'replace' replaces with an "
+ "[HTML_REMOVED] note")
+ parser.add_option("-x", "--extras", action="append",
+ help="Turn on specific extra features (not part of "
+ "the core Markdown spec). See above.")
+ parser.add_option("--use-file-vars",
+ help="Look for and use Emacs-style 'markdown-extras' "
+ "file var to turn on extras. See "
+ "")
+ parser.add_option("--link-patterns-file",
+ help="path to a link pattern file")
+ parser.add_option("--self-test", action="store_true",
+ help="run internal self-tests (some doctests)")
+ parser.add_option("--compare", action="store_true",
+ help="run against Markdown.pl as well (for testing)")
+ parser.set_defaults(log_level=logging.INFO, compare=False,
+ encoding="utf-8", safe_mode=None, use_file_vars=False)
+ opts, paths = parser.parse_args()
+ log.setLevel(opts.log_level)
+
+ if opts.self_test:
+ return _test()
+
+ if opts.extras:
+ extras = {}
+ for s in opts.extras:
+ splitter = re.compile("[,;: ]+")
+ for e in splitter.split(s):
+ if '=' in e:
+ ename, earg = e.split('=', 1)
+ try:
+ earg = int(earg)
+ except ValueError:
+ pass
+ else:
+ ename, earg = e, None
+ extras[ename] = earg
+ else:
+ extras = None
+
+ if opts.link_patterns_file:
+ link_patterns = []
+ f = open(opts.link_patterns_file)
+ try:
+ for i, line in enumerate(f.readlines()):
+ if not line.strip(): continue
+ if line.lstrip().startswith("#"): continue
+ try:
+ pat, href = line.rstrip().rsplit(None, 1)
+ except ValueError:
+ raise MarkdownError("%s:%d: invalid link pattern line: %r"
+ % (opts.link_patterns_file, i+1, line))
+ link_patterns.append(
+ (_regex_from_encoded_pattern(pat), href))
+ finally:
+ f.close()
+ else:
+ link_patterns = None
+
+ from os.path import join, dirname, abspath, exists
+ markdown_pl = join(dirname(dirname(abspath(__file__))), "test",
+ "Markdown.pl")
+ if not paths:
+ paths = ['-']
+ for path in paths:
+ if path == '-':
+ text = sys.stdin.read()
+ else:
+ fp = codecs.open(path, 'r', opts.encoding)
+ text = fp.read()
+ fp.close()
+ if opts.compare:
+ from subprocess import Popen, PIPE
+ print("==== Markdown.pl ====")
+ p = Popen('perl %s' % markdown_pl, shell=True, stdin=PIPE, stdout=PIPE, close_fds=True)
+ p.stdin.write(text.encode('utf-8'))
+ p.stdin.close()
+ perl_html = p.stdout.read().decode('utf-8')
+ if py3:
+ sys.stdout.write(perl_html)
+ else:
+ sys.stdout.write(perl_html.encode(
+ sys.stdout.encoding or "utf-8", 'xmlcharrefreplace'))
+ print("==== markdown2.py ====")
+ html = markdown(text,
+ html4tags=opts.html4tags,
+ safe_mode=opts.safe_mode,
+ extras=extras, link_patterns=link_patterns,
+ use_file_vars=opts.use_file_vars)
+ if py3:
+ sys.stdout.write(html)
+ else:
+ sys.stdout.write(html.encode(
+ sys.stdout.encoding or "utf-8", 'xmlcharrefreplace'))
+ if extras and "toc" in extras:
+ log.debug("toc_html: " +
+ html.toc_html.encode(sys.stdout.encoding or "utf-8", 'xmlcharrefreplace'))
+ if opts.compare:
+ test_dir = join(dirname(dirname(abspath(__file__))), "test")
+ if exists(join(test_dir, "test_markdown2.py")):
+ sys.path.insert(0, test_dir)
+ from test_markdown2 import norm_html_from_html
+ norm_html = norm_html_from_html(html)
+ norm_perl_html = norm_html_from_html(perl_html)
+ else:
+ norm_html = html
+ norm_perl_html = perl_html
+ print("==== match? %r ====" % (norm_perl_html == norm_html))
+
+
+if __name__ == "__main__":
+ sys.exit( main(sys.argv) )
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/package-metadata.json
new file mode 100644
index 0000000..94a33d4
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/revolunet/sublimetext-markdown-preview", "version": "2013.04.01.18.50.45", "description": "markdown preview plugin for sublime text 2"}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/sample.html b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/sample.html
new file mode 100644
index 0000000..c63eacd
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/sample.html
@@ -0,0 +1,141 @@
+Sample Markdown Cheat Sheet
+
+This is a sample markdown file to help you write Markdown quickly :)
+
+If you use the fabulous Sublime Text 2 editor along with the Markdown Preview plugin, open your ST2 Palette with CMD+P
then choose Markdown Preview in browser
to see the result in your browser.
+
+Text basics
+
+this is italic and this is bold . another italic and another bold
+
+this is important
text. and percentage signs : % and %
+
+This is a paragraph with a footnote (builtin parser only). 1
+
+Insert [ toc ]
without spaces to generate a table of contents (builtin parser only).
+
+Indentation
+
+
+ Here is some indented text
+
+
+ even more indented
+
+
+
+Titles
+
+Big title (h1)
+
+Middle title (h2)
+
+Smaller title (h3)
+
+and so on (hX)
+
+and so on (hX)
+
+and so on (hX)
+
+Example lists (1)
+
+
+- bullets can be
-
, +
, or *
+- bullet list 1
+bullet list 2
+
+
+- sub item 1
+sub item 2
+
+with indented text inside
+
+bullet list 3
+- bullet list 4
+- bullet list 5
+
+
+Links
+
+This is an example inline link and another one with a title.
+
+Links can also be reference based : reference 1 or reference 2 with title.
+
+References are usually placed at the bottom of the document
+
+Images
+
+A sample image :
+
+
+
+As links, images can also use references instead of inline links :
+
+
+
+Code
+
+It's quite easy to show code in markdown files.
+
+Backticks can be used to highlight
some words.
+
+Also, any indented block is considered a code block.
+
+<script>
+ document.location = 'http://lmgtfy.com/?q=markdown+cheat+sheet';
+</script>
+
+
+GitHub Flavored Markdown
+
+If you use the Github parser, you can use some of Github Flavored Markdown syntax :
+
+
+- User/Project@SHA: revolunet/sublimetext-markdown-preview@7da61badeda468b5019869d11000307e07e07401
+- User/Project#Issue: revolunet/sublimetext-markdown-preview#1
+- User : @revolunet
+
+
+Some Python code :
+
+import random
+
+class CardGame(object):
+ """ a sample python class """
+ NB_CARDS = 32
+ def __init__(self, cards=5):
+ self.cards = random.sample(range(self.NB_CARDS), 5)
+ print 'ready to play'
+
+
+Some Javascript code :
+
+var config = {
+ duration: 5,
+ comment: 'WTF'
+}
+// callbacks beauty un action
+async_call('/path/to/api', function(json) {
+ another_call(json, function(result2) {
+ another_another_call(result2, function(result3) {
+ another_another_another_call(result3, function(result4) {
+ alert('And if all went well, i got my result :)');
+ });
+ });
+ });
+})
+
+
+About
+
+This plugin and this sample file is proudly brought to you by the revolunet team
+
+
+
+
+-
+
This is the text of the note. ↩
+
+
+
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/sample.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/sample.md
new file mode 100644
index 0000000..abf7b25
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Markdown Preview/sample.md
@@ -0,0 +1,132 @@
+Sample Markdown Cheat Sheet
+===========================
+
+This is a sample markdown file to help you write Markdown quickly :)
+
+If you use the fabulous [Sublime Text 2 editor][ST2] along with the [Markdown Preview plugin][MarkdownPreview], open your ST2 Palette with `CMD+P` then choose `Markdown Preview in browser` to see the result in your browser.
+
+## Text basics
+this is *italic* and this is **bold** . another _italic_ and another __bold__
+
+this is `important` text. and percentage signs : % and `%`
+
+This is a paragraph with a footnote (builtin parser only). [^note-id]
+
+Insert `[ toc ]` without spaces to generate a table of contents (builtin parser only).
+
+## Indentation
+> Here is some indented text
+>> even more indented
+
+## Titles
+# Big title (h1)
+## Middle title (h2)
+### Smaller title (h3)
+#### and so on (hX)
+##### and so on (hX)
+###### and so on (hX)
+
+## Example lists (1)
+
+ - bullets can be `-`, `+`, or `*`
+ - bullet list 1
+ - bullet list 2
+ - sub item 1
+ - sub item 2
+
+ with indented text inside
+
+ - bullet list 3
+ + bullet list 4
+ * bullet list 5
+
+## Links
+
+This is an [example inline link](http://lmgtfy.com/) and [another one with a title](http://lmgtfy.com/ "Hello, world").
+
+Links can also be reference based : [reference 1][ref1] or [reference 2 with title][ref2].
+
+References are usually placed at the bottom of the document
+
+## Images
+
+A sample image :
+
+
+
+As links, images can also use references instead of inline links :
+
+![revolunet logo][revolunet-logo]
+
+
+## Code
+
+It's quite easy to show code in markdown files.
+
+Backticks can be used to `highlight` some words.
+
+Also, any indented block is considered a code block.
+
+
+
+## GitHub Flavored Markdown
+
+If you use the Github parser, you can use some of [Github Flavored Markdown][gfm] syntax :
+
+ * User/Project@SHA: revolunet/sublimetext-markdown-preview@7da61badeda468b5019869d11000307e07e07401
+ * User/Project#Issue: revolunet/sublimetext-markdown-preview#1
+ * User : @revolunet
+
+Some Python code :
+
+```python
+import random
+
+class CardGame(object):
+ """ a sample python class """
+ NB_CARDS = 32
+ def __init__(self, cards=5):
+ self.cards = random.sample(range(self.NB_CARDS), 5)
+ print 'ready to play'
+```
+
+Some Javascript code :
+
+```js
+var config = {
+ duration: 5,
+ comment: 'WTF'
+}
+// callbacks beauty un action
+async_call('/path/to/api', function(json) {
+ another_call(json, function(result2) {
+ another_another_call(result2, function(result3) {
+ another_another_another_call(result3, function(result4) {
+ alert('And if all went well, i got my result :)');
+ });
+ });
+ });
+})
+```
+
+The Github Markdown also brings some [nice Emoji support][emoji] : :+1: :heart: :beer:
+
+[^note-id]: This is the text of the note.
+
+## About
+
+This plugin and this sample file is proudly brought to you by the [revolunet team][revolunet]
+
+ [ref1]: http://revolunet.com
+ [ref2]: http://revolunet.com "rich web apps"
+ [MarkdownREF]: http://daringfireball.net/projects/markdown/basics
+ [MarkdownPreview]: https://github.com/revolunet/sublimetext-markdown-preview
+ [ST2]: http://sublimetext.com
+ [revolunet]: http://revolunet.com
+ [revolunet-logo]: http://www.revolunet.com/static/parisjs8/img/logo-revolunet-carre.jpg "revolunet logo"
+ [gfm]: http://github.github.com/github-flavored-markdown/
+ [emoji]: http://www.emoji-cheat-sheet.com/
+
+
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/Missing.sublime-commands b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/Missing.sublime-commands
new file mode 100644
index 0000000..6fdf4ab
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/Missing.sublime-commands
@@ -0,0 +1,115 @@
+[
+ // File Menu
+ { "caption": "Exit Sublime Text 2", "command": "exit" },
+ { "caption": "New Window", "command": "new_window"},
+ { "caption": "Close Window", "command": "close_window" },
+ { "caption": "File: Save As", "command": "prompt_save_as" },
+ { "caption": "File: Close", "command": "close" },
+ { "caption": "File: Reopen Closed File", "command": "reopen_last_file" },
+
+ // Edit Menu
+ { "caption": "Code Folding: Fold All", "command": "fold_by_level", "args": {"level": 1} },
+
+ { "caption": "Permute Lines: Reverse", "command": "permute_lines", "args": {"operation": "reverse"} },
+ { "caption": "Permute Lines: Unique", "command": "permute_lines", "args": {"operation": "unique"} },
+ { "caption": "Permute Lines: Shuffle", "command": "permute_lines", "args": {"operation": "shuffle"} },
+
+ { "caption": "Permute Selections: Sort", "command": "sort_selection", "args": {"case_sensitive": false} },
+ { "caption": "Permute Selections: Sort (Case Sensitive)", "command": "sort_selection", "args": {"case_sensitive": true} },
+ { "caption": "Permute Selections: Reverse", "command": "permute_selection", "args": {"operation": "reverse"} },
+ { "caption": "Permute Selections: Unique", "command": "permute_selection", "args": {"operation": "unique"} },
+ { "caption": "Permute Selections: Shuffle", "command": "permute_selection", "args": {"operation": "shuffle"} },
+
+ // Find Menu
+ { "caption": "Find", "command": "show_panel", "args": {"panel": "find"} },
+ { "caption": "Find in Files", "command": "show_panel", "args": {"panel": "find_in_files"} },
+ { "caption": "Replace", "command": "show_panel", "args": {"panel": "replace"} },
+ { "caption": "Show Find Results Panel", "command": "show_panel", "args": {"panel": "output.find_results"} },
+
+ { "caption": "Next Result", "command": "next_result" },
+ { "caption": "Previous Result", "command": "previous_result" },
+
+ // View Menu
+ { "caption": "View: Toggle Fullscreen", "command": "toggle_full_screen" },
+ { "caption": "View: Toggle Distraction Free mode", "command": "toggle_distraction_free" },
+ { "caption": "View: Toggle Console", "command": "show_panel", "args": {"panel": "console", "toggle": true} },
+
+ { "caption": "Indentation: Indent Using Spaces", "command": "toggle_setting", "args": {"setting": "translate_tabs_to_spaces"} },
+ { "caption": "Indentation: Tab Width: 1", "command": "set_setting", "args": {"setting": "tab_size", "value": 1} },
+ { "caption": "Indentation: Tab Width: 2", "command": "set_setting", "args": {"setting": "tab_size", "value": 2} },
+ { "caption": "Indentation: Tab Width: 3", "command": "set_setting", "args": {"setting": "tab_size", "value": 3} },
+ { "caption": "Indentation: Tab Width: 4", "command": "set_setting", "args": {"setting": "tab_size", "value": 4} },
+ { "caption": "Indentation: Tab Width: 5", "command": "set_setting", "args": {"setting": "tab_size", "value": 5} },
+ { "caption": "Indentation: Tab Width: 6", "command": "set_setting", "args": {"setting": "tab_size", "value": 6} },
+ { "caption": "Indentation: Tab Width: 7", "command": "set_setting", "args": {"setting": "tab_size", "value": 7} },
+ { "caption": "Indentation: Tab Width: 8", "command": "set_setting", "args": {"setting": "tab_size", "value": 8} },
+ { "caption": "Indentation: Guess Settings From Buffer", "command": "detect_indentation" },
+
+ { "caption": "Line Endings: Windows", "command": "set_line_ending", "args": {"type": "windows"} },
+ { "caption": "Line Endings: Unix", "command": "set_line_ending", "args": {"type": "unix"} },
+ { "caption": "Line Endings: Mac OS 9", "command": "set_line_ending", "args": {"type": "cr"} },
+
+ { "caption": "View: Toggle Spell Check", "command": "toggle_setting", "args": {"setting": "spell_check"} },
+ { "caption": "Spell Check: Next Misspelling", "command": "next_misspelling" },
+ { "caption": "Spell Check: Previous Misspelling", "command": "previous_misspelling" },
+
+ { "caption": "Ruler: None", "command": "set_setting", "args": {"setting": "rulers", "value": []}},
+ { "caption": "Ruler: Column 70", "command": "set_setting", "args": {"setting": "rulers", "value": [70]}},
+ { "caption": "Ruler: Column 78", "command": "set_setting", "args": {"setting": "rulers", "value": [78]}},
+ { "caption": "Ruler: Column 80", "command": "set_setting", "args": {"setting": "rulers", "value": [80]}},
+ { "caption": "Ruler: Column 100", "command": "set_setting", "args": {"setting": "rulers", "value": [100]}},
+ { "caption": "Ruler: Column 120", "command": "set_setting", "args": {"setting": "rulers", "value": [120]}},
+
+ { "caption": "Word Wrap: Automatic Column", "command": "set_setting", "args": {"setting": "wrap_width", "value": 0}},
+ { "caption": "Word Wrap: Column 70", "command": "set_setting", "args": {"setting": "wrap_width", "value": 70}},
+ { "caption": "Word Wrap: Column 78", "command": "set_setting", "args": {"setting": "wrap_width", "value": 78}},
+ { "caption": "Word Wrap: Column 80", "command": "set_setting", "args": {"setting": "wrap_width", "value": 80}},
+ { "caption": "Word Wrap: Column 100", "command": "set_setting", "args": {"setting": "wrap_width", "value": 100}},
+ { "caption": "Word Wrap: Column 120", "command": "set_setting", "args": {"setting": "wrap_width", "value": 120}},
+
+ { "caption": "Layout: Single",
+ "command": "set_layout",
+ "args": {"cols": [0.0, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1]]}
+ },
+ { "caption": "Layout: Columns: 2",
+ "command": "set_layout",
+ "args": {"cols": [0.0, 0.5, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]}
+ },
+ { "caption": "Layout: Columns: 3",
+ "command": "set_layout",
+ "args": {"cols": [0.0, 0.33, 0.66, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1], [2, 0, 3, 1]]}
+ },
+ { "caption": "Layout: Columns: 4",
+ "command": "set_layout",
+ "args": {"cols": [0.0, 0.25, 0.5, 0.75, 1.0], "rows": [0.0, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1], [2, 0, 3, 1], [3, 0, 4, 1]]}
+ },
+ { "caption": "Layout: Rows: 2",
+ "command": "set_layout",
+ "args": {"cols": [0.0, 1.0], "rows": [0.0, 0.5, 1.0], "cells": [[0, 0, 1, 1], [0, 1, 1, 2]]}
+ },
+ { "caption": "Layout: Rows: 3",
+ "command": "set_layout",
+ "args": {"cols": [0.0, 1.0], "rows": [0.0, 0.33, 0.66, 1.0], "cells": [[0, 0, 1, 1], [0, 1, 1, 2], [0, 2, 1, 3]]}
+ },
+ { "caption": "Layout: Grid: 4",
+ "command": "set_layout",
+ "args": {"cols": [0.0, 0.5, 1.0], "rows": [0.0, 0.5, 1.0], "cells": [[0, 0, 1, 1], [1, 0, 2, 1], [0, 1, 1, 2], [1, 1, 2, 2]]}
+ },
+
+ // Tools Menu
+ { "caption": "Cancel Build", "command": "exec", "args": {"kill": true} },
+ { "caption": "Show Build Results Panel", "command": "show_panel", "args": {"panel": "output.exec"} },
+
+ // Project Menu
+ { "caption": "Switch Project in Window", "command": "prompt_select_project" },
+ { "caption": "Project: Open Project", "command": "prompt_open_project" },
+ { "caption": "Project: Edit Project", "command": "open_file", "args": {"file": "${project}"} },
+ { "caption": "Project: Remove all Folders", "command": "close_folder_list" },
+ { "caption": "Project: Refresh Folders", "command": "refresh_folder_list" },
+
+ // Preferences Menu
+ { "caption": "Preferences: Syntax Specific – User", "command": "open_file_settings" },
+ { "caption": "Font: Increase Font Size", "command": "increase_font_size" },
+ { "caption": "Font: Decrease Font Size", "command": "decrease_font_size" },
+ { "caption": "Font: Reset Font Size", "command": "reset_font_size" }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/README.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/README.md
new file mode 100644
index 0000000..09f1d1b
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/README.md
@@ -0,0 +1,8 @@
+# Missing Palette Commands
+
+I really like the _Command Palette_ feature of Sublime Text 2.
+The only problem I have with it is that some useful commands
+have been omitted and are only available through the main menu.
+
+This package provides a `.sublime-commands` file that contains
+the missing commands.
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/package-metadata.json
new file mode 100644
index 0000000..e558006
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Missing Palette Commands/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/fjl/Sublime-Missing-Palette-Commands", "version": "2012.08.08.06.49.39", "description": "Menu Commands that are missing from the Sublime Text 2 Command Palette"}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/.gitignore b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Default.sublime-commands b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Default.sublime-commands
new file mode 100644
index 0000000..d55e1e1
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Default.sublime-commands
@@ -0,0 +1,3 @@
+[
+ { "caption": "Related Files", "command": "related_files" }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Default.sublime-keymap b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Default.sublime-keymap
new file mode 100644
index 0000000..9b0a2d1
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Default.sublime-keymap
@@ -0,0 +1,3 @@
+[
+ { "keys": ["ctrl+super+p"], "command": "related_files"}
+]
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Main.sublime-menu b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Main.sublime-menu
new file mode 100644
index 0000000..b9ddbed
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/Main.sublime-menu
@@ -0,0 +1,27 @@
+[
+ {
+ "caption": "Preferences",
+ "mnemonic": "n",
+ "id": "preferences",
+ "children":
+ [
+ {
+ "caption": "Package Settings",
+ "mnemonic": "P",
+ "id": "package-settings",
+ "children":
+ [
+ {
+ "caption": "RelatedFiles",
+ "children":
+ [
+ { "command": "open_file", "args": {"file": "${packages}/Related Files/RelatedFiles.sublime-settings"}, "caption": "Settings – Default" },
+ { "command": "open_file", "args": {"file": "${packages}/User/RelatedFiles.sublime-settings"}, "caption": "Settings – User" },
+ { "caption": "-" }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/README.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/README.md
new file mode 100644
index 0000000..f2fc0f2
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/README.md
@@ -0,0 +1,36 @@
+# Sublime Text 2 - Related Files
+
+
+
+This plugin provides a quick list of related files to the currently open file.
+
+My main use case is to list related files under a Ruby on Rails project. For example, for an opened "app/controllers/examples_controller.rb", related files would be "app/helpers/examples_helper.rb", "app/views/examples/**", and "spec/controllers/examples_controller_spec.rb".
+
+This plugin was inspired by the existing [Open Related](https://github.com/vojtajina/sublime-OpenRelated) and [Rails Related Files](https://github.com/luqman/SublimeText2RailsRelatedFiles).
+
+I wanted something between the two of them (a quick list of results that could be setup for any kinds of projects, not only Rails), so I created my own.
+
+# Key Shortcut
+
+The default shortcut is mapped to "ctrl+super+p". To change it to something more suitable for your needs, you can easily change that by copying the following and replacing the "keys" to your desired key combination:
+
+```json
+{ "keys": ["ctrl+super+p"], "command": "related_files"}
+```
+
+# Configuration
+
+The plugins comes configured to lookup Rails related files, but you can add your own setups. Let's see an existing example:
+
+```json
+// Test/specs for ruby files
+".+\/(app|lib)\/(.+).rb":
+ [
+ "spec/$2_spec.rb",
+ "test/$2_test.rb"
+ ]
+```
+
+The configuration has two parts: the key, which is a regular expression to match against the currently open file, and a list of globs to map the related files.
+
+You can use the $1, $2, etc. on the glob strings to be replace by the extracted parts from the regex.
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/RelatedFiles.sublime-settings b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/RelatedFiles.sublime-settings
new file mode 100644
index 0000000..eb9502c
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/RelatedFiles.sublime-settings
@@ -0,0 +1,84 @@
+{
+ "patterns": {
+ // Test/specs for ruby files
+ ".+\/(app|lib)\/(.+).rb":
+ [
+ "spec/$2_spec.rb",
+ "test/$2_test.rb"
+ ],
+
+ // Ruby files for test/specs
+ ".+\/(test|spec)\/(.+)_(test|spec).rb":
+ [
+ "app/$2.rb",
+ "lib/$2.rb"
+ ],
+
+ // Rails controllers
+ ".+\/app\/controllers\/(.+)_controller.rb":
+ [
+ "app/views/$1/**",
+ "app/helpers/$1_helper.rb",
+ "config/routes.rb",
+ "spec/requests/$1_spec.rb",
+ "spec/routing/$1_routing_spec.rb"
+ ],
+
+ // Rails helpers
+ ".+\/app\/helpers\/(.+)_helper.rb":
+ [
+ "app/views/$1/**",
+ "app/controllers/$1_controller.rb",
+ "config/routes.rb",
+ "spec/requests/$1_spec.rb"
+ ],
+
+ // Rails views
+ ".+\/app\/views\/(.+)\/[^\/].+":
+ [
+ "app/views/$1/**",
+ "app/controllers/$1_controller.rb",
+ "app/helpers/$1_helper.rb",
+ "config/routes.rb",
+ "spec/controllers/$1_spec.rb",
+ "spec/requests/$1_spec.rb"
+ ],
+
+ // Rails routes
+ ".+\/config\/routes.rb":
+ [
+ "spec/routing/**"
+ ],
+
+ // Rails libs
+ ".+\/(lib)\/(.+).rb":
+ [
+ "spec/lib/$2_spec.rb",
+ "test/lib/$2_test.rb"
+ ],
+
+ // Rails controllers specs
+ ".+/spec/controllers/(.+)_controller_spec.rb":
+ [
+ "app/controllers/$1_controller.rb",
+ "app/helpers/$1_helper.rb",
+ "app/views/$1/**",
+ "config/routes.rb"
+ ],
+
+ // Rails request specs
+ ".+/spec/requests/(.+)_spec.rb":
+ [
+ "app/controllers/$1_controller.rb",
+ "app/helpers/$1_helper.rb",
+ "app/views/$1/**",
+ "config/routes.rb"
+ ],
+
+ // Rails libs specs
+ ".+/spec/lib/(.+)_spec.rb":
+ [
+ "lib/$1.rb"
+ ]
+ }
+}
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/controllers/examples_controller.rb b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/controllers/examples_controller.rb
new file mode 100644
index 0000000..f712c1a
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/controllers/examples_controller.rb
@@ -0,0 +1,3 @@
+class ExamplesController < ApplicationController
+
+end
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/helpers/examples_helper.rb b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/helpers/examples_helper.rb
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/views/examples/index.html b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/views/examples/index.html
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/views/examples/show.html b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/app/views/examples/show.html
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/test/controllers/examples_controller_test.rb b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example1/test/controllers/examples_controller_test.rb
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/app/controllers/examples_controller.rb b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/app/controllers/examples_controller.rb
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/app/views/examples/index.html b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/app/views/examples/index.html
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/app/views/examples/show.html b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/app/views/examples/show.html
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/test/controllers/examples_controller_test.rb b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/fixtures/example2/test/controllers/examples_controller_test.rb
new file mode 100644
index 0000000..e69de29
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/package-metadata.json
new file mode 100644
index 0000000..b709a77
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/fabiokr/sublime-related-files", "version": "2013.03.15.08.29.58", "description": "A Sublime Text 2 plugin to list related files"}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related.py
new file mode 100644
index 0000000..a1c6007
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related.py
@@ -0,0 +1,86 @@
+import os
+import re
+import glob
+import itertools
+
+
+class Related(object):
+ # Initializes the RelatedFiles object.
+ #
+ # file_path - the file to look related files for
+ # patterns - a dictionary of patterns in the following format:
+ # {"(.+)_controller.rb": ["*/the/paths/$1/**", "*/test/$1_controller_test.rb"]}
+ #
+ # The glob paths will have their $i replaced by the matched groups within the file name
+ # matcher.
+ def __init__(self, file_path, patterns, folders):
+ self.__file_path = file_path
+ self.__patterns = patterns
+ self.__root = self.__root(folders)
+ self.__files = []
+ self.__descriptions = []
+ self.__build()
+
+ # # Retrieves a list of all related descriptions.
+ def descriptions(self):
+ return self.__descriptions
+
+ # # Retrieves a list of all related files paths.
+ def files(self):
+ return self.__files
+
+ # Builds a list with all related files and sets self.descriptions and
+ # self.files.
+ def __build(self):
+ files = set()
+
+ file_path = self.__to_posixpath(self.__file_path)
+
+ # for each matching pattern
+ for regex, paths in self.__patterns.iteritems():
+ match = re.compile(regex).match(file_path)
+ if match:
+ # returns a flattened file list
+ files.update(self.__files_for_paths(regex, match, paths))
+
+ # sorts items
+ files = list(files)
+ files.sort()
+
+ self.__files = files
+ self.__descriptions = [self.__file_without_root(file) for file in files]
+
+ # Returns the root folder for the given file and folders
+ def __root(self, folders):
+ for folder in folders:
+ if self.__file_path.startswith(os.path.join(folder, "")):
+ return folder
+
+ # Retrieves a list of files fot the given match and paths
+ def __files_for_paths(self, regex, match, paths):
+ paths = [self.__replaced_path(match, path) for path in paths]
+
+ files = [glob.glob(os.path.join(self.__root, path)) for path in paths]
+ flattened = [self.__to_posixpath(path) for path in list(itertools.chain.from_iterable(files))]
+
+ # Ignores current file
+ if self.__file_path in flattened:
+ flattened.remove(unicode(self.__file_path))
+
+ return flattened
+
+ # Retrieves the file name without the root part.
+ def __file_without_root(self, file):
+ return os.path.basename(self.__root) + file[len(self.__root):]
+
+ # Retrieves a path with its interpolation vars replaces by the found groups
+ # on match.
+ def __replaced_path(self, match, path):
+ replaced_path = path
+ for i, group in enumerate(match.groups()):
+ replaced_path = replaced_path.replace("$%s" % (i + 1), group)
+ return replaced_path
+
+ # Converts paths to posixpaths.
+ def __to_posixpath(self, path):
+ return re.sub("\\\\", "/", path)
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related_files.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related_files.py
new file mode 100644
index 0000000..ef289f1
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related_files.py
@@ -0,0 +1,39 @@
+import sublime
+import sublime_plugin
+from related import *
+
+
+class RelatedFilesCommand(sublime_plugin.WindowCommand):
+ def run(self, index=None):
+ active_file_path = self.__active_file_path()
+
+ if active_file_path:
+ # Builds a list of related files for the current open file.
+ self.__related = Related(active_file_path, self.__patterns(), sublime.active_window().folders())
+
+ self.window.show_quick_panel(self.__related.descriptions(), self.__open_file)
+ else:
+ self.__status_msg("No open files")
+
+ # Opens the file in path.
+ def __open_file(self, index):
+ if index >= 0:
+ self.window.open_file(self.__related.files()[index])
+ else:
+ self.__status_msg("No related files found")
+
+ # Retrieves the patterns from settings.
+ def __patterns(self):
+ return sublime.load_settings("RelatedFiles.sublime-settings").get('patterns')
+
+ # Returns the activelly open file path from sublime.
+ def __active_file_path(self):
+ if self.window.active_view():
+ file_path = self.window.active_view().file_name()
+
+ if file_path and len(file_path) > 0:
+ return file_path
+
+ # Displays a status message on sublime.
+ def __status_msg(self, message):
+ sublime.status_message(message)
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related_test.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related_test.py
new file mode 100644
index 0000000..a47b52a
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/related_test.py
@@ -0,0 +1,52 @@
+import unittest
+import os
+from related import *
+
+
+class RelatedTest(unittest.TestCase):
+
+ def test_descriptions_with_matches(self):
+ self.assertEqual(self.__related().descriptions(), [
+ "example1/app/helpers/examples_helper.rb",
+ "example1/app/views/examples/index.html",
+ "example1/app/views/examples/show.html",
+ "example1/test/controllers/examples_controller_test.rb"
+ ])
+
+ def test_descriptions_without_matches(self):
+ self.assertEqual(self.__related_without_match().descriptions(), [])
+
+ def test_files_with_matches(self):
+ self.assertEqual(self.__related().files(), [
+ self.__expand("fixtures/example1/app/helpers/examples_helper.rb"),
+ self.__expand("fixtures/example1/app/views/examples/index.html"),
+ self.__expand("fixtures/example1/app/views/examples/show.html"),
+ self.__expand("fixtures/example1/test/controllers/examples_controller_test.rb")
+ ])
+
+ def test_files_without_matches(self):
+ self.assertEqual(self.__related_without_match().files(), [])
+
+ def __patterns(self):
+ return {
+ ".+\/app\/controllers\/(.+)_controller.rb": ["app/views/$1/**", "app/helpers/$1_helper.rb"],
+ ".+\/app\/(.+).rb": ["test/$1_test.rb"]
+ }
+
+ def __file(self):
+ return self.__expand("fixtures/example1/app/controllers/examples_controller.rb")
+
+ def __folders(self):
+ return [self.__expand("fixtures/example1"), self.__expand("fixtures/example2")]
+
+ def __expand(self, path):
+ return os.path.join(os.path.dirname(os.path.realpath(__file__)), path)
+
+ def __related(self):
+ return Related(self.__file(), self.__patterns(), self.__folders())
+
+ def __related_without_match(self):
+ return Related("/should/not/match", self.__patterns(), self.__folders())
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/screenshots/list.png b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/screenshots/list.png
new file mode 100644
index 0000000..933c9ab
Binary files /dev/null and b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Related Files/screenshots/list.png differ
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/.gitignore b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/.gitignore
new file mode 100644
index 0000000..4a8e770
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/.gitignore
@@ -0,0 +1,6 @@
+*.pyc
+SmartMarkdown.sublime-project
+SmartMarkdown.sublime-workspace
+release.sh
+test/*
+.ropeproject
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (Linux).sublime-keymap b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (Linux).sublime-keymap
new file mode 100644
index 0000000..a773003
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (Linux).sublime-keymap
@@ -0,0 +1,26 @@
+[
+ { "keys": ["ctrl+;", "ctrl+n"], "command": "headline_move",
+ "args": {"forward": true, "same_level": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+;", "ctrl+p"], "command": "headline_move",
+ "args": {"forward": false, "same_level": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+;", "ctrl+f"], "command": "headline_move",
+ "args": {"forward": true, "same_level": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+;", "ctrl+b"], "command": "headline_move",
+ "args": {"forward": false, "same_level": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (OSX).sublime-keymap b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (OSX).sublime-keymap
new file mode 100644
index 0000000..0d7fb6e
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (OSX).sublime-keymap
@@ -0,0 +1,26 @@
+[
+ { "keys": ["ctrl+c", "ctrl+n"], "command": "headline_move",
+ "args": {"forward": true, "same_level": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+c", "ctrl+p"], "command": "headline_move",
+ "args": {"forward": false, "same_level": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+c", "ctrl+f"], "command": "headline_move",
+ "args": {"forward": true, "same_level": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+c", "ctrl+b"], "command": "headline_move",
+ "args": {"forward": false, "same_level": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (Windows).sublime-keymap b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (Windows).sublime-keymap
new file mode 100644
index 0000000..a773003
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default (Windows).sublime-keymap
@@ -0,0 +1,26 @@
+[
+ { "keys": ["ctrl+;", "ctrl+n"], "command": "headline_move",
+ "args": {"forward": true, "same_level": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+;", "ctrl+p"], "command": "headline_move",
+ "args": {"forward": false, "same_level": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+;", "ctrl+f"], "command": "headline_move",
+ "args": {"forward": true, "same_level": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["ctrl+;", "ctrl+b"], "command": "headline_move",
+ "args": {"forward": false, "same_level": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default.sublime-commands b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default.sublime-commands
new file mode 100644
index 0000000..90028e7
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default.sublime-commands
@@ -0,0 +1,27 @@
+[
+ {
+ "caption": "Pandoc: Render Markdown to temp PDF and View",
+ "command": "pandoc_render",
+ "args":{"open_after":true, "target":"pdf", "save_result":false}
+ },
+ {
+ "caption": "Pandoc: Render Markdown to temp HTML and View",
+ "command": "pandoc_render",
+ "args":{"open_after":true, "target":"html", "save_result":false}
+ },
+ {
+ "caption": "Pandoc: Render Markdown to HTML",
+ "command": "pandoc_render",
+ "args":{"open_after":false, "target":"html", "save_result":true}
+ },
+ {
+ "caption": "Pandoc: Render Markdown to PDF",
+ "command": "pandoc_render",
+ "args":{"open_after":false, "target":"pdf", "save_result":true}
+ },
+ {
+ "caption": "Pandoc: Render Markdown DocX",
+ "command": "pandoc_render",
+ "args":{"open_after":false, "target":"docx", "save_result":true}
+ }
+]
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default.sublime-keymap b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default.sublime-keymap
new file mode 100644
index 0000000..28a78b4
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Default.sublime-keymap
@@ -0,0 +1,72 @@
+[
+ { "keys": ["tab"], "command": "smart_folding", "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "markup.heading.markdown" }
+ ]
+ },
+ { "keys": ["shift+tab"], "command": "global_folding", "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" }
+ ]
+ },
+ { "keys": ["enter"], "command": "smart_list", "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*([-+\\**]|\\d+\\.+)\\s+" }
+ ]
+ },
+ { "keys": ["enter"], "command": "smart_list", "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "selector", "operator": "equal", "operand": "markup.list" }
+ ]
+ },
+ { "keys": ["tab"], "command": "smart_table",
+ "args": {"forward": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(\\||\\+[-=])",
+ "match_all": true}
+ ]
+ },
+ { "keys": ["tab"], "command": "smart_table",
+ "args": {"forward": true}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "\\s*(\\||\\+[-=])",
+ "match_all": true}
+ ]
+ },
+ { "keys": ["shift+tab"], "command": "smart_table",
+ "args": {"forward": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(\\||\\+[-=])",
+ "match_all": true}
+ ]
+ },
+ { "keys": ["shift+tab"], "command": "smart_table",
+ "args": {"forward": false}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "\\s*(\\||\\+[-=])",
+ "match_all": true}
+ ]
+ },
+ {
+ "keys": ["super+shift+."], "command": "change_heading_level",
+ "args": {"up": true}, "context":
+ [
+ {"key": "selector", "operator": "equal", "operand": "text.html.markdown"}
+ ]
+ },
+ {
+ "keys": ["super+shift+,"], "command": "change_heading_level",
+ "args": {"up": false}, "context":
+ [
+ {"key": "selector", "operator": "equal", "operand": "text.html.markdown"}
+ ]
+ }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Main.sublime-menu b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Main.sublime-menu
new file mode 100644
index 0000000..91bce87
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/Main.sublime-menu
@@ -0,0 +1,70 @@
+[
+ {
+ "caption": "Preferences",
+ "mnemonic": "n",
+ "id": "preferences",
+ "children":
+ [
+ {
+ "caption": "Package Settings",
+ "mnemonic": "P",
+ "id": "package-settings",
+ "children":
+ [
+ {
+ "caption": "SmartMarkdown",
+ "children":
+ [
+ {
+ "command": "open_file", "args":
+ {
+ "file": "${packages}/SmartMarkdown/SmartMarkdown.sublime-settings"
+ },
+ "caption": "Settings – Default"
+ },
+ {
+ "command": "open_file", "args":
+ {
+ "file": "${packages}/User/SmartMarkdown.sublime-settings"
+ },
+ "caption": "Settings – User"
+ },
+ { "caption": "-" },
+ {
+ "command": "open_file", "args":
+ {
+ "file": "${packages}/SmartMarkdown/Default.sublime-keymap"
+ },
+ "caption": "Key Bindings – Default"
+ },
+ {
+ "command": "open_file", "args":
+ {
+ "file": "${packages}/User/Default (OSX).sublime-keymap",
+ "platform": "OSX"
+ },
+ "caption": "Key Bindings – User"
+ },
+ {
+ "command": "open_file", "args":
+ {
+ "file": "${packages}/User/Default (Linux).sublime-keymap",
+ "platform": "Linux"
+ },
+ "caption": "Key Bindings – User"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/User/Default (Windows).sublime-keymap",
+ "platform": "Windows"
+ },
+ "caption": "Key Bindings – User"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/SmartMarkdown.sublime-settings b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/SmartMarkdown.sublime-settings
new file mode 100644
index 0000000..69d1fb2
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/SmartMarkdown.sublime-settings
@@ -0,0 +1,11 @@
+{
+ /* Please specify the PATH of pdflatex if you wanna generate PDF */
+ "tex_path": ["/usr/local/texlive/2011/bin/x86_64-darwin",
+ "/usr/local/texlive/2012/bin/x86_64-darwin"],
+ /* Provide your arguments here as a list e.g.: ["--latex-engine=xelatex", "--toc"]
+ arguments that are separated by space must be in separate slots. e.g. ["-H", "template.tex"] */
+ "pandoc_args": [],
+ "pandoc_args_pdf": [],
+ "pandoc_args_html": [],
+ "pandoc_args_docx": []
+}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline.py
new file mode 100644
index 0000000..91dce43
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline.py
@@ -0,0 +1,263 @@
+"""Some utility functions for working with headline of Markdown.
+
+Terminologies
+- Headline :: The headline entity OR the text of the headline
+- Content :: The content under the current headline. It stops after
+ encountering a headline with the same or higher level OR EOF.
+"""
+# Author: Muchenxuan Tong
+
+import re
+import sublime
+
+try:
+ from .utilities import is_region_void
+except ValueError:
+ from utilities import is_region_void
+
+MATCH_PARENT = 1 # Match headlines at the same or higher level
+MATCH_CHILD = 2 # Match headlines at the same or lower level
+MATCH_SILBING = 3 # Only Match headlines at the same level.
+MATCH_ANY = 4 # Any headlines would be matched.
+ANY_LEVEL = -1 # level used when MATCH_ANY is used as match type
+
+
+def region_of_content_of_headline_at_point(view, from_point):
+ """Extract the region of the content of under current headline."""
+ _, level = headline_and_level_at_point(view, from_point)
+ if level == None:
+ return None
+
+ if is_content_empty_at_point(view, from_point):
+ return None
+
+ line_num, _ = view.rowcol(from_point)
+ content_line_start_point = view.text_point(line_num + 1, 0)
+
+ next_headline, _ = find_headline(view, \
+ content_line_start_point, \
+ level, \
+ True, \
+ MATCH_PARENT)
+ if not is_region_void(next_headline):
+ end_pos = next_headline.a - 1
+ else:
+ end_pos = view.size()
+ return sublime.Region(content_line_start_point, end_pos)
+
+
+def headline_and_level_at_point(view, from_point, search_above_and_down=False):
+ """Return the current headline and level.
+
+ If from_point is inside a headline, then return the headline and level.
+ Otherwise depends on the argument it might search above and down.
+ """
+ line_region = view.line(from_point)
+ line_content = view.substr(line_region)
+ # Update the level in case it's headline.ANY_LEVEL
+ level = _extract_level_from_headline(line_content)
+
+ # Search above and down
+ if level is None and search_above_and_down:
+ # Search above
+ headline_region, _ = find_headline(view,\
+ from_point,\
+ ANY_LEVEL,
+ False,
+ skip_folded=True)
+ if not is_region_void(headline_region):
+ line_content, level = headline_and_level_at_point(view,\
+ headline_region.a)
+ # Search down
+ if level is None:
+ headline_region, _ = find_headline(view,\
+ from_point,\
+ ANY_LEVEL,
+ True,
+ skip_folded=True)
+ if not is_region_void(headline_region):
+ line_content, level = headline_and_level_at_point(view, headline_region.a)
+
+ return line_content, level
+
+
+def _extract_level_from_headline(headline):
+ """Extract the level of headline, None if not found.
+
+ """
+ re_string = _get_re_string(ANY_LEVEL, MATCH_ANY)
+ match = re.match(re_string, headline)
+
+ if match:
+ return len(match.group(1))
+ else:
+ return None
+
+
+def is_content_empty_at_point(view, from_point):
+ """Check if the content under the current headline is empty.
+
+ For implementation, check if next line is a headline a the same
+ or higher level.
+
+ """
+ _, level = headline_and_level_at_point(view, from_point)
+ if level is None:
+ raise ValueError("from_point must be inside a valid headline.")
+
+ line_num, _ = view.rowcol(from_point)
+ next_line_region = view.line(view.text_point(line_num + 1, 0))
+ next_line_content = view.substr(next_line_region)
+ next_line_level = _extract_level_from_headline(next_line_content)
+
+ # Note that EOF works too in this case.
+ if next_line_level and next_line_level <= level:
+ return True
+ else:
+ return False
+
+
+def find_headline(view, from_point, level, forward=True, \
+ match_type=MATCH_ANY, skip_headline_at_point=False, \
+ skip_folded=False):
+ """Return the region of the next headline or EOF.
+
+ Parameters
+ ----------
+ view: sublime.view
+
+ from_point: int
+ From which to find.
+
+ level: int
+ The headline level to match.
+
+ forward: boolean
+ Search forward or backward
+
+ match_type: int
+ MATCH_SILBING, MATCH_PARENT, MATCH_CHILD or MATCH_ANY.
+
+ skip_headline_at_point: boolean
+ When searching whether skip the headline at point
+
+ skip_folded: boolean
+ Whether to skip the folded region
+
+ Returns
+ -------
+ match_region: int
+ Matched region, or None if not found.
+
+ match_level: int
+ The level of matched headline, or None if not found.
+
+ """
+ if skip_headline_at_point:
+ # Move the point to the next line if we are
+ # current in a headline already.
+ from_point = _get_new_point_if_already_in_headline(view, from_point,
+ forward)
+
+ re_string = _get_re_string(level, match_type)
+ if forward:
+ match_region = view.find(re_string, from_point)
+ else:
+ all_match_regions = view.find_all(re_string)
+ match_region = _nearest_region_among_matches_from_point(view, \
+ all_match_regions, \
+ from_point, \
+ False, \
+ skip_folded)
+
+ if skip_folded:
+ while (_is_region_folded(match_region, view)):
+ from_point = match_region.b
+ match_region = view.find(re_string, from_point)
+
+ if not is_region_void(match_region):
+ if not is_scope_headline(view, match_region.a):
+ return find_headline(view, match_region.a, level, forward, \
+ match_type, True, skip_folded)
+ else:
+ ## Extract the level of matched headlines according to the region
+ headline = view.substr(match_region)
+ match_level = _extract_level_from_headline(headline)
+ else:
+ match_level = None
+ return (match_region, match_level)
+
+def _get_re_string(level, match_type=MATCH_ANY):
+ """Get regular expression string according to match type.
+
+ Return regular expression string, rather than compiled string. Since
+ sublime's view.find function needs string.
+
+ Parameters
+ ----------
+ match_type: int
+ MATCH_SILBING, MATCH_PARENT, MATCH_CHILD or ANY_LEVEL.
+
+ """
+ if match_type == MATCH_ANY:
+ re_string = r'^(#+)\s.*'
+ else:
+ try:
+ if match_type == MATCH_PARENT:
+ re_string = r'^(#{1,%d})\s.*' % level
+ elif match_type == MATCH_CHILD:
+ re_string = r'^(#{%d,})\s.*' % level
+ elif match_type == MATCH_SILBING:
+ re_string = r'^(#{%d,%d})\s.*' % (level, level)
+ except ValueError:
+ print("match_type has to be specified if level isn't ANY_LEVE")
+ return re_string
+
+
+def _get_new_point_if_already_in_headline(view, from_point, forward=True):
+ line_content = view.substr(view.line(from_point))
+ if _extract_level_from_headline(line_content):
+ line_num, _ = view.rowcol(from_point)
+ if forward:
+ return view.text_point(line_num + 1, 0)
+ else:
+ return view.text_point(line_num, 0) - 1
+ else:
+ return from_point
+
+
+def is_scope_headline(view, from_point):
+ return view.score_selector(from_point, "markup.heading") > 0 or \
+ view.score_selector(from_point, "meta.block-level.markdown") > 0
+
+
+def _nearest_region_among_matches_from_point(view, all_match_regions, \
+ from_point, forward=False,
+ skip_folded=True):
+ """Find the nearest matched region among all matched regions.
+
+ None if not found.
+
+ """
+ nearest_region = None
+
+ for r in all_match_regions:
+ if not forward and r.b <= from_point and \
+ (not nearest_region or r.a > nearest_region.a):
+ candidate = r
+ elif forward and r.a >= from_point and \
+ (not nearest_region or r.b < nearest_region.b):
+ candidate = r
+ else:
+ continue
+ if skip_folded and not _is_region_folded(candidate, view):
+ nearest_region = candidate
+
+ return nearest_region
+
+
+def _is_region_folded(region, view):
+ for i in view.folded_regions():
+ if i.contains(region):
+ return True
+ return False
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline_level.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline_level.py
new file mode 100644
index 0000000..3ad56b9
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline_level.py
@@ -0,0 +1,21 @@
+"""This file is contributed by [David Smith](https://github.com/djs070)
+"""
+import sublime
+import sublime_plugin
+
+
+class ChangeHeadingLevelCommand(sublime_plugin.TextCommand):
+ def run(self, edit, up=True):
+ for region in self.view.sel():
+ line = self.view.line(region)
+ if up:
+ # Increase heading level
+ if not self.view.substr(line)[0] in ['#', ' ']:
+ self.view.insert(edit, line.begin(), " ")
+ self.view.insert(edit, line.begin(), "#")
+ else:
+ # Decrease heading level
+ if self.view.substr(line)[0] == '#':
+ self.view.erase(edit, sublime.Region(line.begin(), line.begin() + 1))
+ if self.view.substr(line)[0] == ' ':
+ self.view.erase(edit, sublime.Region(line.begin(), line.begin() + 1))
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline_move.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline_move.py
new file mode 100644
index 0000000..824d6a9
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/headline_move.py
@@ -0,0 +1,61 @@
+"""This module provides commands for easily moving between headilnes.
+
+The feature is borrowed from [Org-mode](http://org-mode.org).
+
+"""
+# Author: Muchenxuan Tong
+
+import sublime
+import sublime_plugin
+
+try:
+ from . import headline
+ from .utilities import is_region_void
+except ValueError:
+ import headline
+ from utilities import is_region_void
+
+
+class HeadlineMoveCommand(sublime_plugin.TextCommand):
+ def run(self, edit, forward=True, same_level=True):
+ """Move between headlines, forward or backward.
+
+ If same_level is true, only move to headline with the same level
+ or higher level.
+
+ """
+ new_sel = []
+ if same_level:
+ level_type = headline.MATCH_PARENT
+ else:
+ level_type = headline.MATCH_ANY
+
+ for region in self.view.sel():
+ if same_level:
+ _, level = headline.headline_and_level_at_point(self.view,\
+ region.a,
+ search_above_and_down=True)
+ if level is None:
+ return
+ else:
+ level = headline.ANY_LEVEL
+
+ match_region, _ = headline.find_headline(self.view, \
+ region.a, \
+ level, \
+ forward, \
+ level_type, \
+ skip_headline_at_point=True,\
+ skip_folded=True)
+
+ if is_region_void(match_region):
+ return
+ new_sel.append(sublime.Region(match_region.a, match_region.a))
+
+ self.adjust_view(new_sel)
+
+ def adjust_view(self, new_sel):
+ self.view.sel().clear()
+ for region in new_sel:
+ self.view.sel().add(region)
+ self.view.show(region)
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/license.txt b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/license.txt
new file mode 100644
index 0000000..d71c44d
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/license.txt
@@ -0,0 +1,7 @@
+Copyright (C) <2012> Muchenxuan Tong
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/package-metadata.json
new file mode 100644
index 0000000..b5e2cd5
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/demon386/SmartMarkdown", "version": "2013.03.23.12.24.10", "description": "A plugin for facilitating editing markdown in Sublime Text 2. Features are borrowed from Org mode of Emacs."}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/pandoc_render.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/pandoc_render.py
new file mode 100644
index 0000000..67f7320
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/pandoc_render.py
@@ -0,0 +1,124 @@
+"""This file is initially forked from
+[SublimePandoc](https://github.com/jclement/SublimePandoc)
+by [DanielMe](https://github.com/DanielMe/)
+
+@todo naming convention should be foo_bar rather than fooBar.
+@bug PDF export doesn't work in my Mac, gonna check it later.
+
+2012-07-02: Muchenxuan Tong changed some stylical errors (with SublimeLinter)
+"""
+
+import sublime
+import sublime_plugin
+import webbrowser
+import tempfile
+import os
+import os.path
+import sys
+import subprocess
+from subprocess import PIPE
+
+
+class PandocRenderCommand(sublime_plugin.TextCommand):
+ def is_enabled(self):
+ return self.view.score_selector(0, "text.html.markdown") > 0
+
+ def is_visible(self):
+ return True
+
+ def run(self, edit, target="pdf", open_after=True, save_result=False):
+ if target not in ["html", "docx", "pdf"]:
+ raise Exception("Format %s currently unsopported" % target)
+
+ self.setting = sublime.load_settings("SmartMarkdown.sublime-settings")
+
+ encoding = self.view.encoding()
+ if encoding == 'Undefined':
+ encoding = 'UTF-8'
+ elif encoding == 'Western (Windows 1252)':
+ encoding = 'windows-1252'
+ contents = self.view.substr(sublime.Region(0, self.view.size()))
+ contents = contents.encode(encoding)
+
+ file_name = self.view.file_name()
+ if file_name:
+ os.chdir(os.path.dirname(file_name))
+
+ # write buffer to temporary file
+ # This is useful because it means we don't need to save the buffer
+ tmp_md = tempfile.NamedTemporaryFile(delete=False, suffix=".md")
+ tmp_md.write(contents)
+ tmp_md.close()
+
+ # output file...
+ suffix = "." + target
+ if save_result:
+ output_name = os.path.splitext(self.view.file_name())[0] + suffix
+ if not self.view.file_name():
+ raise Exception("Please safe the buffer before trying to export with pandoc.")
+ else:
+ output = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
+ output.close()
+ output_name = output.name
+
+ args = self.pandoc_args(target)
+ self.run_pandoc(tmp_md.name, output_name, args)
+
+ if open_after:
+ self.open_result(output_name, target)
+ #os.unlink(tmp_md.name)
+
+ def run_pandoc(self, infile, outfile, args):
+ cmd = ['pandoc'] + args
+ cmd += [infile, "-o", outfile]
+
+ # Merge the path in settings
+ setting_path = self.setting.get("tex_path", [])
+ for p in setting_path:
+ if p not in os.environ["PATH"]:
+ os.environ["PATH"] += ":" + p
+
+ try:
+ # Use the current directory as working dir whenever possible
+ file_name = self.view.file_name()
+ if file_name:
+ working_dir = os.path.dirname(file_name)
+ p = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE,
+ cwd=working_dir)
+
+ else:
+ p = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE)
+ p.wait()
+ out, err = p.communicate()
+ if err:
+ raise Exception("Command: %s\n" % " ".join(cmd) + "\nErrors: " + err)
+ except Exception as e:
+ sublime.error_message("Fail to generate output.\n{0}".format(e))
+
+ def pandoc_args(self, target):
+ """
+ Create a list of arguments for the pandoc command
+ depending on the target.
+ TODO: Actually do something sensible here
+ """
+ # Merge the args in settings
+ args = self.setting.get("pandoc_args", [])
+
+ if target == "pdf":
+ args += self.setting.get("pandoc_args_pdf", [])
+ if target == "html":
+ args += self.setting.get("pandoc_args_html", []) + ['-t', 'html5']
+ if target == "docx":
+ args += self.setting.get("pandoc_args_docx", []) + ['-t', 'docx']
+ return args
+
+ def open_result(self, outfile, target):
+ if target == "html":
+ webbrowser.open_new_tab(outfile)
+ elif sys.platform == "win32":
+ os.startfile(outfile)
+ elif "mac" in sys.platform or "darwin" in sys.platform:
+ os.system("open %s" % outfile)
+ print(outfile)
+ elif "posix" in sys.platform or "linux" in sys.platform:
+ os.system("xdg-open %s" % outfile)
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/readme.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/readme.md
new file mode 100644
index 0000000..6b0d6a0
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/readme.md
@@ -0,0 +1,59 @@
+# SmartMarkdown for Sublime Text 2 & 3
+
+Author: Muchenxuan Tong (demon386@gmail.com)
+
+## Introduction
+The plugin is aimed at making editing Markdown in Sublime Text 2 easier and more powerful. Ideally, I hope we can bring several amazing features of [Org-mode](http://org-mode.org) of Emacs into Sublime Text.
+
+## Done
+- **Smart Headline folding / unfolding**. Right now you can fold / unfold headlines by pressing **TAB** on it. I assume you use the following formats: # Section; ## Subsection; ### Subsubsection ...
+- **Global Headline Folding / unfolding**. **Shift+Tab** to Fold / Unfold all at any position.
+- **Smart Order / Unordered list**. When editing lists, you can just press **ENTER** and this plugin will automatically continue the list. Once the content of the list becomes empty it will stop.
+- **Move between headlines**.
+ - Use **Ctrl+c Ctrl+n** to move to the next headline (any level); **Ctrl+c Ctrl+p** to the previous one, for Mac. (**Ctrl+; Ctrl+n** and **Ctrl+; Ctrl+p** for Windows and Linux)
+ - Use **Ctrl+c Ctrl+f** to move to the next headline (same level or higher level); **Ctrl+c Ctrl+b** to the previous one, for Mac. (**Ctrl+; Ctrlf** and **Ctrl+; Ctrl+b** for Windows and Linux)
+- **Adjust headline level** Added by [David Smith](https://github.com/djs070).
+ - **Super+Shift+,** for decreasing and **Super+Shift+.** for increasing headline levels.
+- **Smart table**
+ - Currently, the smart table suppose only the Grid table format of [Pandoc](http://johnmacfarlane.net/pandoc/README.html). Use monospaced fonts, otherwise it would appear bizarre.
+ - The behavior is like the table in Org-mode. If you are unfamiliar with Org-mode, just use | (vertical line) to separate the column (e.g. | header1 | header 2 |), and use the **TAB** to reformat the table at point. Everything would fall into the place. Add +- and then press TAB for adding separator between rows. Add += and then press TAB for adding separator between header and the table body. Read the Grid tables section of [Pandoc Userg's Guide](http://johnmacfarlane.net/pandoc/README.html#tables) for more information.
+ - Use **TAB** to move forward a cell in table, **Shift+TAB** to move backward.
+ - Personally I plan to use grid table as a basis and add command for converting to other table formats if necessary.
+- **Basic Pandoc integration with Pandoc** By integrating [SublimePandoc](https://github.com/jclement/SublimePandoc). Added by [DanielMe](https://github.com/DanielMe/).
+ - **Note**: If you need to generate PDF output, please make sure you have pdflatex available ([MacTeX](http://www.tug.org/mactex/2012/) for Mac, or TeX Live for other OS). Please also specify "tex_path" in the package settings (Preference - Package Settings - SmartMarkdown - Settings - User (see Settings - Default as an example.))
+
+## Todo
+- **Embeded R & Python Code for reproducible research**
+- **Better Pandoc integration** Actual support for different Pandoc command line options etc.
+- ...
+
+## What's new
+### v0.2: Support for Sublime Text 3 (added by [UNOwen](https://github.com/UNOwen).)
+### v0.1.6: Add support and bindings for headline level changing. (added by [David Smith](https://github.com/djs070).) The key bindings are: **Super+Shift+,** for decreasing and **Super+Shift+.** for increasing.
+### v0.1.5: Basic smart table (grid table) support added. Basic Pandoc intergration (added by [DanielMe](https://github.com/DanielMe/).)
+### v0.1.3: Add support for global headling folding / unfolding.
+### v0.1.2: Move between headlines supported!
+- Use **Ctrl+c Ctrl+n** to move to the next headline (any level); **Ctrl+c Ctrl+p** to the previous one.
+- Use **Ctrl+c Ctrl+f** to move to the next headline (same level or higher level); **Ctrl+c Ctrl+b** to the previous one.
+- Fixed a bug on bullet list. Thanks to quodlibet (fixed in v0.1.1).
+
+### v0.1.0: Created!
+- Smart Headline folding / unfolding is supported.
+- Smart Lists is supported.
+
+## For Developers
+- Whenever possible, please obey the [PEP 8](http://www.python.org/dev/peps/pep-0008/) style guide. This can be checked easily with the plugin SublimeLinter.
+- git-flow is recommended (but not enforced) as a development work flow. For instruction please read [Why aren't you using git-flow?](http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/). To adapt it, a command line tool [gitflow](https://github.com/nvie/gitflow/) is highly recommended.
+- Please work on the develop branch, it's newer than master. the master branch is for users.
+
+# License
+The plugin is licensed under the MIT license.
+
+
+Copyright (C) <2012> Muchenxuan Tong
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_folding.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_folding.py
new file mode 100644
index 0000000..350e11d
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_folding.py
@@ -0,0 +1,195 @@
+"""Smart folding is a feature borrowed from [Org-mode](http://org-mode.org).
+
+It enables folding / unfolding the headlines by simply pressing TAB on headlines.
+
+Global headline folding / unfolding is recommended to be trigged by Shift + TAB,
+at anywhere.
+
+"""
+# Author: Muchenxuan Tong
+
+import re
+
+import sublime
+import sublime_plugin
+
+try:
+ from . import headline
+ from .utilities import is_region_void
+except ValueError:
+ import headline
+ from utilities import is_region_void
+
+
+HEADLINE_PATTERN = re.compile(r'^(#+)\s.*')
+
+
+class SmartFoldingCommand(sublime_plugin.TextCommand):
+ """Smart folding is used to fold / unfold headline at the point.
+
+ It's designed to bind to TAB key, and if the current line is not
+ a headline, a \t would be inserted.
+
+ """
+ def run(self, edit):
+ ever_matched = False
+ for region in self.view.sel():
+ matched = self.fold_or_unfold_headline_at_point(region.a)
+ if matched:
+ ever_matched = True
+ if not ever_matched:
+ for r in self.view.sel():
+ self.view.insert(edit, r.a, '\t')
+ self.view.show(r)
+
+ def fold_or_unfold_headline_at_point(self, from_point):
+ """Smart folding of the current headline.
+
+ Unfold only when it's totally folded. Otherwise fold it.
+
+ """
+ _, level = headline.headline_and_level_at_point(self.view,
+ from_point)
+ # Not a headline, cancel
+ if level is None or not headline.is_scope_headline(self.view, from_point):
+ return False
+
+ content_region = headline.region_of_content_of_headline_at_point(self.view,
+ from_point)
+ # If the content is empty, Nothing needs to be done.
+ if content_region is None:
+ # Return True because there is a headline anyway.
+ return True
+
+ # Check if content region is folded to decide the action.
+ if self.is_region_totally_folded(content_region):
+ self.unfold_yet_fold_subheads(content_region, level)
+ else:
+ self.view.fold(content_region)
+ return True
+
+ def is_region_totally_folded(self, region):
+ """Decide if the region is folded. Treat empty region as folded."""
+ if (region is None) or (region.a == region.b):
+ return True
+
+ for i in self.view.folded_regions():
+ if i.contains(region):
+ return True
+ return False
+
+ def unfold_yet_fold_subheads(self, region, level):
+ """Unfold the region while keeping the subheadlines folded."""
+ ## First unfold all
+ self.view.unfold(region)
+ ## Fold subheads
+ child_headline_region, _ = headline.find_headline(self.view, region.a, level, True, \
+ headline.MATCH_CHILD)
+
+ while (not is_region_void(child_headline_region) and child_headline_region.b <= region.b):
+ child_content_region = headline.region_of_content_of_headline_at_point(self.view,
+ child_headline_region.a)
+ if child_content_region is not None:
+ self.view.fold(child_content_region)
+ search_start_point = child_content_region.b
+ else:
+ search_start_point = child_headline_region.b
+
+ child_headline_region, _ = headline.find_headline(self.view, \
+ search_start_point, level, True, \
+ headline.MATCH_CHILD,
+ skip_headline_at_point=True)
+
+
+class GlobalFoldingCommand(SmartFoldingCommand):
+ """Global folding / unfolding headlines at any point.
+
+ Unfold only when top-level headlines are totally folded.
+ Otherwise fold.
+
+ """
+ def run(self, edit):
+ if self.is_global_folded():
+ # Unfold all
+ self.unfold_all()
+ else:
+ self.fold_all()
+
+ def is_global_folded(self):
+ """Check if all headlines are folded.
+ """
+ region, level = headline.find_headline(self.view, 0, \
+ headline.ANY_LEVEL, True)
+ # Treating no heeadline as folded, since unfolded all makes
+ # no harm in this situation.
+ if is_region_void(region):
+ return True
+
+ point = region.a
+ # point can be zero
+ while (point is not None and region):
+ region = headline.region_of_content_of_headline_at_point(self.view, \
+ point)
+ if not is_region_void(region):
+ point = region.b
+ if not self.is_region_totally_folded(region):
+ return False
+ else:
+ region, level = headline.find_headline(self.view, point, \
+ headline.ANY_LEVEL, \
+ True,
+ skip_headline_at_point=True)
+ if not is_region_void(region):
+ point = region.a
+ return True
+
+ def unfold_all(self):
+ self.view.unfold(sublime.Region(0, self.view.size()))
+ self.view.show(self.view.sel()[0])
+
+ def fold_all(self):
+ region, level = headline.find_headline(self.view, \
+ 0, \
+ headline.ANY_LEVEL, \
+ True)
+
+ # At this point, headline region is sure to exist, otherwise it would be
+ # treated as gobal folded. (self.is_global_folded() would return True)
+ point = region.a
+ # point can be zero
+ while (point is not None and region):
+ region = headline.region_of_content_of_headline_at_point(self.view, \
+ point)
+ if not is_region_void(region):
+ point = region.b
+ self.view.fold(region)
+ region, level = headline.find_headline(self.view, point, \
+ headline.ANY_LEVEL,
+ True, \
+ skip_headline_at_point=True)
+ if not is_region_void(region):
+ point = region.a
+ self.adjust_cursors_and_view()
+
+ def adjust_cursors_and_view(self):
+ """After folder, adjust cursors and view.
+
+ If the current point is inside the folded region, move it move
+ otherwise it's easy to perform some unintentional editing.
+
+ """
+ folded_regions = self.view.folded_regions()
+ new_sel = []
+
+ for r in self.view.sel():
+ for folded in folded_regions:
+ if folded.contains(r):
+ new_sel.append(sublime.Region(folded.b, folded.b))
+ break
+ else:
+ new_sel.append(r)
+
+ self.view.sel().clear()
+ for r in new_sel:
+ self.view.sel().add(r)
+ self.view.show(r)
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_list.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_list.py
new file mode 100644
index 0000000..c1e229f
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_list.py
@@ -0,0 +1,57 @@
+"""Smart list is used to automatially continue the current list."""
+# Author: Muchenxuan Tong
+
+import re
+
+import sublime
+import sublime_plugin
+
+
+ORDER_LIST_PATTERN = re.compile(r"(\s*)(\d+)(\.\s+)\S+")
+UNORDER_LIST_PATTERN = re.compile(r"(\s*[-+\**]+)(\s+)\S+")
+EMPTY_LIST_PATTERN = re.compile(r"(\s*([-+\**]|\d+\.+))\s+$")
+
+
+class SmartListCommand(sublime_plugin.TextCommand):
+ def run(self, edit):
+ for region in self.view.sel():
+ line_region = self.view.line(region)
+ # the content before point at the current line.
+ before_point_region = sublime.Region(line_region.a,
+ region.a)
+ before_point_content = self.view.substr(before_point_region)
+
+ # Disable smart list when folded.
+ folded = False
+ for i in self.view.folded_regions():
+ if i.contains(before_point_region):
+ self.view.insert(edit, region.a, '\n')
+ folded = True
+ if folded:
+ break
+
+ match = EMPTY_LIST_PATTERN.match(before_point_content)
+ if match:
+ self.view.erase(edit, before_point_region)
+ break
+
+ match = ORDER_LIST_PATTERN.match(before_point_content)
+ if match:
+ insert_text = match.group(1) + \
+ str(int(match.group(2)) + 1) + \
+ match.group(3)
+ self.view.insert(edit, region.a, "\n" + insert_text)
+ break
+
+ match = UNORDER_LIST_PATTERN.match(before_point_content)
+ if match:
+ insert_text = match.group(1) + match.group(2)
+ self.view.insert(edit, region.a, "\n" + insert_text)
+ break
+
+ self.view.insert(edit, region.a, '\n')
+ self.adjust_view()
+
+ def adjust_view(self):
+ for region in self.view.sel():
+ self.view.show(region)
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_table.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_table.py
new file mode 100644
index 0000000..51c6677
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/smart_table.py
@@ -0,0 +1,87 @@
+"""Smart is inspired by the Table behavior of Org-mode.
+
+Markdown itself doesn't support grid table, yet pandoc does.
+
+@todo: add a key binding for converting grid table to the simple one
+"""
+# Author: Muchenxuan Tong
+# LICENSE: MIT
+
+import sublime
+import sublime_plugin
+
+try:
+ from . import table
+except ValueError:
+ import table
+
+
+class SmartTable(sublime_plugin.TextCommand):
+ def run(self, edit, forward=True):
+ new_sel = []
+ for r in self.view.sel():
+ point = r.a
+
+ for i in self.view.folded_regions():
+ if i.contains(sublime.Region(point, point)):
+ return
+ t = table.convert_table_at_point_as_list(self.view, point)
+ t = table.reformat_table_list(t)
+ t_str = table.convert_table_list_to_str(t)
+
+ # Both are 0-based
+ cur_row_num, cur_col_num = table.get_point_row_and_col(self.view, point)
+ table_row_num = len(t)
+ line_num, _ = self.view.rowcol(point)
+ start_line_num = line_num - cur_row_num
+ start_point = self.view.text_point(line_num - cur_row_num, 0)
+ end_line_num = line_num + table_row_num - cur_row_num - 1
+ end_line_start_point = self.view.text_point(end_line_num, 0)
+ end_point = self.view.line(end_line_start_point).b
+
+ # Erase the previous table region, use the new one for substitution.
+ self.view.erase(edit, sublime.Region(start_point, end_point))
+ self.view.insert(edit, start_point, t_str)
+
+ if forward:
+ if cur_col_num is None or cur_col_num >= len(t[0]) - 1:
+ line_num += 1
+ while(table.is_line_separator(self.view, line_num)):
+ line_num += 1
+ cur_col_num = 0
+ else:
+ cur_col_num += 1
+ else:
+ if cur_col_num is None or cur_col_num <= 0:
+ line_num -= 1
+ while(table.is_line_separator(self.view, line_num)):
+ line_num -= 1
+ cur_col_num = len(t[0]) - 1
+ else:
+ cur_col_num -= 1
+
+ # Add a new line when at the end of the table.
+ if line_num < start_line_num or line_num > end_line_num:
+ col_pos = 0
+ if line_num > end_line_num:
+ self.view.insert(edit, self.view.text_point(line_num, 0), "\n")
+ else:
+ col_pos = self.calculate_col_point(t, cur_col_num)
+
+ new_sel.append(self.view.text_point(line_num, col_pos))
+
+ self.view.sel().clear()
+ for r in new_sel:
+ self.view.sel().add(r)
+ self.view.show(r)
+
+ def calculate_col_point(self, formatted_table, col_num):
+ i = 0
+ while table.SEPARATOR_PATTERN.match(formatted_table[i][0]):
+ i += 1
+
+ cols_length = [len(j) for j in formatted_table[i]]
+ point = 2
+ for i in range(col_num):
+ point += cols_length[i] + 3
+ return point
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/table.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/table.py
new file mode 100644
index 0000000..41348c4
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/table.py
@@ -0,0 +1,207 @@
+"""Utilities function for working with grid table of Pandoc
+
+Terminologies
+
+- Table list :: This is not a list of tables, but rather converting the table as
+a nested python list. Each row is a sub-list in the table list.
+
+"""
+# Author: Muchenxuan Tong
+# LICENSE: MIT
+
+import re
+import copy
+
+import sublime
+
+try:
+ from . import utilities
+except ValueError:
+ import utilities
+
+TABLE_PATTERN = re.compile(r"\s*\|")
+SEPARATOR_PATTERN = re.compile(r"\s*(\+[=-])")
+
+
+def convert_table_at_point_as_list(view, from_point):
+ """Get the table at the point.
+ Transform the table to python list.
+
+ Returns
+ -------
+ table: list
+ A nested list representing the table.
+ indent: "str" (@todo not impelmented yet)
+ String of indentation, used in every row.
+
+ """
+ table_above = convert_table_above_or_below_as_list(view, from_point, above=True)
+ table_below = convert_table_above_or_below_as_list(view, from_point, above=False)
+ row_at_point = convert_row_at_point_as_list(view, from_point)
+
+ table = table_above + [row_at_point] + table_below
+ return table
+
+
+def convert_table_above_or_below_as_list(view, from_point, above):
+ """Convert the table above the point as python list.
+
+ Returns
+ -------
+ table: list
+ A nested list representing the table.
+
+ """
+ line_num, _ = view.rowcol(from_point)
+ line_num += - 1 if above else 1
+
+ line_text = utilities.text_at_line(view, line_num)
+ table = []
+
+ while line_text and (TABLE_PATTERN.match(line_text) or
+ SEPARATOR_PATTERN.match(line_text)):
+ table.append(_convert_row_text_as_list(line_text))
+ line_num += -1 if above else 1
+ line_text = utilities.text_at_line(view, line_num)
+
+ if above:
+ table = table[::-1]
+
+ return table
+
+
+def convert_row_at_point_as_list(view, from_point):
+ """Convert the row at point as a python list.
+ """
+ line_num, _ = view.rowcol(from_point)
+ line_text = utilities.text_at_line(view, line_num)
+
+ return _convert_row_text_as_list(line_text)
+
+
+def _convert_row_text_as_list(row_text):
+ """Convert the text of a row into a python list.
+
+ Paramters
+ ---------
+ row_text: str
+ The text of the row.
+
+ Returns
+ -------
+ lst: list
+ The converted list.
+
+ """
+ split_row = row_text.split("|")
+
+ if len(split_row) > 2 and split_row[-1].strip() == "":
+ lst = split_row[1:-1]
+ else:
+ lst = split_row[1:]
+
+ match = SEPARATOR_PATTERN.match(row_text)
+ if match:
+ lst = [match.group(1)]
+
+ return [i.strip() for i in lst]
+
+
+def reformat_table_list(table):
+ """Reformat & align the table list.
+
+ After this, every column is of the same length,
+ and every row is of the same number of column.
+
+ """
+ cols_num = max([len(row) for row in table])
+ cols_length = _get_cols_length(table, cols_num)
+
+ new_table = []
+ for row in table:
+ new_row = []
+ if not SEPARATOR_PATTERN.match(row[0]):
+ for i in range(cols_num):
+ try:
+ col = row[i]
+ new_row.append(col + " " * (cols_length[i] - len(col)))
+ except:
+ new_row.append(" " * cols_length[i])
+ else:
+ marker = row[0][1]
+ for i in range(cols_num):
+ new_row.append(marker * (cols_length[i] + 2))
+ # Add a mark for recognization
+ new_row[0] = "+" + new_row[0]
+ new_table.append(new_row)
+ return new_table
+
+
+def convert_table_list_to_str(table):
+ """Convert the python list to str for outputing.
+
+ """
+ table_str = ""
+ table = copy.deepcopy(table)
+ for row in table:
+ if SEPARATOR_PATTERN.match(row[0]):
+ row[0] = row[0][1:] # Remove the mark added in reformat_table_list
+ row_str = "+"
+ for col_str in row:
+ row_str += col_str + "+"
+ else:
+ row_str = "|"
+ for col_str in row:
+ row_str += " " + col_str + " " + "|"
+ table_str += row_str + "\n"
+ return table_str[:-1]
+
+
+def _get_cols_length(table, cols_num):
+ """Return the max length of every columns.
+ """
+ cols_length = [0] * cols_num
+ for row in table:
+ for (i, col) in enumerate(row):
+ col_len = len(col)
+ if col_len > cols_length[i]:
+ cols_length[i] = col_len
+ return cols_length
+
+
+def get_point_row_and_col(view, from_point):
+ """Return the row and col the current point is in the table.
+ """
+ line_num, _ = view.rowcol(from_point)
+ line_num -= 1
+
+ line_text = utilities.text_at_line(view, line_num)
+ row_num = 0
+ while line_text and (TABLE_PATTERN.match(line_text) or
+ SEPARATOR_PATTERN.match(line_text)):
+ row_num += 1
+ line_num -= 1
+ line_text = utilities.text_at_line(view, line_num)
+
+ line_start_point = view.line(from_point)
+ region = sublime.Region(line_start_point.a, from_point)
+ precedding_text = view.substr(region)
+
+ split_row = precedding_text.split("|")
+ if len(split_row) >= 2:
+ col_num = len(split_row) - 2
+ elif split_row[0].strip() == "":
+ col_num = -1
+ else:
+ col_num = None
+ return (row_num, col_num)
+
+
+def is_line_separator(view, line_num):
+ """Check if the current line is a separator.
+ """
+ text = utilities.text_at_line(view, line_num)
+ if text and SEPARATOR_PATTERN.match(text):
+ return True
+ else:
+ return False
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/utilities.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/utilities.py
new file mode 100644
index 0000000..2510143
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SmartMarkdown/utilities.py
@@ -0,0 +1,23 @@
+"""Some utility functions for working with sublime.
+"""
+
+
+def text_at_line(view, line_num):
+ """Return the content at line. None if out of boundary."""
+ if line_num < 0:
+ return None
+
+ max_line_num, _ = view.rowcol(view.size())
+ if line_num > max_line_num:
+ return None
+
+ point = view.text_point(line_num, 0)
+ line_region = view.line(point)
+ return view.substr(line_region)
+
+def is_region_void(region):
+ if region == None:
+ return True
+ if region.a == -1 and region.b == -1:
+ return True
+ return False
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/README.mkd b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/README.mkd
new file mode 100644
index 0000000..a0d0f05
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/README.mkd
@@ -0,0 +1,80 @@
+Solarized Colorscheme for Sublime Text
+=============================
+
+See the [Solarized homepage](http://ethanschoonover.com/solarized) for screenshots,
+details and colorscheme versions for Vim, Mutt, popular terminal emulators and
+other applications.
+
+
+Downloads
+---------
+
+If you have come across this page via github please visit the main [Solarized homepage](http://ethanschoonover.com/solarized). The original [Solarized repository] has many more themes and a number of [test files].
+
+[Solarized homepage]: http://ethanschoonover.com/solarized
+[Solarized repository]: https://github.com/altercation/solarized
+[test files]: https://github.com/altercation/solarized/tree/master/utils/tests
+
+
+Sublime Text Support
+---------
+
+This theme is fully compatible with [Sublime Text][Sublime]!
+
+To install it, ensure that you have installed Sublime Package Control following [these instructions][SublimePackage]
+
+Open the Sublime command palette with `Ctrl + Shift + P`, type / select `Package Control: Install Package`,
+then from the package control list, type / select `Solarized Color Scheme (TextMate)`
+
+Note that packages are auto-updating, so as new modifications are made they will automatically be installed.
+
+[Sublime]: http://www.sublimetext.com/dev
+[SublimePackage]: http://wbond.net/sublime_packages/package_control/installation
+
+
+Contribute
+---------
+
+The goal is to get as-close-as-possible to the rendering of the same file in Vim. If you would like to help, here's how to get involved.
+
+
+1. Fork this repo and checkout your own copy.
+2. Download the [sample documents](https://github.com/altercation/solarized/tree/master/utils/tests).
+3. Checkout this guide to [TextMate theme development](http://manual.macromates.com/en/themes).
+4. Check the [issues](https://github.com/deplorableword/textmate-solarized/issues) to see what needs working on.
+
+Contributors
+---------
+* [deplorableword](https://github.com/deplorableword)
+* [fentie](https://github.com/fentie)
+* [bmthykm](https://github.com/bmthykm)
+* [Zegnat](https://github.com/zegnat)
+* [markstory](https://github.com/markstory)
+* [rays](https://github.com/rays)
+* [joshcarr](https://github.com/joshcarr)
+* [thatRD](https://github.com/thatRD)
+* [oesmith](https://github.com/oesmith)
+* [evanmoran](https://github.com/evanmoran)
+* [iristyle](https://github.com/iristyle)
+* [braver](https://github.com/braver)
+
+License
+-------
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/Solarized (dark).tmTheme b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/Solarized (dark).tmTheme
new file mode 100644
index 0000000..b15208e
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/Solarized (dark).tmTheme
@@ -0,0 +1,2142 @@
+
+
+
+
+ name
+ Solarized (dark)
+ settings
+
+
+ settings
+
+ background
+ #002B36
+ caret
+ #839496
+ foreground
+ #839496
+ invisibles
+ #073642
+ lineHighlight
+ #073642
+ selection
+ #EEE8D5
+
+
+
+ name
+ Comment
+ scope
+ comment
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ String
+ scope
+ string
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ StringNumber
+ scope
+ string
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ Regexp
+ scope
+ string.regexp
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Number
+ scope
+ constant.numeric
+ settings
+
+ foreground
+ #D33682
+
+
+
+ name
+ Variable
+ scope
+ variable.language, variable.other
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Keyword
+ scope
+ keyword
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Storage
+ scope
+ storage
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Class name
+ scope
+ entity.name.class, entity.name.type.class
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Function name
+ scope
+ entity.name.function
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Variable start
+ scope
+ punctuation.definition.variable
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Embedded code markers
+ scope
+ punctuation.section.embedded.begin, punctuation.section.embedded.end
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Built-in constant
+ scope
+ constant.language, meta.preprocessor
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Support.construct
+ scope
+ support.function.construct, keyword.other.new
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ User-defined constant
+ scope
+ constant.character, constant.other
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Inherited class
+ scope
+ entity.other.inherited-class
+ settings
+
+
+
+ name
+ Function argument
+ scope
+ variable.parameter
+ settings
+
+
+
+ name
+ Tag name
+ scope
+ entity.name.tag
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #268BD2
+
+
+
+ name
+ Tag start/end
+ scope
+ punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ Tag attribute
+ scope
+ entity.other.attribute-name
+ settings
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ Library function
+ scope
+ support.function
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Continuation
+ scope
+ punctuation.separator.continuation
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Library constant
+ scope
+ support.constant
+ settings
+
+
+
+ name
+ Library class/type
+ scope
+ support.type, support.class
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Library Exception
+ scope
+ support.type.exception
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Special
+ scope
+ keyword.other.special-method
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Library variable
+ scope
+ support.other.variable
+ settings
+
+
+
+ name
+ Invalid
+ scope
+ invalid
+ settings
+
+
+
+ name
+ Quoted String
+ scope
+ string.quoted.double, string.quoted.single
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Quotes
+ scope
+ punctuation.definition.string.begin, punctuation.definition.string.end
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ CSS: Property
+ scope
+ entity.name.tag.css, support.type.property-name.css, meta.property-name.css
+ settings
+
+ fontStyle
+
+ foreground
+ #839496
+
+
+
+ name
+ CSS: @font-face
+ scope
+ source.css
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ CSS: Selector
+ scope
+ meta.selector.css
+ settings
+
+ fontStyle
+
+ foreground
+ #839496
+
+
+
+ name
+ CSS: {}
+ scope
+ punctuation.section.property-list.css
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ CSS: Numeric Value
+ scope
+ meta.property-value.css constant.numeric.css, keyword.other.unit.css,constant.other.color.rgb-value.css
+ settings
+
+ fontStyle
+
+ foreground
+ #268BD2
+
+
+
+ name
+ CSS: Value
+ scope
+ meta.property-value.css
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ CSS: !Important
+ scope
+ keyword.other.important.css
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ CSS: Standard Value
+ scope
+ support.constant.color
+ settings
+
+ foreground
+ #6C71C4
+
+
+
+ name
+ CSS: Tag
+ scope
+ entity.name.tag.css
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ CSS: : ,
+ scope
+ punctuation.separator.key-value.css, punctuation.terminator.rule.css
+ settings
+
+ fontStyle
+
+ foreground
+ #839496
+
+
+
+ name
+ CSS .class
+ scope
+ entity.other.attribute-name.class.css
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ CSS :pseudo
+ scope
+ entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ CSS: #id
+ scope
+ entity.other.attribute-name.id.css
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #B58900
+
+
+
+ name
+ JS: Function Name
+ scope
+ meta.function.js, entity.name.function.js, support.function.dom.js
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ JS: Source
+ scope
+ text.html.basic source.js.embedded.html
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ JS: Function
+ scope
+ storage.type.function.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ JS: Numeric Constant
+ scope
+ constant.numeric.js
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ JS: []
+ scope
+ meta.brace.square.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ JS: Storage Type
+ scope
+ storage.type.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ ()
+ scope
+ meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js
+ settings
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ {}
+ scope
+ meta.brace.curly.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ HTML: Doctype
+ scope
+ entity.name.tag.doctype.html, meta.tag.sgml.html, string.quoted.double.doctype.identifiers-and-DTDs.html
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #839496
+
+
+
+ name
+ HTML: Comment Block
+ scope
+ comment.block.html
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #839496
+
+
+
+ name
+ HTML: Script
+ scope
+ entity.name.tag.script.html
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ HTML: Style
+ scope
+ source.css.embedded.html string.quoted.double.html
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ HTML: Text
+ scope
+ text.html.ruby
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #839496
+
+
+
+ name
+ HTML: =
+ scope
+ text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html
+ settings
+
+ fontStyle
+
+ foreground
+ #657B83
+
+
+
+ name
+ HTML: something=
+ scope
+ text.html.basic entity.other.attribute-name.html
+ settings
+
+ foreground
+ #657B83
+
+
+
+ name
+ HTML: "
+ scope
+ text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html, punctuation.definition.string.begin.html, punctuation.definition.string.end.html
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ HTML: <tag>
+ scope
+ entity.name.tag.block.any.html
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #268BD2
+
+
+
+ name
+ HTML: style
+ scope
+ source.css.embedded.html entity.name.tag.style.html
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ HTML: <style>
+ scope
+ entity.name.tag.style.html
+ settings
+
+ fontStyle
+
+
+
+
+ name
+ HTML: {}
+ scope
+ text.html.basic punctuation.section.property-list.css
+ settings
+
+ fontStyle
+
+
+
+
+ name
+ HTML: Embeddable
+ scope
+ source.css.embedded.html, comment.block.html
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #839496
+
+
+
+ name
+ Ruby: Variable definition
+ scope
+ punctuation.definition.variable.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Ruby: Function Name
+ scope
+ meta.function.method.with-arguments.ruby
+ settings
+
+ foreground
+ #657B83
+
+
+
+ name
+ Ruby: Variable
+ scope
+ variable.language.ruby
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Ruby: Function
+ scope
+ entity.name.function.ruby
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Ruby: Keyword Control
+ scope
+ keyword.control.ruby, keyword.control.def.ruby
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Class
+ scope
+ keyword.control.class.ruby, meta.class.ruby
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Class Name
+ scope
+ entity.name.type.class.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Ruby: Keyword
+ scope
+ keyword.control.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Support Class
+ scope
+ support.class.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Ruby: Special Method
+ scope
+ keyword.other.special-method.ruby
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Constant
+ scope
+ constant.language.ruby, constant.numeric.ruby
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Ruby: Constant Other
+ scope
+ variable.other.constant.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Ruby: :symbol
+ scope
+ constant.other.symbol.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Ruby: Punctuation Section ''
+ scope
+ punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Ruby: Special Method
+ scope
+ keyword.other.special-method.ruby
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ PHP: Include
+ scope
+ keyword.control.import.include.php
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Ruby: erb =
+ scope
+ text.html.ruby meta.tag.inline.any.html
+ settings
+
+ fontStyle
+
+ foreground
+ #839496
+
+
+
+ name
+ Ruby: erb ""
+ scope
+ text.html.ruby punctuation.definition.string.begin, text.html.ruby punctuation.definition.string.end
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ PHP: Quoted Single
+ scope
+ punctuation.definition.string.begin, punctuation.definition.string.end
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Class Names
+ scope
+ support.class.php
+ settings
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ PHP: []
+ scope
+ keyword.operator.index-start.php, keyword.operator.index-end.php
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ PHP: Array
+ scope
+ meta.array.php
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ PHP: Array()
+ scope
+ meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ PHP: Array Construct
+ scope
+ support.function.construct.php
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ PHP: Array Begin
+ scope
+ punctuation.definition.array.begin, punctuation.definition.array.end
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ PHP: Numeric Constant
+ scope
+ constant.numeric.php
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ PHP: New
+ scope
+ keyword.other.new.php
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ PHP: ::
+ scope
+ keyword.operator.class
+ settings
+
+ fontStyle
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ PHP: Other Property
+ scope
+ variable.other.property.php
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Class
+ scope
+ storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ PHP: Semicolon
+ scope
+ punctuation.terminator.expression.php
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Inherited Class
+ scope
+ meta.other.inherited-class.php
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ PHP: Storage Type
+ scope
+ storage.type.php
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ PHP: Function
+ scope
+ entity.name.function.php
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Function Construct
+ scope
+ support.function.construct.php
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ PHP: Function Call
+ scope
+ entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Comment
+ scope
+ keyword.other.phpdoc
+ settings
+
+ fontStyle
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Source Emebedded
+ scope
+ source.php.embedded.block.html
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ PHP: Storage Type Function
+ scope
+ storage.type.function.php
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: constant
+ scope
+ constant.numeric.c
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ C: Meta Preprocessor
+ scope
+ meta.preprocessor.c.include, meta.preprocessor.macro.c
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: Keyword
+ scope
+ keyword.control.import.define.c, keyword.control.import.include.c
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: Function Preprocessor
+ scope
+ entity.name.function.preprocessor.c
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: include <something.c>
+ scope
+ meta.preprocessor.c.include string.quoted.other.lt-gt.include.c, meta.preprocessor.c.include punctuation.definition.string.begin.c, meta.preprocessor.c.include punctuation.definition.string.end.c
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ C: Function
+ scope
+ support.function.C99.c, support.function.any-method.c, entity.name.function.c
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ C: "
+ scope
+ punctuation.definition.string.begin.c, punctuation.definition.string.end.c
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ C: Storage Type
+ scope
+ storage.type.c
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ diff: header
+ scope
+ meta.diff, meta.diff.header
+ settings
+
+ background
+ #B58900
+ fontStyle
+ italic
+ foreground
+ #EEE8D5
+
+
+
+ name
+ diff: deleted
+ scope
+ markup.deleted
+ settings
+
+ background
+ #EEE8D5
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ diff: changed
+ scope
+ markup.changed
+ settings
+
+ background
+ #EEE8D5
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ diff: inserted
+ scope
+ markup.inserted
+ settings
+
+ background
+ #EEE8D5
+ foreground
+ #2AA198
+
+
+
+ name
+ Markdown: Linebreak
+ scope
+ text.html.markdown meta.dummy.line-break
+ settings
+
+ background
+ #B58900
+ foreground
+ #EEE8D5
+
+
+
+ name
+ Markdown: Raw
+ scope
+ text.html.markdown markup.raw.inline
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ reST raw
+ scope
+ text.restructuredtext markup.raw
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Other: Removal
+ scope
+ other.package.exclude, other.remove
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Other: Add
+ scope
+ other.add
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: {}
+ scope
+ punctuation.section.group.tex , punctuation.definition.arguments.begin.latex, punctuation.definition.arguments.end.latex, punctuation.definition.arguments.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: {text}
+ scope
+ meta.group.braces.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Tex: Other Math
+ scope
+ string.other.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Tex: {var}
+ scope
+ variable.parameter.function.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Tex: Math \\
+ scope
+ punctuation.definition.constant.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: Constant Math
+ scope
+ text.tex.latex constant.other.math.tex, constant.other.general.math.tex, constant.other.general.math.tex, constant.character.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: Other Math String
+ scope
+ string.other.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Tex: $
+ scope
+ punctuation.definition.string.begin.tex, punctuation.definition.string.end.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: \label
+ scope
+ keyword.control.label.latex, text.tex.latex constant.other.general.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: \label { }
+ scope
+ variable.parameter.definition.label.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: Function
+ scope
+ support.function.be.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Tex: Support Function Section
+ scope
+ support.function.section.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Tex: Support Function
+ scope
+ support.function.general.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: Comment
+ scope
+ punctuation.definition.comment.tex, comment.line.percentage.tex
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ Tex: Reference Label
+ scope
+ keyword.control.ref.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Python: storage
+ scope
+ storage.type.class.python, storage.type.function.python, storage.modifier.global.python
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Python: import
+ scope
+ keyword.control.import.python, keyword.control.import.from.python
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Python: Support.exception
+ scope
+ support.type.exception.python
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Shell: builtin
+ scope
+ support.function.builtin.shell
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Shell: variable
+ scope
+ variable.other.normal.shell
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Shell: DOT_FILES
+ scope
+ source.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Shell: meta scope in loop
+ scope
+ meta.scope.for-in-loop.shell, variable.other.loop.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Shell: ""
+ scope
+ punctuation.definition.string.end.shell, punctuation.definition.string.begin.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Shell: Meta Block
+ scope
+ meta.scope.case-block.shell, meta.scope.case-body.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Shell: []
+ scope
+ punctuation.definition.logical-expression.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Shell: Comment
+ scope
+ comment.line.number-sign.shell
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ Java: import
+ scope
+ keyword.other.import.java
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Java: meta-import
+ scope
+ storage.modifier.import.java
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Java: Class
+ scope
+ meta.class.java storage.modifier.java
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Java: /* comment */
+ scope
+ source.java comment.block
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Java: /* @param */
+ scope
+ comment.block meta.documentation.tag.param.javadoc keyword.other.documentation.param.javadoc
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Perl: variables
+ scope
+ punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Perl: functions
+ scope
+ support.function.perl
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Perl: comments
+ scope
+ comment.line.number-sign.perl
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #586E75
+
+
+
+ name
+ Perl: quotes
+ scope
+ punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Perl: \char
+ scope
+ constant.character.escape.perl
+ settings
+
+ foreground
+ #DC322F
+
+
+
+
+ name
+ Markdown: Headings
+ scope
+ markup.heading.markdown, markup.heading.1.markdown, markup.heading.2.markdown, markup.heading.3.markdown, markup.heading.4.markdown, markup.heading.5.markdown, markup.heading.6.markdown
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Markdown: Bold
+ scope
+ markup.bold.markdown
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #839496
+
+
+
+ name
+ Markdown: Italic
+ scope
+ markup.italic.markdown
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #839496
+
+
+
+ name
+ Markdown: Punctuation for Bold, Italic, and Inline Block
+ scope
+ punctuation.definition.bold.markdown, punctuation.definition.italic.markdown, punctuation.definition.raw.markdown
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Markdown: Bulleted List
+ scope
+ markup.list.unnumbered.markdown
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Markdown: Numbered List
+ scope
+ markup.list.numbered.markdown
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Markdown: Block and Inline Block
+ scope
+ markup.raw.block.markdown, markup.raw.inline.markdown
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Markdown: Quote Block and Punctuation
+ scope
+ markup.quote.markdown, punctuation.definition.blockquote.markdown
+ settings
+
+ foreground
+ #6C71C4
+
+
+
+ name
+ Markdown: Seperator
+ scope
+ meta.separator.markdown
+ settings
+
+ foreground
+ #D33682
+
+
+
+ name
+ Markdown: Link and Reference URL
+ scope
+ meta.image.inline.markdown, markup.underline.link.markdown
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #586E75
+
+
+
+ name
+ Markdown: Link Title, Image Description
+ scope
+ string.other.link.title.markdown, string.other.link.description.markdown
+ settings
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ Markdown: Angle Brakets on Link and Image
+ scope
+ punctuation.definition.link.markdown
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ Markdown: Parens on Link and Image
+ scope
+ punctuation.definition.metadata.markdown
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ Markdown: Square Brakets on Link, Image, and Reference
+ scope
+ punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.constant.markdown
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ SublimeLinter Annotations
+ scope
+ sublimelinter.notes
+ settings
+
+ background
+ #eee8d5
+ foreground
+ #eee8d5
+
+
+
+ name
+ SublimeLinter Error Outline
+ scope
+ sublimelinter.outline.illegal
+ settings
+
+ background
+ #93a1a1
+ foreground
+ #93a1a1
+
+
+
+ name
+ SublimeLinter Error Underline
+ scope
+ sublimelinter.underline.illegal
+ settings
+
+ background
+ #dc322f
+
+
+
+ name
+ SublimeLinter Warning Outline
+ scope
+ sublimelinter.outline.warning
+ settings
+
+ background
+ #839496
+ foreground
+ #839496
+
+
+
+ name
+ SublimeLinter Warning Underline
+ scope
+ sublimelinter.underline.warning
+ settings
+
+ background
+ #b58900
+
+
+
+ name
+ SublimeLinter Violation Outline
+ scope
+ sublimelinter.outline.violation
+ settings
+
+ background
+ #657b83
+ foreground
+ #657b83
+
+
+
+ name
+ SublimeLinter Violation Underline
+ scope
+ sublimelinter.underline.violation
+ settings
+
+ background
+ #cb4b16
+
+
+
+ name
+ SublimeBracketHighlighter
+ scope
+ brackethighlighter.all
+ settings
+
+ background
+ #002b36
+ foreground
+ #cb4b16
+
+
+
+ uuid
+ A4299D9B-1DE5-4BC4-87F6-A757E71B1597
+
+
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/Solarized (light).tmTheme b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/Solarized (light).tmTheme
new file mode 100644
index 0000000..b51af59
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/Solarized (light).tmTheme
@@ -0,0 +1,2146 @@
+
+
+
+
+ name
+ Solarized (light)
+ settings
+
+
+ settings
+
+ background
+ #FDF6E3
+ caret
+ #002B36
+ foreground
+ #586E75
+ invisibles
+ #EEE8D5
+ lineHighlight
+ #EEE8D5
+ selection
+ #073642
+
+
+
+ name
+ Comment
+ scope
+ comment
+ settings
+
+ fontStyle
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ String
+ scope
+ string
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ StringNumber
+ scope
+ string
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ Regexp
+ scope
+ string.regexp
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Number
+ scope
+ constant.numeric
+ settings
+
+ foreground
+ #D33682
+
+
+
+ name
+ Variable
+ scope
+ variable.language, variable.other
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Keyword
+ scope
+ keyword
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Storage
+ scope
+ storage
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Class name
+ scope
+ entity.name.class, entity.name.type.class
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Function name
+ scope
+ entity.name.function
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Variable start
+ scope
+ punctuation.definition.variable
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Embedded code markers
+ scope
+ punctuation.section.embedded.begin, punctuation.section.embedded.end
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Built-in constant
+ scope
+ constant.language, meta.preprocessor
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Support.construct
+ scope
+ support.function.construct, keyword.other.new
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ User-defined constant
+ scope
+ constant.character, constant.other
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Inherited class
+ scope
+ entity.other.inherited-class
+ settings
+
+
+
+ name
+ Function argument
+ scope
+ variable.parameter
+ settings
+
+
+
+ name
+ Tag name
+ scope
+ entity.name.tag
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #268BD2
+
+
+
+ name
+ Tag start/end
+ scope
+ punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end
+ settings
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ Tag attribute
+ scope
+ entity.other.attribute-name
+ settings
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ Library function
+ scope
+ support.function
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Continuation
+ scope
+ punctuation.separator.continuation
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Library constant
+ scope
+ support.constant
+ settings
+
+
+
+ name
+ Library class/type
+ scope
+ support.type, support.class
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Library Exception
+ scope
+ support.type.exception
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Special
+ scope
+ keyword.other.special-method
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Library variable
+ scope
+ support.other.variable
+ settings
+
+
+
+ name
+ Invalid
+ scope
+ invalid
+ settings
+
+
+
+ name
+ Quoted String
+ scope
+ string.quoted.double, string.quoted.single
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Quotes
+ scope
+ punctuation.definition.string.begin, punctuation.definition.string.end
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ CSS: Property
+ scope
+ entity.name.tag.css, support.type.property-name.css, meta.property-name.css
+ settings
+
+ fontStyle
+
+ foreground
+ #657B83
+
+
+
+ name
+ CSS: @font-face
+ scope
+ source.css
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ CSS: Selector
+ scope
+ meta.selector.css
+ settings
+
+ fontStyle
+
+ foreground
+ #657B83
+
+
+
+ name
+ CSS: {}
+ scope
+ punctuation.section.property-list.css
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ CSS: Numeric Value
+ scope
+ meta.property-value.css constant.numeric.css, keyword.other.unit.css,constant.other.color.rgb-value.css
+ settings
+
+ fontStyle
+
+ foreground
+ #268BD2
+
+
+
+ name
+ CSS: Value
+ scope
+ meta.property-value.css
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ CSS: !Important
+ scope
+ keyword.other.important.css
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ CSS: Standard Value
+ scope
+ support.constant.color
+ settings
+
+ foreground
+ #6C71C4
+
+
+
+ name
+ CSS: Tag
+ scope
+ entity.name.tag.css
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ CSS: : ,
+ scope
+ punctuation.separator.key-value.css, punctuation.terminator.rule.css
+ settings
+
+ fontStyle
+
+ foreground
+ #657B83
+
+
+
+ name
+ CSS .class
+ scope
+ entity.other.attribute-name.class.css
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ CSS :pseudo
+ scope
+ entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ CSS: #id
+ scope
+ entity.other.attribute-name.id.css
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #B58900
+
+
+
+ name
+ JS: Function Name
+ scope
+ meta.function.js, entity.name.function.js, support.function.dom.js
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ JS: Source
+ scope
+ text.html.basic source.js.embedded.html
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ JS: Function
+ scope
+ storage.type.function.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ JS: Numeric Constant
+ scope
+ constant.numeric.js
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ JS: []
+ scope
+ meta.brace.square.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ JS: Storage Type
+ scope
+ storage.type.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ ()
+ scope
+ meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js
+ settings
+
+ foreground
+ #93A1A1
+
+
+
+ name
+ {}
+ scope
+ meta.brace.curly.js
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ HTML: Doctype
+ scope
+ entity.name.tag.doctype.html, meta.tag.sgml.html, string.quoted.double.doctype.identifiers-and-DTDs.html
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #839496
+
+
+
+ name
+ HTML: Comment Block
+ scope
+ comment.block.html
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #839496
+
+
+
+ name
+ HTML: Script
+ scope
+ entity.name.tag.script.html
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ HTML: Style
+ scope
+ source.css.embedded.html string.quoted.double.html
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ HTML: Text
+ scope
+ text.html.ruby
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #657b83
+
+
+
+ name
+ HTML: =
+ scope
+ text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html
+ settings
+
+ fontStyle
+
+ foreground
+ #657B83
+
+
+
+ name
+ HTML: something=
+ scope
+ text.html.basic entity.other.attribute-name.html
+ settings
+
+ foreground
+ #657B83
+
+
+
+ name
+ HTML: "
+ scope
+ text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html, punctuation.definition.string.begin.html, punctuation.definition.string.end.html
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ HTML: <tag>
+ scope
+ entity.name.tag.block.any.html
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #268BD2
+
+
+
+ name
+ HTML: style
+ scope
+ source.css.embedded.html entity.name.tag.style.html
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ HTML: <style>
+ scope
+ entity.name.tag.style.html
+ settings
+
+ fontStyle
+
+
+
+
+ name
+ HTML: {}
+ scope
+ text.html.basic punctuation.section.property-list.css
+ settings
+
+ fontStyle
+
+
+
+
+ name
+ HTML: Embeddable
+ scope
+ source.css.embedded.html, comment.block.html
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #839496
+
+
+
+ name
+ Ruby: Variable definition
+ scope
+ punctuation.definition.variable.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Ruby: Function Name
+ scope
+ meta.function.method.with-arguments.ruby
+ settings
+
+ foreground
+ #657B83
+
+
+
+ name
+ Ruby: Variable
+ scope
+ variable.language.ruby
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Ruby: Function
+ scope
+ entity.name.function.ruby
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Ruby: Keyword Control
+ scope
+ keyword.control.ruby, keyword.control.def.ruby
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Class
+ scope
+ keyword.control.class.ruby, meta.class.ruby
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Class Name
+ scope
+ entity.name.type.class.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Ruby: Keyword
+ scope
+ keyword.control.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Support Class
+ scope
+ support.class.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Ruby: Special Method
+ scope
+ keyword.other.special-method.ruby
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Ruby: Constant
+ scope
+ constant.language.ruby, constant.numeric.ruby
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Ruby: Constant Other
+ scope
+ variable.other.constant.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Ruby: :symbol
+ scope
+ constant.other.symbol.ruby
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Ruby: Punctuation Section ''
+ scope
+ punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Ruby: Special Method
+ scope
+ keyword.other.special-method.ruby
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ PHP: Include
+ scope
+ keyword.control.import.include.php
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Ruby: erb =
+ scope
+ text.html.ruby meta.tag.inline.any.html
+ settings
+
+ fontStyle
+
+ foreground
+ #839496
+
+
+
+ name
+ Ruby: erb ""
+ scope
+ text.html.ruby punctuation.definition.string.begin, text.html.ruby punctuation.definition.string.end
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ PHP: Quoted Single
+ scope
+ punctuation.definition.string.begin, punctuation.definition.string.end
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Class Names
+ scope
+ support.class.php
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ PHP: []
+ scope
+ keyword.operator.index-start.php, keyword.operator.index-end.php
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ PHP: Array
+ scope
+ meta.array.php
+ settings
+
+ foreground
+ #586E75
+
+
+
+ name
+ PHP: Array()
+ scope
+ meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ PHP: Array Construct
+ scope
+ support.function.construct.php
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ PHP: Array Begin
+ scope
+ punctuation.definition.array.begin, punctuation.definition.array.end
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ PHP: Numeric Constant
+ scope
+ constant.numeric.php
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ PHP: New
+ scope
+ keyword.other.new.php
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ PHP: ::
+ scope
+ keyword.operator.class
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ PHP: Other Property
+ scope
+ variable.other.property.php
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Class
+ scope
+ storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ PHP: Semicolon
+ scope
+ punctuation.terminator.expression.php
+ settings
+
+ foreground
+ #657B83
+
+
+
+ name
+ PHP: Inherited Class
+ scope
+ meta.other.inherited-class.php
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ PHP: Storage Type
+ scope
+ storage.type.php
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ PHP: Function
+ scope
+ entity.name.function.php
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Function Construct
+ scope
+ support.function.construct.php
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ PHP: Function Call
+ scope
+ entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php
+ settings
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Comment
+ scope
+ keyword.other.phpdoc
+ settings
+
+ fontStyle
+
+ foreground
+ #839496
+
+
+
+ name
+ PHP: Source Emebedded
+ scope
+ source.php.embedded.block.html
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ PHP: Storage Type Function
+ scope
+ storage.type.function.php
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: constant
+ scope
+ constant.numeric.c
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ C: Meta Preprocessor
+ scope
+ meta.preprocessor.c.include, meta.preprocessor.macro.c
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: Keyword
+ scope
+ keyword.control.import.define.c, keyword.control.import.include.c
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: Function Preprocessor
+ scope
+ entity.name.function.preprocessor.c
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ C: include <something.c>
+ scope
+ meta.preprocessor.c.include string.quoted.other.lt-gt.include.c, meta.preprocessor.c.include punctuation.definition.string.begin.c, meta.preprocessor.c.include punctuation.definition.string.end.c
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ C: Function
+ scope
+ support.function.C99.c, support.function.any-method.c, entity.name.function.c
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ C: "
+ scope
+ punctuation.definition.string.begin.c, punctuation.definition.string.end.c
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ C: Storage Type
+ scope
+ storage.type.c
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ diff: header
+ scope
+ meta.diff, meta.diff.header
+ settings
+
+ background
+ #B58900
+ fontStyle
+ italic
+ foreground
+ #EEE8D5
+
+
+
+ name
+ diff: deleted
+ scope
+ markup.deleted
+ settings
+
+ background
+ #EEE8D5
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ diff: changed
+ scope
+ markup.changed
+ settings
+
+ background
+ #EEE8D5
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ diff: inserted
+ scope
+ markup.inserted
+ settings
+
+ background
+ #EEE8D5
+ foreground
+ #2AA198
+
+
+
+ name
+ Markdown: Linebreak
+ scope
+ text.html.markdown meta.dummy.line-break
+ settings
+
+ background
+ #B58900
+ foreground
+ #EEE8D5
+
+
+
+ name
+ Markdown: Raw
+ scope
+ text.html.markdown markup.raw.inline
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ reST raw
+ scope
+ text.restructuredtext markup.raw
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Other: Removal
+ scope
+ other.package.exclude, other.remove
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Other: Add
+ scope
+ other.add
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: {}
+ scope
+ punctuation.section.group.tex , punctuation.definition.arguments.begin.latex, punctuation.definition.arguments.end.latex, punctuation.definition.arguments.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: {text}
+ scope
+ meta.group.braces.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Tex: Other Math
+ scope
+ string.other.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Tex: {var}
+ scope
+ variable.parameter.function.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Tex: Math \\
+ scope
+ punctuation.definition.constant.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: Constant Math
+ scope
+ text.tex.latex constant.other.math.tex, constant.other.general.math.tex, constant.other.general.math.tex, constant.character.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: Other Math String
+ scope
+ string.other.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Tex: $
+ scope
+ punctuation.definition.string.begin.tex, punctuation.definition.string.end.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: \label
+ scope
+ keyword.control.label.latex, text.tex.latex constant.other.general.math.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: \label { }
+ scope
+ variable.parameter.definition.label.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Tex: Function
+ scope
+ support.function.be.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Tex: Support Function Section
+ scope
+ support.function.section.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Tex: Support Function
+ scope
+ support.function.general.tex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Tex: Comment
+ scope
+ punctuation.definition.comment.tex, comment.line.percentage.tex
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ Tex: Reference Label
+ scope
+ keyword.control.ref.latex
+ settings
+
+ fontStyle
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Python: storage
+ scope
+ storage.type.class.python, storage.type.function.python, storage.modifier.global.python
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Python: import
+ scope
+ keyword.control.import.python, keyword.control.import.from.python
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Python: Support.exception
+ scope
+ support.type.exception.python
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Shell: builtin
+ scope
+ support.function.builtin.shell
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Shell: variable
+ scope
+ variable.other.normal.shell
+ settings
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Shell: DOT_FILES
+ scope
+ source.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Shell: meta scope in loop
+ scope
+ meta.scope.for-in-loop.shell, variable.other.loop.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Shell: ""
+ scope
+ punctuation.definition.string.end.shell, punctuation.definition.string.begin.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #859900
+
+
+
+ name
+ Shell: Meta Block
+ scope
+ meta.scope.case-block.shell, meta.scope.case-body.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Shell: []
+ scope
+ punctuation.definition.logical-expression.shell
+ settings
+
+ fontStyle
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Shell: Comment
+ scope
+ comment.line.number-sign.shell
+ settings
+
+ fontStyle
+ italic
+
+
+
+ name
+ Java: import
+ scope
+ keyword.other.import.java
+ settings
+
+ fontStyle
+
+ foreground
+ #CB4B16
+
+
+
+ name
+ Java: meta-import
+ scope
+ storage.modifier.import.java
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Java: Class
+ scope
+ meta.class.java storage.modifier.java
+ settings
+
+ fontStyle
+
+ foreground
+ #B58900
+
+
+
+ name
+ Java: /* comment */
+ scope
+ source.java comment.block
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Java: /* @param */
+ scope
+ comment.block meta.documentation.tag.param.javadoc keyword.other.documentation.param.javadoc
+ settings
+
+ fontStyle
+
+ foreground
+ #586E75
+
+
+
+ name
+ Perl: variables
+ scope
+ punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Perl: functions
+ scope
+ support.function.perl
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Perl: comments
+ scope
+ comment.line.number-sign.perl
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #586E75
+
+
+
+ name
+ Perl: quotes
+ scope
+ punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ Perl: \char
+ scope
+ constant.character.escape.perl
+ settings
+
+ foreground
+ #DC322F
+
+
+
+
+ name
+ Markdown: Headings
+ scope
+ markup.heading.markdown, markup.heading.1.markdown, markup.heading.2.markdown, markup.heading.3.markdown, markup.heading.4.markdown, markup.heading.5.markdown, markup.heading.6.markdown
+ settings
+
+ foreground
+ #268BD2
+
+
+
+ name
+ Markdown: Bold
+ scope
+ markup.bold.markdown
+ settings
+
+ fontStyle
+ bold
+ foreground
+ #586E75
+
+
+
+ name
+ Markdown: Italic
+ scope
+ markup.italic.markdown
+ settings
+
+ fontStyle
+ italic
+ foreground
+ #586E75
+
+
+
+ name
+ Markdown: Punctuation for Bold, Italic, and Inline Block
+ scope
+ punctuation.definition.bold.markdown, punctuation.definition.italic.markdown, punctuation.definition.raw.markdown
+ settings
+
+ foreground
+ #DC322F
+
+
+
+ name
+ Markdown: Bulleted List
+ scope
+ markup.list.unnumbered.markdown
+ settings
+
+ foreground
+ #B58900
+
+
+
+ name
+ Markdown: Numbered List
+ scope
+ markup.list.numbered.markdown
+ settings
+
+ foreground
+ #859900
+
+
+
+ name
+ Markdown: Block and Inline Block
+ scope
+ markup.raw.block.markdown, markup.raw.inline.markdown
+ settings
+
+ foreground
+ #2AA198
+
+
+
+ name
+ markup.quote.markdown
+ scope
+ markup.quote.markdown
+ settings
+
+ foreground
+ #6C71C4
+
+
+
+
+ name
+ punctuation.definition.blockquote.markdown
+ scope
+ punctuation.definition.blockquote.markdown
+ settings
+
+ foreground
+ #6C71C4
+
+
+
+
+ name
+ Markdown: Seperator
+ scope
+ meta.separator.markdown
+ settings
+
+ foreground
+ #D33682
+
+
+
+
+ name
+ Markdown: Link URL, Reference
+ scope
+ markup.underline.link.markdown
+ settings
+
+ foreground
+ #839496
+
+
+
+
+ name
+ Markdown: Link Title
+ scope
+ markup.underline.link.markdown
+ settings
+
+ foreground
+ #839496
+
+
+
+
+ name
+ Markdown: Link Punctuation
+ scope
+ meta.link.inet.markdown, meta.link.email.lt-gt.markdown, punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.link.markdown
+ settings
+
+ foreground
+ #DC322F
+
+
+
+
+ name
+ text plain
+ scope
+ text.plain
+ settings
+
+ foreground
+ #657B83
+
+
+
+ name
+ SublimeLinter Annotations
+ scope
+ sublimelinter.notes
+ settings
+
+ background
+ #eee8d5
+ foreground
+ #eee8d5
+
+
+
+ name
+ SublimeLinter Error Outline
+ scope
+ sublimelinter.outline.illegal
+ settings
+
+ background
+ #93a1a1
+ foreground
+ #93a1a1
+
+
+
+ name
+ SublimeLinter Error Underline
+ scope
+ sublimelinter.underline.illegal
+ settings
+
+ background
+ #dc322f
+
+
+
+ name
+ SublimeLinter Warning Outline
+ scope
+ sublimelinter.outline.warning
+ settings
+
+ background
+ #839496
+ foreground
+ #839496
+
+
+
+ name
+ SublimeLinter Warning Underline
+ scope
+ sublimelinter.underline.warning
+ settings
+
+ background
+ #b58900
+
+
+
+ name
+ SublimeLinter Violation Outline
+ scope
+ sublimelinter.outline.violation
+ settings
+
+ background
+ #657b83
+ foreground
+ #657b83
+
+
+
+ name
+ SublimeLinter Violation Underline
+ scope
+ sublimelinter.underline.violation
+ settings
+
+ background
+ #cb4b16
+
+
+
+ name
+ SublimeBracketHighlighter
+ scope
+ brackethighlighter.all
+ settings
+
+ background
+ #FDF6E3
+ foreground
+ #cb4b16
+
+
+
+ uuid
+ 38E819D9-AE02-452F-9231-ECC3B204AFD7
+
+
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/package-metadata.json
new file mode 100644
index 0000000..8806a64
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/Solarized Color Scheme/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/SublimeColors/Solarized", "version": "2012.11.02.15.06.04", "description": "A port of the popular Solarized Theme for Sublime Text 2"}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/Default.sublime-commands b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/Default.sublime-commands
new file mode 100644
index 0000000..e98178c
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/Default.sublime-commands
@@ -0,0 +1,66 @@
+[
+ {
+ "caption": "StringEncode: HTML Entitize",
+ "command": "html_entitize"
+ },
+ {
+ "caption": "StringEncode: HTML Deentitize",
+ "command": "html_deentitize"
+ },
+ {
+ "caption": "StringEncode: XML Entitize",
+ "command": "xml_entitize"
+ },
+ {
+ "caption": "StringEncode: XML Deentitize",
+ "command": "xml_deentitize"
+ },
+ {
+ "caption": "StringEncode: Safe HTML Entitize",
+ "command": "safe_html_entitize"
+ },
+ {
+ "caption": "StringEncode: Safe HTML Deentitize",
+ "command": "safe_html_deentitize"
+ },
+ {
+ "caption": "StringEncode: JSON Escape",
+ "command": "json_escape"
+ },
+ {
+ "caption": "StringEncode: JSON Unescape",
+ "command": "json_unescape"
+ },
+ {
+ "caption": "StringEncode: URL Encode",
+ "command": "url_encode"
+ },
+ {
+ "caption": "StringEncode: URL Decode",
+ "command": "url_decode"
+ },
+ {
+ "caption": "StringEncode: Base64 Encode",
+ "command": "base64_encode"
+ },
+ {
+ "caption": "StringEncode: Base64 Decode",
+ "command": "base64_decode"
+ },
+ {
+ "caption": "StringEncode: Escape regex",
+ "command": "escape_regex"
+ },
+ {
+ "caption": "StringEncode: Escape LIKE",
+ "command": "escape_like"
+ },
+ {
+ "caption": "StringEncode: Decimal to Hexadecimal",
+ "command": "dec_hex"
+ },
+ {
+ "caption": "StringEncode: Hexadecimal to Decimal",
+ "command": "hex_dec"
+ }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/Example.sublime-keymap b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/Example.sublime-keymap
new file mode 100644
index 0000000..84dce04
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/Example.sublime-keymap
@@ -0,0 +1,14 @@
+[
+ { "keys": ["super+shift+7"], "command": "xml_entitize", "scope": "text.xml" },
+ { "keys": ["super+ctrl+7"], "command": "xml_deentitize", "scope": "text.xml" },
+ { "keys": ["super+shift+7"], "command": "html_entitize" },
+ { "keys": ["super+ctrl+7"], "command": "html_deentitize" },
+ { "keys": ["super+shift+8"], "command": "json_escape" },
+ { "keys": ["super+ctrl+8"], "command": "json_unescape" },
+ { "keys": ["super+shift+6"], "command": "base64_encode" },
+ { "keys": ["super+ctrl+6"], "command": "base64_decode" },
+ { "keys": ["super+shift+5"], "command": "url_encode" },
+ { "keys": ["super+ctrl+5"], "command": "url_decode" },
+ { "keys": ["ctrl+shift+r"], "command": "escape_regex" },
+ { "keys": ["super+ctrl+3"], "command": "hex_dec" }
+]
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/README.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/README.md
new file mode 100644
index 0000000..18aa332
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/README.md
@@ -0,0 +1,52 @@
+StringEncode plugin for Sublime Text 2
+======================================
+
+Converts characters from one "encoding" to another using a transformation (think HTML entities, not character encodings).
+
+Installation
+------------
+
+1. Using Package Control, install "StringEncode"
+
+Or:
+
+1. Open the Sublime Text 2 Packages folder
+ - OS X: ~/Library/Application Support/Sublime Text 2/Packages/
+ - Windows: %APPDATA%/Sublime Text 2/Packages/
+ - Linux: ~/.Sublime Text 2/Packages/
+2. clone this repo
+3. Install keymaps for the commands (see Example.sublime-keymap for my preferred keys)
+
+Commands
+--------
+
+`html_entitize`: Converts characters to their HTML entity
+
+`html_deentitize`: Converts HTML entities to a character
+
+`url_encode`: Uses urllib.quote to escape special URL characters
+
+`url_decode`: Uses urllib.unquote to convert escaped URL characters
+
+`json_escape`: Escapes a string and surrounds it in quotes, according to the JSON encoding.
+
+`json_unescape`: Unescapes a string (include the quotes!) according to JSON encoding.
+
+`base64_encode`: Uses base64 to encode into base64
+
+`base64_decode`: Uses base64 to decode from base64
+
+`escape_regex`: Escapes regex meta characters
+
+`escape_like`: Escapes SQL-LIKE meta characters
+
+`safe_html_entitize`: Converts characters to their HTML entity, but preserves HTML reserved characters
+
+`safe_html_deentitize`: Converts HTML entities to a character, but preserves HTML reserved characters
+
+TODO
+----
+
+`xml_entitize`: Converts characters to their XML entity
+
+`xml_deentitize`: Converts XML entities to a character
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/package-metadata.json
new file mode 100644
index 0000000..f32ec30
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/colinta/SublimeStringEncode", "version": "1.5.1", "description": "Converts characters from one encoding to another using a transformation (think HTML entities, not character encodings)."}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/package.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/package.json
new file mode 100644
index 0000000..1da7f07
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/package.json
@@ -0,0 +1,7 @@
+{
+ "repo": "SublimeStringEncode",
+ "name": "StringEncode",
+ "description": "Converts characters from one encoding to another using a transformation (think HTML entities, not character encodings).",
+ "author": "Colin Thomas-Arnold (colinta)",
+ "homepage": "https://github.com/colinta/SublimeStringEncode"
+}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/string_encode.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/string_encode.py
new file mode 100644
index 0000000..efadd24
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/StringEncode/string_encode.py
@@ -0,0 +1,165 @@
+# coding: utf8
+
+import sublime_plugin
+import urllib
+import base64
+import re
+import json
+
+
+class StringEncode(sublime_plugin.TextCommand):
+ def run(self, edit):
+ e = self.view.begin_edit('encode')
+ regions = [region for region in self.view.sel()]
+
+ # sort by region.end() DESC
+ def get_end(region):
+ return region.end()
+ regions.sort(key=get_end, reverse=True)
+
+ for region in regions:
+ if region.empty():
+ continue
+ text = self.view.substr(region)
+ replacement = self.encode(text)
+ self.view.replace(edit, region, replacement)
+ self.view.end_edit(e)
+
+
+html_escape_table = {
+ u"\"": """, u"'": "'", u"<": "<", u">": ">", u"¡": "¡", u"¢": "¢", u"£": "£", u"¤": "¤", u"¥": "¥", u"¦": "¦", u"§": "§", u"¨": "¨", u"©": "©", u"ª": "ª", u"«": "«", u"¬": "¬", u"®": "®", u"¯": "¯", u"°": "°", u"±": "±", u"²": "²", u"³": "³", u"´": "´", u"µ": "µ", u"¶": "¶", u"·": "·", u"¸": "¸", u"¹": "¹", u"º": "º", u"»": "»", u"¼": "¼", u"½": "½", u"¾": "¾", u"¿": "¿", u"À": "À", u"Á": "Á", u"Â": "Â", u"Ã": "Ã", u"Ä": "Ä", u"Å": "Å", u"Æ": "Æ", u"Ç": "Ç", u"È": "È", u"É": "É", u"Ê": "Ê", u"Ë": "Ë", u"Ì": "Ì", u"Í": "Í", u"Î": "Î", u"Ï": "Ï", u"Ð": "Ð", u"Ñ": "Ñ", u"Ò": "Ò", u"Ó": "Ó", u"Ô": "Ô", u"Õ": "Õ", u"Ö": "Ö", u"×": "×", u"Ø": "Ø", u"Ù": "Ù", u"Ú": "Ú", u"Û": "Û", u"Ü": "Ü", u"Ý": "Ý", u"Þ": "Þ", u"ß": "ß", u"à": "à", u"á": "á", u"â": "â", u"ã": "ã", u"ä": "ä", u"å": "å", u"æ": "æ", u"ç": "ç", u"è": "è", u"é": "é", u"ê": "ê", u"ë": "ë", u"ì": "ì", u"í": "í", u"î": "î", u"ï": "ï", u"ð": "ð", u"ñ": "ñ", u"ò": "ò", u"ó": "ó", u"ô": "ô", u"õ": "õ", u"ö": "ö", u"÷": "÷", u"ø": "ø", u"ù": "ù", u"ú": "ú", u"û": "û", u"ü": "ü", u"ý": "ý", u"þ": "þ", u"ÿ": "ÿ", u"Œ": "Œ", u"œ": "œ", u"Š": "Š", u"š": "š", u"Ÿ": "Ÿ", u"ƒ": "ƒ", u"ˆ": "ˆ", u"˜": "˜", u"Α": "Α", u"Β": "Β", u"Γ": "Γ", u"Δ": "Δ", u"Ε": "Ε", u"Ζ": "Ζ", u"Η": "Η", u"Θ": "Θ", u"Ι": "Ι", u"Κ": "Κ", u"Λ": "Λ", u"Μ": "Μ", u"Ν": "Ν", u"Ξ": "Ξ", u"Ο": "Ο", u"Π": "Π", u"Ρ": "Ρ", u"Σ": "Σ", u"Τ": "Τ", u"Υ": "Υ", u"Φ": "Φ", u"Χ": "Χ", u"Ψ": "Ψ", u"Ω": "Ω", u"α": "α", u"β": "β", u"γ": "γ", u"δ": "δ", u"ε": "ε", u"ζ": "ζ", u"η": "η", u"θ": "θ", u"ι": "ι", u"κ": "κ", u"λ": "λ", u"μ": "μ", u"ν": "ν", u"ξ": "ξ", u"ο": "ο", u"π": "π", u"ρ": "ρ", u"ς": "ς", u"σ": "σ", u"τ": "τ", u"υ": "υ", u"φ": "φ", u"χ": "χ", u"ψ": "ψ", u"ω": "ω", u"ϑ": "ϑ", u"ϒ": "ϒ", u"ϖ": "ϖ", u"–": "–", u"—": "—", u"‘": "‘", u"’": "’", u"‚": "‚", u"“": "“", u"”": "”", u"„": "„", u"†": "†", u"‡": "‡", u"•": "•", u"…": "…", u"‰": "‰", u"′": "′", u"″": "″", u"‹": "‹", u"›": "›", u"‾": "‾", u"⁄": "⁄", u"€": "€", u"ℑ": "ℑ", u"℘": "℘", u"ℜ": "ℜ", u"™": "™", u"ℵ": "ℵ", u"←": "←", u"↑": "↑", u"→": "→", u"↓": "↓", u"↔": "↔", u"↵": "↵", u"⇐": "⇐", u"⇑": "⇑", u"⇒": "⇒", u"⇓": "⇓", u"⇔": "⇔", u"∀": "∀", u"∂": "∂", u"∃": "∃", u"∅": "∅", u"∇": "∇", u"∈": "∈", u"∉": "∉", u"∋": "∋", u"∏": "∏", u"∑": "∑", u"−": "−", u"∗": "∗", u"√": "√", u"∝": "∝", u"∞": "∞", u"∠": "∠", u"∧": "∧", u"∨": "∨", u"∩": "∩", u"∪": "∪", u"∫": "∫", u"∴": "∴", u"∼": "∼", u"≅": "≅", u"≈": "≈", u"≠": "≠", u"≡": "≡", u"≤": "≤", u"≥": "≥", u"⊂": "⊂", u"⊃": "⊃", u"⊄": "⊄", u"⊆": "⊆", u"⊇": "⊇", u"⊕": "⊕", u"⊗": "⊗", u"⊥": "⊥", u"⋅": "⋅", u"⌈": "⌈", u"⌉": "⌉", u"⌊": "⌊", u"⌋": "⌋", u"〈": "〈", u"〉": "〉", u"◊": "◊", u"♠": "♠", u"♣": "♣", u"♥": "♥", u"♦": "♦",
+}
+xml_escape_table = {
+ u"\"": """, u"'": "'", u"<": "<", u">": ">"
+}
+html_reserved_list = (u"\"", u"'", u"<", u">", u"&")
+
+
+class HtmlEntitizeCommand(StringEncode):
+ def encode(self, text):
+ text = text.replace('&', '&')
+ for k in html_escape_table:
+ v = html_escape_table[k]
+ text = text.replace(k, v)
+ ret = ''
+ for i, c in enumerate(text):
+ if ord(c) > 127:
+ ret += hex(ord(c)).replace('0x', '') + ';'
+ else:
+ ret += c
+ return ret
+
+
+class HtmlDeentitizeCommand(StringEncode):
+ def encode(self, text):
+ for k in html_escape_table:
+ v = html_escape_table[k]
+ text = text.replace(v, k)
+ while re.search('[xX][a-fA-F0-9]+;', text):
+ match = re.search('[xX]([a-fA-F0-9]+);', text)
+ text = text.replace(match.group(0), unichr(int('0x' + match.group(1), 16)))
+ text = text.replace('&', '&')
+ return text
+
+
+class SafeHtmlEntitizeCommand(StringEncode):
+ def encode(self, text):
+ for k in html_escape_table:
+ # skip HTML reserved characters
+ if k in html_reserved_list:
+ continue
+ v = html_escape_table[k]
+ text = text.replace(k, v)
+ ret = ''
+ for i, c in enumerate(text):
+ if ord(c) > 127:
+ ret += hex(ord(c)).replace('0x', '') + ';'
+ else:
+ ret += c
+ return ret
+
+
+class SafeHtmlDeentitizeCommand(StringEncode):
+ def encode(self, text):
+ for k in html_escape_table:
+ # skip HTML reserved characters
+ if k in html_reserved_list:
+ continue
+ v = html_escape_table[k]
+ text = text.replace(v, k)
+ while re.search('[xX][a-fA-F0-9]+;', text):
+ match = re.search('[xX]([a-fA-F0-9]+);', text)
+ text = text.replace(match.group(0), unichr(int('0x' + match.group(1), 16)))
+ text = text.replace('&', '&')
+ return text
+
+
+class XmlEntitizeCommand(StringEncode):
+ def encode(self, text):
+ text = text.replace('&', '&')
+ for k in xml_escape_table:
+ v = xml_escape_table[k]
+ text = text.replace(k, v)
+ return text
+
+
+class XmlDeentitizeCommand(StringEncode):
+ def encode(self, text):
+ for k in xml_escape_table:
+ v = xml_escape_table[k]
+ text = text.replace(v, k)
+ text = text.replace('&', '&')
+ return text
+
+
+class JsonEscapeCommand(StringEncode):
+ def encode(self, text):
+ return json.dumps(text)
+
+
+class JsonUnescapeCommand(StringEncode):
+ def encode(self, text):
+ return json.loads(text)
+
+
+class UrlEncodeCommand(StringEncode):
+ def encode(self, text):
+ return urllib.quote(text)
+
+
+class UrlDecodeCommand(StringEncode):
+ def encode(self, text):
+ return urllib.unquote(text)
+
+
+class Base64EncodeCommand(StringEncode):
+ def encode(self, text):
+ return base64.b64encode(text)
+
+
+class Base64DecodeCommand(StringEncode):
+ def encode(self, text):
+ return base64.b64decode(text)
+
+
+class Escaper(StringEncode):
+ def encode(self, text):
+ return re.sub(r'(?.*)$",
+ "NOTE": "NOTE[\\s]*?:+(?P.*)$",
+ "FIXME": "FIX ?ME[\\s]*?:+(?P\\S.*)$",
+ "CHANGED": "CHANGED[\\s]*?:+(?P\\S.*)$"
+}
+```
+
+Note that the pattern _must_ provide at least one named group which will be used to group the comments in results.
+
+By default, searching is not case sensitive. You can change this behaviour by adding
+
+ "case_sensitive": true
+
+to the todo settings object.
+
+
+## Excluding files and folders
+
+Global settings `folder_exclude_patterns`, `file_exclude_patterns` and `binary_file_patterns` are excluded from search results.
+
+To exclude further directories, add directory names (not glob pattern or regexp) to `folder_exclude_patterns` in todo settings:
+
+```javascript
+"todo": {
+ "folder_exclude_patterns": [
+ "vendor",
+ "tmp"
+ ]
+}
+```
+
+To add file excludes, add glob patterns to `file_exclude_patterns`:
+
+```javascript
+"file_exclude_patterns": [
+ "*.css"
+]
+```
+
+
+## Results title
+
+Override the results view title by setting `result_title`
+
+```javascript
+"result_title": "TODO Results"
+```
+
+# Usage
+
+`Show TODOs: Project and open files` scans all files in your project
+`Show TODOs: Open files only` scans only open, saved files
+Both are triggered from the command palette. No default key bindings are provided.
+
+## Navigating results
+
+Results can be navigated by keyboard and mouse:
+
+ * `n`ext, `p`revious, `c`lear, `enter`
+ * `alt-double click` (`shift-double click` in Linux)
+
+ Note that due to the lack of support for context in mousemaps right now,
+ alt-double click will trigger in _any_ document, though it should be a no-op.
+
+# License
+
+All of SublimeTODO is licensed under the MIT license.
+
+Copyright (c) 2012 Rob Cowie
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/messages.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/messages.json
new file mode 100644
index 0000000..ce3c122
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/messages.json
@@ -0,0 +1,3 @@
+{
+ "1.1.0": "messages/1.1.0.txt"
+}
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/messages/1.1.0.txt b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/messages/1.1.0.txt
new file mode 100644
index 0000000..647fe56
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/messages/1.1.0.txt
@@ -0,0 +1,6 @@
+SublimeTODO 1.1.0 Changelog:
+
+ - Repo reorg to support explicit versioning and Package Control upgrade messages.
+
+ - [LINUX] alt + dblclick is replaced by shift + dblclick to prevent clash
+ with common alt+click+drag method of moving windows.
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/package-metadata.json
new file mode 100644
index 0000000..83e3860
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/robcowie/SublimeTODO", "version": "1.1.3", "description": "Extract TODO-type comments from open files and project folders"}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/packages.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/packages.json
new file mode 100644
index 0000000..423b3cc
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/packages.json
@@ -0,0 +1,20 @@
+{
+ "schema_version": "1.2",
+ "packages": [
+ {
+ "name": "SublimeTODO",
+ "description": "Extract TODO-type comments from open files and project folders",
+ "author": "Rob Cowie",
+ "homepage": "https://github.com/robcowie/SublimeTODO",
+ "last_modified": "2012-11-12 10:16:00",
+ "platforms": {
+ "*": [
+ {
+ "version": "1.1.2",
+ "url": "https://nodeload.github.com/robcowie/SublimeTODO/zipball/1.1.2"
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/todo.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/todo.py
new file mode 100644
index 0000000..40c15c0
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/todo.py
@@ -0,0 +1,441 @@
+# -*- coding: utf-8 -*-
+
+## TODO: Implement TODO_IGNORE setting (http://mdeering.com/posts/004-get-your-textmate-todos-and-fixmes-under-control)
+## TODO: Make the output clickable (å la find results)
+## TODO: Occasional NoneType bug
+## todo: Make the sections foldable (define them as regions?)
+
+""""""
+
+from collections import namedtuple
+from datetime import datetime
+import functools
+import fnmatch
+from itertools import groupby
+import logging
+from os import path, walk
+import re
+import threading
+
+import sublime
+import sublime_plugin
+
+
+DEBUG = True
+
+DEFAULT_SETTINGS = {
+ 'result_title': 'TODO Results',
+
+ 'core_patterns': {
+ 'TODO': r'TODO[\s]*?:+(?P.*)$',
+ 'NOTE': r'NOTE[\s]*?:+(?P.*)$',
+ 'FIXME': r'FIX ?ME[\s]*?:+(?P.*)$',
+ 'CHANGED': r'CHANGED[\s]*?:+(?P.*)$'
+ },
+
+ 'patterns': {}
+}
+
+Message = namedtuple('Message', 'type, msg')
+
+## LOGGING SETUP
+try:
+ from logging import NullHandler
+except ImportError:
+ class NullHandler(logging.Handler):
+ def handle(self, record):
+ pass
+
+ def emit(self, record):
+ pass
+
+ def createLock(self):
+ self.lock = None
+
+log = logging.getLogger('SublimeTODO')
+log.handlers = [] ## hack to prevent extraneous handlers on ST2 auto-reload
+log.addHandler(NullHandler())
+log.setLevel(logging.INFO)
+if DEBUG:
+ log.addHandler(logging.StreamHandler())
+ log.setLevel(logging.DEBUG)
+
+
+def do_when(conditional, callback, *args, **kwargs):
+ if conditional():
+ return callback(*args, **kwargs)
+ sublime.set_timeout(functools.partial(do_when, conditional, callback, *args, **kwargs), 50)
+
+
+class Settings(dict):
+ """Combine default and user settings"""
+ def __init__(self, user_settings):
+ settings = DEFAULT_SETTINGS.copy()
+ settings.update(user_settings)
+ ## Combine core_patterns and patterns
+ settings['core_patterns'].update(settings['patterns'])
+ settings['patterns'] = settings.pop('core_patterns')
+ super(Settings, self).__init__(settings)
+
+
+class ThreadProgress(object):
+ def __init__(self, thread, message, success_message, file_counter):
+ self.thread = thread
+ self.message = message
+ self.success_message = success_message
+ self.file_counter = file_counter
+ self.addend = 1
+ self.size = 8
+ sublime.set_timeout(lambda: self.run(0), 100)
+
+ def run(self, i):
+ if not self.thread.is_alive():
+ if hasattr(self.thread, 'result') and not self.thread.result:
+ sublime.status_message('')
+ return
+ sublime.status_message(self.success_message)
+ return
+
+ before = i % self.size
+ after = (self.size - 1) - before
+ sublime.status_message('%s [%s=%s] (%s files scanned)' % \
+ (self.message, ' ' * before, ' ' * after, self.file_counter))
+ if not after:
+ self.addend = -1
+ if not before:
+ self.addend = 1
+ i += self.addend
+ sublime.set_timeout(lambda: self.run(i), 100)
+
+
+
+class TodoExtractor(object):
+ def __init__(self, settings, filepaths, dirpaths, ignored_dirs, ignored_file_patterns,
+ file_counter):
+ self.filepaths = filepaths
+ self.dirpaths = dirpaths
+ self.patterns = settings['patterns']
+ self.settings = settings
+ self.file_counter = file_counter
+ self.ignored_dirs = ignored_dirs
+ self.ignored_files = ignored_file_patterns
+ self.log = logging.getLogger('SublimeTODO.extractor')
+
+ def iter_files(self):
+ """"""
+ seen_paths_ = []
+ files = self.filepaths
+ dirs = self.dirpaths
+ exclude_dirs = self.ignored_dirs
+
+ for filepath in files:
+ pth = path.realpath(path.abspath(filepath))
+ if pth not in seen_paths_:
+ seen_paths_.append(pth)
+ yield pth
+
+ for dirpath in dirs:
+ dirpath = path.abspath(dirpath)
+ for dirpath, dirnames, filenames in walk(dirpath):
+ ## remove excluded dirs
+ ## TODO: These are not patterns. Consider making them glob patterns
+ for dir in exclude_dirs:
+ if dir in dirnames:
+ self.log.debug(u'Ignoring dir: {0}'.format(dir))
+ dirnames.remove(dir)
+
+ for filepath in filenames:
+ pth = path.join(dirpath, filepath)
+ pth = path.realpath(path.abspath(pth))
+ if pth not in seen_paths_:
+ seen_paths_.append(pth)
+ yield pth
+
+ def filter_files(self, files):
+ """"""
+ exclude_patterns = [re.compile(patt) for patt in self.ignored_files]
+ for filepath in files:
+ if any(patt.match(filepath) for patt in exclude_patterns):
+ continue
+ yield filepath
+
+ def search_targets(self):
+ """Yield filtered filepaths for message extraction"""
+ return self.filter_files(self.iter_files())
+
+ def extract(self):
+ """"""
+ message_patterns = '|'.join(self.patterns.values())
+ case_sensitivity = 0 if self.settings.get('case_sensitive', False) else re.IGNORECASE
+ patt = re.compile(message_patterns, case_sensitivity)
+ for filepath in self.search_targets():
+ try:
+ f = open(filepath)
+ self.log.debug(u'Scanning {0}'.format(filepath))
+ for linenum, line in enumerate(f):
+ for mo in patt.finditer(line):
+ ## Remove the non-matched groups
+ matches = [Message(msg_type, msg) for msg_type, msg in mo.groupdict().iteritems() if msg]
+ for match in matches:
+ yield {'filepath': filepath, 'linenum': linenum + 1, 'match': match}
+ except IOError:
+ ## Probably a broken symlink
+ f = None
+ finally:
+ self.file_counter.increment()
+ if f is not None:
+ f.close()
+
+
+class TodoRenderer(object):
+ def __init__(self, settings, window, file_counter):
+ self.window = window
+ self.settings = settings
+ self.file_counter = file_counter
+
+ @property
+ def view_name(self):
+ """The name of the new results view. Defined in settings."""
+ return self.settings['result_title']
+
+ @property
+ def header(self):
+ hr = u'+ {0} +'.format('-' * 76)
+ return u'{hr}\n| TODOS @ {0:<68} |\n| {1:<76} |\n{hr}\n'.format(
+ datetime.now().strftime('%A %d %B %Y %H:%M').decode("utf-8"),
+ u'{0} files scanned'.format(self.file_counter),
+ hr=hr)
+
+ @property
+ def view(self):
+ existing_results = [v for v in self.window.views()
+ if v.name() == self.view_name and v.is_scratch()]
+ if existing_results:
+ v = existing_results[0]
+ else:
+ v = self.window.new_file()
+ v.set_name(self.view_name)
+ v.set_scratch(True)
+ v.settings().set('todo_results', True)
+ return v
+
+ def format(self, messages):
+ """Yield lines for rendering into results view. Includes headers and
+ blank lines.
+ Lines are returned in the form (type, content, [data]) where type is either
+ 'header', 'whitespace' or 'result'
+ """
+ key_func = lambda m: m['match'].type
+ messages = sorted(messages, key=key_func)
+
+ for message_type, matches in groupby(messages, key=key_func):
+ matches = list(matches)
+ if matches:
+ yield ('header', u'\n## {0} ({1})'.format(message_type.upper().decode('utf8', 'ignore'), len(matches)), {})
+ for idx, m in enumerate(matches, 1):
+ msg = m['match'].msg.decode('utf8', 'ignore') ## Don't know the file encoding
+ filepath = path.basename(m['filepath'])
+ line = u"{idx}. {filepath}:{linenum} {msg}".format(
+ idx=idx, filepath=filepath, linenum=m['linenum'], msg=msg)
+ yield ('result', line, m)
+
+ def render_to_view(self, formatted_results):
+ """This blocks the main thread, so make it quick"""
+ ## Header
+ result_view = self.view
+ edit = result_view.begin_edit()
+ result_view.erase(edit, sublime.Region(0, result_view.size()))
+ result_view.insert(edit, result_view.size(), self.header)
+ result_view.end_edit(edit)
+
+ ## Region : match_dicts
+ regions = {}
+
+ ## Result sections
+ for linetype, line, data in formatted_results:
+ edit = result_view.begin_edit()
+ insert_point = result_view.size()
+ result_view.insert(edit, insert_point, line)
+ if linetype == 'result':
+ rgn = sublime.Region(insert_point, result_view.size())
+ regions[rgn] = data
+ result_view.insert(edit, result_view.size(), u'\n')
+ result_view.end_edit(edit)
+
+ result_view.add_regions('results', regions.keys(), '')
+
+ ## Store {Region : data} map in settings
+ ## TODO: Abstract this out to a storage class Storage.get(region) ==> data dict
+ ## Region() cannot be stored in settings, so convert to a primitive type
+ # d_ = regions
+ d_ = dict(('{0},{1}'.format(k.a, k.b), v) for k, v in regions.iteritems())
+ result_view.settings().set('result_regions', d_)
+
+ ## Set syntax and settings
+ result_view.set_syntax_file('Packages/SublimeTODO/todo_results.hidden-tmLanguage')
+ result_view.settings().set('line_padding_bottom', 2)
+ result_view.settings().set('line_padding_top', 2)
+ result_view.settings().set('word_wrap', False)
+ result_view.settings().set('command_mode', True)
+ self.window.focus_view(result_view)
+
+
+class WorkerThread(threading.Thread):
+ def __init__(self, extractor, renderer):
+ self.extractor = extractor
+ self.renderer = renderer
+ threading.Thread.__init__(self)
+
+ def run(self):
+ ## Extract in this thread
+ todos = self.extractor.extract()
+ rendered = list(self.renderer.format(todos))
+
+ ## Render into new window in main thread
+ def render():
+ self.renderer.render_to_view(rendered)
+ sublime.set_timeout(render, 10)
+
+
+class FileScanCounter(object):
+ """Thread-safe counter used to update the status bar"""
+ def __init__(self):
+ self.ct = 0
+ self.lock = threading.RLock()
+ self.log = logging.getLogger('SublimeTODO')
+
+ def __call__(self, filepath):
+ self.log.debug(u'Scanning %s' % filepath)
+ self.increment()
+
+ def __str__(self):
+ with self.lock:
+ return '%d' % self.ct
+
+ def increment(self):
+ with self.lock:
+ self.ct += 1
+
+ def reset(self):
+ with self.lock:
+ self.ct = 0
+
+
+class TodoCommand(sublime_plugin.TextCommand):
+
+ def search_paths(self, window, open_files_only=False):
+ """Return (filepaths, dirpaths)"""
+ return (
+ [view.file_name() for view in window.views() if view.file_name()],
+ window.folders() if not open_files_only else []
+ )
+
+ def run(self, edit, open_files_only=False):
+ window = self.view.window()
+ settings = Settings(self.view.settings().get('todo', {}))
+
+
+ ## TODO: Cleanup this init code. Maybe move it to the settings object
+ filepaths, dirpaths = self.search_paths(window, open_files_only=open_files_only)
+
+ ignored_dirs = settings.get('folder_exclude_patterns', [])
+ ## Get exclude patterns from global settings
+ ## Is there really no better way to access global settings?
+ global_settings = sublime.load_settings('Global.sublime-settings')
+ ignored_dirs.extend(global_settings.get('folder_exclude_patterns', []))
+
+ exclude_file_patterns = settings.get('file_exclude_patterns', [])
+ exclude_file_patterns.extend(global_settings.get('file_exclude_patterns', []))
+ exclude_file_patterns.extend(global_settings.get('binary_file_patterns', []))
+ exclude_file_patterns = [fnmatch.translate(patt) for patt in exclude_file_patterns]
+
+ file_counter = FileScanCounter()
+ extractor = TodoExtractor(settings, filepaths, dirpaths, ignored_dirs,
+ exclude_file_patterns, file_counter)
+ renderer = TodoRenderer(settings, window, file_counter)
+
+ worker_thread = WorkerThread(extractor, renderer)
+ worker_thread.start()
+ ThreadProgress(worker_thread, 'Finding TODOs', '', file_counter)
+
+
+class NavigateResults(sublime_plugin.TextCommand):
+ DIRECTION = {'forward': 1, 'backward': -1}
+ STARTING_POINT = {'forward': -1, 'backward': 0}
+
+ def __init__(self, view):
+ super(NavigateResults, self).__init__(view)
+
+ def run(self, edit, direction):
+ view = self.view
+ settings = view.settings()
+ results = self.view.get_regions('results')
+ if not results:
+ sublime.status_message('No results to navigate')
+ return
+
+ ##NOTE: numbers stored in settings are coerced to floats or longs
+ selection = int(settings.get('selected_result', self.STARTING_POINT[direction]))
+ selection = selection + self.DIRECTION[direction]
+ try:
+ target = results[selection]
+ except IndexError:
+ target = results[0]
+ selection = 0
+
+ settings.set('selected_result', selection)
+ ## Create a new region for highlighting
+ target = target.cover(target)
+ view.add_regions('selection', [target], 'selected', 'dot')
+ view.show(target)
+
+
+class ClearSelection(sublime_plugin.TextCommand):
+ def run(self, edit):
+ self.view.erase_regions('selection')
+ self.view.settings().erase('selected_result')
+
+
+class GotoComment(sublime_plugin.TextCommand):
+ def __init__(self, *args):
+ self.log = logging.getLogger('SublimeTODO.nav')
+ super(GotoComment, self).__init__(*args)
+
+ def run(self, edit):
+ ## Get the idx of selected result region
+ selection = int(self.view.settings().get('selected_result', -1))
+ ## Get the region
+ selected_region = self.view.get_regions('results')[selection]
+ ## Convert region to key used in result_regions (this is tedious, but
+ ## there is no other way to store regions with associated data)
+ data = self.view.settings().get('result_regions')['{0},{1}'.format(selected_region.a, selected_region.b)]
+ self.log.debug(u'Goto comment at {filepath}:{linenum}'.format(**data))
+ new_view = self.view.window().open_file(data['filepath'])
+ do_when(lambda: not new_view.is_loading(), lambda: new_view.run_command("goto_line", {"line": data['linenum']}))
+
+
+class MouseGotoComment(sublime_plugin.TextCommand):
+ def __init__(self, *args):
+ self.log = logging.getLogger('SublimeTODO.nav')
+ super(MouseGotoComment, self).__init__(*args)
+
+ def highlight(self, region):
+ target = region.cover(region)
+ self.view.add_regions('selection', [target], 'selected', 'dot')
+ self.view.show(target)
+
+ def get_result_region(self, pos):
+ line = self.view.line(pos)
+ return line
+
+ def run(self, edit):
+ if not self.view.settings().get('result_regions'):
+ return
+ ## get selected line
+ pos = self.view.sel()[0].end()
+ result = self.get_result_region(pos)
+ self.highlight(result)
+ data = self.view.settings().get('result_regions')['{0},{1}'.format(result.a, result.b)]
+ self.log.debug(u'Goto comment at {filepath}:{linenum}'.format(**data))
+ new_view = self.view.window().open_file(data['filepath'])
+ do_when(lambda: not new_view.is_loading(), lambda: new_view.run_command("goto_line", {"line": data['linenum']}))
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/todo_results.hidden-tmLanguage b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/todo_results.hidden-tmLanguage
new file mode 100644
index 0000000..e0cd6b4
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/SublimeTODO/todo_results.hidden-tmLanguage
@@ -0,0 +1,49 @@
+
+
+
+
+ name
+ TODO Results
+
+ patterns
+
+
+ match
+
+ ^[\s]{0,2}([\d]+\.) ([^:]+)(:)([\d]+) (.*)$
+ captures
+
+ 1
+
+ name
+ constant.numeric.item-number.todo-list
+
+ 2
+
+ name
+ entity.name.filename.todo-list
+
+ 3
+
+ name
+ punctuation.definition.delimiter
+
+ 4
+
+ name
+ constant.numeric.line-number.todo-list
+
+ 5
+
+ name
+ entity.name.match.todo-list
+
+
+
+
+ scopeName
+ text.todo-list
+ uuid
+ 2ce8c28e-9c29-4f7f-bc65-7c5311732d29
+
+
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/.gitignore b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/.gitignore
new file mode 100644
index 0000000..3aa864b
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/.gitignore
@@ -0,0 +1 @@
+TODO.md
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/Default.sublime-commands b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/Default.sublime-commands
new file mode 100644
index 0000000..dd4df34
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/Default.sublime-commands
@@ -0,0 +1,10 @@
+[
+ {
+ "caption": "Trailing Spaces: Toggle Trailing Spaces Highlighting",
+ "command": "toggle_trailing_spaces"
+ },
+ {
+ "caption": "Trailing Spaces: Delete Trailing Spaces",
+ "command": "delete_trailing_spaces"
+ }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/MIT-LICENSE b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/MIT-LICENSE
new file mode 100644
index 0000000..7104d54
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright 2010 Jean-Denis Vauguet
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/Main.sublime-menu b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/Main.sublime-menu
new file mode 100644
index 0000000..3d966e3
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/Main.sublime-menu
@@ -0,0 +1,123 @@
+[
+ {
+ "id": "edit",
+ "children":
+ [
+ {
+ "caption": "Trailing Spaces",
+ "id": "trailing-spaces",
+ "children":
+ [
+ {
+ "command": "delete_trailing_spaces",
+ "caption": "Delete"
+ },
+ { "caption": "-" },
+ {
+ "command": "toggle_trailing_spaces_modified_lines_only",
+ "caption": "Modified Lines Only",
+ "checkbox": true
+ },
+ {
+ "command": "toggle_trailing_spaces",
+ "caption": "Highlight Regions",
+ "checkbox": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "preferences",
+ "children":
+ [
+ {
+ "caption": "Package Settings",
+ "mnemonic": "P",
+ "id": "package-settings",
+ "children":
+ [
+ {
+ "caption": "Trailing Spaces",
+ "children":
+ [
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/TrailingSpaces/README.md",
+ "platform": "Windows"
+ },
+ "caption": "Help"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/TrailingSpaces/README.md",
+ "platform": "OSX"
+ },
+ "caption": "Help"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/TrailingSpaces/README.md",
+ "platform": "Linux"
+ },
+ "caption": "Help"
+ },
+ { "caption": "-" },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/TrailingSpaces/trailing_spaces.sublime-settings",
+ "platform": "Windows"
+ },
+ "caption": "Settings - Default"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/TrailingSpaces/trailing_spaces.sublime-settings",
+ "platform": "OSX"
+ },
+ "caption": "Settings - Default"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/TrailingSpaces/trailing_spaces.sublime-settings",
+ "platform": "Linux"
+ },
+ "caption": "Settings - Default"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/User/trailing_spaces.sublime-settings",
+ "platform": "Windows"
+ },
+ "caption": "Settings - User"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/User/trailing_spaces.sublime-settings",
+ "platform": "OSX"
+ },
+ "caption": "Settings - User"
+ },
+ {
+ "command": "open_file",
+ "args": {
+ "file": "${packages}/User/trailing_spaces.sublime-settings",
+ "platform": "Linux"
+ },
+ "caption": "Settings - User"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/README.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/README.md
new file mode 100644
index 0000000..0627b55
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/README.md
@@ -0,0 +1,313 @@
+Trailing Spaces
+===============
+
+A [Sublime Text 2](http://www.sublimetext.com/2) and
+[3](http://www.sublimetext.com/3) plugin that allows you to…
+
+**highlight trailing spaces and delete them in a flash!**
+
+Synopsis
+--------
+
+Sublime Text provides a way to automate deletion of trailing spaces *upon file
+saving* (more on this at the end of this file). Depending on your settings, it
+may be more handy to just highlight them and/or delete them by hand, at any
+time. This plugin provides just that, and a *lot* of options to fine-tune the
+way you want to decimate trailing spaces.
+
+Installation
+------------
+
+It is available through
+[Sublime Package Contol](http://wbond.net/sublime_packages/package_control) and
+this is the recommended way of installation (brings configuration instructions,
+automatic updates with changelogs…).
+
+### Alternative installation methods
+
+#### From github
+
+You can install from github if you want, although Package Control automates
+just that. Go to your `Packages` subdirectory under ST2's data directory:
+
+* Windows: `%APPDATA%\Sublime Text 2`
+* OS X: `~/Library/Application Support/Sublime Text 2`
+* Linux: `~/.config/sublime-text-2`
+* Portable Installation: `Sublime Text 2/Data`
+
+Then clone this repository:
+
+ git clone git://github.com/SublimeText/TrailingSpaces.git
+
+#### Manually
+
+[Download](https://github.com/SublimeText/TrailingSpaces/archive/master.zip)
+the plugin as a zip. Copy the *Trailing Spaces* directory to its location
+(see prior section).
+
+Usage
+-----
+
+### Deletion
+
+The main feature you gain from using this plugin is that of deleting all
+trailing spaces in the currently edited document. In order to use this
+deletion feature, you may either:
+
+* click on "Edit / Trailing Spaces / Delete";
+* bind the deletion command to a keyboard shortcut:
+
+To add a key binding, open "Preferences / Key Bindings - User" and add:
+
+``` js
+{ "keys": ["ctrl+shift+t"], "command": "delete_trailing_spaces" }
+```
+
+With this setting, pressing Ctrl + Shift + t will delete all
+trailing spaces at once in the current file! For OSX users, quoting wbond:
+"When porting a key binding across OSes, it is common for the ctrl key on
+Windows and Linux to be swapped out for super on OS X"
+(eg. use "super+ctrl+t" instead).
+
+*Beware*: the binding from this example overrides the default ST's mapping
+for reopening last closed file. You can look at the default bindings in
+"Preferences / Key Bindings - Default".
+
+### Toggling highlighting
+
+At any time, you can toggle highlighting on and off. You may either:
+
+- click on "Edit / Trailing Spaces / Highlight Regions"
+- bind the toggling command to a keyboard shortcut:
+
+``` js
+// I like "d", as in "detect" (overrides a default binding, though).
+{ "keys": ["ctrl+shift+d"], "command": "toggle_trailing_spaces" }
+```
+
+Options
+-------
+
+Several options are available to customize the plugin's behavior. Those
+settings are stored in a configuration file, as JSON. You must use a specific
+file: Go to "Preferences / Package Settings / Trailing Spaces / Settings
+- User" to add you custom settings. You can look at the default values in
+"Settings - Default", in the same menu.
+
+A few of them are also accessible through the "Edit / Trailing Spaces" menu.
+Sometimes, editing a setting will require a fresh Sublime Text to be applied
+properly, so try relaunching ST before reporting an issue ;)
+
+All settings are global (ie. applied to all opened documents).
+
+### Changing the highlighting color
+
+*Default: "invalid"*
+
+You may change the highlighting color, providing a color scope name such as
+ "error", "comment"… just like that:
+
+``` js
+{ "trailing_spaces_highlight_color": "comment" }
+```
+
+The scope should be defined in your current theme file. Here is a dummy,
+fully-fledged example (feel free to cut irrelevant pieces for your settings)
+of such a custom color scope:
+
+``` xml
+
+ name
+ Invalid - Illegal
+ scope
+ invalid.illegal
+ settings
+
+ background
+ #F93232
+ fontStyle
+
+ foreground
+ #F9F2CE
+
+
+```
+
+You would then use the value of "invalid.illegal".
+
+### Keeping trailing spaces invisible
+
+You can make trailing spaces "invisible" yet still rely on the deletion
+command. To do that, set the highlight scope to an empty string:
+
+``` js
+{ "trailing_spaces_highlight_color": "" }
+```
+
+Beware: this is **not** the same as *disabling* the highlighting (see "On-
+Demand Matching" below). With this setting, the plugin still runs when opening
+a file, and in the background afterwards; you just won't see the trailing
+spaces (they are being highlighted with a "transparent" color).
+
+### Include Current Line
+
+*Default: true*
+
+Highlighting of trailing spaces in the currently edited line can be annoying:
+each time you are about to start a new word, the space you type is matched as
+a trailing spaces. Currently edited line can thus be ignored:
+
+``` js
+{ "trailing_spaces_include_current_line": false }
+```
+
+Even though the trailing spaces are not highlighted on this line, they are
+still internally matched and will be delete when firing the deletion command.
+
+### Include Empty Lines
+
+*Default: true*
+
+When firing the deletion command, empty lines are matched as trailing regions,
+and end up being deleted. You can specifically ignore them:
+
+``` js
+{ "trailing_spaces_include_empty_lines": false }
+```
+
+They will not be highlighted either.
+
+### Modified Lines Only
+
+*Default: false (reopen ST to update)*
+
+When firing the deletion command, trailing regions *in the entire document* are
+deleted. There are some use-cases when deleting trailing spaces *only on lines
+you edited* is smarter; for instance when commiting changes to some third-party
+source code.
+
+At any time, you can change which area is covered when deleting trailing
+regions. You may either:
+
+- click on "Edit / Trailing Spaces / Modified Lines Only"
+- specify as a setting:
+
+``` js
+{ "trailing_spaces_modified_lines_only": true }
+```
+
+There is also a command to toggle this feature on and off. You may thus define
+a key binding:
+
+``` js
+{ "keys": ["pick+a+shortcut"], "command": "toggle_trailing_spaces_modified_lines_only" }
+```
+
+### Trim On Save
+
+*Default: false*
+
+Setting this to `true` will ensure trailing spaces are deleted when you save
+your document. It abides by the other settings, such as *Modified Lines Only*.
+
+``` js
+{ "trailing_spaces_trim_on_save": true }
+```
+
+### Save After Trim
+
+*Default: false*
+
+You may not want to always trim trailing spaces on save, but the other way
+around could prove useful. Setting this to `true` will automatically save your
+document after you fire the deletion command:
+
+``` js
+{ "trailing_spaces_save_after_trim": true }
+```
+
+It is obviously ignored if *Trim On Save* is on.
+
+### Live Matching vs On-demand Matching
+
+*Default: true (reopen ST to update)*
+
+By default, trailing regions are matched every time you edit the document, and
+when you open it.
+
+This feature is entirely optional and you may set it off: firing the deletion
+command will cause the trailing spaces to be deleted as expected even though
+they were not matched prior to your request. If you are afraid of the plugin
+to cause slowness (for instance, you already installed several *heavy*
+plugins), you can disable live matching:
+
+``` js
+{ "trailing_spaces_enabled": false }
+```
+
+In this case, for no trailing regions are matched until you request them to be
+deleted, no highlighting occurs—it is in fact disabled, regardless of your
+"scope" setting. If you want to check the trailing spaces regions, you can
+toggle highlighting on and off. In this case, it may come in handy to define
+a binding for the toggling command. When "On-demand Matching" is on and some
+trailing spaces are highlighted, added ones will obviously not be. Toggling
+highlight off and on will refresh them.
+
+### For power-users only!
+
+#### Disabled for large files
+
+The plugin is disabled altogether for large files, for it may cause slowness.
+The default threshold is around 1 million of characters. This is
+configurable (in "File Settings - User") and the unit is number of chars:
+
+``` js
+{ "trailing_spaces_file_max_size": 1000}
+```
+
+#### The matching pattern
+
+*Default: [ \t]+*
+
+Trailing spaces are line-ending regions containing at least one simple space,
+tabs, or both. This pattern should be all you ever need, but if you *do* want
+to abide by another definition to cover edge-cases, go ahead:
+
+``` js
+// *danger* will match newline chars and many other folks
+"trailing_spaces_regexp": "[\\s]+"
+```
+
+About Sublime Text's built-in features
+--------------------------------------
+
+Trailing Spaces is designed to be a drop-in replacement of the limited
+*Trim Whitespace On Save* built-in feature. ST is indeed able to delete
+trailing spaces upon saving files, and maybe that's all you need!
+
+In order to enable this behavior, edit "Preferences / Settings - User"
+to add the following:
+
+``` js
+{ "trim_trailing_white_space_on_save": true }
+```
+
+As Trailing Spaces bypasses this setting, you will have to uninstall it to
+benefit from this setting.
+
+Made a little less obvious in the documentation are settings to showcase
+whitespaces (*not only trailing ones!*):
+
+``` js
+{ "draw_white_space": "all" }
+```
+
+and to ensure a newline is kept at end of file upon saving:
+
+``` js
+{ "ensure_newline_at_eof_on_save": true }
+```
+
+The former will display *all* whitespaces in your files. There is another value
+of "selection" which display whitespaces under (you got it) your current text
+selection.
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages.json
new file mode 100644
index 0000000..efaff86
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages.json
@@ -0,0 +1,4 @@
+{
+ "install": "messages/install.txt",
+ "v1.0.0": "messages/v1.0.0.txt"
+}
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages/install.txt b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages/install.txt
new file mode 100644
index 0000000..141f30c
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages/install.txt
@@ -0,0 +1,40 @@
+
+
+ Thank you for installing Trailing Spaces
+ ----------------------------------------
+
+ You're now ready to give trailing spaces *a hard time*!
+
+ Wait… I guess Package Control just introduced some of them :(
+ Why don't you try clicking "Edit / Trailing Spaces / Delete"?
+
+
+
+Documentation
+=============
+
+Although the usage of this plugin is dead simple, it comes with several options. All
+details are available in the documentation, and you can read it by clicking on
+"Preferences / Package Settings / Trailing Spaces / Help", or in a prettier form, by
+browsing https://github.com/SublimeText/TrailingSpaces.
+
+Key Binding
+===========
+
+This plugin does not come with a default key binding for the deletion command. You can
+pick your own key binding and define it in "Preferences / Key Bindings - User", or just
+stick to using the menu entry under "Edit". Check the help for advice on this.
+
+Upgrades & Issues
+=================
+
+Package Control will automatically update all packages every time the editor is started,
+so there is nothing for you to worry about. If you however do find the plugin not to work
+as it used to, head to the issues tracker (see links below) to report the problem.
+
+Useful Links
+============
+
+* Documentation & Code: https://github.com/SublimeText/TrailingSpaces
+* Report issues / Request New Features / Roadmap: https://github.com/SublimeText/TrailingSpaces/issues
+* Follow me on twitter: @jdvauguet
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages/v1.0.0.txt b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages/v1.0.0.txt
new file mode 100644
index 0000000..adb1f3b
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/messages/v1.0.0.txt
@@ -0,0 +1,65 @@
+
+
+ Trailing Spaces update [v1.0.0]
+ -------------------------------
+
+ Hope you've been happy gaving trailin' a hard time so far.
+
+ I added several features to help you in this honorable quest…
+
+ All details accessible through:
+
+ "Preferences / Package Settings / Trailing Spaces / Help"
+
+
+
+New feature: Modified Lines Only
+================================
+
+As proposed by a fellow user, it is now possible to target only the lines
+modified by You and You Only when deleting trailing spaces.
+
+This feature will certainly please coders who edit third-party code filled
+with trailing spaces but do not want to commit giant diffs, just their little
+fix, while keeping it clean.
+
+New feature: Trim On Save
+=========================
+
+This option allows for automatic deletion upon saving. No more lost trailing
+spaces! A perfect combo to the "Modified Lines Only" setting I guess.
+
+New feature: Save After Trim
+============================
+
+A different kind of automation: many users just want those trailings out and
+forget 'bout them. It is now made even easier with this auto-saving hook. Fire
+the deletion command, and your document is clean on the hard drive!
+
+At the current time, "Trim On Save" and "Save After Trim" cannot be both
+enabled (the former wins), but this is on the roadmap.
+
+New Menu
+========
+
+Some of the settings seemed a bit more important than the others. Along the
+deletion command, the toggling command/state and the "Modified Lines Only"
+setting have been elected first-class citizens of the new "Edit / Trailing
+Spaces" menu. Any change made by click here is live, persistent and reflected
+in the JSON settings file. Settings are global to all open documents.
+
+Improvements & Misc.
+====================
+
+- Support for custom matching patterns (danger!).
+- Performance improvements (reduced overhead, with some room for further
+ improvements).
+- Better documentation (both code & user doc).
+- Lazy "On-demand" matching improved.
+
+Useful Links
+============
+
+* Documentation & Code: https://github.com/SublimeText/TrailingSpaces
+* Report issues / Request New Features / Roadmap: https://github.com/SublimeText/TrailingSpaces/issues
+* Follow me on twitter: @jdvauguet
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/package-metadata.json
new file mode 100644
index 0000000..52d06dd
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/SublimeText/TrailingSpaces", "version": "2013.03.07.20.09.52", "description": "Highlight trailing spaces and delete them in a flash."}
\ No newline at end of file
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/packages.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/packages.json
new file mode 100644
index 0000000..f7bb205
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/packages.json
@@ -0,0 +1,20 @@
+{
+ "schema_version": "1.2",
+ "packages": [
+ {
+ "name": "TrailingSpaces",
+ "description": "Highlight trailing spaces and delete them in a flash.",
+ "author": "Jean-Denis Vauguet",
+ "homepage": "https://github.com/SublimeText/TrailingSpaces/",
+ "last_modified": "2013-03-08 01:00:00",
+ "platforms": {
+ "*": [
+ {
+ "version": "1.0.0",
+ "url": "https://nodeload.github.com/SublimeText/TrailingSpaces/zip/v1.0.0"
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/trailing_spaces.py b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/trailing_spaces.py
new file mode 100644
index 0000000..57a8902
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/trailing_spaces.py
@@ -0,0 +1,453 @@
+'''
+Provides both a trailing spaces highlighter and a deletion command.
+
+See README.md for details.
+
+@author: Jean-Denis Vauguet , Oktay Acikalin
+@license: MIT (http://www.opensource.org/licenses/mit-license.php)
+@since: 2011-02-25
+'''
+
+import sublime
+import sublime_plugin
+import difflib
+import codecs
+
+DEFAULT_MAX_FILE_SIZE = 1048576
+DEFAULT_IS_ENABLED = True
+DEFAULT_MODIFIED_LINES_ONLY = False
+
+# Global settings object and flags.
+# Flags duplicate some of the (core) JSON settings, in case the settings file has
+# been corrupted or is empty (ST2 really dislikes that!)
+ts_settings_filename = "trailing_spaces.sublime-settings"
+ts_settings = None
+trailing_spaces_live_matching = DEFAULT_IS_ENABLED
+trim_modified_lines_only = DEFAULT_MODIFIED_LINES_ONLY
+startup_queue = []
+on_disk = None
+
+
+# Private: Loads settings and sets whether the plugin (live matching) is enabled.
+#
+# Returns nothing.
+def plugin_loaded():
+ global ts_settings_filename, ts_settings, trailing_spaces_live_matching
+ global current_highlighting_scope, trim_modified_lines_only, startup_queue
+ global DEFAULT_COLOR_SCOPE_NAME, on_disk
+
+ ts_settings = sublime.load_settings(ts_settings_filename)
+ trailing_spaces_live_matching = bool(ts_settings.get("trailing_spaces_enabled",
+ DEFAULT_IS_ENABLED))
+ current_highlighting_scope = ts_settings.get("trailing_spaces_highlight_color",
+ "invalid")
+ DEFAULT_COLOR_SCOPE_NAME = current_highlighting_scope
+ trim_modified_lines_only = bool(ts_settings.get("trailing_spaces_modified_lines_only",
+ DEFAULT_MODIFIED_LINES_ONLY))
+
+ if trailing_spaces_live_matching:
+ for view in startup_queue:
+ match_trailing_spaces(view)
+ else:
+ current_highlighting_scope = ""
+ if ts_settings.get("trailing_spaces_highlight_color") != current_highlighting_scope:
+ persist_settings()
+
+
+# Private: Updates user's settings with in-memory values.
+#
+# Allows for persistent settings from the menu.
+#
+# Returns nothing.
+def persist_settings():
+ sublime.save_settings(ts_settings_filename)
+
+
+# Private: Determine if the view is a "Find results" view.
+#
+# view - the view, you know
+#
+# Returns True or False.
+def is_find_results(view):
+ return view.settings().get('syntax') and "Find Results" in view.settings().get('syntax')
+
+
+# Private: Get the regions matching trailing spaces.
+#
+# As the core regexp matches lines, the regions are, well, "per lines".
+#
+# view - the view, you know
+#
+# Returns both the list of regions which map to trailing spaces and the list of
+# regions which are to be highlighted, as a list [matched, highlightable].
+def find_trailing_spaces(view):
+ sel = view.sel()[0]
+ line = view.line(sel.b)
+ include_empty_lines = bool(ts_settings.get("trailing_spaces_include_empty_lines",
+ DEFAULT_IS_ENABLED))
+ include_current_line = bool(ts_settings.get("trailing_spaces_include_current_line",
+ DEFAULT_IS_ENABLED))
+ regexp = ts_settings.get("trailing_spaces_regexp") + "$"
+ no_empty_lines_regexp = "(?<=\S)%s$" % regexp
+
+ offending_lines = view.find_all(regexp if include_empty_lines else no_empty_lines_regexp)
+
+ if include_current_line:
+ return [offending_lines, offending_lines]
+ else:
+ current_offender = view.find(regexp if include_empty_lines else no_empty_lines_regexp, line.a)
+ removal = False if current_offender == None else line.intersects(current_offender)
+ highlightable = [i for i in offending_lines if i != current_offender] if removal else offending_lines
+ return [offending_lines, highlightable]
+
+
+# Private: Find the fraking trailing spaces in the view and flags them as such!
+#
+# It will refresh highlighted regions as well. Does not execute if the
+# document's size exceeds the file_max_size setting, or if the fired in a view
+# which is not a legacy document (helper/build views and so on).
+#
+# view - the view, you know
+#
+# Returns nothing.
+def match_trailing_spaces(view):
+ if ts_settings is None:
+ startup_queue.append(view)
+ return
+
+ # Silently pass if file is too big.
+ if max_size_exceeded(view):
+ return
+
+ if not is_find_results(view):
+ (matched, highlightable) = find_trailing_spaces(view)
+ add_trailing_spaces_regions(view, matched)
+ highlight_trailing_spaces_regions(view, highlightable)
+
+
+# Private: Checks whether the document is bigger than the max_size setting.
+#
+# view - the view, you know
+#
+# Returns True or False.
+def max_size_exceeded(view):
+ return view.size() > ts_settings.get('trailing_spaces_file_max_size',
+ DEFAULT_MAX_FILE_SIZE)
+
+
+# Private: Marks specified regions as trailing spaces.
+#
+# view - the view, you know
+# regions - regions qualified as trailing spaces
+#
+# Returns nothing.
+def add_trailing_spaces_regions(view, regions):
+ view.erase_regions('TrailingSpacesMatchedRegions')
+ view.add_regions('TrailingSpacesMatchedRegions',
+ regions,
+ "",
+ "",
+ sublime.HIDE_ON_MINIMAP)
+
+
+# Private: Highlights specified regions as trailing spaces.
+#
+# It will use the scope enforced by the state of the toggable highlighting.
+#
+# view - the view, you know
+# regions - regions qualified as trailing spaces
+#
+# Returns nothing.
+def highlight_trailing_spaces_regions(view, regions):
+ view.erase_regions("TrailingSpacesHighlightedRegions")
+ view.add_regions('TrailingSpacesHighlightedRegions',
+ regions,
+ current_highlighting_scope or "",
+ "",
+ sublime.HIDE_ON_MINIMAP)
+
+
+# Private: Toggles highlighting of all trailing spaces in the view.
+#
+# It has no effect is the plugin is disabled.
+#
+# view - the view, you know
+#
+# Returns True (highlighting was turned on) or False (turned off).
+def toggle_highlighting(view):
+ global current_highlighting_scope
+
+ # If the scope is that of an invisible, there is nothing to toggle.
+ if DEFAULT_COLOR_SCOPE_NAME == "":
+ return "disabled!"
+
+ # If performing live, highlighted trailing regions must be updated
+ # internally.
+ if not trailing_spaces_live_matching:
+ (matched, highlightable) = find_trailing_spaces(view)
+ highlight_trailing_spaces_regions(view, highlightable)
+
+ scope = DEFAULT_COLOR_SCOPE_NAME if current_highlighting_scope == "" else ""
+ current_highlighting_scope = scope
+ highlight_trailing_spaces_regions(view, view.get_regions('TrailingSpacesHighlightedRegions'))
+ return "off" if current_highlighting_scope == "" else "on"
+
+
+# Clear all the highlighted regions in all views.
+#
+# FIXME: this is not used! Delete?
+#
+# window - the window, you know
+#
+# Returns nothing.
+def clear_trailing_spaces_highlight(window):
+ for view in window.views():
+ view.erase_regions('TrailingSpacesMatchedRegions')
+
+
+# Find edited lines since last save, as line numbers, based on diff.
+#
+# It uses a Differ object to compute the diff between the file as red on the
+# disk, and the current buffer (which may differ from the disk's state). See
+# http://docs.python.org/2/library/difflib.html for details about diff codes.
+#
+# It relies on a full diff, so it may be expensive computation for very large
+# files (diff generation + looping through all lines).
+#
+# old - a buffer of lines, as in "old version"
+# new - a buffer of lines, as in "new version"
+#
+# Returns the list of edited line numbers.
+def modified_lines_as_numbers(old, new):
+ d = difflib.Differ()
+ diffs = d.compare(old, new)
+
+ # Pretty Naive Algorithm (tm):
+ # - split off the "Differ code", to check whether:
+ # - the line is in either in both files or just b: increment the line number
+ # - the line is only in b: it qualifies as an edited line!
+ # Starting from -1 as ST2 is internally 0-based for lines.
+ lineNum = -1
+ edited_lines = []
+ for line in diffs:
+ code = line[:2]
+ # those lines with "? " are not real! watch out!
+ if code in (" ", "+ "):
+ lineNum += 1
+ if code == "+ ":
+ edited_lines.append(lineNum)
+
+ return False if not edited_lines else edited_lines
+
+
+# Private: Find the dirty lines.
+#
+# view - the view, you know
+#
+# Returns the list of regions matching dirty lines.
+def get_modified_lines(view):
+ try:
+ on_disk
+ on_buffer = view.substr(sublime.Region(0, view.size())).splitlines()
+ except UnicodeDecodeError:
+ sublime.status_message("File format incompatible with this feature (UTF-8 files only)")
+ return
+
+ lines = []
+ line_numbers = modified_lines_as_numbers(on_disk, on_buffer)
+ if line_numbers:
+ lines = [view.full_line(view.text_point(number,0)) for number in line_numbers]
+ return lines
+
+
+# Private: Finds the trailing spaces regions to be deleted.
+#
+# It abides by the user settings: while in mode "Only Modified Lines", it returns
+# the subset of trailing spaces regions which are within dirty lines; otherwise, it
+# returns all trailing spaces regions for the document.
+#
+# view - the view, you know
+#
+# Returns a list of regions to be deleted.
+def find_regions_to_delete(view):
+ # If the plugin has been running in the background, regions have been matched.
+ # Otherwise, we must find trailing spaces right now!
+ if trailing_spaces_live_matching:
+ regions = view.get_regions('TrailingSpacesMatchedRegions')
+ else:
+ (regions, highlightable) = find_trailing_spaces(view)
+
+ # Filtering is required in case triming is restricted to dirty regions only.
+ if trim_modified_lines_only:
+ modified_lines = get_modified_lines(view)
+
+ # If there are no dirty lines, don't do nothing.
+ if not modified_lines:
+ return
+
+ # Super-private: filters trailing spaces regions to dirty lines only.
+ #
+ # As one cannot perform a smart find_all within arbitrary boundaries, we must do some
+ # extra work:
+ # - we want to loop through the modified lines set, not the whole trailing regions
+ # - but we need a way to match modified lines with trailings to those very regions
+ #
+ # Hence the reversed dict on regions: keys are the text_point of the begining of
+ # each region, values are the region's actual boundaries. As a Region is unhashable,
+ # trailing regions are being recreated later on from those two values.
+ #
+ # We loop then loop through the modified lines: for each line, we get its begining
+ # text_point, and check whether it matches a line with trailing spaces in the
+ # reversed dict. If so, this is a match (a modified line with trailing spaces), so
+ # we can re-create and store a Region for the relevant trailing spaces boundaries.
+ #
+ # Returns the filtered list of trailing spaces regions for the modified lines set.
+ def only_those_with_trailing_spaces():
+ regions_by_begin = {}
+ matches = []
+ for region in regions:
+ begin = view.line(region).begin()
+ regions_by_begin[begin] = (region.begin(), region.end())
+
+ for line in modified_lines:
+ text_point = line.begin()
+ if text_point in regions_by_begin:
+ matches.append(sublime.Region(regions_by_begin[text_point][0], regions_by_begin[text_point][1]))
+
+ return matches
+
+ regions = only_those_with_trailing_spaces()
+
+ return regions
+
+# Private: Deletes the trailing spaces regions.
+#
+# view - the view, you know
+# edit - the Edit object spawned by the deletion command
+#
+# Returns the number of deleted regions.
+def delete_trailing_regions(view, edit):
+ regions = find_regions_to_delete(view)
+
+ if regions:
+ # Trick: reversing the regions takes care of the growing offset while
+ # deleting the successive regions.
+ regions.reverse()
+ for r in regions:
+ view.erase(edit, r)
+ return len(regions)
+ else:
+ return 0
+
+
+# Public: Toggles the highlighting on or off.
+class ToggleTrailingSpacesCommand(sublime_plugin.WindowCommand):
+ def run(self):
+ view = self.window.active_view()
+ if max_size_exceeded(view):
+ sublime.status_message("File is too big, trailing spaces handling disabled.")
+ return
+
+ state = toggle_highlighting(view)
+ ts_settings.set("trailing_spaces_highlight_color", current_highlighting_scope)
+ persist_settings()
+ sublime.status_message('Highlighting of trailing spaces is %s' % state)
+
+ def is_checked(self):
+ return current_highlighting_scope != ""
+
+
+# Public: Toggles "Modified Lines Only" mode on or off.
+class ToggleTrailingSpacesModifiedLinesOnlyCommand(sublime_plugin.WindowCommand):
+ def run(self):
+ global trim_modified_lines_only
+
+ was_on = ts_settings.get("trailing_spaces_modified_lines_only")
+ ts_settings.set("trailing_spaces_modified_lines_only", not was_on)
+ persist_settings()
+
+ # TODO: use ts_settings.add_on_change() when it lands in ST3
+ trim_modified_lines_only = ts_settings.get('trailing_spaces_modified_lines_only')
+ message = "Let's trim trailing spaces everywhere" if was_on \
+ else "Let's trim trailing spaces only on modified lines"
+ sublime.status_message(message)
+
+ def is_checked(self):
+ return ts_settings.get("trailing_spaces_modified_lines_only")
+
+
+# Public: Matches and highlights trailing spaces on key events, according to the
+# current settings.
+class TrailingSpacesListener(sublime_plugin.EventListener):
+ def on_modified(self, view):
+ if trailing_spaces_live_matching:
+ match_trailing_spaces(view)
+
+ def on_activated(self, view):
+ if trailing_spaces_live_matching:
+ match_trailing_spaces(view)
+
+ def on_selection_modified(self, view):
+ if trailing_spaces_live_matching:
+ match_trailing_spaces(view)
+
+ def on_activated(self, view):
+ self.freeze_last_version(view)
+ if trailing_spaces_live_matching:
+ match_trailing_spaces(view)
+
+ def on_pre_save(self, view):
+ self.freeze_last_version(view)
+ if ts_settings.get("trailing_spaces_trim_on_save"):
+ view.run_command("delete_trailing_spaces")
+
+ # Toggling messes with what is red from the disk, and it breaks the diff
+ # used when modified_lines_only is true. Honestly, I don't know why (yet).
+ # Anyway, let's cache the persisted version of the document's buffer for
+ # later use on specific event, so that we always have a decent version of
+ # "what's on the disk" to work with.
+ def freeze_last_version(self, view):
+ global on_disk
+
+ file_name = view.file_name()
+ # For some reasons, the on_activated hook gets fired on a ghost document
+ # from time to time.
+ if file_name:
+ on_disk = codecs.open(file_name, "r", "utf-8").read().splitlines()
+
+
+# Public: Deletes the trailing spaces.
+class DeleteTrailingSpacesCommand(sublime_plugin.TextCommand):
+ def run(self, edit):
+ if max_size_exceeded(self.view):
+ sublime.status_message("File is too big, trailing spaces handling disabled.")
+ return
+
+ deleted = delete_trailing_regions(self.view, edit)
+
+ if deleted:
+ if ts_settings.get("trailing_spaces_save_after_trim") \
+ and not ts_settings.get("trailing_spaces_trim_on_save"):
+ sublime.set_timeout(lambda: self.save(self.view), 10)
+
+ msg_parts = {"nbRegions": deleted,
+ "plural": 's' if deleted > 1 else ''}
+ message = "Deleted %(nbRegions)s trailing spaces region%(plural)s" % msg_parts
+ else:
+ message = "No trailing spaces to delete!"
+
+ sublime.status_message(message)
+
+ def save(self, view):
+ if view.file_name() is None:
+ view.run_command('prompt_save_as')
+ else:
+ view.run_command('save')
+
+
+# ST3 features a plugin_loaded hook which is called when ST's API is ready.
+#
+# We must therefore call our init callback manually on ST2. It must be the last
+# thing in this plugin (thanks, beloved contributors!).
+if not int(sublime.version()) > 3000:
+ plugin_loaded()
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/trailing_spaces.sublime-settings b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/trailing_spaces.sublime-settings
new file mode 100644
index 0000000..235c739
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/TrailingSpaces/trailing_spaces.sublime-settings
@@ -0,0 +1,56 @@
+// Trailing Spaces' default settings.
+//
+// In order to tweak the settings, you should NOT edit this file, but instead
+// the user-specific, empty-by-default version under "Preferences / Package
+// Settings / Trailing Spaces / Settings - User".
+//
+// See Trailing Spaces' README for detailled instructions.
+{
+ // By default, Trailing Spaces is "live". It means the trailing spaces
+ // regions will be matched in the background, and highlighted if a color
+ // scope is defined, when the document is opened and edited.
+ // Set to false to disable live matching and highlighting (the deletion
+ // command remains available, so-called "lazy matching").
+ "trailing_spaces_enabled" : true,
+
+ // Highlight color is specified as a scope. You may define and use a custom
+ // scope to better fit your colorscheme.
+ "trailing_spaces_highlight_color" : "invalid",
+
+ // By default, empty lines are cleared as well when calling the deletion
+ // command.
+ // Set to false to ignore empty lines upon deletion.
+ "trailing_spaces_include_empty_lines" : true,
+
+ // By default, the line being currently edited will have its trailing
+ // spaces highlighted.
+ // Set to false to ignore trailing spaces on the edited line.
+ "trailing_spaces_include_current_line" : true,
+
+ // By default, trailing spaces are deleted within the whole document.
+ // Set to true to affect only the lines you edited since last save.
+ // Trailing spaces will still be searched for and highlighted in the whole
+ // document.
+ "trailing_spaces_modified_lines_only": false,
+
+ // By default, nothing happens on save.
+ // Set to true to trim trailing spaces before saving, with respect to the
+ // other settings.
+ "trailing_spaces_trim_on_save": false,
+
+ // By default, deleting trailing spaces does not cause the document to be
+ // saved.
+ // Set to true to force saving after trailing spaces have been deleted.
+ // This setting is irrelevant and will be ignored if trim_on_save is true.
+ "trailing_spaces_save_after_trim": false,
+
+ // ---- NEXT SETTINGS ARE FOR POWER USERS ONLY! ----
+
+ // Highlighting will be disabled if the edited file's size is larger than
+ // this.
+ // Adjust the value (in number of chars) to whatever fits your performance.
+ "trailing_spaces_file_max_size" : 1048576,
+
+ // By default, only simple spaces and tabs are matched as "trailing spaces".
+ "trailing_spaces_regexp": "[ \t]+"
+}
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/Default (Windows).sublime-keymap b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/Default (Windows).sublime-keymap
new file mode 100644
index 0000000..adac1a1
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/Default (Windows).sublime-keymap
@@ -0,0 +1,522 @@
+ [
+ // since we assign Ctrl+Shift+V to clipboard manager, use paste / indent with default Ctrl+v
+ { "keys": ["ctrl+v"], "command": "paste_and_indent" },
+
+ //HACK: override the vertical column selections to use Ctrl+Shift in RDP
+ { "keys": ["ctrl+shift+up"], "command": "select_lines", "args": {"forward": false} },
+ { "keys": ["ctrl+shift+down"], "command": "select_lines", "args": {"forward": true} },
+
+ //HACK: restore default shift+tab keybindings because SmartMarkdown messes with them too much
+ { "keys": ["shift+tab"], "command": "insert", "args": {"characters": "\t"} },
+ { "keys": ["shift+tab"], "command": "unindent", "context":
+ [
+ { "key": "setting.shift_tab_unindent", "operator": "equal", "operand": true }
+ ]
+ },
+ { "keys": ["shift+tab"], "command": "unindent", "context":
+ [
+ { "key": "preceding_text", "operator": "regex_match", "operand": "^[\t ]*" }
+ ]
+ },
+ { "keys": ["shift+tab"], "command": "unindent", "context":
+ [
+ { "key": "text", "operator": "regex_contains", "operand": "\n" }
+ ]
+ },
+ { "keys": ["shift+tab"], "command": "prev_field", "context":
+ [
+ { "key": "has_prev_field", "operator": "equal", "operand": true }
+ ]
+ },
+
+ //Abacus - https://github.com/khiltd/Abacus
+ { "keys": ["ctrl+alt+\\"], "command": "abacus" },
+
+ // Bracketeer - https://github.com/colinta/SublimeBracketeer
+ { "keys": ["super+]"], "command": "bracketeer_indent" },
+ { "keys": ["ctrl+shift+["], "command": "bracketeer_select" },
+ { "keys": ["ctrl+["], "command": "bracketeer_goto", "args": { "goto": "left" } },
+ { "keys": ["ctrl+]"], "command": "bracketeer_goto", "args": { "goto": "right" } },
+ { "keys": ["ctrl+alt+["], "command": "bracketeer_goto", "args": { "goto": "both" } },
+ { "keys": ["ctrl+alt+]"], "command": "bracketeer_goto", "args": { "goto": "both" } },
+ //|
+ //| BRACKETEER
+ //|
+ { "keys": ["{"], "command": "bracketeer", "args": { "braces": "{}", "unindent": true } },
+ { "keys": ["}"], "command": "bracketeer", "args": { "braces": "{}", "pressed": "}", "unindent": true } },
+ { "keys": ["["], "command": "bracketeer", "args": { "braces": "[]" } },
+ { "keys": ["]"], "command": "bracketeer", "args": { "braces": "[]", "pressed": "]" } },
+ { "keys": ["("], "command": "bracketeer", "args": { "braces": "()" } },
+ { "keys": [")"], "command": "bracketeer", "args": { "braces": "()", "pressed": ")" } },
+ //| reStructured Text
+ { "keys": ["alt+`"], "command": "bracketeer", "args": { "braces": "````", "pressed": "``" }, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
+ ]
+ },
+ { "keys": ["*"], "command": "bracketeer", "args": { "braces": "**", "pressed": "*" }, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
+ ]
+ },
+ //| DJANGO CURLIES
+ // For django, liquid, jinja. All the grammars *I* have list 'source.smarty' as
+ // when the cursor is inside "{}"s
+ { "keys": ["{"], "command": "bracketeer", "args": { "braces": "{ }" }, "context":
+ [{ "key": "selector", "operator": "equal", "operand": "source.smarty" }]
+ },
+ { "keys": ["{"], "command": "bracketeer", "args": { "braces": "{ }" }, "context":
+ [{ "key": "selector", "operator": "equal", "operand": "meta.brace.curly" }]
+ },
+ { "keys": ["%"], "command": "bracketeer", "args": { "braces": "% %" }, "context":
+ [{ "key": "selector", "operator": "equal", "operand": "source.smarty" }]
+ },
+ { "keys": ["%"], "command": "bracketeer", "args": { "braces": "% %" }, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "meta.brace.curly" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "<$", "match_all": true }
+ ]
+ },
+ { "keys": ["%"], "command": "insert_snippet", "args": { "contents": " $1 %>$0" }, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "source.ruby" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "<%$", "match_all": true }
+ ]
+ },
+ { "keys": [">"], "command": "insert_snippet", "args": { "contents": ">$1<% $0" }, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "source.ruby" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "%$", "match_all": true }
+ ]
+ },
+ { "keys": ["="], "command": "insert_snippet", "args": { "contents": "= $1 %>$0" }, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "source.ruby" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "<%$", "match_all": true }
+ ]
+ },
+ { "keys": ["-"], "command": "insert_snippet", "args": { "contents": "- $1 %>$0" }, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "source.ruby" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "<%$", "match_all": true }
+ ]
+ },
+ { "keys": ["#"], "command": "bracketeer", "args": { "braces": "# #" }, "context":
+ [{ "key": "selector", "operator": "equal", "operand": "source.smarty" }]
+ },
+ //| QUOTES
+ { "keys": ["\""], "command": "bracketeer", "args": { "braces": "\"\"", "pressed": "\"" } },
+ { "keys": ["ctrl+'","ctrl+'"], "command": "bracketeer", "args": { "braces": "\"\"\"\n\n\"\"\"" } },
+ { "keys": ["'"], "command": "bracketeer", "args": { "braces": "''", "pressed": "'" } },
+ { "keys": ["ctrl+'","'"], "command": "bracketeer", "args": { "braces": "'''\n\n'''" } },
+ { "keys": ["`"], "command": "bracketeer", "args": { "braces": "``", "pressed": "`" } },
+ { "keys": ["ctrl+'","`"], "command": "insert_snippet", "args": { "contents": "```${1:syntax}\n$0\n```" } },
+ { "keys": ["«"], "command": "bracketeer", "args": { "braces": "«»" } },
+ { "keys": ["»"], "command": "bracketeer", "args": { "braces": "«»", "pressed": "»" } },
+ { "keys": ["‹"], "command": "bracketeer", "args": { "braces": "‹›" } },
+ { "keys": ["›"], "command": "bracketeer", "args": { "braces": "‹›", "pressed": "›" } },
+ { "keys": ["“"], "command": "bracketeer", "args": { "braces": "“”" } },
+ { "keys": ["”"], "command": "bracketeer", "args": { "braces": "“”", "pressed": "”" } },
+ { "keys": ["‘"], "command": "bracketeer", "args": { "braces": "‘’" } },
+ { "keys": ["’"], "command": "bracketeer", "args": { "braces": "‘’", "pressed": "’" } },
+ //|
+ //| AUTO DELETE MATCHING '', "", [], etc.
+ //|
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "\"$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^\"" }
+ ]
+ },
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "'$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^'" }
+ ]
+ },
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "`$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^`" }
+ ]
+ },
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "«$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^»" }
+ ]
+ },
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "‹$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^›" }
+ ]
+ },
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "“$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^”" }
+ ]
+ },
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "‘$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^’" }
+ ]
+ },
+ { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context":
+ [
+ { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" },
+ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
+ { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^\\*" }
+ ]
+ },
+ //|
+ //| Bracket and select
+ //|
+ { "keys": ["ctrl+alt+[", "backspace"], "command": "bracketeer", "args": { "braces": "", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "{"], "command": "bracketeer", "args": { "braces": "{}", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "{"], "command": "bracketeer", "args": { "braces": "{}", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", " "], "command": "bracketeer", "args": { "braces": " ", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", " "], "command": "bracketeer", "args": { "braces": " ", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "["], "command": "bracketeer", "args": { "braces": "[]", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "["], "command": "bracketeer", "args": { "braces": "[]", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "("], "command": "bracketeer", "args": { "braces": "()", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "("], "command": "bracketeer", "args": { "braces": "()", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "\""], "command": "bracketeer", "args": { "braces": "\"\"", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "\""], "command": "bracketeer", "args": { "braces": "\"\"", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "ctrl+shift+'"], "command": "bracketeer", "args": { "braces": "\"\"\"\"\"\"", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "ctrl+shift+'"], "command": "bracketeer", "args": { "braces": "\"\"\"\"\"\"", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "'"], "command": "bracketeer", "args": { "braces": "''", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "'"], "command": "bracketeer", "args": { "braces": "''", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "ctrl+'"], "command": "bracketeer", "args": { "braces": "''''''", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "ctrl+'"], "command": "bracketeer", "args": { "braces": "''''''", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "`"], "command": "bracketeer", "args": { "braces": "``", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "`"], "command": "bracketeer", "args": { "braces": "``", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "ctrl+`"], "command": "bracketeer", "args": { "braces": "``````", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "ctrl+`"], "command": "bracketeer", "args": { "braces": "``````", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "«"], "command": "bracketeer", "args": { "braces": "«»", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "«"], "command": "bracketeer", "args": { "braces": "«»", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "‹"], "command": "bracketeer", "args": { "braces": "‹›", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "‹"], "command": "bracketeer", "args": { "braces": "‹›", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "“"], "command": "bracketeer", "args": { "braces": "“”", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "“"], "command": "bracketeer", "args": { "braces": "“”", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "‘"], "command": "bracketeer", "args": { "braces": "‘’", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "‘"], "command": "bracketeer", "args": { "braces": "‘’", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "alt+`"], "command": "bracketeer", "args": { "braces": "````", "select": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+alt+[", "alt+`"], "command": "bracketeer", "args": { "braces": "````", "select": true, "replace": true }, "context":
+ [{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }]
+ },
+ { "keys": ["ctrl+[", "*"], "command": "bracketeer", "args": { "braces": "**", "select": true }, "context":
+ [
+ { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true },
+ { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
+ ]
+ },
+ { "keys": ["ctrl+alt+[", "*"], "command": "bracketeer", "args": { "braces": "**", "select": true, "replace": true }, "context":
+ [
+ { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true },
+ { "key": "selector", "operator": "equal", "operand": "text.restructuredtext" }
+ ]
+ },
+
+ //BracketHighlighter - https://github.com/facelessuser/BracketHighlighter/
+ {
+ "keys": ["ctrl+shift+b", "ctrl+shift+b"], "command": "bracket_highlighter_key",
+ "args": {"lines": true}
+ },
+ {
+ "keys": ["alt+up"], "command": "bracket_highlighter_key",
+ "args":
+ {
+ "lines" : true,
+ "plugin":
+ {
+ "type": ["quote","bracket","tag"],
+ "command": "bracket_plugins.select_bracket",
+ "args": {"select": "left"}
+ }
+ }
+ },
+ {
+ "keys": ["alt+down"], "command": "bracket_highlighter_key",
+ "args":
+ {
+ "lines" : true,
+ "plugin":
+ {
+ "type": ["quote","bracket","tag"],
+ "command": "bracket_plugins.select_bracket",
+ "args": {"select": "right"}
+ }
+ }
+ },
+ {
+ "keys": ["ctrl+shift+b","ctrl+shift+s"], "command": "bracket_highlighter_key",
+ "args":
+ {
+ "lines" : true,
+ "plugin":
+ {
+ "type": ["quote","bracket","tag"],
+ "command": "bracket_plugins.select_bracket"
+ }
+ }
+ },
+ {
+ "keys": ["ctrl+shift+b","ctrl+shift+t"], "command": "bracket_highlighter_key",
+ "args":
+ {
+ "ignore": ["quote"],
+ "plugin":
+ {
+ "type": ["tag"],
+ "command": "bracket_plugins.select_tag"
+ }
+ }
+ },
+ {
+ "keys": ["ctrl+shift+b","ctrl+shift+n"], "command": "bracket_highlighter_key",
+ "args":
+ {
+ "ignore": ["quote"],
+ "plugin":
+ {
+ "type": ["tag"],
+ "command": "bracket_plugins.select_attr",
+ "args": {"direction": "right"}
+ }
+ }
+ },
+ {
+ "keys": ["ctrl+shift+b","ctrl+shift+q"], "command": "bracket_highlighter_key",
+ "args":
+ {
+ "plugin": {"type": ["quote"],"command" : "bracket_plugins.swap_quotes"}
+ }
+ },
+ {
+ "keys": ["ctrl+shift+b","ctrl+shift+j"], "command": "swap_brackets"
+ },
+ {
+ "keys": ["ctrl+shift+b","ctrl+shift+["], "command": "bracket_highlighter_key",
+ "args":
+ {
+ "plugin": {"type": ["quote", "tag", "bracket"],"command" : "bracket_plugins.fold_bracket"}
+ }
+ },
+
+ // ClipboardManager - https://github.com/colinta/SublimeClipboardManager
+ { "keys": ["ctrl+x"], "command": "clipboard_manager_cut" },
+ { "keys": ["ctrl+c"], "command": "clipboard_manager_copy" },
+ { "keys": ["ctrl+v"], "command": "clipboard_manager_paste", "args": { "indent": true } },
+ { "keys": ["ctrl+alt+v"], "command": "clipboard_manager_next_and_paste" },
+ { "keys": ["ctrl+shift+alt+v"], "command": "clipboard_manager_previous_and_paste" },
+ //{ "keys": ["ctrl+pageup"], "command": "clipboard_manager_next" },
+ //{ "keys": ["ctrl+pagedown"], "command": "clipboard_manager_previous" },
+ //{ "keys": ["ctrl+home"], "command": "clipboard_manager_show" },
+ { "keys": ["ctrl+shift+v"], "command": "clipboard_manager_choose_and_paste" },
+
+ // EasyMotion - https://github.com/tednaleid/sublime-EasyMotion
+ {
+ "keys": ["ctrl+.", ""],
+ "command": "easy_motion", "args": {"select_text": false}
+ },
+ {
+ "keys": ["ctrl+.", "enter"],
+ "command": "easy_motion", "args": {"select_text": false, "character": "enter"}
+ },
+ {
+ "keys": ["ctrl+shift+.", ""],
+ "command": "easy_motion", "args": {"select_text": true}
+ },
+ {
+ "keys": ["ctrl+shift+.", "enter"],
+ "command": "easy_motion", "args": {"select_text": true, "character": "enter"}
+ },
+
+ // ExportHTML - https://github.com/facelessuser/ExportHtml
+ // use defaults
+
+ // FileDiffs - https://github.com/colinta/SublimeFileDiffs
+ { "keys": ["ctrl+shift+d"], "command": "file_diff_menu" },
+
+ // MarkDown Preview - https://github.com/revolunet/sublimetext-markdown-preview
+ { "keys": ["ctrl+alt+m"], "command": "markdown_preview", "args": {"target": "browser"} },
+
+ // Smart Markdown - https://github.com/demon386/SmartMarkdown
+ // accept all the defaults for building lists and tables
+ { "keys": ["tab"], "command": "smart_folding", "context":
+ [{ "key": "selector", "operator": "equal", "operand": "markup.heading.markdown" }]
+ },
+ { "keys": ["enter"], "command": "smart_list", "context": [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*([-+\\**]|\\d+\\.+)\\s+" }
+ ]},
+ { "keys": ["enter"], "command": "smart_list", "context": [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "selector", "operator": "equal", "operand": "markup.list" }
+ ]},
+ { "keys": ["tab"], "command": "smart_table", "args": {"forward": true}, "context": [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(\\||\\+[-=])", "match_all": true}
+ ]},
+ { "keys": ["tab"], "command": "smart_table", "args": {"forward": true}, "context": [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "\\s*(\\||\\+[-=])", "match_all": true}
+ ]},
+ { "keys": ["shift+tab"], "command": "smart_table", "args": {"forward": false}, "context": [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(\\||\\+[-=])",
+ "match_all": true}
+ ]},
+ { "keys": ["shift+tab"], "command": "smart_table", "args": {"forward": false}, "context": [
+ { "key": "selector", "operator": "equal", "operand": "text.html.markdown" },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*" },
+ { "key": "following_text", "operator": "regex_contains", "operand": "\\s*(\\||\\+[-=])", "match_all": true}
+ ]},
+ {
+ "keys": ["super+shift+."], "command": "change_heading_level", "args": {"up": true}, "context": [
+ {"key": "selector", "operator": "equal", "operand": "text.html.markdown"}
+ ]},
+ {
+ "keys": ["super+shift+,"], "command": "change_heading_level", "args": {"up": false}, "context": [
+ {"key": "selector", "operator": "equal", "operand": "text.html.markdown"}
+ ]},
+
+ //Sublime Text 2 - Related Files - https://github.com/fabiokr/sublime-related-files
+ { "keys": ["ctrl+alt+t"], "command": "related_files" },
+
+ //SublimeTODO - https://github.com/robcowie/SublimeTODO
+ // {
+ // "keys": ["n"], "command": "goto_next_result",
+ // "context": [{ "key": "setting.todo_results", "operator": "equal", "operand": true }]
+ // }
+ {
+ "keys": ["n"], "command": "navigate_results",
+ //// {"key": "setting.todo_results"}
+ "context": [ {"key": "setting.command_mode", "operand": true}],
+ "args": {"direction": "forward"}
+ },
+ {
+ "keys": ["down"], "command": "navigate_results",
+ // {"key": "setting.todo_results"}
+ "context": [{"key": "setting.command_mode", "operand": true}],
+ "args": {"direction": "forward"}
+ },
+ {
+ "keys": ["j"], "command": "navigate_results",
+ "context": [{"key": "setting.command_mode", "operand": true}],
+ // {"key": "setting.todo_results"}
+ "args": {"direction": "forward"}
+ },
+ {
+ "keys": ["p"], "command": "navigate_results",
+ // {"key": "setting.todo_results"}
+ "context": [{"key": "setting.command_mode", "operand": true}],
+ "args": {"direction": "backward"}
+ },
+ {
+ "keys": ["up"], "command": "navigate_results",
+ //{"key": "setting.todo_results"}
+ "context": [{"key": "setting.command_mode", "operand": true}],
+ "args": {"direction": "backward"}
+ },
+ {
+ "keys": ["k"], "command": "navigate_results",
+ "context": [{"key": "setting.command_mode", "operand": true}],
+ //{"key": "setting.todo_results"}
+ "args": {"direction": "backward"}
+ },
+ {
+ "keys": ["c"], "command": "clear_selection",
+ // {"key": "setting.todo_results"}
+ "context": [{"key": "setting.command_mode", "operand": true}]
+ },
+ {
+ "keys": ["enter"], "command": "goto_comment",
+ // {"key": "setting.todo_results"}
+ "context": [{"key": "setting.command_mode", "operand": true}]
+ },
+
+ //Snippet Browsing Keybindings
+ { "keys": ["shift+f1"], "command": "show_overlay",
+ "args": {"overlay": "command_palette", "text": "snippet"} }
+]
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/README.md b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/README.md
new file mode 100644
index 0000000..94d0340
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/README.md
@@ -0,0 +1,38 @@
+SublimeKeyMap.Editor
+====================
+
+A simple repository used to host / share my customized Sublime Text 2 key bindings for Sublime editor enhancement plugins
+
+Designed to be incorporated into `Package Control.sublime-settings` like:
+
+```json
+{
+ "installed_packages":
+ [
+ "Abacus",
+ "Block Cursor Everywhere",
+ "Bracketeer",
+ "BracketHighlighter",
+ "Clipboard Manager",
+ "EasyMotion",
+ "ExportHtml",
+ "FileDiffs",
+ "Markdown Preview",
+ "Missing Palette Commands",
+ "Related Files",
+ "SmartMarkdown",
+ "Solarized Color Scheme",
+ "StringEncode",
+ "SublimeTODO",
+ "TrailingSpaces",
+ ],
+ "package_name_map": {
+ "SublimeKeyMap.Editor": "ZZZ.EthanBrown.SublimeKeyMap.Editor"
+ },
+ "repositories":
+ [
+ "https://github.com/abrookins/OpenSearchResult",
+ "https://github.com/Iristyle/SublimeKeyMap.Editor"
+ ]
+}
+```
diff --git a/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/package-metadata.json b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/package-metadata.json
new file mode 100644
index 0000000..2745b25
--- /dev/null
+++ b/EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/ZZZ.EthanBrown.SublimeKeyMap.Editor/package-metadata.json
@@ -0,0 +1 @@
+{"url": "https://github.com/Iristyle/SublimeKeyMap.Editor", "version": "2013.03.26.11.48.08", "description": "A simple repository used to host / share my customized Sublime Text 2 key bindings for Sublime editor enhancement plugins"}
\ No newline at end of file