Run Shell Script When Saving a File in Sublime Text 3

Run shell script when saving a file in Sublime Text 3

Check out SublimeOnSaveBuild. All you need to do is set up a build system like SASS Build, LESS-build, Nodejs, etc., or your own custom build system, so that it's working without intervention when you press CtrlB. Then, enter the particulars into SublimeOnSaveBuild's config file (which allows you to filter by file extension, so you only trigger it when saving .sass files, for example) and you're all set - the build will trigger each time you save a file with the specified extension.

To set up the config file, first open Preferences → Package Settings → SublimeOnSaveBuild → Settings - Default, and copy the entire contents. Close the file, and paste the contents into Preferences → Package Settings → SublimeOnSaveBuild → Settings - User, customizing anything you wish. Save the file, and things should proceed automagically from there. Setting "build_on_save": 0 will disable the plugin.

How to run a shell command after saving file in Sublime 3

Based on your question, I'm going to assume that you're using the Hooks package to be able to run arbitrary commands based on events. If you haven't installed that package yet, then you'll need to do that too; the items talked about here are not available in core Sublime.

This package can execute any arbitrary command that you want, but note that this means Sublime commands; that is commands provided either by the core of Sublime or by packages and plugins that you have installed. Thus including the name of a shell command will not work; Sublime silently ignores commands that you tell it to run that it doesn't know about.

That said, the exec command is available directly in any Sublime installation and can execute any arbitrary shell command or program that you tell it to. This command is what is used to execute a build system, for example.

In fact, most of the keys available in a Build system by default (excluding the keys that tell Sublime when your build should apply) are actually arguments to the exec command that tell it what to execute.

Of particular interest to you is the shell_cmd argument, which takes any arbitrary command that you might enter in a command prompt and executes it.

Based on the documentation of the package in question, the configuration option you want would be something like this:

"on_post_save_user": [
{
// Runs `exec` command
"command": "exec",

// Invokes `exec` with `shell_cmd="google-chrome"`
"args": {
"shell_cmd": "google-chrome"
},

// Runs `exec` via `window.run_command`
"scope": "window"
}
]

With the caveat that I don't use this particular package and I can't verify that this is all that might be required, this tells the package to run the exec command (which is indeed a window command), telling it to execute google-chrome.

Other options may be required to exec to do what you want, depending on what that is. It's also unclear from the package documentation whether it supports the standard build system variables like $file to represent the current file or not, which may or may not be a problem.

Note also that since the exec command is what executes build systems, if show_panel_on_build is turned on in your user preferences (which it is by default unless you turn it off), the exec command will open a panel at the bottom of the window to tell you what the command you're running is doing.

How to run command on save in Sublime Text 3?

Sublime-hooks package allows you to run packages based on event (on new, on save, etc.), so you can use it to achieve your goal. Just add this code to CSS syntax settings:

"on_pre_save_language": [
{
"command": "css_comb"
}
]

If you are familiar with plugins maybe you can make a plugin that extends EventListener and override on_post_save or on_pre_save methods.

Auto-run a command on saving in Sublime Text

Yes this can be done with a simple event driven plugin like the one I've written below.

The plugin has been tested but not with the eslint command since I did not want to install that package. Clearly any command could be run instead of eslint in the plugin's run_command("eslint") line. If the desired command takes args then they can be specified like this: run_command("command", {"arg_1": val, "arg_2": val}).

The on_post_save_async(self, view) method (in my plugin below) will be called after the view, i.e. the active buffer, has been saved - note that this includes auto-saves. on_post_save_async() runs in a separate thread and does not block the application. You could alter the plugin to use a similar method depending of whether you want eslint called before or after the file save has taken place and whether the method should block the application or be run in its own non-blocking thread. These are the 4 alternatives:

  • on_pre_save(self, view): Called just before a view is saved. It blocks the application until the method returns.
  • on_pre_save_async(self, view): Called just before a view is saved. Runs in a separate thread, and does not block the application.
  • on_post_save(self, view): Called after a view has been saved. It blocks the application until the method returns.
  • on_post_save_async(self, view): Called after a view has been saved. Runs in a separate thread, and does not block the application. [Currently used in the plugin below.]
  • The Sublime Text EventListener documentation is located here - there are on load methods too.

Save the plugin below somewhere in in your Sublime Text packages hierarchy with a .py extension. e.g. ~/.config/sublime-text-3/Packages/User/AutoRunESLintOnSave.py and it should work straight away.

import sublime, sublime_plugin

class AutoRunESLintOnSave(sublime_plugin.EventListener):
""" A class to listen for events triggered by ST. """

def on_post_save_async(self, view):
"""
This is called after a view has been saved. It runs in a separate thread
and does not block the application.
"""

file_path = view.file_name()
if not file_path:
return
NOT_FOUND = -1
pos_dot = file_path.rfind(".")
if pos_dot == NOT_FOUND:
return
file_extension = file_path[pos_dot:]
if file_extension.lower() in [".js", ".jsx"]:
view.window().run_command("eslint")

# Slight variations are needed for an ApplicationCommand,
# a WindowCommand, or a TextCommand.
#
# view.run_command("text_command")
# view.window().run_command("window_command")
# sublime.run_command("application_command")
#
# Need args? Use this:
#
# view.run_command("command", {"arg_1": val, "arg_2": val})

Instead of using file extensions to trigger running the eslint command you could use the buffer's syntax, the code is even more concise.

    def on_post_save_async(self, view):
""" Syntax version. """

current_syntax = view.settings().get("syntax")
if ("JavaScript.sublime-syntax" in current_syntax
or "JSX.sublime-syntax" in current_syntax):
view.window().run_command("eslint")

# You could, of course, use an exact match:
#
# current_syntax = view.settings().get("syntax")
# if current_syntax == "Packages/JavaScript/JavaScript.sublime-syntax":
# view.window().run_command("eslint")
#
# Run `view.settings().get("syntax")` in the console for the active syntax path.

Save all files before running custom command in Sublime3

The trick is to only save for files that are dirty and exist on disk.

# Write out every buffer (active window) with changes and a file name.
window = sublime.active_window()
for view in window.views():
if view.is_dirty() and view.file_name():
view.run_command('save')

I had a similar issue with PHPUNITKIT.

save_all_on_run: Only save files that exist on disk and have dirty buffers

Note: the "save_all_on_run" option no longer saves files that don't
exist on disk.

The reason for this change is trying to save a file that doesn't exist
on disk prompts the user with a "save file" dialog, which is generally
not desired behaviour.

Maybe another option "save_all_on_run_strict" option can be added
later that will try to save even the files that don't exist on disk.

https://github.com/gerardroche/sublime-phpunit/commit/3138e2b75a8fbb7a5cb8d7dacabc3cf72a77c1bf

How to execute sub-shell commands in Sublime Text 3 build systems?

Indeed your issue is that the $ is special in sublime-build files because it's used to denote variable expansions in the build system fields that support it, such as the ${file_path} that you're using to get the path of the current file.

In the normal course of operations if you were to use a $ in front of text, Sublime treats it as a variable to expand, and any variables that have names that it doesn't understand get replaced with an empty string.

So for example, something like this to echo your home directory won't work:

"shell_cmd": "echo $HOME",

Sublime sees $HOME as a variable, it doesn't know what that is so it expands it to an empty string, and the result is to just execute the echo command with no arguments.

In order to tell Sublime that the $ in your command is meant to be a literal $ that it passes on to the shell, you need to quote it as \$; if Sublime sees that sequence, then it replaces \$ with $ and does nothing else, which lets the text pass through.

However sublime-build files are JSON, and in JSON \$ is not a valid escape sequence, so doing this will stop the file from parsing as JSON, which will end you in a situation where you try to build and the status bar will say No build system because the file couldn't be loaded.

So, taken all together the simple example here would need to look like this:

"shell_cmd": "echo \\$HOME",

Now when the file is loaded as JSON, the \\ is converted into a single character by the parser, leaving Sublime to see the \$ and handle it like you want.

It's interesting to note in your case that using the $() syntax is actually triggering what may be a bug in Sublime, because it's actually causing the entire shell_cmd key to be set to an empty string, which makes the command that executes the build think the key isn't set and causes the error that you're seeing.

Saving the work done on a Ubuntu terminal through Sublime text

Yes. If you use '.sh', Sublime will automatically recognize the Bash commands when you open the file. Technically, though, you can use whatever file extension you like. You can always go to View > Syntax > Shell Script (Bash), to see Bash syntax highlighting on a file with a different file extension.

Run TypeScript file on Sublime text

In this answer, I'm assuming that you already have installed Node.js and typescript on your local machine. If not, you can install Node.js from here and after that, you can run the following command to install typescript and ts-node using node package manager:

npm install -g typescript
npm install -g ts-node

Now, you are ready to follow these steps:

  • Open the typescript file -that you need to run- on sublime text 3.

  • Click on Tools tab, then Build System, then New Build System.
    Sample Image

  • A new file will open.. override its content with the following JSON object. The cmd parameter uses ts-node based on the suggestion of @idleberg. And @OdatNurd suggested adding "selector": "source.ts" to make the build automatically selected for TypeScript files so you don't have to manually select it.

{
"shell": true,
"cmd": ["ts-node", "$file"],
"selector": "source.js"
}
  • Save the file with the name ts.sublime-build.
  • Finally, build the script using ts as shown below if it wasn't automatically selected.

Sample Image

  • Now, click ctrl + B to run the script. And you should see the output on the sublime text console.


Related Topics



Leave a reply



Submit