3
votes

I'm trying to make a key binding to open up my favorite git application with current Sublime Text 3 $project_path folder, but somehow Sublime Text 3 doesn't convert the variables into the actual path.

Below you can find my current keyboard bindings file.

[
    {
        "keys": ["super+ctrl+alt+g"],
        "command": "exec",
        "args":
        {
            "shell_cmd": "open -a Gitbox $project_path"
        }
    }
]

$project_path doesn't convert into the actual project path... What am I doing wrong? Should I use a "Build System" instead? I looked into build systems but the problem there is that you would have to select a scope of files (for example *.rb) and I want this keyboard shortcut to be valid for all my projects/files.

In textmate2 the same shortcut was easily achieved by creating a new "Command" in the Bundle Editor and assigning a shortcut to it. The command then would be:

#!/usr/bin/ruby
exec "open -a Gitbox '#{ENV['TM_PROJECT_DIRECTORY']}'"

So I'm trying to achieve this same thing in Sublime Text 3 but something is going wrong.

Thanks!

2

2 Answers

2
votes

Edit:

In the meantime I've built a generic plugin which gives you the ability to open any external application with an key stroke or via the command palette. The plugin can be found here: ExternalTools

You can easily install it via the command palette cmd+shift+p

In your case you can go to Preferences / Key Bindings and add the following:

{ 
    "keys": ["super+ctrl+alt+g"], 
    "command": "external_tools_run", 
    "args": { "cmd": ["open", "-a", "Gitbox", "$project_path"] }
} 

I still down't own a mac so there is a chance that it is not working properly. In this case I would be pleased if you can give me a feedback (see Issues).


Original Answer:

I have spend a few hours searching on the same problem. After all I decided to create a small plugin with my own place holders.

import sublime, sublime_plugin

class RunAppCommand(sublime_plugin.WindowCommand):
    def run(self, app_args):
        app_args = self.fill_placeholder(app_args)
        self.window.run_command("exec", {"cmd": app_args } )        

def fill_placeholder(self, args):
    res = []
    proj_folder = self.get_project_folder()

    for arg in args:
        arg = arg.replace("$PROJECT_FOLDER", proj_folder)
        res.append(arg)

    return res

def get_project_folder(self,default=None):
    proj_folder = ""

    if self.window.project_file_name():
        proj = self.window.project_data()

    proj_folder_obj = self.get_first(proj["folders"])
    if proj_folder_obj:
        proj_folder = proj_folder_obj["path"]

    elif self.window.folders():
        proj_folder = self.get_first(self.window.folders())

    if not proj_folder:
        sublime.status_message("No project folder located")
        return default

    return proj_folder        

def get_first(self, iterable, default=None):
    if iterable:
        for item in iterable:
        return item
    return default

After you have saved the code above to Packages/User/RunApp.py you can make your command work just by adding the following to your Default.sublime-keymap:

{ "keys": ["super+ctrl+alt+g"], "command": "run_app", "args": { "app_args": ["open", "-a", "Gitbox", "$PROJECT_FOLDER"]}}

This may be not the best solution but it works for me.

0
votes

Also spent some hours searching here - thanks to fboers example i could finally create a plugin myself.

So here's my solution: exec2 - expands all the sublime-variables as it should be and then forwards it to exec.

Save this as Packages/Exec2/Exec2.py.

import sublime
import sublime_plugin

class Exec2Command(sublime_plugin.WindowCommand):
    def run(self, cmd):
        new_cmd = [sublime.expand_variables (value, self.window.extract_variables()) for value in cmd]
        self.window.run_command("exec", {"cmd": new_cmd } )     

Example for the keybinding:

{ "keys": ["ctrl+F7"], "command": "exec2", "args" : { "cmd": ["V:/v4_tools/v4Doccer.exe", "--mdi", "${file}"]}  },