I would like to apply black
whenever I save a Python file in Sublime Text 3. How can I do that?
(Bonus points if there is a quick way to disable it)
I would like to apply black
whenever I save a Python file in Sublime Text 3. How can I do that?
(Bonus points if there is a quick way to disable it)
The answer above is really nice. In case you do not want to write your own package or plugin and you do not like the Formatter package, there is also the sublack package, which I think supports quick enabling/disabling of running black on save.
You install sublack the usual way via package control (Ctrl-Shift-P (Mac: Cmd-Shift-P) Package Controll: Install package). Afterwards you can format the current file either manually:
Run Black on current file: Press Ctrl-Alt-B to format the entire file. You can also Ctrl-Shift-P (Mac: Cmd-Shift-P) and select Sublack: Format file.
or you can:
Toggle Black on save for current view : Press Ctrl-Shift-P (Mac: Cmd-Shift-P) and select Sublack: Toggle black on save for current view.
Alternatively, you can also enable to run black on save permanently, by creating a user setting (Preferences -> Package Settings -> sublack -> settings) similar to the following:
{
"black_on_save": true,
"black_line_length": 80,
}
Package Control: Install Package
which python
Preferences/Package Settings/sublack/Settings On right panel
{
"black_on_save": true,
"black_command": WHICH_PYTHON_RESULT
}
To do something like this you would need a package or plugin that is capable of triggering an external command whenever an on_post_save
event is triggered in Sublime for a Python file.
The Formatter package is an example of a package that does this sort of thing and it's README mentions that it supports Black as well. I don't use that package myself so I can't recommend it one way or the other. There may be other packages that provide a similar functionality as well, although this is the only one I spotted that mentions that it supports Black explicitly.
In theory any formatting package or package to execute commands on save events that lets you specify the command to execute could likely be configured to work as well.
For the sake of completeness, a plugin to do something like this can be created fairly quickly by creating a ViewEventListener
that only triggers inside of Python files and uses the internal exec
command to execute the black
command.
An example of such a plugin would be the following (this video provides instructions on how to set up a plugin in Sublime if you're unsure how to do that) which for meta points has been formatted on save by itself:
import sublime
import sublime_plugin
import os
class FormatWithBlackOnSave(sublime_plugin.ViewEventListener):
"""
Listen for file saves and run the black code formatter on Python files
as they are saved, unless they have a setting indicating that the autoformat
should be disabled.
"""
@classmethod
def is_applicable(self, settings):
return "/Python/" in settings.get("syntax") and not settings.get(
"black_disabled", False
)
def on_post_save(self):
path, file = os.path.split(self.view.file_name())
settings = sublime.load_settings("Preferences.sublime-settings")
show_panel_on_build = (settings.get("show_panel_on_build", True),)
override_panel = settings.get("black_override_panel", False)
env = settings.get("black_env", {})
args = settings.get("black_arguments", [])
if override_panel:
settings.set("show_panel_on_build", not show_panel_on_build)
window = self.view.window() or sublime.active_window()
window.run_command(
"exec",
{
"shell_cmd": 'black {args} "{file}"'.format(
file=file, args=" ".join(args)
),
"working_dir": path,
"env": env,
},
)
if override_panel:
settings.set("show_panel_on_build", show_panel_on_build)
Once that's in place in your User
package, you should also add some custom settings to your Preferences.sublime-settings
file to control it:
// When this is True, the plugin will not execute on save.
"black_disabled": false,
// Override the value of the `show_panel_on_build` setting that controls
// whether the output panel appears when the command is executed. When
// true the value of that setting is temporarily inverted.
"black_override_panel": false,
// The arguments (other than the current file) to pass to black
"black_arguments": [],
// Optional environment variables to use while running the tool
// (for example to set the path); works as in a `sublime-build` file.
"black_env": {
}
This requires you to install the black
command yourself (e.g. pip install black
) and will execute it with the given arguments for the current file, so long as the file is a Python file and the black_disabled
setting is set to false
as above.
The plugin uses the internal exec
command, which uses the preference show_panel_on_build
to determine if a panel that shows you the output of the command should appear or not. The default value for that setting is true
, which means that every time you save a Python file the panel would open with a message like:
reformatted black.py
All done!
1 file reformatted.
[Finished in 0.2s]
The black_override_panel
setting makes the plugin invert the value of the show_panel_on_build
while it's executing the command; either not showing it when it normally would or vice versa.
Altering the setting in your preferences will globally disable the event listener from triggering in all Python files. You can also create a file in your User
package with a name like Black.sublime-commands
with the following content:
[
{
"caption": "Black: Toggle Format-on-save for this view",
"command": "toggle_setting",
"args": {
"setting": "black_disabled"
}
}
]
That would add a command to the command palette that inverts the state of the setting in the current file; that would allow you to disable the plugin only for certain files or enable it only for certain files.
© 2022 - 2024 — McMap. All rights reserved.