def on_query_context(self, key, _operator, operand, _match_all): global MAX_LEN global PREVIOUS_INDEX if key != "side.signature_help": PREVIOUS_INDEX = 0 return False # Let someone else handle this key binding. if self.view.is_popup_visible(): # We use the "operand" for the number -1 or +1. See the key bindings. if PREVIOUS_INDEX is None: PREVIOUS_INDEX = 0 # if enter is pressed if operand == 0: point = self.view.sel()[0].begin() # user types a function name # user types a ( # a signature help is automatically shown on ( # a user press enter # user expect the cursor to bellow one line # actual behavior # the user is navigated to the function definition # so handle that case last_char = self.view.substr(point - 1) if last_char == '(': return False word = get_function_name(self.view, point) locations = definition(word, self.view) location = locations[PREVIOUS_INDEX] # sublime crashes if window.focus_view is called # setting a timeout, fixes is # I don't know why this is the case def fix_window_focus_view_crash(): open_view(location, self.view) self.view.hide_popup() sublime.set_timeout(fix_window_focus_view_crash, 0) return True # else up or down is pressed new_index = PREVIOUS_INDEX + operand # # clamp signature index new_index = max(0, min(new_index, MAX_LEN - 1)) # # only update when changed if new_index != PREVIOUS_INDEX or (PREVIOUS_INDEX == 0 and operand == 1 and MAX_LEN != 1): self.view.run_command('side_show_signature', {'index': new_index}) PREVIOUS_INDEX = new_index return True # We handled this key binding. else: return False
def show_signature_help(self, point, word): locations = definition(word, self.view) self.view.run_command('side_show_signature', { 'locations': locations, 'point': point })
def run(self, edit): """ index - if specified goto that index location. """ window = sublime.active_window() point = self.view.sel()[0].begin() word = get_word(self.view, point) locations = definition(word, self.view) if len(locations) == 0: symbols = find_symbols(self.view) word_regions = self.view.find_all(r"\b{}\b".format(word)) between_symbols_region = get_region_between_symbols(point, symbols, self.view) words_between_regions = filter_regions_by_region(word_regions, between_symbols_region) scope_name = self.view.scope_name(point) words_between_regions = filter_regions_by_scope_name(words_between_regions, scope_name, self.view) # make sure that there is at least one item in list if len(words_between_regions) < 1: return definition_point = words_between_regions[0].begin() file_name = self.view.file_name() row, col = self.view.rowcol(definition_point) row += 1 col += 1 location = (file_name, None, (row, col)) open_view(location, self.view) return if len(locations) == 1: open_view(locations[0], self.view) return if len(locations) > 1: chose_one_location_from_many(locations, self.view)
def handle_hover(self, point, is_class=False): word = get_word(self.view, point) locations = definition(word, self.view) self.view.run_command('side_show_signature', { 'locations': locations, 'point': point })
def on_load(self): global panel_state window = sublime.active_window() debug('on_load', self.view.id()) # select all unique references references = self.view.indexed_references() words = list(set(map(lambda x: x[1], references))) files_to_index = set() for word in words: definitions = definition(word, self.view) if len(definitions) == 1: # add the absolute file name absolute_file_path = definitions[0][0] if not window.find_open_file(absolute_file_path): debug('added [ {} ] files_to_index because of symbol {}'.format(absolute_file_path, word)) files_to_index.add(absolute_file_path) # indexing for absolute_file_path in files_to_index: panel_name = absolute_file_path with open(absolute_file_path) as file: panel = window.find_output_panel(panel_name) # if it is indexed continue if panel: # keep track of it debug("[ {} ] panel already exist".format(panel_name)) panel_state[panel_name].add(self.view.id()) debug('panel_state when panel exist', panel_state) continue # else index it content = file.read() debug('read file') # trigger index command self.view.run_command('side_index_file', { 'content': content, 'panel_name': panel_name }) # keep track of it if not panel_state.get(panel_name): debug('create state for [ {} ]'.format(panel_name)) panel_state[panel_name] = set() panel_state[panel_name].add(self.view.id()) debug('panel_state after creating state', panel_state)
def handle_selection_modified(self): global phantom_sets_by_buffer buffer_id = self.view.buffer_id() phantom_set = phantom_sets_by_buffer.get(buffer_id) if not phantom_set: phantom_set = sublime.PhantomSet(self.view, 'references_phantom') phantom_sets_by_buffer[buffer_id] = phantom_set point = self.view.sel()[0].begin() word_region = self.view.word(point) word = self.view.substr(word_region) scope_name = self.view.scope_name(word_region.begin()) phantoms = [] if is_function(scope_name) or is_class(scope_name): text = [] reference_count = len(reference(word, self.view)) if reference_count == 1: text.append("{} reference".format(reference_count)) else: text.append("{} references".format(reference_count)) definition_count = len(definition(word, self.view)) if definition_count == 1: text.append("{} definition".format(definition_count)) else: text.append("{} definitions".format(definition_count)) content = """ <body id="side-references" style="color: color(var(--foreground) alpha(0.4))"> <small style="margin:0;padding:0;">{}</small> </body> """.format(" | ".join(text)) phantoms.append(sublime.Phantom(word_region, content, sublime.LAYOUT_BELOW)) phantom_set.update(phantoms) else: # outside of function word phantom_sets_by_buffer.pop(buffer_id, None)
def run(self, edit, locations=None, point=None, index=None): """ index - when specified show the current location. """ global MAX_LEN global PREVIOUS_INDEX # restart the counter of signature help to 0 PREVIOUS_INDEX = 0 if point is None: point = self.view.sel()[0].begin() word = None if locations is None: word = get_function_name(self.view, point) locations = definition(word, self.view) if len(locations) == 0: return MAX_LEN = len(locations) # display the reference count if len(locations) > 1 and index is None: self.view.run_command('side_show_signature', { 'locations': locations, 'point': point, 'index': 0 }) return location = None if index: location = locations[index] else: location = locations[0] file_path, relative_file_path, row_col = location row, _col = row_col # signature row function_line = get_line(self.view, file_path, row).strip() signature, row = self.get_signature(function_line, file_path, row) # prettify signature signature = signature.strip('{').strip(':') docs = self.get_docs(file_path, row_col) if docs: docs = """ <div style="padding: 7px; border-top: 1px solid color(var(--foreground) alpha(0.1))"> {} </div>""".format(docs) # prettify file origin if len(relative_file_path) > 70: relative_file_path = '...' + relative_file_path[-50:] if len(locations) == 1: range_count = '' else: current_index = 1 if index is None else index + 1 range_count = "[{}-{}]".format(current_index, len(locations)) origin = """ <div style="padding: 7px; border-top: 1px solid color(var(--foreground) alpha(0.1)); color: color(var(--foreground) alpha(0.7))"> {} {} </div>""".format(range_count, relative_file_path) content = """ <body id="side-hover" style="margin:0"> <div style="color: var(--orangish); padding: 7px;"> {} </div> {} {} </body>""".format(escape(signature, False), origin, docs) if index is not None: self.view.update_popup(content) self._show_popup(content, point) # end of command execution # perfect place to clear the linecache linecache.clearcache()