且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

SublimeText:使用当前文件作为 arg 运行 exec(选项卡上下文菜单)

更新时间:2023-12-06 08:34:40

一般来说,如果不使用某种插件代码将该信息传达给应用程序,就无法执行命令并向其提供当前活动文件的名称命令.

正如在键绑定、菜单等中定义的那样,您需要为预定义的命令提供参数,这意味着命令中的某些内容需要能够根据您提供的参数知道当前文件,或者该命令需要隐式地只处理当前文件,而不会被告知这样做.

做这样的事情最方便的方法是创建一个 sublime-build 文件来运行你想要运行的命令,然后使用 $file cmd 条目中的 variable表示当前文件,然后将您的菜单命令绑定到 build 命令,以便触发构建.

这里的缺点是这会妨碍将构建用于其他用途;build 命令仅执行当前选定的构建,因此它要求您在开始使用菜单之前先设置构建系统,或者将构建系统设置为 Automatic 以便Sublime 将在正确的时间执行正确的构建.无论哪种方式都可能会或可能不会妨碍您将构建用于其他目的而无需在中间采取手动步骤.

另一种方法是创建一个插件来实现 exec 命令的一个版本,该命令将扩展变量本身,而不是要求 build 命令将它们扩展为

此类插件的示例如下(如果您不熟悉使用,请参阅此视频自定义插件):

import sublime导入 sublime_plugin从 Default.exec 导入 ExecCommand类 MenuExecCommand(ExecCommand):def run(self, **kwargs):变量 = self.window.extract_variables()键入(cmd"、shell_cmd"、working_dir"):如果输入 kwargs:kwargs[key] = sublime.expand_variables(kwargs[key], variables)super().run(**kwargs)

这实现了一个名为 menu_exec 的命令,它与 exec 在调用时完全一样,除了 cmd 中的变量shell_cmdworking_dir 参数的扩展方式与它们在 sublime-build 文件中的方式相同.

使用该插件,您的 sublime-menu 条目会将 exec 交换为 menu_exec 并使用 $file 表示当前文件:

[{"caption": "DecodeJ","command": "menu_exec",参数":{"cmd": "P:\\decoder.exe $file"}},]

注意:如果您的文件名包含空格,您应该用双引号将变量括起来;"P:\\decoder.exe \"$file\"" 例如;否则外部命令可能无法获得正确的文件名.

I have created a tab context menu to decode some data. Now, I need to take current file(Tab context menu) as 1st argument to decode this file using exec.

Currently I'm using hardcoded path. How can I pass the name of the current file instead?

[
  { "command": "exec", "args": {"cmd": "P:\\decoder.exe P:\\in.txt"}, "caption": "DecodeJ" },
]

Generally speaking there's no way to execute a command and provide to it the name of the currently active file without using some sort of plugin code to convey that information to the command.

As defined in key bindings, menus and so on you need to provide arguments to commands that are predefined, which means that something in the command needs to be able to know based on the argument that you provided that you meant the current file, or the command needs to implicitly just work on the current file without being told to do so.

The most expedient way to do something like this would be to create a sublime-build file that runs the command that you want to run, and then use the $file variable in the cmd entry to represent the current file, followed by binding your menu command to the build command instead so that it triggers a build.

The downsides here are that this can get in the way of using builds for other uses; the build command only executes the currently selected build so it requires that you first set the build system before you start using the menu, or that you set the build system to Automatic so that Sublime will execute the correct build at the correct time. Either way may or may not get in the way of your ability to use builds for other purposes without having to take manual steps in the middle.

An alternative to this would be to create a plugin that implements a version of the exec command that will expand variables itself instead of requiring that the build command expand them for it.

An example of such a plugin would be the following (see this video if you're unfamiliar with using custom plugins):

import sublime
import sublime_plugin

from Default.exec import ExecCommand


class MenuExecCommand(ExecCommand):
    def run(self, **kwargs):
        variables = self.window.extract_variables()

        for key in ("cmd", "shell_cmd", "working_dir"):
            if key in kwargs:
                kwargs[key] =  sublime.expand_variables(kwargs[key], variables)

        super().run(**kwargs)

This implements a command named menu_exec that does exactly what exec would do when invoked, except that variables in the cmd, shell_cmd and working_dir arguments will be expanded the same way as they are in sublime-build files.

With that plugin your sublime-menu entry would swap exec for menu_exec and use $file to represent the current file:

[
    { 
        "caption": "DecodeJ",
        "command": "menu_exec", 
        "args": {
            "cmd": "P:\\decoder.exe $file"
        }
    },
]

Note: If your file names contain spaces, you should wrap the variable in double quotes; "P:\\decoder.exe \"$file\"" for example; otherwise the external command might not get the right filename.