The ShellCommand
plugin allows arbitrary shell commands to be run and their output to be sent to buffers or panels.
It can:
- run pretty much any shell command, either typed into a prompt or configured in key bindings and commands;
- the output from a command is directable to either a new buffer or a panel;
- subsequent commands can cause other panels to re-run their commands, i.e., to 'refresh' themselves;
- the output of a shell command can be controlled by any syntax definition.
Whilst working on a number of Emacs-style extensions for Sublime it became clear that much of the functionality of extensions such as dired
and magit
required little more than the ability to move from one buffer to another, invoking commands based on context on the way.
For example, dired
shows a list of files and directories, and then allows users to interact with those files by selecting items in the buffer and pressing some key combinations. This way files and directories can be opened, renamed, deleted, zipped up, compared, and so on.
Similarly, the incredibly useful magit
firstly shows the status of a Git repo and then allows files to be staged, unstaged, committed and diffed, whilst branches can be switched between, rebased, merged, pushed, pulled and more.
So this extension is the factoring out of the core functionality on top of which tools like dired
and magit
can be built. A Sublime-style version of magit
should be available shortly.
The package is available on Package Control.
The built-in bindings are based on similar functionality for Emacs (see Execute External Command):
alt+!
will show a prompt into which a shell command can be typed;alt+|
will also show a prompt, but will use any selections or text under the cursor (or the current file if nothing is selected) as standard input to the shell command (i.e.,stdin
);g
in a view that is showing the output of a shell command will cause the command to be run again.
In addition to this it's possible to customise the behaviour for many different scenarios.
For detailed information about using your shell configuration options see Using a Shell Configuration File.
There is one command provided in the Command Pallette, which is Shell Command
. This provides a prompt into which a shell command can be entered. Any selections in the active view will be fed to the command as standard input. If there are no selections then the entire buffer will be passed through.
Indicates whether to show a message when the shell command returns no output, or the output is just whitespace. The default value is False
, i.e., no window is created if the command doesn't return anything.
## success_but_no_output_message
This is the message to show in the window or panel if the show_success_but_no_output_message
value is set to True
. The default value copies the equivalent from Emacs, i.e., "Shell command succeeded with no output".
Note that the following key bindings are for illustrative purposes only.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command"
}
]
This is the most basic use of the plugin, and will result in a prompt being provided to the user, into which any string can be typed. On pressing [ENTER]
the string will be processed as a shell command and the output will be rendered in a new view. The buffer in the view is read only.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"prompt": "Enter a command",
"title": "My Command"
}
}
]
Using these arguments the caption next to the prompt can be changed, as well as the title of the output view.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"prompt": "Enter a command",
"title": "My Command",
"panel": true
}
}
]
Often the output of a command is only required for a short amount of time, in which case a panel might be more appropriate.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"command": "git status"
}
}
]
To run a particular shell command use the command
parameter.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"command": "ls -al",
"region": "arg"
}
}
]
If the region
option is set to 'arg' then any active selections are appended to the command as arguments. If there are no active selections then the word under the cursor is used. In this example if there were no selections, and no word under the cursor then the ls -al
command would be run as is, most likely giving the contents of the project directory. But if a directory name were under the cursor, or was selected, then its contents would be listed.
[
{
"caption": "Word Count",
"command": "shell_command",
"args": {
"command": "wc -w",
"region": "stdin"
}
}
]
If the region
option is set to 'stdin' then any active selections are piped to the command as standard input (stdin). If there are no active selections then the entire buffer is used. In this example if there were no selections, and no word under the cursor then the wc -w
command would count the number of words in the current buffer.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"command_prefix": "git",
"prompt": "Git Command"
}
}
]
Sometimes it's useful to provide a command prompt that relates to a specific shell command, and the user would then only need to provide the parameters. This example creates a prompt labelled 'Git Command', into which the user need only type the Git command itself, and any parameters. For example, to run git status
, only status
would need to be entered into the prompt.
[
{
"caption": "Word Count",
"command": "shell_command",
"args": {
"stdin": "A contrived example. The output should be 8",
"command": "wc -w"
}
}
]
To pass a string of text to a command use the stdin
argument.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"command": "git diff",
"syntax": "Diff",
"title": "Diff"
},
}
]
This will run git diff
against whatever file is selected, and then use the Diff
syntax file (Packages/Diff/Diff.tmLanguage
) to format the output.
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"command": "git diff",
"syntax": "Diff",
"title": "Diff"
},
"context": [{ "key": "setting.ShellCommand" }]
}
]
This is the same command as before -- running git diff
on the file that the cursor is pointing at -- but this time the command will only work if the view is a ShellCommand
window.
If a shell command is executed whilst in the context of the output of another shell command and the action would affect the first view, then a refresh can be sent after the command has run. This uses the refresh
argument. For example, say a view contains a listing of the working directory created with the following shell command:
[
{
"keys": ["ctrl+enter", "1"],
"command": "shell_command",
"args": {
"command": "ls -al"
}
}
]
If we then have two further shell commands -- one that creates a new file, and one that deletes the file whose name is under the cursor -- we would want to ensure that the ls
view updates after either of these commands is run. The settings for the two add and delete commands might look like this:
[
{
"keys": ["ctrl+enter", "2"],
"command": "shell_command",
"args": {
"command": "cp README.md tmp",
"refresh": true
}
},
{
"keys": ["ctrl+enter", "3"],
"command": "shell_command",
"args": {
"command": "rm",
"arg_required": true,
"region": "arg",
"refresh": true
}
},
]
By default long-running commands will update the buffer as and when data is available. For some short commands this can look a little jerky and it might be best to wait for the command to complete before updating the buffer. This can be achieved with the 'wait for completion' flag:
[
{
"keys": ["ctrl+enter"],
"command": "shell_command",
"args": {
"wait_for_completion": true
}
}
]
2014-06-26 (v0.11.1)
- The working directory is set to be the directory of the current file, but if the 'root' (deduced from the current file) is required, the option
root_dir
can be set toTrue
. (@markbirbeck) Fixes issue #25.
2014-06-26 (v0.11.0)
- Commands were failing on Windows due to an unnecessary check that
stdout
was ready. (@markbirbeck) Fixes issue #13. Thanks to @bergtholdt who drew attention to the problem and proposed a slightly different solution. - Working directory selection is now much smarter, based on using the current file's path to find out which folder or project the file belongs to. (@bergtholdt) Fixes issue #17.
- The working directory is set to be the 'root' deduced from the current file, but if the directory of the current file is required, the option
root_dir
can be set toFalse
. (@markbirbeck) Fixes issue #24. - Menu entries that were supposed to provide access to settings and key bindings were opening the wrong files. (@markbirbeck) Fixes issue #22.
CR/LF
sequences are now mapped toLF
which improves display on Windows. (@markbirbeck) Fixes issue #21.- A link to a wiki page from the README was incorrect. (@mrjoelkemp) Fixes issue #19 and #20. Thanks also to @reqshark who spotted the same problem and also provided a solution.
2014-03-20 (v0.10.0)
- Passing a buffer with UTF-8 characters in as the stdin for a command caused the command to fail. (@markbirbeck) Fixes issue #16.
2014-03-15 (v0.9.0)
- Commands were failing if run in a window with no open folders or files. (@mrvoss) Fixes issue #14.
2014-03-14 (v0.8.0)
- Any text selected in the current buffer, or the entire buffer, can now be fed to a command as standard input, rather than as an argument. (@pcantrell) Fixes issue #5.
2014-03-11 (v0.7.0)
- A shell configuration script can now be executed before commands. The script is either set in
$ENV
(as perbash
conventions) or using theshell_configuration_file
configuration setting. (@mikeerickson) Fixes issue #8.
2014-03-10 (v0.6.0)
- The working directory is no longer derived primarily from the currently selected file. Instead any directory that has been saved in the view settings, or the project directory or the first open folder, is used. (@mikeerickson) Fixes issue #6.
2014-03-07 (v0.5.0)
- If there is no output from a command then no panel or window is created. This used to work, until async commands were implemented, but now it really does work. (@aldanor) Fixes issue #11.
2013-11-26 (v0.4.0)
-
Long-running commands will now update the buffer as and when data is available. For example, Grunt could be made to watch a project and update the buffer by running the command
grunt --no-color
. However, note that there is currently no way to terminate the process (see issue #10). Fixes issue #4. -
To change the default behaviour for long running commands, use the 'wait for completion' flag.
2013-10-07 (v0.3.0)
- Commands now really are run asynchronously. (@SirLenz0rlot) Fixes issue #2.
- Add
shell_command_on_region
to align with Emacs version.
2013-10-07 (v0.2.0)
- Some crucial text commands were not included (@bizoo). Fixes issue #1.
- The region under the cursor was not being used as a parameter.
2013-10-04 (v0.1.0)
- Initial release.