Last active
June 28, 2016 14:24
-
-
Save bizoo/e733c06a0491a11566541785b7ce4a49 to your computer and use it in GitHub Desktop.
Modified ST3 symbol.py to propose active file items first and and an other item than the current one by default
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sublime | |
import sublime_plugin | |
import os.path | |
def lookup_symbol(window, symbol): | |
if len(symbol.strip()) < 3: | |
return [] | |
index_locations = window.lookup_symbol_in_index(symbol) | |
open_file_locations = window.lookup_symbol_in_open_files(symbol) | |
def file_in_location_list(fname, locations): | |
for l in locations: | |
if l[0] == fname: | |
return True | |
return False | |
# Combine the two lists, overriding results in the index with results | |
# from open files, while trying to preserve the order of the files in | |
# the index. | |
locations = [] | |
ofl_ignore = [] | |
for l in index_locations: | |
if file_in_location_list(l[0], open_file_locations): | |
if not file_in_location_list(l[0], ofl_ignore): | |
for ofl in open_file_locations: | |
if l[0] == ofl[0]: | |
locations.append(ofl) | |
ofl_ignore.append(ofl) | |
else: | |
locations.append(l) | |
for ofl in open_file_locations: | |
if not file_in_location_list(ofl[0], ofl_ignore): | |
locations.append(ofl) | |
return locations | |
def symbol_at_point(view, pt): | |
symbol = view.substr(view.expand_by_class(pt, sublime.CLASS_WORD_START | sublime.CLASS_WORD_END, "[]{}()<>:.")) | |
locations = lookup_symbol(view.window(), symbol) | |
if len(locations) == 0: | |
symbol = view.substr(view.word(pt)) | |
locations = lookup_symbol(view.window(), symbol) | |
# Put current file in the top of the list | |
locations.sort(key=lambda x: x[0] != view.file_name()) | |
return symbol, locations | |
def open_location(window, l): | |
fname, display_fname, rowcol = l | |
row, col = rowcol | |
window.open_file( | |
fname + ":" + str(row) + ":" + str(col), | |
sublime.ENCODED_POSITION | sublime.FORCE_GROUP) | |
def format_location(l): | |
fname, display_fname, rowcol = l | |
row, col = rowcol | |
return display_fname + ":" + str(row) | |
def location_href(l): | |
return "%s:%d:%d" % (l[0], l[2][0], l[2][1]) | |
def filter_current_symbol(view, point, symbol, locations): | |
""" | |
Filter the point specified from the list of symbol locations. This | |
results in a nicer user experience so the current symbol doesn't pop up | |
when hovering over a class definition. We don't just skip all class and | |
function definitions for the sake of languages that split the definition | |
and implementation. | |
""" | |
def match_view(path, view): | |
fname = view.file_name() | |
if fname is None: | |
if path.startswith('<untitled '): | |
path_view = view.window().find_open_file(path) | |
return path_view and path_view.id() == view.id() | |
return False | |
return path == fname | |
new_locations = [] | |
for l in locations: | |
if match_view(l[0], view): | |
symbol_begin_pt = view.text_point(l[2][0] - 1, l[2][1] - 1) | |
symbol_end_pt = symbol_begin_pt + len(symbol) | |
if point >= symbol_begin_pt and point <= symbol_end_pt: | |
continue | |
new_locations.append(l) | |
return new_locations | |
def navigate_to_symbol(view, symbol, locations): | |
def select_entry(window, locations, idx, orig_view, orig_sel): | |
if idx >= 0: | |
open_location(window, locations[idx]) | |
else: | |
if orig_view: | |
orig_view.sel().clear() | |
orig_view.sel().add_all(orig_sel) | |
window.focus_view(orig_view) | |
orig_view.show(orig_sel[0]) | |
def highlight_entry(window, locations, idx): | |
fname, display_fname, rowcol = locations[idx] | |
row, col = rowcol | |
window.open_file( | |
fname + ":" + str(row) + ":" + str(col), | |
group=window.active_group(), | |
flags=sublime.TRANSIENT | sublime.ENCODED_POSITION | sublime.FORCE_GROUP) | |
orig_sel = None | |
if view: | |
orig_sel = [r for r in view.sel()] | |
# Try to find it in the current file but not in the line | |
defindex = 0 | |
if len(locations) > 1 and view.file_name(): | |
for index, location in enumerate(locations): | |
fname, _, rowcol = location | |
if os.path.normpath(fname) == os.path.normpath(view.file_name()): | |
symbol_begin_pt = view.text_point(*[x - 1 for x in rowcol]) | |
symbol_end_pt = symbol_begin_pt + len(symbol) | |
if not sublime.Region(symbol_begin_pt, symbol_end_pt).contains(view.sel()[0]): | |
defindex = index | |
break | |
if len(locations) == 0: | |
sublime.status_message("Unable to find " + symbol) | |
elif len(locations) == 1: | |
open_location(view.window(), locations[0]) | |
else: | |
window = view.window() | |
window.show_quick_panel( | |
items=[format_location(l) for l in locations], | |
selected_index=defindex, | |
on_select=lambda x: select_entry(window, locations, x, view, orig_sel), | |
on_highlight=lambda x: highlight_entry(window, locations, x), | |
flags=sublime.KEEP_OPEN_ON_FOCUS_LOST) | |
class GotoDefinition(sublime_plugin.WindowCommand): | |
def run(self, symbol=None): | |
v = self.window.active_view() | |
if not symbol and not v: | |
return | |
if not symbol: | |
pt = v.sel()[0] | |
symbol, locations = symbol_at_point(v, pt) | |
else: | |
locations = lookup_symbol(self.window, symbol) | |
navigate_to_symbol(v, symbol, locations) | |
class ContextGotoDefinitionCommand(sublime_plugin.TextCommand): | |
def run(self, edit, event): | |
pt = self.view.window_to_text((event["x"], event["y"])) | |
symbol, locations = symbol_at_point(self.view, pt) | |
navigate_to_symbol(self.view, symbol, locations) | |
def is_visible(self, event): | |
pt = self.view.window_to_text((event["x"], event["y"])) | |
symbol, locations = symbol_at_point(self.view, pt) | |
return len(locations) > 0 | |
def want_event(self): | |
return True | |
class ShowDefinitions(sublime_plugin.EventListener): | |
def on_hover(self, view, point, hover_zone): | |
if not view.settings().get('show_definitions'): | |
return | |
if hover_zone != sublime.HOVER_TEXT: | |
return | |
def score(scopes): | |
return view.score_selector(point, scopes) | |
# Limit where we show the hover popup | |
if score('text.html') and not score('text.html source'): | |
is_class = score('meta.attribute-with-value.class') | |
is_id = score('meta.attribute-with-value.id') | |
if not is_class and not is_id: | |
return | |
else: | |
if not score('source'): | |
return | |
if score('comment'): | |
return | |
# Only show definitions in a string if there is interpolated source | |
if score('string') and not score('string source'): | |
return | |
symbol, locations = symbol_at_point(view, point) | |
locations = filter_current_symbol(view, point, symbol, locations) | |
if not locations: | |
return | |
location_map = {location_href(l): l for l in locations} | |
def on_navigate(href): | |
open_location(view.window(), location_map[href]) | |
links = [] | |
for l in locations: | |
links.append('<a href="%s">%s</a>' % ( | |
location_href(l), format_location(l))) | |
links = '<br>'.join(links) | |
plural = 's' if len(locations) > 1 else '' | |
body = """ | |
<style> | |
p { | |
font-family: sans-serif; | |
font-size: 1.05em; | |
margin: 0; | |
} | |
p.definitions { | |
font-size: 1.1em; | |
font-weight: bold; | |
margin-bottom: 0.25em; | |
} | |
</style> | |
<p class="definitions">Definition%s:</p> | |
<p>%s</p> | |
""" % (plural, links) | |
view.show_popup( | |
body, | |
flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY, | |
location=point, | |
on_navigate=on_navigate, | |
max_width=1024) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment