I wrote some sample code a few days ago for someone on IRC that shows popups when clicking on the gutter. It’s a bit hacky and unreliable for empty lines (which is why I left the choice to the developer on what to do in that case), but it generally works pretty well. I intend to add this to SublimeLinter.
import sublime
import sublime_plugin
def is_coord_on_gutter(view, x, y):
"""Determine if x and y coordinates are over the gutter.
Because this is inapplicable for empty lines,
returns `None` to let the caller decide on what do to.
"""
original_pt = view.window_to_text((x, y))
if view.rowcol(original_pt)[1] != 0:
return False
# If the line is empty,
# we will always get the same textpos
# regardless of x coordinate.
# Return `None` in this case and let the caller decide.
if view.line(original_pt).empty():
return None
# ST will put the caret behind the first character
# if we click on the second half of the char.
# Use view.em_width() / 2 to emulate this.
adjusted_pt = view.window_to_text((x + view.em_width() / 2, y))
if adjusted_pt != original_pt:
return False
return True
class TestListener(sublime_plugin.EventListener):
def on_text_command(self, view, cmd, args):
if cmd == 'drag_select' and 'event' in args:
event = args['event']
print("single-clicked", args)
pt = view.window_to_text((event['x'], event['y']))
print("text pos:", pt)
on_gutter = is_coord_on_gutter(view, event['x'], event['y'])
print("is gutter", on_gutter)
print("button", event['button'])
if on_gutter is not False and event['button'] == 1:
print("showing popup")
# show asynchronously to not get the popup
# cancelled by the following selection change
def async_popup():
view.show_popup("fancy error text be here", location=pt)
sublime.set_timeout_async(async_popup)