问题
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