Sublime Forum

Are syntax specific mouse bindings possible?

#1

Let’s say I have this in my Default (Linux).sublime-mousemap:

  {
    "button": "button1",
    "count": 1,
    "modifiers": ["ctrl"],
    "press_command": "drag_select",
    "command": "goto_definition"
  },

It binds ctrl+mouse button 1 to Go To Definition. However, for languages supported by the Language Server Plugin eg. Rust, the command is not goto_definition but lsp_symbol_definition. So I tried adding another, context-specific mouse binding:

  {
    "button": "button1",
    "count": 1,
    "modifiers": ["ctrl"],
    "press_command": "drag_select",
    "command": "goto_definition"
  },
  {
    "button": "button1",
    "count": 1,
    "modifiers": ["ctrl"],
    "press_command": "drag_select",
    "command": "lsp_symbol_definition",
    "context": [
      { "key": "selector", "operator": "equal", "operand": "source.rust" }
    ]
  },

However now the Rust-specific one works, but the more general one does not. I would have assumed that if the specific context for a binding doesn’t match, the more general one that does match would work. (There’s no documentation for mouse bindings like there is for key bindings to confirm that, though.)

Is there a way to have this kind of syntax-specific mouse binding that doesn’t override the one without a context?

0 Likes

#2

No, this is currently not possible unless the plugin would call/forward on to the general command if it sees it cannot handle it correctly itself. There is a feature request for mouse map contexts here:

0 Likes

#3

LSP might take over your built-in commands in the future: https://github.com/sublimelsp/LSP/issues/1093

There’s a yak to shave though; disabling capabilities per language server instead of globally. This is because some built-in commands behave better than some language server’s equivalent. Especially Goto Symbol In Project is hard to beat.

0 Likes

#4

@kingkeith I think that info is out of date, because I just discovered that I can do this, but it’s not obvious how. I just have to make sure that the least specific binding comes last:

  {
    "button": "button1",
    "count": 1,
    "modifiers": ["ctrl"],
    "press_command": "drag_select",
    "command": "lsp_symbol_definition",
    "context": [
      { "key": "selector", "operator": "equal", "operand": "source.rust" }
    ]
  },
  {
    "button": "button1",
    "count": 1,
    "modifiers": ["ctrl"],
    "press_command": "drag_select",
    "command": "goto_definition"
  },
1 Like

#5

Are you sure?

[
    {
        "button": "button1", "count": 1,
        "press_command": "echo",
        "press_args": {
            "file": "python"
        },
        "context": [
            { "key": "selector", "operator": "equal", "operand": "source.python" }
        ]
    },
    {
        "button": "button1", "count": 1,
        "press_command": "echo",
        "press_args": {
            "file": "json"
        },
        "context": [
            { "key": "selector", "operator": "equal", "operand": "source.json" }
        ]
    },
    {
        "button": "button1", "count": 1,
        "press_command": "echo",
        "press_args": {
            "file": "anything else"
        },
    },
]

If context actually worked in a sublime-mousemap, then this should display either python, json or anything else in the console depending on which of the commands you pick.

What it actually does however is just use the last one in the file, whichever that happens to be, whether it has context or not. That follows with the idea that context is not considered, and since the bindings are loaded in order, the last one seen “wins”.

1 Like

#6

Haha nope, I am not at all sure. I tried random things and thought I found something that worked. However…

Yep, you are indeed correct. I went back and checked with a Rust project using LSP, and suddenly my ctrl+click “go to” action was a lot less precise, suggesting it was not at all using the LSP’s suggestions.

I think what I need to do (if I really want this to work) is write a shim-style plugin that resolves the context somehow and calls the correct action.

0 Likes