Sublime Text 3 基于文件路径构建系统

SublimeText 3 Build System based on file path

我需要 运行 不同的编译器,具体取决于正在编辑的文件将与哪个版本的应用程序一起使用。

源文件始终存储在包含版本号的路径中。

所以文件 %APPDATA%\App\Settings\Source.file 需要 运行

%ProgramFiles%\App\Compiler.exe "%APPDATA%\App\Settings\Source.file"


%APPDATA%\App\Settings\Source.file 需要 运行

%ProgramFiles%\App\Compiler.exe "%APPDATA%\App\Settings\Source.file"

我尝试按照此处的高级示例进行操作: https://www.sublimetext.com/docs/3/build_systems.html#advanced_example

但 python 真的不是我的菜,我似乎无法得到任何东西 运行

基本工作,但我无法指定版本:

    {
        "cmd": ["c:\Program Files\App\10\compile.exe", "$file"],
        "selector": "source.app",
        "file_patterns": "*.ext"
    }

但这不是:

        {
        "target": "app_build", 
        "selector": "source.app",
        "file_patterns": "*.ext"
    }

.py 文件

    import sublime
    import sublime_plugin

    class AppBuildCommand(sublime_plugin.WindowCommand):

        def run (self):

            vars = self.window.extract_variables()
            compiler = vars['file_path']

            compiler = compiler.split("\")

            compiler_path = "c:\Program Files\App\" + compiler[compiler.index("App")+1] + "\Compiler.exe"

            file = vars['file']

            self.window.run_command (compiler + " \"" + file + "\"")

也试过没有成功:

    args = []
    args.append(compiler)
    args.append(file)

    self.window.run_command("cmd", args)

The run_command() method is for executing internal Sublime commands (i.e. the things you would bind to a key or trigger from a menu), so part of the reason why this isn't working for you is that you're trying to get Sublime to 运行 a command instead of having it execute an external program.

A build system is normally executed by the exec command; this is essentially the default value of the target key if you don't provide it in your sublime-build file. exec is responsible for using the arguments given to it by Sublime to start up an external process, capture it's output and display it in the output panel at the bottom of the window.

In order to customize what gets executed, you do need to implement you own WindowCommand and use the target key to tell Sublime to 运行 it, but that command is then responsible for doing what exec would do, which includes starting an external process and capturing the output.

The example that's listed in the documentation uses subprocess.Popen() to perform this task, along with having to track if the task is 运行 close it, etc.

An easy way to pull this off is to create your command as a subclass of the command that Sublime normally uses to 运行 the build, so that you can customize how the build starts but let existing code take care of all of the details.

An example of such a command would be something like the following:

import sublime
import sublime_plugin

import os

from Default.exec import ExecCommand


class AppBuildCommand(ExecCommand):
    def run(self, **kwargs):
        # Get the list of variables known to build systems
        variables = self.window.extract_variables()

        # Is there a file path? There won't be if the file hasn't been saved
        # yet.
        if "file_path" in variables:
            # Pull out the file path, split it into parts, and use the segment
            # after the "App" segment as the value of a new variable named
            # version.
            file_path = variables["file_path"].upper().split(os.sep)
            if "APP" in file_path:
                variables["version"] = file_path[file_path.index("APP") + 1]

        # Expand any remaining variables in our arguments and then execute the
        # build.
        kwargs = sublime.expand_variables(kwargs, variables)
        super().run(**kwargs)

An example of a sublime-build file that uses this command for the build would be:

{
    "target": "app_build",
    "cancel": {"kill": true},

    "cmd": ["c:\Program Files\App\\${version:100}\compile.exe", "$file"],

    "selector": "source.app",
    "file_patterns": ["*.ext"]
}

The command itself examines the path of the current file for the segment that follows the App segment (here case insensitively just in case), and uses that to create a new build system variable named version. If the file hasn't been saved yet (and thus has no name on disk) or if there isn't a path segment named App in it, then the variable is not created.

The last two lines expand any variables that haven't been expanded yet, and then tell the exec command to execute the build.

The sublime-build file can be in every way a normal sublime-build file, but the changes you need to make are:

  1. You need to use target to indicate that our command should be the one to execute

  2. You should (but don't need to) set the cancel key to tell Sublime how to cancel your build if you choose the cancel build command; this one tells Sublime to execute the same app_build command that it used to start the build, but give it an extra argument to say the build should be terminated.

  3. Anywhere you want to access the version number from the path of the file, use the notation \${version:DEFAULT}.

The variable needs to be specified this way (i.e. with the two \ characters in front) because Sublime will automatically try to expand any variables in the build system keys that exec recognizes before it calls the command.

Since at the time the command gets called we haven't set the value of the version variable yet, this will make Sublime assume that the value is the empty string, which removes it from the string and stops us from being able to detect that it's there.

In order to get Sublime to leave the variable alone, you need to use the $ notation as an indication that this should not be treated as a special $ character; Sublime will convert $ to $ and pass it through to our command. In the sublime-build file you need to use \$ because $ is not a valid JSON character escape.

The :DEFAULT portion is optional; this is what will be used as the expanded text if the version variable isn't set. In the example above it's set to 100, but in practice you'd set it to something like 9 or 11 instead. The variable won't be set if the command couldn't figure out the version to use, so you can use this to set a default version to be used in that case (if this makes sense for your use case).

This video series on build systems in Sublime Text has more information in general on how build sytems work, which includes several videos on custom build targets and how they work, including more information on advanced custom targets that subclass the ExecCommand as we're doing here (disclaimer: I am the author).