How to create Sublime Text 3 build system which reads shebang

允我心安 提交于 2019-12-21 20:39:09

问题


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?


回答1:


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.




回答2:


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:


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



来源:https://stackoverflow.com/questions/39606221/how-to-create-sublime-text-3-build-system-which-reads-shebang

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!