Sublime Forum

Execute external tool from SublimeMerge

#1

Hi all,

I’ve tried out SublimeMerge recently but my workflow requires to call an external tool on a (changed) file, ideally via the File Menu (see screenshot). I’ve tried to add a menu entry via File.sublime-menu which worked, but there doesn’t seem to be an “exec” command or similar available. So basically I have the button but it seems I can only map built-in commands to it?

file_menu

Is there a possibilty to call an external command (a python script in this case, but could also be a .exe file) from the file menu I’am not aware of, and if not, is this a planned feature for the future?

Thanks in advance and best regards

1 Like

#2

I believe that the lack of the exec command is due to the fact that Merge doesn’t support plugins yet (although it is on the roadmap) and the exec command from Sublime is defined in a plugin. I don’t think Merge has the ability to execute arbitrary programs directly, but you can use it to execute git commands, and you can set up arbitrary git aliases to do pretty much whatever you want, so that might help you out.

For example, I created /home/tmartin/test.py with the following content and made it executable:

#!/bin/env python3

import sys

print("I'm a python script running for '%s'" % sys.argv[1])

I then set up an alias named script to invoke it in my git config:

[alias]
    script = "!f() { /home/tmartin/test.py $1; }; f"

I then set up a File.sublime-menu file in my merge User package like so:

[
    { "caption": "-" },
    {
        "caption": "Run my script",
        "command": "git", "args": {
            "argv": ["script", "$path"]
        }
    },
]

This uses the internal git command to execute git with any arguments you provide, which here are the alias script and also the path of the current file.

So now the command is in the menu:

image

After picking the command, you can click the Show Git Output button in the header (to the left of the branch name) to see what it did:

image

I’ve never done anything like this on Windows or MacOS, but I would imagine that git should support aliases for them in the same way.

5 Likes

Possible to launch git-bash from current repository?
[Sublime Merge]Hope for multi-user feature
#3

Interesting approach, didn’t cross my mind to use a git alias for that. I was able to reproduce it (Win10) and it works, I think I’ll go with that solution until there is a ‘proper’ exec implemented.
It’s also nice that GUI apps seem to work with the git alias, I tried with calc.exe for now.

Background is that I have to use an ancient version control system (ClearCase) with a graphical version tree that is sadly necessary in a lot of cases. My git repository lays on top of that ClearCase repo, but from time to time I have to interact with it. Being able to do so directly from SublimeMerge is a great help, though.

Also, I’ve looked into SublimeText and found the python file that implements the exec there. Just out of curiosity, are SublimeMerge and SublimeEdit similar enough under the hood to have a chance to get the SublimeText exec working without modifications in SublimeMerge?

Best regards

0 Likes

#4

The two share a lot of the same code base under the hood to a degree (only the Devs know how much though) but Merge doesn’t yet have the ability to be augmented via plugins.

For example, Merge has the ability to allow you to provide arguments to commands via the Command Palette by entering them manually (like tag names) or by selecting from a list of options (like choosing which remote to push to). It appeared in Development builds of Sublime Text first because it was developed for Merge (which was not yet announced).

Plugin support is on the roadmap as something that will probably happen, but I haven’t seen anything in the way of what the API could/would/should look like to be able to extend it. The Text version of exec assumes the existence of output panels to be able to show you the output, which doesn’t directly extend to Merge.

On the other hand, Merge does have some ability to display output as seen above and the code that’s responsible for executing a subprocess is just pure Python, so I would guess that in theory something like this would be possible, though it may require some modifications.

0 Likes

#5

Makes sense, especially this early in development. In some parts of the interface the similarities are quite obvious, but the lack of any *.py files inside the installed default package are a strong indicator that support for plugins is missing atm. However, having a plugin system similar to SublimeText would be a killer feature that’ll set SublimeMerge apart from the other git guis. SourceTree has this “External Command”-feature, but it is really inflexible and didn’t work too well in my case.

Anyway, the solution you suggested works really well for me. Thank you very much for taking the time to write it down in such detail, this made reproducing it really easy :+1:

1 Like

#6

@OdatNurd Hi! How you doing? This thread is really interesting and I’d like to give it a shot to your explanations… in fact, my long-term goal would be able to spawn some good fabric2 scripts using my python virtualenv on windows+sublimemerge2000

But before that ambitious goal :slight_smile: … I’d like to understand why the context menu isn’t being populated properly when I’ve tried to run your hello world gist, here’s the steps I’ve followed on windows7/sublime_merge2000:

  • Created a dummy File.sublime-menu:

      [
          { "caption": "-" },
          {
              "caption": "Run my script",
              "command": "python", "args": {
                  "argv": ["-c", "print('hello')"]
              }
          },
      ]
    
  • Pasted that file into multiple locations such as Data\Packages\File.sublime-menu, Data\Packages\User\File.sublime-menu, Data\Packages\Installed Packages\File.sublime-menu, Data\Installed Packages\User\File.sublime-menu … Probably the right place you guys meant in the above posts was Data\Packages\User\File.sublime-menu but all these attempts were to discard possible mistakes.

  • Restarted sublime-merge (probably this is not necessary)

Anyway, considering these steps, do you see what I’m doing wrong here?

Also… once I figure out how to solve that issue… would you know how to send as command args the git working directory as well as the treeish (or any other relevant info) from the commit graph item that spawned the command? That’d be pretty awesome :wink:

Thanks in advance :slight_smile:

0 Likes

#7

The crux of your problem is that there’s no such command python.

Note that in most regards, a sublime-menu file in Merge is the same as one in Text, so command is the name of the command to execute. Merge contains a git command to allow for executing any git related commands that it doesn’t expose itself (since it doesn’t do any manipulations on the repository itself and defers to git) but it doesn’t have the ability to execute arbitrary commands.

That’s why the post above gets around that restriction by setting up a git alias; the git command executes the git alias, and git executes the command for you.

Going on from there, the correct location for the file would be User\File.sublime-menu (or some other package, if you’d rather) in the folder that opens when you use Preferences > Browse Packages... to find your Packages folder (which always gives you the correct location regardless of platform or installation method).

When I put your file there, the menu item appears, but it’s disabled:

image

The reason the command appears disabled is the same here as it would be in Text; there’s no such command, so the core disables the menu entry because it doesn’t have any way to execute anything. The same thing happens in Text if you add a missing command to a menu, which is why various menu entries (like those in the Preferences menu) disable themselves if the plugin host crashes.

The list of available variables in menus is listed in the menu documentation for Merge. The first ones listed are available no matter what menu you’re using, and then each menu has some additional variables that apply only within itself.

So for example in the File.sublime-menu in addition to the global items, $path gives you repository-relative path to the selected file.

2 Likes

#8

Clear as water now! As usual, tyvm :slight_smile:

The main mistake I was having was the fact of trying to make thing work
by trial & error (usually this is a bad strategy)… Plus, I wasn’t even spawning the right context menu in the first place. That said, after reading your good explanation and most importantly, reading the nice docs everything
makes sense now.

It seems you can have multiline aliases pretty easily on windows… right now my main strategy will be spawning directly fab2.exe from the virtualenv location, that should do the trick… regarding to run python scripts from my virtualenvs I’m not pretty sure what’d be the best way to do it… guess using the d:/virtualenvs/myvenv/Scripts/python.exe interpreter should do the trick without having to activate it on the alias? dunno :confused:

0 Likes

#9

Can we (users) somehow implement “Copy patch to clipboard” / “Paste patch from clipboard” then, through this “custom script call” (macOS especially)?

UPDATE.
done, it works:

in /Users/<username>/Library/Application Support/Sublime Merge/Packages/User/Commit.sublime-menu:

    {
        "caption": "Copy patch",
        "command": "git", "args": {
            "argv": [ "copy-patch", "$commit" ]
        }
    },
    {
        "caption": "Paste patch (am)",
        "command": "git", "args": {
            "argv": [ "paste-patch-am" ]
        }
    },
    {
        "caption": "Paste patch (apply)",
        "command": "git", "args": {
            "argv": [ "paste-patch-apply" ]
        }
    },

om global .gitconfig:

[alias]
    copy-patch = "!f() { git format-patch -k -1 --stdout $1 | pbcopy; }; f"
    paste-patch-apply = "!f() { pbpaste | git apply; }; f"
    paste-patch-am = "!f() { pbpaste | git am -3 -k; }; f"
0 Likes