How to create Sublime Text 3 build system which re

2019-04-11 02:07发布

How can I create a build system in Sublime Text 3 where "cmd" is replaced with a shebang if it exists?

More specifically, is there a way to alter the Python build system to use the version of Python specified in the shebang, and use a default if no shebang is present?

3条回答
Viruses.
2楼-- · 2019-04-11 02:32

If think the only way to do this using a standard .sublime-build file is to pass your file to another script which then parses the shebang and passes it on to the correct Python version.

Alternatively, you could specify build variants, but then you will have to choose the desired build variant manually.

查看更多
聊天终结者
3楼-- · 2019-04-11 02:35

Sublime build systems have an option named target which specifies a WindowCommand that is to be invoked to perform the build. By default this is the internal exec command. You can create your own command that would examine the file for a shebang and use that interpreter or some default otherwise.

For example (caveat: I'm not super proficient in Python so this is probably quite ugly):

import sublime, sublime_plugin

class ShebangerCommand(sublime_plugin.WindowCommand):
    def parseShebang (self, filename):
        with open(filename, 'r') as handle:
            shebang = handle.readline ().strip ().split (' ', 1)[0]
        if shebang.startswith ("#!"):
            return shebang[2:]
        return None

    def createExecDict(self, sourceDict):
        current_file = self.window.active_view ().file_name()
        args = dict (sourceDict)

        interpreter = args.pop ("interpreter_default", "python")
        exec_args = args.pop ("interpreter_args", ["-u"])
        shebang = self.parseShebang (current_file)

        args["shell_cmd"] = "{} {} \"{}\"".format (shebang or interpreter,
                                                   " ".join (exec_args),
                                                   current_file)

        return args

    def run(self, **kwargs):
        self.window.run_command ("exec", self.createExecDict (kwargs))

You would save this in Packages/User as a python file (e.g. shebanger.py).

This creates a new command named shebanger that collects the arguments it's been given, examines the file in the currently active view of the window the build is triggered in to see if the first line is a shebang, and then synthesizes the arguments needed for the exec command and runs it.

Since the default python build system assumes it is building the current file and passing -u as an argument, that's what this command replicates as well. Note however that this code is not 100% correct because any arguments in the shebang line will be ignored, but you get the general idea.

In use, you would modify the default Python.sublime-build file to look like this:

{
    // WindowCommand to execute for this build
    "target": "shebanger",

    // Use this when there is no shebang
    "interpreter_default": "python",

    // Args to pass to the interpreter
    "interpreter_args": ["-u"],

    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "selector": "source.python",

    "env": {"PYTHONIOENCODING": "utf-8"},

    "variants":
    [
        {
            "name": "Syntax Check",
            "interpreter_args": ["-m py_compile"],
        }
    ]
}

Notice that in the variant we override what the interpreter arguments are; you could also override the default interpreter there as well if desired.

查看更多
一夜七次
4楼-- · 2019-04-11 02:52

My python.sublime-build

{
    "cmd": ["py", "-u", "$file"],
    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "selector": "source.python",
    "shell":true
}

In windows I used py launcher to detect the versions according to the shebang

查看更多
登录 后发表回答