Files
ChocolateyPackages/Sublime/Antiki/antiki.py
2013-06-07 14:03:33 -04:00

107 lines
2.6 KiB
Python

import sublime, sublime_plugin, re, subprocess, time, os, os.path
class AntikiCommand(sublime_plugin.TextCommand):
def run(self, edit):
antiki(self.view, edit)
def antiki(view, edit):
if view.is_read_only(): return
base = view.file_name()
if base is not None: base = os.path.dirname(base)
cfg = sublime.load_settings("Antiki.sublime-settings")
env = build_env(cfg, base=base)
cwd = expand(cfg.get('cwd', '.'), env)
enc = cfg.get('encoding', 'utf-8')
sels = view.sel()
end = None
for sel in sels:
# ensure that there is at least one following line.
if sel.end() == view.size():
view.insert(edit, view.size(), '\n')
row, _ = view.rowcol(sel.b)
head, op, cmd = resolve_head(view, row)
if cmd is None: continue
indent = head + ' ' * len(op)
end = resolve_body(view, row+1, indent)
out = head + op + cmd + '\n'
out = out + '\n'.join(
indent + line.decode(enc, 'ignore').rstrip() for line in perform_cmd(env, cwd, cmd)
) + '\n'
end = replace_lines(view, edit, row, end-row, out)
if end is None: return # don't play with the selection..
end = view.line(end.b)
view.sel().clear()
eol = end.end()
if end.empty():
view.insert(edit, eol, head)
eol += len(head)
view.sel().add(sublime.Region(eol,eol))
def build_env(cfg, base=None):
env = os.environ.copy()
env['BASE'] = str(base or env.get("HOME") or '.')
mod = cfg.get('env', {})
for key in mod:
env[key] = str(expand(mod[key], env))
return env
''' example:
$ echo $BASE
/Users/scott/Library/Application Support/Sublime Text 2/Packages/Antiki
'''
def expand(val, env):
return val.format(**env)
def perform_cmd(env, cwd, cmd):
args = cmd
pipe = subprocess.Popen(
args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, shell=True, env=env, cwd=cwd
)
ticks = 0
while ticks < 1000:
ticks += 1
time.sleep(.01)
if pipe.poll() is not None:
return pipe.stdout.readlines()
pipe.kill()
return pipe.stdout.readlines()
def replace_lines(view, edit, dest_row, dest_ct, src):
dest = sublime.Region(
view.text_point(dest_row,0),
view.text_point(dest_row+dest_ct,0)
)
view.replace(edit, dest, src)
end = view.text_point(dest_row,0) + len(src)
return sublime.Region(end,end)
rx_antiki = re.compile('^([ \t]*)([$] +)(.*)$')
def resolve_head(view, row):
line = get_line(view, row)
m = rx_antiki.match(line)
if m: return m.groups()
return None, None, None
def resolve_body(view, row, indent):
while True:
line = get_line(view, row)
if not line: return row
if not line.startswith(indent): return row
row += 1
def get_line(view, row=0):
point = view.text_point(row, 0)
if row < 0: return None
line = view.line(point)
return view.substr(line).strip('\r\n')