Sublime Forum

Hover/click events in gutter?

#1

Hey guys. I’ve currently been working on a plugin that places a random coloured image on each line, based on the SVN commit number. (Example here)

Now I’d like to move forward by creating a click (or hover) event that will open a popup displaying the commit message. Am I able to do this? I can’t really find any documentation on gutter events, or the popups.

Thanks!

0 Likes

Need handle for Sublime's Gutter and Fold-arrow
#2

Currently, there are no click events that are specific to the gutter.

I don’t believe there is any sort of functionality related to hovering, but you can get the mouse position by implementing want_event.  The event parameter requires that the command is called from a mouse-binding. ( see: /Packages/Default/Default.sublime-mousemap for examples )

This method will technically allow your command to function on gutter clicks, although I’m not sure that you’ll be able to differentiate between the gutter & view given the results ( x, y, mouseButton ).  You should, however, be able to figure out the line numbers by using the window_to_ commands mentioned in Jon’s post.
 



 
As far as official popup documentation goes, that post you linked to is pretty much it.

@facelessuser created a pretty useful library that extends the base popup functionality and is pretty well documented.  Check it out @ Sublime Markdown Popups.

2 Likes

#3

Hey fico, thanks for your response. I’ll have a play with event and make sure to fill people in on how it goes.

With popups, do you know if I’m able to place an a href in them, and have it direct to a URL that would open in the browser? Thanks

1 Like

#4

The following code will show a popup (basic, built-in ST3 functionality) with a link that will open the URL in the default browser (or indeed, any file in it’s default/associated program/application):

import sublime, sublime_plugin
import subprocess

class ExampleCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        # popup example code borrowed from https://forum.sublimetext.com/t/dev-build-3070/14538
        self.view.show_popup('Hello, <b>World!</b><br /><a href="https://www.sublimetext.com/">Click here to go to the ST3 website in your default browser</a>', on_navigate=self.navigate)
    
    def navigate(self, href):
        # code borrowed/improved from https://github.com/titoBouzout/SideBarEnhancements/blob/81523e4036aa9ee518b95906a9b235c32d48a6a9/SideBar.py#L1897-L1912
        platform = sublime.platform()
        try:
            if platform == 'windows':
                commands = ['cmd', '/c', 'start', href]
            elif platform == 'linux':
                commands = ['xdg-open', href]
            else:
                commands = ['open', href]
            subprocess.Popen(commands)
        except Exception as e:
            self.view.show_popup(repr(e))
3 Likes

#5

Thanks kingkeith, I appreciate your help!

0 Likes

#6

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)
3 Likes

Getting a drop down icon in a view
#7

Hey @kingkeith, @FichteFoll

Thanks for your help! I’d just thought I’d let you know that I finished my plugin.

It places a colour next to each line, which represents a commit number. Uncommitted lines are left blank. Clicking the gutter icon will show a popup that has the revision number, committer, and commit message. I’ve added some settings so that you can restrict file-types, auto-blame files in a certain directory etc.

You can see an image example here.

Again, thanks for your help guys. The information you gave me did wonders.

2 Likes

#8

And there we go:

I wonder what happens when plugins clash, however.

0 Likes

#9

that only helps with hovering in the gutter, not clicking though - so the empty line problem will still exist

0 Likes

#10

OP asked about a click or hover event. We now have hover events.

I also find the click-script to be rather hacky especially because of the empty lines issue, and with the hover event I don’t think I’ll use it anymore, since it is a better user experience.

0 Likes