def fmt(filename, src): return post('/fmt', { 'fn': filename or '', 'src': src, 'tab_indent': gs.setting('fmt_tab_indent'), 'tab_width': gs.setting('fmt_tab_width'), }, u"")
def resolve_snippets(ctx): cl = set() types = [''] if ctx.get('local') else ctx.get('types') vars = {} for k, v in ctx.iteritems(): if gs.is_a_string(v): vars[k] = v try: snips = [] snips.extend(gs.setting('default_snippets', [])) snips.extend(gs.setting('snippets', [])) for m in snips: try: if snippet_match(ctx, m): for ent in m.get('snippets', []): text = ent.get('text', '') title = ent.get('title', '') value = ent.get('value', '') if text and value: for typename in types: vars['typename'] = typename vars['typename_abbr'] = typename[0].lower( ) if typename else '' txt, ttl, val = expand_snippet_vars( vars, text, title, value) s = u'%s\t%s \u0282' % (txt, ttl) cl.add((s, val)) except: gs.notice(DOMAIN, gs.traceback()) except: gs.notice(DOMAIN, gs.traceback()) return list(cl)
def cb(): global hello_sarting if hello_sarting: return hello_sarting = True print 'starting gocode' call_cmd(['gocode']) margo_cmd = list(gs.setting('margo_cmd', [])) if not margo_cmd: err = 'Missing `margo_cmd`' gs.notice("MarGo", err) hello_sarting = False return margo_cmd.extend([ "-d", "-call", "replace", "-addr", gs.setting('margo_addr', '') ]) print 'starting margo' out, err, _ = gs.runcmd(margo_cmd) out = out.strip() err = err.strip() if err: gs.notice(DOMAIN, err) elif out: gs.notice(DOMAIN, 'MarGo started %s' % out) hello_sarting = False
def do_hello(): global hello_sarting if hello_sarting: return hello_sarting = True tid = gs.begin(DOMAIN, 'Starting Gocode', False) call_cmd(['gocode']) gs.end(tid) margo_cmd = list(gs.setting('margo_cmd', [])) if margo_cmd: margo_cmd.extend([ "-d", "-call", "replace", "-addr", gs.setting('margo_addr', '') ]) tid = gs.begin(DOMAIN, 'Starting MarGo', False) out, err, _ = gs.runcmd(margo_cmd) gs.end(tid) out = out.strip() err = err.strip() if err: gs.notice(DOMAIN, err) elif out: gs.notice(DOMAIN, 'MarGo started %s' % out) hello_sarting = False else: err = 'Missing `margo_cmd`' gs.notice("MarGo", err) hello_sarting = False
def call(path='/', args={}, default={}, cb=None, message=''): try: if args is None: a = '' elif isinst(args, {}): a = { 'env': gs.env(), 'tab_indent': gs.setting('fmt_tab_indent'), 'tab_width': gs.setting('fmt_tab_width'), } for k, v in args.iteritems(): if v is None: v = '' a[k] = v else: a = args except: a = args def f(): res, err = post(path, a, default, False, True) if cb: sublime.set_timeout(lambda: cb(res, err), 0) dispatch(f, 'call %s: %s' % (path, message))
def do_hello(): global hello_sarting if hello_sarting: return hello_sarting = True tid = gs.begin(DOMAIN, 'Starting Gocode', False) call_cmd([mg9.GOCODE_BIN]) gs.end(tid) margo_cmd = list(gs.setting('margo_cmd', [])) margo_cmd = [ mg9.MARGO0_BIN, "-d", "-call", "replace", "-addr", gs.setting('margo_addr', '') ] tid = gs.begin(DOMAIN, 'Starting MarGo', False) out, err, _ = gs.runcmd(margo_cmd) gs.end(tid) out = out.strip() err = err.strip() if err: gs.notice(DOMAIN, err) elif out: gs.println(DOMAIN, 'MarGo started %s' % out) hello_sarting = False
def resolve_snippets(ctx): cl = set() types = [''] if ctx.get('local') else ctx.get('types') vars = {} for k,v in ctx.iteritems(): if gs.is_a_string(v): vars[k] = v try: snips = [] snips.extend(gs.setting('default_snippets', [])) snips.extend(gs.setting('snippets', [])) for m in snips: try: if snippet_match(ctx, m): for ent in m.get('snippets', []): text = ent.get('text', '') title = ent.get('title', '') value = ent.get('value', '') if text and value: for typename in types: vars['typename'] = typename vars['typename_abbr'] = typename[0].lower() if typename else '' txt, ttl, val = expand_snippet_vars(vars, text, title, value) s = u'%s\t%s \u0282' % (txt, ttl) cl.add((s, val)) except: gs.notice(DOMAIN, gs.traceback()) except: gs.notice(DOMAIN, gs.traceback()) return list(cl)
def call(path='/', args={}, default={}, cb=None, message=''): try: if args is None: a = '' elif isinst(args, {}): a = { 'env': gs.env(), 'tab_indent': gs.setting('fmt_tab_indent'), 'tab_width': gs.setting('fmt_tab_width'), } for k, v in args.items(): if v is None: v = '' a[k] = v else: a = args except: a = args def f(): res, err = post(path, a, default, False, True) if cb: sublime.set_timeout(lambda: cb(res, err), 0) dispatch(f, 'call %s: %s' % (path, message))
def on_query_completions(self, view, prefix, locations): pos = locations[0] scopes = view.scope_name(pos).split() if 'source.go' not in scopes: return [] # if we complete inside e.g. a map's key we're going to cause subtle bugs so bail if 'string.quoted.double.go' in scopes or 'string.quoted.single.go' in scopes or 'string.quoted.raw.go' in scopes: # afaik we must return something in order to disable st2's word completion return [(' ', '$0')] if not self.gocode_set: self.gocode_set = True # autostart the daemon gs.runcmd([gs.setting('gocode_cmd', 'gocode')]) # gocode is case-sesitive so push the location back to the 'dot' so it gives # gives us everything then st2 can pick the matches for us offset = pos - len(prefix) src = view.substr(sublime.Region(0, view.size())) fn = view.file_name() if not src or not fn: return [] cl = self.complete(fn, offset, src) if gs.setting('autocomplete_snippets', True): if scopes[-1] == 'source.go': cl.extend(gs.GLOBAL_SNIPPETS) elif scopes[-1] == 'meta.block.go' and ('meta.function.plain.go' in scopes or 'meta.function.receiver.go' in scopes): cl.extend(gs.LOCAL_SNIPPETS) return cl
def on_query_completions(self, view, prefix, locations): pos = locations[0] scopes = view.scope_name(pos).split() if ('source.go' not in scopes) or (gs.setting('gscomplete_enabled', False) is not True): return [] if gs.IGNORED_SCOPES.intersection(scopes): return ([], AC_OPTS) show_snippets = gs.setting('autocomplete_snippets', True) is True package_end_pt = self.find_end_pt(view, 'package', 0, pos) if package_end_pt < 0: return ([gs.GLOBAL_SNIPPET_PACKAGE], AC_OPTS) if show_snippets else ([], AC_OPTS) # gocode is case-sesitive so push the location back to the 'dot' so it gives # gives us everything then st2 can pick the matches for us offset = pos - len(prefix) src = view.substr(sublime.Region(0, view.size())) fn = view.file_name() if not src or not fn: return ([], AC_OPTS) cl = self.complete(fn, offset, src, view.substr(sublime.Region(pos, pos+1)) == '(') pc = view.substr(sublime.Region(pos-1, pos)) if show_snippets and (pc.isspace() or pc.isalpha()): if scopes[-1] == 'source.go': cl.extend(gs.GLOBAL_SNIPPETS) elif scopes[-1] == 'meta.block.go' and ('meta.function.plain.go' in scopes or 'meta.function.receiver.go' in scopes): cl.extend(gs.LOCAL_SNIPPETS) return (cl, AC_OPTS)
def complete(self, fn, offset, src): comps = [] cmd = gs.setting('gocode_cmd', 'gocode') can_pass_char_offset = gs.setting('gocode_accepts_character_offsets', False) if can_pass_char_offset is True: offset = 'c%s' % offset else: offset = gs.char_to_byte_offset(src, offset) args = [cmd, "-f=json", "autocomplete", fn, str(offset)] js, err = gs.runcmd(args, src) if err: sublime.error_message(err) else: try: js = json.loads(js) if js and js[1]: for ent in js[1]: if ent['name'] == 'main': continue etype = ent['type'] eclass = ent['class'] ename = ent['name'] tname = self.typeclass_prefix(eclass, etype) + ename if ent['class'] == 'func': comps.append(self.parse_decl_hack(etype, ename, tname)) elif ent['class'] != 'PANIC': comps.append((tname, ename)) except KeyError as e: sublime.error_message('Error while running gocode, possibly malformed data returned: %s' % e) except ValueError as e: sublime.error_message("Error while decoding gocode output: %s" % e) return comps
def complete(self, fn, offset, src, func_name_only): comps = [] autocomplete_tests = gs.setting("autocomplete_tests", False) autocomplete_closures = gs.setting("autocomplete_closures", False) ents, err = mg9.complete(fn, src, offset) if err: gs.notice(DOMAIN, err) name_fx = None name_fx_pat = gs.setting("autocomplete_filter_name") if name_fx_pat: try: name_fx = re.compile(name_fx_pat) except Exception as ex: gs.notice(DOMAIN, "Cannot filter completions: %s" % ex) for ent in ents: if name_fx and name_fx.search(ent["name"]): continue tn = ent["type"] cn = ent["class"] nm = ent["name"] is_func = cn == "func" is_func_type = cn == "type" and tn.startswith("func(") if is_func: if nm in ("main", "init"): continue if not autocomplete_tests and nm.startswith(("Test", "Benchmark", "Example")): continue if is_func or is_func_type: s_sfx = u"\u0282" t_sfx = gs.CLASS_PREFIXES.get("type", "") f_sfx = gs.CLASS_PREFIXES.get("func", "") params, ret = declex(tn) decl = [] for i, p in enumerate(params): n, t = p if t.startswith("..."): n = "..." decl.append("${%d:%s}" % (i + 1, n)) decl = ", ".join(decl) ret = ret.strip("() ") if is_func: if func_name_only: comps.append(("%s\t%s %s" % (nm, ret, f_sfx), nm)) else: comps.append(("%s\t%s %s" % (nm, ret, f_sfx), "%s(%s)" % (nm, decl))) else: comps.append(("%s\t%s %s" % (nm, tn, t_sfx), nm)) if autocomplete_closures: comps.append(("%s {}\tfunc() {...} %s" % (nm, s_sfx), "%s {\n\t${0}\n}" % tn)) elif cn != "PANIC": comps.append(("%s\t%s %s" % (nm, tn, self.typeclass_prefix(cn, tn)), nm)) return comps
def complete(self, fn, offset, src, func_name_only): global last_gopath gopath = gs.env().get('GOPATH') if gopath and gopath != last_gopath: out, _, _ = gsshell.run(cmd=['go', 'env', 'GOOS', 'GOARCH']) vars = out.strip().split() if len(vars) == 2: last_gopath = gopath libpath = os.path.join(gopath, 'pkg', '_'.join(vars)) gsshell.run(cmd=['gocode', 'set', 'lib-path', libpath], cwd=gsbundle.BUNDLE_GOBIN) comps = [] cmd = gs.setting('gocode_cmd', 'gocode') offset = 'c%s' % offset args = [cmd, "-f=json", "autocomplete", fn, offset] js, err, _ = gsshell.run(cmd=args, input=src) if err: gs.notice(DOMAIN, err) else: try: js = json.loads(js) if js and js[1]: for ent in js[1]: tn = ent['type'] cn = ent['class'] nm = ent['name'] sfx = self.typeclass_prefix(cn, tn) if cn == 'func': if nm in ('main', 'init'): continue act = gs.setting('autocomplete_tests', False) if not act and nm.startswith( ('Test', 'Benchmark', 'Example')): continue params, ret = declex(tn) ret = ret.strip('() ') if func_name_only: a = nm else: a = [] for i, p in enumerate(params): n, t = p if t.startswith('...'): n = '...' a.append('${%d:%s}' % (i + 1, n)) a = '%s(%s)' % (nm, ', '.join(a)) comps.append(('%s\t%s %s' % (nm, ret, sfx), a)) elif cn != 'PANIC': comps.append(('%s\t%s %s' % (nm, tn, sfx), nm)) except KeyError as e: gs.notice( DOMAIN, 'Error while running gocode, possibly malformed data returned: %s' % e) except ValueError as e: gs.notice(DOMAIN, "Error while decoding gocode output: %s" % e) return comps
def fmt(fn, src): res, err = bcall('fmt', { 'fn': fn or '', 'src': src or '', 'tabIndent': gs.setting('fmt_tab_indent'), 'tabWidth': gs.setting('fmt_tab_width'), }) return res.get('src', ''), err
def imports(fn, src, toggle): return bcall('imports', { 'fn': fn or '', 'src': src or '', 'toggle': toggle or [], 'tabIndent': gs.setting('fmt_tab_indent'), 'tabWidth': gs.setting('fmt_tab_width'), })
def imports(filename, src, toggle): return post('/imports', { 'fn': filename or '', 'src': src, 'toggle': toggle, 'tab_indent': gs.setting('fmt_tab_indent'), 'tab_width': gs.setting('fmt_tab_width'), }, {})
def watch(): global file_refs global th view = gs.active_valid_go_view() if view is not None and (view.file_name() and gs.setting('comp_lint_enabled') is True): fn = view.file_name() fr = ref(fn) with sem: if fr: fr.view = view highlight(fr) sublime.set_timeout(watch, 500) return if gs.setting('gslint_enabled') is not True: if view: with sem: for fn in file_refs: fr = file_refs[fn] cleanup(fr.view) file_refs = {} sublime.set_timeout(watch, 2000) return if view and not view.is_loading(): fn = view.file_name() fr = ref(fn) with sem: if fr: # always use the active view (e.g in split-panes) fr.view = view highlight(fr) else: fr = FileRef(view) file_refs[fn] = fr if fr.state == 0: src = view.substr(sublime.Region(0, view.size())) if src != fr.src: fr.src = src fr.tm = time.time() if fr.tm > 0.0: timeout = int(gs.setting('gslint_timeout', 500)) delta = int((time.time() - fr.tm) * 1000.0) if delta >= timeout: fr.tm = 0.0 fr.state = -1 if not th: th = GsLintThread() th.start() th.putq(fn) sublime.set_timeout(watch, 500)
def imports(fn, src, toggle): return bcall( 'imports', { 'fn': fn or '', 'src': src or '', 'toggle': toggle or [], 'tabIndent': gs.setting('fmt_tab_indent'), 'tabWidth': gs.setting('fmt_tab_width'), })
def doc(fn, src, offset, f): return acall('doc', { 'fn': fn or '', 'src': src or '', 'offset': offset or 0, 'env': gs.env(), 'tabIndent': gs.setting('fmt_tab_indent'), 'tabWidth': gs.setting('fmt_tab_width'), }, f)
def complete(self, fn, offset, src, func_name_only): global last_gopath gopath = gs.env().get('GOPATH') if gopath and gopath != last_gopath: out, _, _ = gsshell.run(cmd=['go', 'env', 'GOOS', 'GOARCH']) vars = out.strip().split() if len(vars) == 2: last_gopath = gopath libpath = os.path.join(gopath, 'pkg', '_'.join(vars)) gsshell.run(cmd=['gocode', 'set', 'lib-path', libpath], cwd=gsbundle.BUNDLE_GOBIN) comps = [] cmd = gs.setting('gocode_cmd', 'gocode') offset = 'c%s' % offset args = [cmd, "-f=json", "autocomplete", fn, offset] js, err, _ = gsshell.run(cmd=args, input=src) if err: gs.notice(DOMAIN, err) else: try: js = json.loads(js) if js and js[1]: for ent in js[1]: tn = ent['type'] cn = ent['class'] nm = ent['name'] sfx = self.typeclass_prefix(cn, tn) if cn == 'func': if nm in ('main', 'init'): continue act = gs.setting('autocomplete_tests', False) if not act and nm.startswith(('Test', 'Benchmark', 'Example')): continue params, ret = declex(tn) ret = ret.strip('() ') if func_name_only: a = nm else: a = [] for i, p in enumerate(params): n, t = p if t.startswith('...'): n = '...' a.append('${%d:%s}' % (i+1, n)) a = '%s(%s)' % (nm, ', '.join(a)) comps.append(('%s\t%s %s' % (nm, ret, sfx), a)) elif cn != 'PANIC': comps.append(('%s\t%s %s' % (nm, tn, sfx), nm)) except KeyError as e: gs.notice(DOMAIN, 'Error while running gocode, possibly malformed data returned: %s' % e) except ValueError as e: gs.notice(DOMAIN, "Error while decoding gocode output: %s" % e) return comps
def fmt(fn, src): res, err = bcall( "fmt", { "fn": fn or "", "src": src or "", "tabIndent": gs.setting("fmt_tab_indent"), "tabWidth": gs.setting("fmt_tab_width"), }, ) return res.get("src", ""), err
def doc(fn, src, offset, f): tid = gs.begin(DOMAIN, 'Fetching doc info') def cb(res, err): gs.end(tid) f(res, err) acall('doc', { 'fn': fn or '', 'src': src or '', 'offset': offset or 0, 'env': gs.env(), 'tabIndent': gs.setting('fmt_tab_indent'), 'tabWidth': gs.setting('fmt_tab_width'), }, cb)
def run(self, edit): if not gs.is_go_source_view(self.view): return region = sublime.Region(0, self.view.size()) src = self.view.substr(region) args = [gs.setting("gofmt_cmd", "gofmt"), "-d"] diff, err = gs.runcmd(args, src) if err: fn = self.view.file_name() err = err.replace('<standard input>', fn) gs.notice('GsFmt', 'File %s contains errors' % fn) elif diff: err = '' try: edit = self.view.begin_edit() ed = SublimeEditor(self.view, edit) err = thatcher.patch(ed, diff) except Exception as e: err = "%s\n\n%s" % (err, e) finally: self.view.end_edit(edit) if err: def cb(): if ed.dirty: self.view.run_command('undo') gs.notice("GsFmt", "Could not patch the buffer: %s" % err) sublime.set_timeout(cb, 0)
def doc(fn, src, offset, f): tid = gs.begin(DOMAIN, 'Fetching doc info') def cb(res, err): gs.end(tid) f(res, err) acall( 'doc', { 'fn': fn or '', 'src': src or '', 'offset': offset or 0, 'env': gs.env(), 'tabIndent': gs.setting('fmt_tab_indent'), 'tabWidth': gs.setting('fmt_tab_width'), }, cb)
def run(self, edit): scopes = self.view.scope_name(0).split() if 'source.go' not in scopes: return region = sublime.Region(0, self.view.size()) src = self.view.substr(region) args = [gs.setting("gofmt_cmd", "gofmt"), "-d"] diff, err = gs.runcmd(args, src) if err: fn = self.view.file_name() err = err.replace('<standard input>', fn) def report_error(): sublime.status_message('GsFmt: File %s contains errors' % fn) sublime.set_timeout(report_error, 0) elif diff: err = '' try: edit = self.view.begin_edit() ed = SublimeEditor(self.view, edit) err = thatcher.patch(ed, diff) except Exception as e: err = "%s\n\n%s" % (err, e) finally: self.view.end_edit(edit) if err: def report_err(): self.view.run_command('undo') sublime.status_message("GsFmt: Could not patch the buffer: %s" % err) sublime.set_timeout(report_err, 0)
def init(self): if self.c: try: self.c.close() except: pass self.c = httplib.HTTPConnection(gs.setting('margo_addr', ''), timeout=5)
def on_install_done(c): s = output_str(c) x = c.exception() if x: tpl = 'Error while installing dependencies\nCommand: %s\nException: %s\nOutput: %s' gs.show_output(DOMAIN, tpl % (c.cmd, x, s), merge_domain=True) js, _, _ = gsshell.run(cmd=BUNDLE_GOSUBLIME9, shell=True) js = json.loads(js) for k,v in js.iteritems(): if v: gs.environ9[k] = v print_install_log(c, s) c = gsshell.Command(cmd=[ BUNDLE_MARGO, "-d", "-call", "replace", "-addr", gs.setting('margo_addr', '') ]) c.on_done = on_margo_done c.start() gsshell.run(cmd=[BUNDLE_GOCODE, 'close'])
def init(self): if self.c: try: self.c.close() except: pass self.c = http.client.HTTPConnection(gs.setting('margo_addr', ''), timeout=5)
def show_pkgfiles(dirname): ents = [] m = {} try: dirname = os.path.abspath(dirname) for fn in gs.list_dir_tree(dirname, ext_filter, gs.setting('fn_exclude_prefixes', [])): name = os.path.relpath(fn, dirname).replace('\\', '/') m[name] = fn ents.append(name) except Exception as ex: gs.notice(DOMAIN, 'Error: %s' % ex) if ents: ents.sort(key = lambda a: a.lower()) try: s = " ../ ( current: %s )" % dirname m[s] = os.path.join(dirname, "..") ents.insert(0, s) except Exception: pass def cb(i, win): if i >= 0: fn = m[ents[i]] if os.path.isdir(fn): win.run_command("gs_browse_files", {"dir": fn}) else: gs.focus(fn, 0, 0, win) gs.show_quick_panel(ents, cb) else: gs.show_quick_panel([['', 'No files found']])
def lint(self, view): self.rc -= 1 if self.rc == 0: err = '' cmd = gs.setting('gslint_cmd', 'gotype') real_path = view.file_name() pat_prefix = '' pwd = dirname(real_path) fn = basename(real_path) # normalize the path so we can compare it below real_path = pathjoin(pwd, fn) tmp_path = pathjoin(pwd, '.GoSublime~tmp~%d~%s~' % (view.id(), fn)) try: if cmd: files = [] if real_path: for fn in listdir(pwd): if fn.lower().endswith('.go'): fn = pathjoin(pwd, fn) if fn != real_path: files.append(fn) src = view.substr(sublime.Region(0, view.size())).encode('utf-8') if files: # m = LEADING_COMMENTS_PAT.sub('', src) m = LEADING_COMMENTS_PAT.match(src) m = PACKAGE_NAME_PAT.search(src, m.end(1) if m else 0) if m: pat_prefix = '^' + re.escape(tmp_path) with open(tmp_path, 'wb') as f: f.write(src) args = [cmd, '-p', m.group(1), tmp_path] args.extend(files) _, err = gs.runcmd(args) unlink(tmp_path) else: sublime.status_message('Cannot find PackageName') else: _, err = gs.runcmd([cmd], src) except Exception as e: sublime.status_message(str(e)) regions = [] view_id = view.id() self.errors[view_id] = {} for m in re.finditer(r'%s:(\d+):(\d+):\s+(.+)\s*$' % pat_prefix, err, re.MULTILINE): line, start, err = int(m.group(1))-1, int(m.group(2))-1, m.group(3) self.errors[view_id][line] = err pos = view.line(view.text_point(line, 0)).begin() + start if pos >= view.size(): pos = view.size() - 1 regions.append(sublime.Region(pos, pos)) if regions: flags = sublime.DRAW_EMPTY_AS_OVERWRITE view.add_regions('GsLint-errors', regions, 'invalid.illegal', 'cross', flags) else: view.erase_regions('GsLint-errors') self.on_selection_modified(view)
def lint(self, view): self.rc -= 1 if self.rc == 0: cmd = gs.setting('gslint_cmd', 'gotype') if cmd: filelist = self.generate_filelist_for_lint(view) filelist = [cmd] + filelist _, err = gs.runcmd(filelist, "") else: err = '' lines = LINE_PAT.findall(err) regions = [] view_id = view.id() self.errors[view_id] = {} if lines: for m in lines: if m[0] == view.file_name(): #check if this error message is for the current file line, start, err = int(m[1])-1, int(m[2])-1, m[3] self.errors[view_id][line] = err lr = view.line(view.text_point(line, start)) regions.append(sublime.Region(lr.begin() + start, lr.end())) if regions: flags = sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_OUTLINED flags = sublime.DRAW_EMPTY_AS_OVERWRITE flags = sublime.DRAW_OUTLINED view.add_regions('GsLint-errors', regions, 'invalid.illegal', 'cross', flags) else: view.erase_regions('GsLint-errors') self.on_selection_modified(view)
def init(self): if self.c: try: self.c.close() except: pass self.c = httplib.HTTPConnection(gs.setting("margo_addr", ""), timeout=5)
def complete(fn, src, pos): home = gs.home_path() builtins = (gs.setting('autocomplete_builtins') is True or gs.setting('complete_builtins') is True) res, err = bcall('gocode_complete', { 'Dir': gs.basedir_or_cwd(fn), 'Builtins': builtins, 'Fn': fn or '', 'Src': src or '', 'Pos': pos or 0, 'Home': home, 'Env': gs.env({ 'XDG_CONFIG_HOME': home, }), }) res = gs.dval(res.get('completions'), []) return res, err
def do_comp_lint(dirname, fn): fr = ref(fn, False) reports = {} if not fr: return fn = gs.apath(fn, dirname) bindir, _ = gs.temp_dir('bin') local_env = { 'GOBIN': bindir, } pat = r'%s:(\d+)(?:[:](\d+))?\W+(.+)\s*' % re.escape(os.path.basename(fn)) pat = re.compile(pat, re.IGNORECASE) for c in gs.setting('comp_lint_commands'): try: cmd = c.get('cmd') if not cmd: continue cmd_domain = ' '.join(cmd) shell = c.get('shell') is True env = {} if c.get('global') is True else local_env out, err, _ = gsshell.run(cmd=cmd, shell=shell, cwd=dirname, env=env) if err: gs.notice(DOMAIN, err) out = out.replace('\r', '').replace('\n ', '\\n ').replace('\n\t', '\\n\t') for m in pat.findall(out): try: row, col, msg = m row = int(row) - 1 col = int(col) - 1 if col else 0 msg = msg.replace('\\n', '\n').strip() if row >= 0 and msg: msg = '%s: %s' % (cmd_domain, msg) if reports.get(row): reports[row].msg = '%s\n%s' % (reports[row].msg, msg) reports[row].col = max(reports[row].col, col) else: reports[row] = Report(row, col, msg) except: pass except: gs.notice(DOMAIN, gs.traceback()) def cb(): fr.reports = reports fr.state = 1 highlight(fr) sublime.set_timeout(cb, 0)
def _save_all(win, wd): if gs.setting('autosave') is True and win is not None: for v in win.views(): try: fn = v.file_name() if fn and v.is_dirty() and fn.endswith('.go') and os.path.dirname(fn) == wd: v.run_command('gs_fmt_save') except Exception: gs.error_traceback(DOMAIN)
def complete(fn, src, pos): home = gs.home_path() builtins = gs.setting("autocomplete_builtins") is True or gs.setting("complete_builtins") is True res, err = bcall( "gocode_complete", { "Dir": gs.basedir_or_cwd(fn), "Builtins": builtins, "Fn": fn or "", "Src": src or "", "Pos": pos or 0, "Home": home, "Env": gs.env({"XDG_CONFIG_HOME": home}), }, ) res = gs.dval(res.get("completions"), []) return res, err
def complete(self, fn, offset, src, func_name_only): comps = [] cmd = gs.setting('gocode_cmd', 'gocode') offset = 'c%s' % offset args = [cmd, "-f=json", "autocomplete", fn, offset] js, err, _ = gs.runcmd(args, src) if err: gs.notice('GsComplete', err) else: try: js = json.loads(js) if js and js[1]: for ent in js[1]: tn = ent['type'] cn = ent['class'] nm = ent['name'] sfx = self.typeclass_prefix(cn, tn) if cn == 'func': if nm in ('main', 'init'): continue act = gs.setting('autocomplete_tests', False) if not act and nm.startswith(('Test', 'Benchmark', 'Example')): continue params, ret = declex(tn) ret = ret.strip('() ') if func_name_only: a = nm else: a = [] for i, p in enumerate(params): n, t = p if t.startswith('...'): n = '...' a.append('${%d:%s}' % (i+1, n)) a = '%s(%s)' % (nm, ', '.join(a)) comps.append(('%s\t%s %s' % (nm, ret, sfx), a)) elif cn != 'PANIC': comps.append(('%s\t%s %s' % (nm, tn, sfx), nm)) except KeyError as e: gs.notice('GsComplete', 'Error while running gocode, possibly malformed data returned: %s' % e) except ValueError as e: gs.notice('GsComplete', "Error while decoding gocode output: %s" % e) return comps
def run(self, edit): if gs.setting('comp_lint_enabled') is not True: return fn = self.view.file_name() fn = os.path.abspath(fn) if fn: dirname = gs.basedir_or_cwd(fn) file_refs[fn] = FileRef(self.view) gsq.dispatch(CL_DOMAIN, lambda: do_comp_lint(dirname, fn), '')
def _save_all(win, wd): if gs.setting('autosave') is True and win is not None: for v in win.views(): try: fn = v.file_name() if fn and v.is_dirty() and fn.endswith( '.go') and os.path.dirname(fn) == wd: v.run_command('gs_fmt_save') except Exception: gs.error_traceback(DOMAIN)
def do_post_save(view): if not gs.is_pkg_view(view): return for c in gs.setting('on_save', []): cmd = c.get('cmd', '') args = c.get('args', {}) msg = 'running on_save command %s' % cmd tid = gs.begin(DOMAIN, msg, set_status=False) try: view.run_command(cmd, args) except Exception as ex: gs.notice(DOMAIN, 'Error %s' % ex) finally: gs.end(tid)
def fix_shell_cmd(shell, cmd): if not gs.is_a(cmd, []): cmd = [cmd] if shell: sh = gs.setting('shell') cmd_str = ' '.join(cmd) if sh: shell = False cmd = [] for v in sh: if v: cmd.append(str(v).replace('$CMD', cmd_str)) else: cmd = [cmd_str] return (shell, [gs.astr(v) for v in cmd])
def do_post_save(view): if not gs.is_pkg_view(view): return domain = 'GoSublime-On-Save' for c in gs.setting('on_save', []): cmd = c.get('cmd', '') args = c.get('args', {}) msg = 'running on_save command %s' % cmd tid = gs.begin(domain, msg, set_status=False) gs.println(msg) try: view.run_command(cmd, args) except Exception as ex: gs.notice(domain, 'Error %s' % ex) finally: gs.end(tid)
def fix_shell_cmd(shell, cmd): if not gs.is_a(cmd, []): cmd = [cmd] if shell: sh = gs.setting('shell') cmd_str = ' '.join(cmd) cmd_map = {'CMD': cmd_str} if sh: shell = False cmd = [] for v in sh: if v: cmd.append(string.Template(v).safe_substitute(cmd_map)) else: cmd = [cmd_str] return (shell, [gs.astr(v) for v in cmd])
def do_hello(): global hello_sarting if hello_sarting: return hello_sarting = True margo_cmd = [ mg9.MARGO0_BIN, "-d", "-call", "replace", "-addr", gs.setting('margo_addr', '') ] tid = gs.begin(DOMAIN, 'Starting MarGo', False) out, err, _ = gsshell.run(margo_cmd) gs.end(tid) out = out.strip() err = err.strip() if err: gs.notice(DOMAIN, err) elif out: gs.println(DOMAIN, 'MarGo started %s' % out) hello_sarting = False
def on_install_done(c): s = output_str(c) x = c.exception() if x: tpl = 'Error while installing dependencies\nCommand: %s\nException: %s\nOutput: %s' gs.show_output(DOMAIN, tpl % (c.cmd, x, s), merge_domain=True) js, _, _ = gsshell.run(cmd=BUNDLE_GOSUBLIME9, shell=True) js = json.loads(js) for k, v in js.iteritems(): if v: gs.environ9[k] = v print_install_log(c, s) c = gsshell.Command(cmd=[ BUNDLE_MARGO, "-d", "-call", "replace", "-addr", gs.setting('margo_addr', '') ]) c.on_done = on_margo_done c.start() gsshell.run(cmd=[BUNDLE_GOCODE, 'close'])
def is_enabled(self): return gs.setting('fmt_enabled', False) is True and gs.is_go_source_view(self.view)
def run(self, edit): view = self.view pt = view.sel()[0].begin() if view.substr(sublime.Region(pt - 1, pt)) == '(': depth = 1 else: depth = 0 c = '' while True: line = view.line(pt) scope = view.scope_name(pt) if 'string' in scope or 'comment' in scope: pt = view.extract_scope(pt).begin() - 1 continue c = view.substr(sublime.Region(pt - 1, pt)) if not c: pt = -1 break if c.isalpha() and depth >= 0: while c.isalpha() or c == '.': pt += 1 c = view.substr(sublime.Region(pt - 1, pt)) # curly braces ftw break # break outer while loop if c == ')': depth -= 1 elif c == '(': depth += 1 i = pt while True: pc = view.substr(sublime.Region(i - 1, i)) if pc == '.' or pc.isalpha(): i -= 1 else: break if i != pt: pt = i continue pt -= 1 if pt <= line.begin(): pt = -1 break while not c.isalpha() and pt > 0: pt -= 1 c = view.substr(sublime.Region(pt - 1, pt)) if pt <= 0 or view.scope_name(pt).strip() == 'source.go': self.show_hint("// can't find selector") return line = view.line(pt) line_start = line.begin() s = view.substr(line) if not s: self.show_hint('// no source') return scopes = [ 'support.function.any-method.go', 'meta.function-call.go', 'support.function.builtin.go', ] found = False while True: scope = view.scope_name(pt).strip() for s in scopes: if scope.endswith(s): found = True break if found or pt <= line_start: break pt -= 1 if not found: self.show_hint("// can't find function call") return s = view.substr(sublime.Region(line_start, pt)) m = END_SELECTOR_PAT.match(s) if not m: self.show_hint("// can't match selector") return offset = (line_start + m.end()) coffset = 'c%d' % offset sel = m.group(1) name = m.group(2) candidates = [] src = view.substr(sublime.Region(0, view.size())) fn = view.file_name() or '<stdin>' cmd = gs.setting('gocode_cmd', 'gocode') args = [cmd, "-f=json", "autocomplete", fn, coffset] js, err, _ = gs.runcmd(args, src) if err: gs.notice(DOMAIN, err) else: try: js = json.loads(js) if js and js[1]: candidates = js[1] except: pass c = {} for i in candidates: if i['name'] == name: if c: c = None break c = i if not c: self.show_hint('// no candidates found') return s = '// %s %s\n%s' % (c['name'], c['class'], c['type']) self.show_hint(s)
def complete(self, fn, offset, src, func_name_only): comps = [] autocomplete_tests = gs.setting('autocomplete_tests', False) autocomplete_closures = gs.setting('autocomplete_closures', False) ents, err = mg9.complete(fn, src, offset) if err: gs.notice(DOMAIN, err) name_fx = None name_fx_pat = gs.setting('autocomplete_filter_name') if name_fx_pat: try: name_fx = re.compile(name_fx_pat) except Exception as ex: gs.notice(DOMAIN, 'Cannot filter completions: %s' % ex) for ent in ents: if name_fx and name_fx.search(ent['name']): continue tn = ent['type'] cn = ent['class'] nm = ent['name'] is_func = (cn == 'func') is_func_type = (cn == 'type' and tn.startswith('func(')) if is_func: if nm in ('main', 'init'): continue if not autocomplete_tests and nm.startswith( ('Test', 'Benchmark', 'Example')): continue if is_func or is_func_type: s_sfx = u'\u0282' t_sfx = gs.CLASS_PREFIXES.get('type', '') f_sfx = gs.CLASS_PREFIXES.get('func', '') params, ret = declex(tn) decl = [] for i, p in enumerate(params): n, t = p if t.startswith('...'): n = '...' decl.append('${%d:%s}' % (i + 1, n)) decl = ', '.join(decl) ret = ret.strip('() ') if is_func: if func_name_only: comps.append(( '%s\t%s %s' % (nm, ret, f_sfx), nm, )) else: comps.append(( '%s\t%s %s' % (nm, ret, f_sfx), '%s(%s)' % (nm, decl), )) else: comps.append(( '%s\t%s %s' % (nm, tn, t_sfx), nm, )) if autocomplete_closures: comps.append(( '%s {}\tfunc() {...} %s' % (nm, s_sfx), '%s {\n\t${0}\n}' % tn, )) elif cn != 'PANIC': comps.append(( '%s\t%s %s' % (nm, tn, self.typeclass_prefix(cn, tn)), nm, )) return comps
def on_query_completions(self, view, prefix, locations): pos = locations[0] scopes = view.scope_name(pos).split() if ('source.go' not in scopes) or (gs.setting('gscomplete_enabled', False) is not True): return [] if gs.IGNORED_SCOPES.intersection(scopes): return ([], AC_OPTS) types = [] for r in view.find_by_selector('source.go keyword.control.go'): if view.substr(r) == 'type': end = r.end() r = view.find(r'\s+(\w+)', end) if r.begin() == end: types.append(view.substr(r).lstrip()) try: default_pkgname = basename(dirname(view.file_name())) except Exception: default_pkgname = '' if not REASONABLE_PKGNAME_PAT.match(default_pkgname): default_pkgname = '' r = view.find('package\s+(\w+)', 0) ctx = { 'global': True, 'pkgname': view.substr(view.word(r.end())) if r else '', 'types': types or [''], 'has_types': len(types) > 0, 'default_pkgname': default_pkgname, 'fn': view.file_name() or '', } show_snippets = gs.setting('autocomplete_snippets', True) is True if not ctx.get('pkgname'): return (resolve_snippets(ctx), AC_OPTS) if show_snippets else ([], AC_OPTS) # gocode is case-sesitive so push the location back to the 'dot' so it gives # gives us everything then st2 can pick the matches for us offset = pos - len(prefix) src = view.substr(sublime.Region(0, view.size())) fn = view.file_name() or '<stdin>' if not src: return ([], AC_OPTS) nc = view.substr(sublime.Region(pos, pos + 1)) cl = self.complete(fn, offset, src, nc.isalpha() or nc == "(") pc = view.substr(sublime.Region(pos - 1, pos)) if show_snippets and (pc.isspace() or pc.isalpha()): if scopes[-1] == 'source.go': cl.extend(resolve_snippets(ctx)) elif scopes[-1] == 'meta.block.go' and ( 'meta.function.plain.go' in scopes or 'meta.function.receiver.go' in scopes): ctx['global'] = False ctx['local'] = True cl.extend(resolve_snippets(ctx)) return (cl, AC_OPTS)