def tag_name_completions(self): """ Create a completion list with all known tag names. It uses the keys of `self.tag_attributes` dictionary as it contains all known/supported tag names and is available/cached anyway. """ return sublime.CompletionList([ sublime.CompletionItem( trigger=tag, completion_format=sublime.COMPLETION_FORMAT_TEXT, kind=KIND_TAG_MARKUP, details=f'Expands to <code>{html.escape(tag)}</code>') for tag in self.tag_attributes ], sublime.INHIBIT_WORD_COMPLETIONS)
class SublimeTextCommandArgsCompletionPythonListener( sublime_plugin.EventListener): _default_args_dict = { c: sublime.CompletionItem( trigger="args", completion="{{{q}$1{q}: $0}}".format(q=c), completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=KIND_SNIPPET, ) for c in "'\"" } _RE_LINE_BEFORE = re.compile(r"\w+\s*\.\s*run_command\s*\(" r"\s*(['\"])(\w+)\1,\s*\w*$") def on_query_completions(self, view, prefix, locations): loc = locations[0] python_arg_scope = "source.python meta.function-call.arguments.python," if not view.score_selector(loc, python_arg_scope) or not is_plugin(view): return before_region = sublime.Region(view.line(loc).a, loc) before = view.substr(before_region) m = self._RE_LINE_BEFORE.search(before) if not m: return quote_char, command_name = m.groups() logger.debug("building args completions for command %r", command_name) command_args = get_args_from_command_name(command_name) if command_args is None: return self._default_args_dict[quote_char] completion = create_args_snippet_from_command_args(command_args, quote_char, for_json=False) return [ sublime.CompletionItem( trigger="args", annotation="auto-detected", completion=completion, completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=KIND_SNIPPET, ) ]
def as_completion(self, with_key=False): if with_key: # TODO doesn't escape json chars formatted_value = _escape_in_snippet( sublime.encode_value(self.value)) contents = '"{}": ${{0:{}}},'.format(self.name, formatted_value) completion_format = sublime.COMPLETION_FORMAT_SNIPPET else: contents = self.name completion_format = sublime.COMPLETION_FORMAT_TEXT return sublime.CompletionItem( trigger=self.name, annotation=self.source, completion=contents, completion_format=completion_format, kind=KIND_VARIABLE, )
def completion_item(self, item): details = "" if edn.Keyword("doc") in item: d = {} for k, v in item.items(): d[k.name] = v.name if isinstance(v, edn.Keyword) else v details = f"""<a href="{sublime.command_url("tutkain_show_popup", args={"item": d})}">More</a>""" return sublime.CompletionItem( item.get(edn.Keyword("candidate")), kind=completion_kinds().get( item.get(edn.Keyword("type")).name, sublime.KIND_AMBIGUOUS), annotation=" ".join(item.get(edn.Keyword("arglists"), [])), details=details, )
def extends_completions(self): resources = sublime.find_resources("*.sublime-theme") resources += sublime.find_resources("*.hidden-theme") names = {res.rsplit("/", 1)[-1] for res in resources} if self.view.file_name(): names -= {ResourcePath.from_file_path(self.view.file_name()).name} sorted_names = sorted(names) logger.debug("Found %d themes to complete: %r", len(names), sorted_names) return [ sublime.CompletionItem( trigger=name, completion=name, kind=KIND_THEME, ) for name in sorted_names ]
def expand_tag_attributes(self, view, locations): # Get the contents of each line, from the beginning of the line to # each point lines = [view.substr(sublime.Region(view.line(l).a, l)) for l in locations] # Reverse the contents of each line, to simulate having the regex # match backwards lines = [l[::-1] for l in lines] # Check the first location looks like an expression rex = re.compile(r"([\w-]+)([.#])(\w+)") expr = match(rex, lines[0]) if not expr: return [] # Ensure that all other lines have identical expressions for i in range(1, len(lines)): ex = match(rex, lines[i]) if ex != expr: return [] # Return the completions arg, op, tag = rex.match(expr).groups() arg = arg[::-1] tag = tag[::-1] expr = expr[::-1] if op == '.': snippet = '<{0} class=\"{1}\">$1</{0}>$0'.format(tag, arg) desc = '<{0} class="{1}">'.format(tag, arg) else: snippet = '<{0} id=\"{1}\">$1</{0}>$0'.format(tag, arg) desc = '<{0} id="{1}">'.format(tag, arg) return [sublime.CompletionItem( trigger=expr, completion=snippet, completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_MARKUP, 't', 'Tag'), details="Expands to <code>" + desc + "</code>" )]
def prepare_completion(self, view: sublime.View, this_dir: str, directory: str) -> sublime.CompletionItem: path = os.path.join(this_dir, directory) annotation = "" annotation_head = "" annotation_head_kind = sublime.KIND_ID_AMBIGUOUS details_head = "" details_parts = [] if os.path.isdir(path): annotation = "Dir" annotation_head = "📁" annotation_head_kind = sublime.KIND_ID_MARKUP details_head = "Directory" elif os.path.isfile(path): annotation = "File" annotation_head = "📄" annotation_head_kind = sublime.KIND_ID_MARKUP details_head = "File" details_parts.append("Size: " + naturalsize(os.stat(path).st_size)) if path.endswith((".gif", ".jpeg", ".jpg", ".png")): details_head = "Image" with io.open(path, "rb") as f: read_data = f.read() if path.endswith( (".jpeg", ".jpg")) else f.read(24) try: w, h = getimageinfo.getImageInfo(read_data) details_parts.append("Height: " + str(h)) details_parts.append("Width: " + str(w)) except Exception: pass return sublime.CompletionItem( trigger=directory.replace(".", "·"), annotation=annotation, completion=autofilename.apply_post_replacements(view, directory), kind=(annotation_head_kind, annotation_head, details_head), details=", ".join(details_parts), )
def complete_property_name(self, view, prefix, pt): suffix = ": $0;" text = view.substr(sublime.Region(pt, view.line(pt).end())) matches = self.re_value.search(text) if matches: colon, space, value, term = matches.groups() if colon: # don't append anything if the next character is a colon suffix = "" elif value: # only append colon if value already exists suffix = ":" if space else ": " elif term == ";": # ommit semicolon if rule is already terminated suffix = ": $0" return (sublime.CompletionItem( trigger=prop, completion=prop + suffix, completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=KIND_CSS_PROPERTY) for prop in self.props)
def parse_v4(item): """ Parses a gocode item and returns a sublime v4 completion. """ type = item['class'][0].capitalize() trigger = item['name'] kind = kindof(item['class']) completion = item['name'] annotation = item['type'] format = sublime.COMPLETION_FORMAT_TEXT if item['class'] == 'func': func = parse_func(item) completion = func['snip'] annotation = func['rets'] format = sublime.COMPLETION_FORMAT_SNIPPET return sublime.CompletionItem(trigger=trigger, annotation=annotation, completion=completion, completion_format=format, kind=(kind, type, ''))
def _plugin_completions(cmd_classes): for cmd_class in cmd_classes: name = get_command_name(cmd_class) module = cmd_class.__module__ package_name = module.split(".")[0] if issubclass(cmd_class, sublime_plugin.TextCommand): kind = KIND_TEXT elif issubclass(cmd_class, sublime_plugin.WindowCommand): kind = KIND_WINDOW elif issubclass(cmd_class, sublime_plugin.ApplicationCommand): kind = KIND_APPLICATION else: kind = KIND_COMMAND yield sublime.CompletionItem( trigger=name, annotation=package_name, completion=name, kind=kind, details=(cmd_class.__doc__ or "").strip(), # TODO link to show full description )
def complete_property_value(self, view, prefix, pt): completions = [] text = view.substr( sublime.Region(view.line(pt).begin(), pt - len(prefix))) matches = self.re_name.search(text) if matches: prop = matches.group(1) values = self.props.get(prop) if values: details = "<code>{prop}</code> property-value".format( prop=prop) if next_none_whitespace(view, pt) == ";": suffix = "" else: suffix = "$0;" for value in values: if isinstance(value, str): desc = self.re_trigger.sub(r"\1", value) snippet = value else: desc, snippet = value if "(" in snippet: kind = KIND_CSS_FUNCTION else: kind = KIND_CSS_CONSTANT completions.append( sublime.CompletionItem(trigger=desc, completion=snippet + suffix, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=kind, details=details)) return completions
def complete_property_value(self, view, prefix, pt): completions = [] text = view.substr( sublime.Region(view.line(pt).begin(), pt - len(prefix))) matches = self.re_name.search(text) if matches: prop = matches.group(1) values = self.props.get(prop) if values: details = f"<code>{prop}</code> property-value" if match_selector(view, pt, "meta.group"): # don't append semicolon in groups e.g.: `@media screen (prop: val)` suffix = "" elif next_none_whitespace(view, pt) == ";": suffix = "" else: suffix = "$0;" for value in values: if isinstance(value, list): desc, snippet = value kind = KIND_CSS_FUNCTION else: desc = value snippet = value kind = KIND_CSS_CONSTANT completions.append( sublime.CompletionItem(trigger=desc, completion=snippet + suffix, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=kind, details=details)) return completions
def add_drives(self) -> None: if sublime.platform() != "windows": return drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives() drive_list = list( itertools.compress(string.ascii_uppercase, map(lambda x: ord(x) - ord("0"), bin(drive_bitmask)[:1:-1])) ) # Overrides default auto completion # https://github.com/BoundInCode/AutoFileName/issues/18 for driver in drive_list: g_auto_completions.append( sublime.CompletionItem( trigger=f"{driver}:{self.sep}", annotation="Drive", completion=f"{driver}:{self.sep}", kind=(sublime.KIND_ID_MARKUP, "🖴", "Drive"), details="", ) ) if time.time() - self.start_time > MAXIMUM_WAIT_TIME: return
def on_query_completions(self, prefix, locations): view = self.view if view.syntax().name != 'Nextflow': return if len(locations) > 1: return point = locations[0] if not view.score_selector(point - 1, 'source.nextflow meta.definition.workflow.nextflow punctuation.accessor.dot.process-out.nextflow'): return out_word_region = view.word(point - 2) if view.substr(out_word_region) != 'out': return proc_name_region = view.word(out_word_region.a - 1) proc_name = view.substr(proc_name_region) if not proc_name: return folders = view.window().folders() if not folders: return root_dir = Path(folders[0]) emits = [] for path in root_dir.rglob('**/*.nf'): emits += get_output_channel_emits(path, proc_name) if not emits: return flags = sublime.INHIBIT_REORDER | sublime.INHIBIT_WORD_COMPLETIONS completions = sublime.CompletionList( completions=[ sublime.CompletionItem( trigger=emit, annotation=chan, ) for emit, chan in emits ], flags=flags ) return completions
def on_query_completions(self, view, prefix, locations): self._state["location"] = locations[0] self._state["prefix"] = prefix before, region_includes_beginning = get_before(view, AUTOCOMPLETE_CHAR_LIMIT) after, region_includes_end = get_after(view, AUTOCOMPLETE_CHAR_LIMIT) response = autocomplete( before, after, view.file_name(), region_includes_beginning, region_includes_end, ) self._state["completions"] = response["results"] completions = [ sublime.CompletionItem( r.get("new_prefix"), annotation="tabnine", completion="{}$0{}".format( escape_tab_stop_sign(r.get("new_prefix")), r.get("new_suffix", "") ), completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=( sublime.KIND_ID_COLOR_PURPLISH, ATTRIBUTION_ELEMENT, r.get("detail", ""), ), ) for r in self._state["completions"] ] return sublime.CompletionList( completions=completions, flags=sublime.DYNAMIC_COMPLETIONS | sublime.INHIBIT_REORDER, )
def format_item(trigger, kind, details): if kind in (KIND_HEADER_DICT, KIND_CAPTURUE, KIND_CONTEXT): completion_format = sublime.COMPLETION_FORMAT_SNIPPET suffix = ":\n " elif kind is KIND_HEADER_LIST: completion_format = sublime.COMPLETION_FORMAT_SNIPPET suffix = ":\n - " elif kind is KIND_FUNCTION_TRUE: completion_format = sublime.COMPLETION_FORMAT_SNIPPET suffix = ": ${1:true}" elif kind is KIND_FUNCTION_FALSE: completion_format = sublime.COMPLETION_FORMAT_SNIPPET suffix = ": ${1:false}" else: completion_format = sublime.COMPLETION_FORMAT_TEXT suffix = ": " return sublime.CompletionItem( trigger=trigger, kind=kind, details=details, completion=trigger + suffix, completion_format=completion_format, )
def on_query_completions(self, view, prefix, locations): # match inside a CSS document and # match inside the style attribute of HTML tags, incl. just before the quote that closes the attribute value css_selector_scope = "source.css - meta.selector.css" html_style_attr_selector_scope = "text.html meta.attribute-with-value.style.html " + \ "string.quoted - punctuation.definition.string.begin.html" selector_scope = css_selector_scope + ', ' + html_style_attr_selector_scope prop_name_scope = "meta.property-name.css" prop_value_scope = "meta.property-value.css" loc = locations[0] # When not inside CSS, don’t trigger if not view.match_selector(loc, selector_scope): # if the text immediately after the caret is a HTML style tag beginning, and the character before the # caret matches the CSS scope, then probably the user is typing here (where | represents the caret): # <style type="text/css">.test { f|</style> # i.e. after a "style" HTML open tag and immediately before the closing tag. # so we want to offer CSS completions here. if view.match_selector(loc, 'text.html meta.tag.style.end punctuation.definition.tag.begin.html') and \ view.match_selector(loc - 1, selector_scope): pass else: return [] if not self.props: self.props = parse_css_data() self.regex = re.compile(r"([a-zA-Z-]+):\s*$") l = [] if (view.match_selector(loc, prop_value_scope) or # This will catch scenarios like: # - .foo {font-style: |} # - <style type="text/css">.foo { font-weight: b|</style> view.match_selector(loc - 1, prop_value_scope)): alt_loc = loc - len(prefix) line = view.substr( sublime.Region(view.line(alt_loc).begin(), alt_loc)) match = re.search(self.regex, line) if match: prop_name = match.group(1) if prop_name in self.props: values = self.props[prop_name] add_semi_colon = view.substr(sublime.Region( loc, loc + 1)) != ';' for value in values: if isinstance(value, str): # Removes snippet placeholders - only practically # works for a single placeholder desc = re.sub(r'\$(?:\d+|\{\d+:[^}]*\})', '', value) snippet = value else: desc = value[0] snippet = value[1] if add_semi_colon: snippet += ";" kind = [sublime.KIND_ID_VARIABLE, "c", "Constant"] if "(" in snippet: kind = [sublime.KIND_ID_FUNCTION, "f", "Function"] l.append( sublime.CompletionItem(trigger=desc, completion=snippet, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=kind, details="<code>" + prop_name + "</code> property value")) return (l, sublime.INHIBIT_WORD_COMPLETIONS) return None else: add_colon = not view.match_selector(loc, prop_name_scope) for prop in self.props: l.append( sublime.CompletionItem( trigger=prop, completion=prop + ": " if add_colon else prop, kind=[sublime.KIND_ID_KEYWORD, "p", "Property"])) return (l, sublime.INHIBIT_WORD_COMPLETIONS)
def on_query_completions(self, view, prefix, locations): # only suggest completions based on the first cursor loc = locations[0] if not view.match_selector(loc, 'source.lsl'): return None from .keyword_data_loader import LSL_KEYWORD_DATA if LSL_KEYWORD_DATA is None: return None completions = [] flags = 0 # we don't modify flags # FIXME: fix using data with new structure for word, result in LSL_KEYWORD_DATA.items(): if not word.startswith(prefix): continue # events if view.match_selector( loc, 'meta.class.state.body.lsl - meta.block.event.lsl, -string.quoted.double.lsl' ): if result.get('scope', None) == 'support.function.event': if 'params' in result: c = '{}({}){}'.format( word, ', '.join('{} ${{{}:{}}}'.format( param['type'], idx, param['name']) for idx, param in enumerate( result['params'], 1)), r'${LSL_WHITESPACE_BEFORE}{${LSL_WHITESPACE_INSIDE_FIRST}$0${LSL_WHITESPACE_INSIDE_LAST}}' ) else: c = '{}(){}'.format( word, r'${LSL_WHITESPACE_BEFORE}{${LSL_WHITESPACE_INSIDE_FIRST}$0${LSL_WHITESPACE_INSIDE_LAST}}' ) if fuzzy_match(prefix, word)[0]: completions.append( sublime.CompletionItem( trigger=word, annotation='event', completion=c, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[ sublime.KIND_ID_NAVIGATION, 'e', 'Event' ], details='')) # functions if view.match_selector( loc, 'meta.function.declaration.body.lsl, meta.block.event.lsl, meta.parameters.lsl, -string.quoted.double.lsl' ): if result['scope'].startswith('support.function.builtin'): if 'params' in result: c = '{}({})'.format( word, ', '.join('${{{}:{} {}}}'.format( idx, param['type'], param['name']) for idx, param in enumerate( result['params'], 1))) else: c = '{}()'.format(word) if 'type' not in result: c += r';${LSL_WHITESPACE_AFTER}$0' if fuzzy_match(prefix, word)[0]: completions.append( sublime.CompletionItem( trigger=word, annotation='({}) function'.format( result.get('type', 'void')), completion=c, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[ sublime.KIND_ID_FUNCTION, 'f', 'Function' ], details='')) # constants if view.match_selector( loc, 'source.lsl - meta.class.state.body.lsl, meta.function.declaration.body.lsl, meta.block.event.lsl, meta.parameters.lsl, -string.quoted.double.lsl' ): if result['scope'].startswith('constant.language.'): if fuzzy_match(prefix, word)[0]: completions.append( sublime.CompletionItem( trigger=word, annotation='{} ({})'.format( result['type'], result['value']), completion=word, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[ sublime.KIND_ID_VARIABLE, 'c', 'Constant' ], details='')) if 'params' in result: c = '{}, {}{}'.format( word, ', '.join('${{{}:{} {}}}'.format( idx, param['type'], param['name']) for idx, param in enumerate( result['params'], 1)), r', ${LSL_WHITESPACE_AFTER}$0') if fuzzy_match(prefix, word)[0]: completions.append( sublime.CompletionItem( trigger=word, annotation='{}, …'.format(', '.join( '{} {}'.format(param['type'], param['name']) for param in result['params'])), completion=c, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[ sublime.KIND_ID_VARIABLE, 'c', 'Constant' ], details='')) # types if view.match_selector( loc, 'source.lsl - meta.class.state.body, meta.function.declaration.body.lsl, meta.block.event.lsl, meta.parameters.lsl, -string.quoted.double.lsl' ): if result.get('scope', None) == 'storage.type': if fuzzy_match(prefix, word)[0]: completions.append( sublime.CompletionItem( trigger=word, annotation='storage type', completion=word, completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_TYPE, 't', 'Type'], details='')) completions.append( sublime.CompletionItem( trigger=word, annotation='{} x = value;'.format(word), completion='{} {}'.format( word, r'${1:x} = ${2:value};${LSL_WHITESPACE_AFTER}$0' ), completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_TYPE, 't', 'Type'], details='')) # completions for `keyword.control.*` moved to `./.sublime/completions/lsl_keyword_control.sublime-completions` # log functions if view.match_selector( loc, 'meta.function.declaration.body.lsl, meta.block.event.lsl, -string.quoted.double.lsl' ): if result.get('scope', None) == 'reserved.log': completions.append( sublime.CompletionItem( trigger='print', annotation='(float f)', completion= 'print(${1:float f});${LSL_WHITESPACE_AFTER}$0', completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_FUNCTION, 'f', 'Function'], details="Don't spam LindenLab!")) completions.append( sublime.CompletionItem( trigger='print', annotation='(integer i)', completion= 'print(${1:integer i});${LSL_WHITESPACE_AFTER}$0', completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_FUNCTION, 'f', 'Function'], details="Don't spam LindenLab!")) completions.append( sublime.CompletionItem( trigger='print', annotation='(key k)', completion= 'print(${1:key k});${LSL_WHITESPACE_AFTER}$0', completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_FUNCTION, 'f', 'Function'], details="Don't spam LindenLab!")) completions.append( sublime.CompletionItem( trigger='print', annotation='(list l)', completion= 'print(${1:list l});${LSL_WHITESPACE_AFTER}$0', completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_FUNCTION, 'f', 'Function'], details="Don't spam LindenLab!")) completions.append( sublime.CompletionItem( trigger='print', annotation='(rotation r)', completion= 'print(${1:rotation r});${LSL_WHITESPACE_AFTER}$0', completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_FUNCTION, 'f', 'Function'], details="Don't spam LindenLab!")) completions.append( sublime.CompletionItem( trigger='print', annotation='(string s)', completion= 'print(${1:string s});${LSL_WHITESPACE_AFTER}$0', completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_FUNCTION, 'f', 'Function'], details="Don't spam LindenLab!")) completions.append( sublime.CompletionItem( trigger='print', annotation='(vector v)', completion= 'print(${1:vector v});${LSL_WHITESPACE_AFTER}$0', completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=[sublime.KIND_ID_FUNCTION, 'f', 'Function'], details="Don't spam LindenLab!")) # TODO: sort with itemgetter as that is faster # FIXME: fix sorting with CompletionItem # completions.sort(key=lambda completion: fuzzy_match(prefix, completion[0])[1], reverse=True) if completions: return (completions, flags) return None
def on_query_completions(self, prefix, locations): global last_view_id global cached_symbols global cached_references completions = sublime.CompletionList() # views is an array of view-s not including self.view views = self.sort_views_by_relevance() symbols = [] current_view_symbols = find_symbols(self.view) if last_view_id != self.view.id(): cached_symbols = find_symbols(self.view, views) symbols.extend(current_view_symbols) symbols.extend(cached_symbols) self.items = [] # easy way to filter out hash completions unique_symbols = [] for symbol_location in symbols: _file_name, base_file_name, _region, symbol, symbol_type = symbol_location completion_item = sublime.CompletionItem( symbol, annotation=base_file_name, completion=symbol, kind=(sublime.KIND_ID_AMBIGUOUS, symbol_type, '') ) if symbol not in unique_symbols: unique_symbols.append(symbol) self.items.append(completion_item) references = [] current_view_references = find_references(self.view) if last_view_id != self.view.id(): cached_references = find_references(self.view, views) references.extend(current_view_references) references.extend(cached_references) for symbol_location in references: _file_name, base_file_name, _region, symbol, symbol_type = symbol_location completion_item = sublime.CompletionItem( symbol, annotation=base_file_name, completion=symbol, kind=(sublime.KIND_ID_AMBIGUOUS, symbol_type, '') ) if symbol not in unique_symbols: unique_symbols.append(symbol) self.items.append(completion_item) completions.set_completions(self.items) last_view_id = self.view.id() return completions
def completion_item(self, item): return sublime.CompletionItem( item.get("candidate"), kind=completion_kinds().get(item.get("type"), sublime.KIND_AMBIGUOUS), )
def ensure_completions_cached(pfile, view): pos = view.sel()[0].b if pfile.cached_completions is not None: c_start, c_word, c_completions = pfile.cached_completions if c_start <= pos: slice = view.substr(sublime.Region(c_start, pos)) if slice.startswith(c_word) and not re.match(".*\\W", slice): return (c_completions, False) data = run_command(view, {"type": "completions", "types": True, "includeKeywords": True}, silent=True) if data is None: return (None, False) # print(data) completions = [] completions_arity = [] for rec in data["completions"]: rec_name = rec.get('name').replace('$', '\\$') rec_type = rec.get("type", None) if arg_completion_enabled and rec_type is not None and rec_type.startswith("fn("): retval = parse_function_type(rec).get('retval') if retval is None or retval == "()": retval = "" elif retval.startswith("{"): retval = "{}" elif retval.startswith("["): retval = "[]" if retval != "": # retval = " -> " + retval retval = " ➜ " + retval arguments = get_arguments(rec_type) fn_name = rec_name + "(" + create_arg_str(arguments) + ")" if not is_st4: completions.append((rec.get("name") + fn_completion_icon(arguments, retval), fn_name)) else: completions.append(sublime.CompletionItem( (rec.get("name") + fn_completion_icon(arguments, retval)), annotation='fn', completion=fn_name, completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=sublime.KIND_FUNCTION )) else: rec_name = removeQuotes(rec_name); if not is_st4: completions.append((rec.get("name") + "\t" + completion_icon(rec_type), rec_name)) else: completions.append(sublime.CompletionItem( rec.get("name"), annotation=completion_icon(rec_type), completion=rec_name, kind=sublime.KIND_VARIABLE )) # put the auto completions of functions with lower arity at the bottom of the autocomplete list # so they don't clog up the autocompeltions at the top of the list completions = completions + completions_arity pfile.cached_completions = (data["start"], view.substr(sublime.Region(data["start"], pos)), completions) return (completions, True)
def to_completion(self): return [ sublime.CompletionItem(n.name, annotation="convention", kind=SCOPE_KIND) for n in sorted(self) ]
def load_completions(): global completions, function_names, cgi completions_data = { filename: load_json_data(filename) for filename in COMPLETION_FILES } # tags completions["cfml_tags"] = [] completions["cfml_tags_in_script"] = [] completions["cfml_cf_tags_in_script"] = [] completions["cfml_tag_attributes"] = {} completions["cfml_tag_attribute_values"] = {} for tag_name in sorted(completions_data["cfml_tags"].keys()): if isinstance(completions_data["cfml_tags"][tag_name], list): completions_data["cfml_tags"][tag_name] = { "attributes": completions_data["cfml_tags"][tag_name], "attribute_values": {}, } tag_attributes = completions_data["cfml_tags"][tag_name]["attributes"] completions["cfml_tags"].append( make_tag_completion(tag_name, tag_attributes[0])) completions["cfml_tags_in_script"].append( make_tag_completion(tag_name[2:], tag_attributes[0])) completions["cfml_cf_tags_in_script"].append( make_cf_script_tag_completion(tag_name, tag_attributes[0])) completions["cfml_tag_attributes"][tag_name] = [ sublime.CompletionItem( a, "required", a + '="$1"', sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_MARKUP, "a", tag_name), ) for a in tag_attributes[0] ] completions["cfml_tag_attributes"][tag_name].extend([ sublime.CompletionItem( a, "optional", a + '="$1"', sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_MARKUP, "a", tag_name), ) for a in tag_attributes[1] ]) # attribute values tag_attribute_values = completions_data["cfml_tags"][tag_name][ "attribute_values"] completions["cfml_tag_attribute_values"][tag_name] = {} for attribute_name in sorted(tag_attribute_values.keys()): completions["cfml_tag_attribute_values"][tag_name][ attribute_name] = [ sublime.CompletionItem( v, attribute_name, v, sublime.COMPLETION_FORMAT_TEXT, kind=(sublime.KIND_ID_AMBIGUOUS, "v", tag_name), ) for v in tag_attribute_values[attribute_name] ] # functions completions["cfml_functions"] = {"basic": [], "required": [], "full": []} function_names = [] for funct in sorted(completions_data["cfml_functions"].keys()): completions["cfml_functions"]["basic"].append( sublime.CompletionItem( funct, "cfml.fn", funct + "($0)", sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_FUNCTION, "f", "function"), details=completions_data["cfml_functions"][funct][0], )) completions["cfml_functions"]["required"].append( sublime.CompletionItem( funct, "cfml.fn", funct + completions_data["cfml_functions"][funct][1][0], sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_FUNCTION, "f", "function"), details=completions_data["cfml_functions"][funct][0], )) completions["cfml_functions"]["full"].append( sublime.CompletionItem( funct, "cfml.fn", funct + completions_data["cfml_functions"][funct][1][1], sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_FUNCTION, "f", "function"), details=completions_data["cfml_functions"][funct][0], )) function_names.append(funct) # function params completions["cfml_function_params"] = {} for funct in sorted(completions_data["cfml_function_params"].keys()): completions["cfml_function_params"][funct] = {} for param in sorted( completions_data["cfml_function_params"][funct].keys()): completions["cfml_function_params"][funct][param] = [] for value in completions_data["cfml_function_params"][funct][ param]: completions["cfml_function_params"][funct][param].append( sublime.CompletionItem( value, param, value, kind=(sublime.KIND_ID_AMBIGUOUS, "p", funct), )) # member functions completions["cfml_member_functions"] = { "basic": [], "required": [], "full": [] } for member_function_type in sorted( completions_data["cfml_member_functions"].keys()): for funct in sorted(completions_data["cfml_member_functions"] [member_function_type].keys()): completions["cfml_member_functions"]["basic"].append( sublime.CompletionItem( funct, member_function_type + ".fn", funct + "($0)", sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_FUNCTION, "m", "method"), details=completions_data["cfml_member_functions"] [member_function_type][funct][0], )) completions["cfml_member_functions"]["required"].append( sublime.CompletionItem( funct, member_function_type + ".fn", funct + completions_data["cfml_member_functions"] [member_function_type][funct][1][0], sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_FUNCTION, "m", "method"), details=completions_data["cfml_member_functions"] [member_function_type][funct][0], )) completions["cfml_member_functions"]["full"].append( sublime.CompletionItem( funct, member_function_type + ".fn", funct + completions_data["cfml_member_functions"] [member_function_type][funct][1][1], sublime.COMPLETION_FORMAT_SNIPPET, kind=(sublime.KIND_ID_FUNCTION, "m", "method"), details=completions_data["cfml_member_functions"] [member_function_type][funct][0], )) # CGI scope cgi = load_json_data("cgi") completions["cgi"] = [ sublime.CompletionItem( scope_variable.split(".").pop().upper(), "CGI Scope", kind=(sublime.KIND_ID_VARIABLE, "c", "CFML"), ) for scope_variable in sorted(cgi.keys()) ]
def build_value_completion(self, value): return sublime.CompletionItem(value, completion=value, annotation="Value", kind=sublime.KIND_KEYWORD)
}, "rules": [ { // "scope": "string", // "foreground": "#00FF00", }, ], }""".replace(" ", "\t") KIND_SCHEME = (sublime.KIND_ID_VARIABLE, "s", "Scheme") KIND_VARIABLE = (sublime.KIND_ID_VARIABLE, 'v', 'Variable') BUILTIN_VARIABLES = [ sublime.CompletionItem( trigger=var, annotation="built-in", completion=var, kind=KIND_VARIABLE, ) for var in ( "--background", "--foreground", "--accent", "--bluish", "--cyanish", "--greenish", "--orangish", "--pinkish", "--purplish", "--redish", "--yellowish", ) ]
def get_tag_completions(inside_tag=True): """ Generate a default completion list for HTML """ normal_tags = ('abbr', 'acronym', 'address', 'applet', 'article', 'aside', 'audio', 'b', 'basefont', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'button', 'center', 'canvas', 'caption', 'cdata', 'cite', 'colgroup', 'code', 'content', 'data', 'datalist', 'dialog', 'dir', 'div', 'dd', 'del', 'details', 'dfn', 'dl', 'dt', 'element', 'em', 'embed', 'fieldset', 'figure', 'figcaption', 'font', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'i', 'ins', 'isindex', 'kbd', 'keygen', 'li', 'label', 'legend', 'main', 'map', 'mark', 'meter', 'nav', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'span', 'strong', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'tt', 'u', 'ul', 'var', 'video') snippet_tags = (('a', 'a href=\"$1\">$0</a>'), ('area', 'area shape=\"$1\" coords=\"$2\" href=\"$3\">'), ('audio', 'audio src=\"$1\">$0</audio>'), ('base', 'base href=\"$1\">'), ('br', 'br>'), ('col', 'col>'), ('hr', 'hr>'), ('iframe', 'iframe src=\"$1\">$0</iframe>'), ('input', 'input type=\"$1\" name=\"$2\">'), ('img', 'img src=\"$1\">'), ('link', 'link rel=\"stylesheet\" type=\"text/css\" href=\"$1\">'), ('meta', 'meta ${1:charset=\"utf-8\"}>'), ('param', 'param name=\"$1\" value=\"$2\">'), ('progress', 'progress value=\"$1\" max=\"$2\">'), ('script', 'script${2: type=\"${1:text/javascript}\"}>$0</script>'), ('slot', 'slot name=name=\"$1\">$0</slot>'), ('source', 'source src=\"$1\" type=\"$2\">'), ('style', 'style type=\"${1:text/css}\">$0</style>'), ('track', 'track kind=\"$1\" src=\"$2\">'), ('wbr', 'wbr>'), ('video', 'video src=\"$1\">$0</video>')) tag_begin = '' if inside_tag else '<' return sublime.CompletionList([ *(sublime.CompletionItem( trigger=tag, completion=f'{tag_begin}{tag}>$0</{tag}>', completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=KIND_TAG_MARKUP, details=f'Expands to <code><{tag}>$0</{tag}></code>') for tag in normal_tags), *(sublime.CompletionItem( trigger=tag, completion=f'{tag_begin}{completion}', completion_format=sublime.COMPLETION_FORMAT_SNIPPET, kind=KIND_TAG_MARKUP, details=f'Expands to <code><{html.escape(completion)}</code>') for tag, completion in snippet_tags) ], sublime.INHIBIT_WORD_COMPLETIONS)
def parse_script(self, file_path: str, file_data: str = None) -> None: if file_data is None: file_data = open(file_path, encoding="utf-8", errors="ignore").read() file_mtime = os.path.getmtime(file_path) else: file_mtime = time.time() compl = SymbolCompletions() compl.file = file_path compl.mtime = file_mtime compl.dependencies = self.rgx_include.findall(file_data) compl.completions = [] compl.documentation = [] compl.symbol_list = {} has_main = False resref = self.get_resref(file_path) custom_mark = "⋄" if resref != "nwscript" else "" # Function completion for (fun_doc, fun_type, fun_name, fun_args) in self.rgx_fun.findall(file_data): if fun_name in ("main", "StartingConditional"): has_main = True else: if fun_name not in compl.symbol_list: # Register new symbol # Parse function arguments args = [] args_comp_list = [] i = 0 if fun_args != "" and not fun_args.isspace(): for (arg_type, arg_name, arg_value) in self.rgx_fun_arg.findall(fun_args): default = "" if arg_value != "" and not arg_value.isspace(): default += "=" + arg_value else: arg_value = None args.append((arg_type, arg_name, arg_value)) args_comp_list.append( "${%d:%s %s}" % (i + 1, arg_type, arg_name + default)) i += 1 # Add completion compl.symbol_list[fun_name] = len(compl.completions) if self.st4: compl.completions.append( sublime.CompletionItem( trigger=fun_name, annotation=custom_mark + fun_type, completion="%s(%s)" % (fun_name, ", ".join(args_comp_list)), completion_format=sublime. COMPLETION_FORMAT_SNIPPET, kind=sublime.KIND_FUNCTION, details="Defined in " + resref)) else: compl.completions.append([ "%s\t%s%s()" % (fun_name, custom_mark, fun_type), "%s(%s)" % (fun_name, ", ".join(args_comp_list)) ]) doc = Documentation() doc.signature = ("f", fun_type, fun_name, args) doc.script_resref = resref doc.fix = self.settings.get("doc_fixes").get( resref, {}).get(fun_name, None) if doc.fix is None: doc.fix = get_doc_fix(resref, fun_name) doc.text = self.remove_comments(fun_doc) compl.documentation.append(doc) else: # Set documentation if none existing_index = compl.symbol_list[fun_name] existing_doc = compl.documentation[existing_index] if existing_doc.text is None: existing_doc.text = self.remove_comments(fun_doc) # const completions glob_rgx = self.rgx_global_nwscript if resref == "nwscript" else self.rgx_global_const for (glob_type, glob_name, glob_value, glob_doc) in glob_rgx.findall(file_data): compl.symbol_list[glob_name] = len(compl.completions) if self.st4: compl.completions.append( sublime.CompletionItem( trigger=glob_name, annotation=custom_mark + glob_type + "=" + glob_value, completion=glob_name, completion_format=sublime.COMPLETION_FORMAT_TEXT, kind=(sublime.KIND_ID_VARIABLE, "c", "Constant"), details="Defined in " + resref)) else: compl.completions.append([ "%s\t%s%s=%s" % (glob_name, custom_mark, glob_type, glob_value), glob_name ]) doc = Documentation() doc.signature = ("c", glob_type, glob_name, glob_value) doc.script_resref = resref doc.text = (glob_doc if glob_doc != "" and not glob_doc.isspace() else None) compl.documentation.append(doc) # #define completions for (def_doc, def_name, def_value) in self.rgx_define.findall(file_data): compl.symbol_list[def_name] = len(compl.completions) if self.st4: compl.completions.append( sublime.CompletionItem( trigger=def_name, annotation=custom_mark + def_value, completion=def_name, completion_format=sublime.COMPLETION_FORMAT_TEXT, kind=(sublime.KIND_ID_VARIABLE, "d", "Define"), details="Defined in " + resref)) else: compl.completions.append([ "%s\t%s%s" % (def_name, custom_mark, def_value), def_name ]) doc = Documentation() doc.signature = ("d", def_name, def_value) doc.script_resref = resref doc.text = ("\n".join([line[2:] for line in def_doc.splitlines()]) if def_doc != "" and not def_doc.isspace() else None) compl.documentation.append(doc) # struct completions for (struct_doc, struct_name) in self.rgx_struct.findall(file_data): if self.st4: compl.completions.append( sublime.CompletionItem( trigger=struct_name, annotation=custom_mark + "struct", completion=struct_name, completion_format=sublime.COMPLETION_FORMAT_TEXT, kind=sublime.KIND_TYPE, details="Defined in " + resref)) else: compl.structs_completions.append( ["%s\t%sstruct" % (struct_name, custom_mark), struct_name]) doc = Documentation() doc.signature = ("s", struct_name) doc.script_resref = resref doc.text = self.remove_comments(struct_doc) compl.structs_doc[struct_name] = doc # update include completions if self.include_completions is not None: file_dir = os.path.dirname(file_path) if file_dir in self.include_completions: if has_main: self.include_completions[file_dir].discard(resref) else: self.include_completions[file_dir].add(resref) self.symbol_completions[resref] = compl return (resref, compl)