Skip to content

Instantly share code, notes, and snippets.

@tav
Created August 7, 2012 06:31
Show Gist options
  • Select an option

  • Save tav/3282403 to your computer and use it in GitHub Desktop.

Select an option

Save tav/3282403 to your computer and use it in GitHub Desktop.
"""Tav's Sublime Kit."""
import re
import sublime, sublime_plugin
from datetime import datetime
from json import dump, load
from os.path import dirname, expanduser, isdir, isfile, realpath, split
from time import time
# -----------------------------------------------------------------------------
# Region Skipping
# -----------------------------------------------------------------------------
linebreaks_re = re.compile('\n[\t ]*\n+')
find_linebreaks = linebreaks_re.search
split_linebreaks = linebreaks_re.split
def skip_region(view, scroll):
size = view.size()
start = view.sel()[0].begin()
if scroll == 1:
content = view.substr(sublime.Region(start, size))
segment = content.lstrip()
diff = len(content) - len(segment)
match = find_linebreaks(segment)
if match:
idx = start + diff + match.end() - 1
else:
idx = size
else:
content = view.substr(sublime.Region(0, start))
segment = content.rstrip()
diff = len(content) - len(segment)
split = split_linebreaks(segment)
if split:
idx = start - diff - len(split[-1]) - 1
else:
idx = 0
row, _ = view.rowcol(idx)
pt = view.text_point(row, 0)
view.sel().clear()
view.sel().add(sublime.Region(pt))
view.show(pt)
class SkipRegionDownCommand(sublime_plugin.TextCommand):
def run(self, edit):
skip_region(self.view, 1)
class SkipRegionUpCommand(sublime_plugin.TextCommand):
def run(self, edit):
skip_region(self.view, -1)
# -----------------------------------------------------------------------------
# Pager
# -----------------------------------------------------------------------------
def page(view, scroll):
end, _ = view.rowcol(view.size())
row, col = view.rowcol(view.sel()[0].begin())
row += scroll
if not (0 <= row <= end):
return
pt = view.text_point(row, 0)
view.sel().clear()
view.sel().add(sublime.Region(pt))
view.show_at_center(pt)
class PagerDownCommand(sublime_plugin.TextCommand):
def run(self, edit):
page(self.view, 1)
class PagerUpCommand(sublime_plugin.TextCommand):
def run(self, edit):
page(self.view, -1)
# -----------------------------------------------------------------------------
# Angilify
# -----------------------------------------------------------------------------
class AngilifyCommand(sublime_plugin.TextCommand):
def run(self, edit):
view = self.view
for region in view.sel():
if region.empty():
region = view.line(region)
view.insert(edit, region.begin(), '<')
view.insert(edit, region.end()+1, '>')
# -----------------------------------------------------------------------------
# Column Repeater
# -----------------------------------------------------------------------------
class RepeatColumnCommand(sublime_plugin.TextCommand):
def run(self, edit):
view = self.view
for region in view.sel():
idx = region.begin() - 1
if idx < 0:
continue
char = view.substr(idx)
if char in ('\n', '\t'):
continue
_, col = view.rowcol(idx)
view.insert(edit, idx, char * (78 - col))
# -----------------------------------------------------------------------------
# Utility Cache
# -----------------------------------------------------------------------------
class RecentSet(dict):
__slots__ = ('_clock',)
def __init__(self, *args):
self._clock = 0
for arg in args:
self.add(arg)
def add(self, key):
dict.__setitem__(self, key, self._clock)
self._clock += 1
def elems(self):
return sorted(self.keys(), key=lambda x: self[x], reverse=1)[:100]
# -----------------------------------------------------------------------------
# File Status
# -----------------------------------------------------------------------------
HISTORY_FILE = expanduser("~/.sublime.history")
if 'FILE_CACHE' not in globals():
args = ()
if isfile(HISTORY_FILE):
try:
history = open(HISTORY_FILE, 'rb')
args = load(history)
history.close()
except Exception, err:
print "ERROR: couldn't open history: %s", err
FILE_CACHE = RecentSet(*args)
class FileModifiedStatusEventHandler(sublime_plugin.EventListener):
last_saved = 0
def save_file_usage(self, view):
filename = view.file_name()
if not filename:
return
FILE_CACHE.add(filename)
now = time()
if (now - self.last_saved) < 10:
return
files = FILE_CACHE.elems()
if not files:
return
try:
history = open(HISTORY_FILE, "wb")
dump(files, history)
history.close()
self.last_saved = now
except Exception, err:
print "ERROR: couldn't save history: %s" % err
def on_close(self, view):
self.save_file_usage(view)
def on_load(self, view):
self.save_file_usage(view)
view.set_status("-", "-:--")
def on_modified(self, view):
view.set_status("-", "-:**")
def on_new(self, view):
view.set_status("-", "-:??")
def on_post_save(self, view):
self.save_file_usage(view)
view.set_status("-", "-:--")
class GetRecentCommand(sublime_plugin.WindowCommand):
showing = 0
def run(self):
if self.showing:
pass
# print "hiding"
# self.showing = 0
# self.window.run_command("hide_quick_panel", {"cancel": True})
else:
print "showing"
self.showing = FILE_CACHE.elems()
self.window.show_quick_panel(self.showing, self.select)
def select(self, idx):
showing = self.showing
self.showing = 0
if idx == -1:
return
self.window.open_file(showing[idx])
# -----------------------------------------------------------------------------
# Git Utility
# -----------------------------------------------------------------------------
def get_git_directory(view, cache={}, expire=10*60):
path = view.file_name()
if not path:
return
now = time()
path = dirname(realpath(path))
if path in cache and cache[path]['age'] > now:
return cache[path]['root']
temp, root = path, None
while temp:
if isdir(join(temp, '.git')):
root = temp
break
temp = dirname(temp)
cache[path] = {'root': root, 'age': now+expire}
return root
def normalise_repo_name(view):
path = get_git_directory(view)
if path:
path = split(path)
if len(path) == 2:
return ' '.join([e.title() for e in path[1].split('-')])
# -----------------------------------------------------------------------------
# Snippets
# -----------------------------------------------------------------------------
COPYRIGHT_HEADER = (
"%(comment)s Public Domain (-) " + str(datetime.utcnow().year) +
""" The %(app)s Authors.
%(comment)s See the %(app)s UNLICENSE file for details."""
)
GO_CMD = """%s
package main
import (
"$2"
)
func main() {
$0
}
"""
GO_PKG = """%s
package $2
import (
"$3"
)
func $4($5)$6 {
$0
}
"""
GO_AN = "interface{}"
GO_EF = """${1:f}, err ${2::=} ${4:some.Method}(${5:params})
if err != nil {
${6:body}
return ${7:nil}, err
}
$0"""
GO_MAP = "map[${1:string}]${2:string}"
GO_FU = """func $1($2)$3 {
$0
}"""
GO_IN = """type $1 interface {
$0
}"""
GO_ME = """func ($1) $2($3)$4 {
$0
}"""
GO_ST = """type $1 struct {
$0
}"""
class AutoHeaderEventHandler(sublime_plugin.EventListener):
def on_query_completions(self, view, prefix, locations):
pt = locations[0]
scopes = view.scope_name(pt).split()
if 'source.go' not in scopes:
return []
app = normalise_repo_name(view)
if app:
app = "${1:%s}" % app
else:
app = "$1"
header = COPYRIGHT_HEADER % dict(comment="//", app=app)
return [
('cmd\tNew Command', GO_CMD % header),
('pkg\tNew Package', GO_PKG % header),
('error\tStandard Error', 'error'),
('an\tinteface{}', GO_AN),
('ef\tError Boilerplate', GO_EF),
('fu\tNew Function', GO_FU),
('in\tNew Interface', GO_IN),
('map\tNew Map', GO_MAP),
('me\tNew Method', GO_ME),
('st\tNew Struct', GO_ST),
('byte\t[]byte type', '[]byte'),
('int64\tint64 type', 'int64'),
('int\tint type', 'int'),
('int32\tint32 type', 'int32'),
('uint\tuint type', 'uint'),
('uint64\tuint64 type', 'uint64'),
('uint32\tuint32 type', 'uint32'),
('float64\tfloat64 type', 'float64'),
('float32\tfloat32 type', 'float32'),
('string\tstring type', 'string'),
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment