问题
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" },
]
回答1:
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.
来源:https://stackoverflow.com/questions/56934013/sublimetext-run-the-exec-with-current-file-as-arg-tab-context-menu