Sublime text 3 при сохранении документа выполнить действие?
Приветствую жаждущих к познанию, Вопрос: Есть такая команда в Sublime text3 { "keys": ["ctrl+shift+c"], "command": "htmlprettify" }, Выравнивает код в файле, можно ли ее как то переписать что бы она работала при сохранении документа ? может кто сталкивался подскажите пжл. спс.
Ответы (1 шт):
1. Кратко
- Чтобы запустить консольную команду в Sublime Text через палитру команд (command palette), горячие клавиши и другими способами, необходимо преобразовать её во внутреннюю команду Sublime. Используйте для этого функцию
popen_print_output()фреймворка Suricate. - Чтобы запустить внутреннюю команду Sublime по событию сохранения файла, используйте хук
on_pre_save_asyncдля синтаксиса Вашего файла, установив плагин Hooks. - Чтобы запускать цепочки внутренних команд Sublime, используйте плагин Multicommand.
2. Пользовательские настройки vs. плагины
В вопросе упоминается команда htmlprettify плагина HTMLPrettify — оболочки для консольного бьютифаера js-beautify. я не рекомендую в подобных случаях использовать плагины по нижеследующим причинам:
- Если можно быстро и удобно прикрутить консольную команду, как в нашем случае, то тащить плагин, собственно, не нужно.
- По моему опыту, плагины создают немало дополнительных проблем и часто устаревают. Так, на момент написания этого ответа последний релиз плагина HTML-Prettify был выпущен в октябре 2018, тогда как последний релиз js-beautify — 2 недели назад.
- Плагины могут вызывать баги в неожиданных местах.
- В довесок к конфигурации для консольной программы плагины могут требовать дополнительных настроек для себя.
- Плагины отнимают удобные сочетания клавиш, засоряют меню и контекстное меню.
Поэтому вместо того, чтобы показывать пример для внутренней команды Sublime htmlprettify, ниже рассказывается, как при сохранении файла запускать команду его форматирования консольной программой js-beautify.
3. Шаг 1 — Подготовка запускаемой консольной команды
Прежде чем переходить к Sublime Text, убеждаемся, что js-beautify, запущенный в терминале, форматирует файл так, как мы хотим.
Допустим, мы имеем неотформатированный файл KiraExampleHTML.html
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Kira example title</title></head><body><p>Kira Goddess!</p></body></html>
Устанавливаем js-beautify через npm или альтернативный пакетный менеджер, если программа ещё не установлена, → запускаем в терминале команду:
D:\SashaDebugging\KiraFormatFileBySave>js-beautify --editorconfig --file KiraExampleHTML.html --replace
beautified KiraExampleHTML.html
Примечание: так как в вопросе указан тег html, я привожу в пример файл .html. Но точно такую же команду js-beautify можно применять и к файлам .js.
Примечание: аргумент командной строки --editorconfig работает только если корневая папка проекта содержит файл .editorconfig. js-beautify не имеет опции вроде --editorconfig-path, чтобы мы могли использовать настройки из файла .editorconfig, расположенного в другой директории.
После форматирования файл KiraExampleHTML.html выглядит следующим образом:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Kira example title</title>
</head>
<body>
<p>Kira Goddess!</p>
</body>
</html>
Это форматирование — ожидаемое поведение.
4. Шаг 2 — Запускаем консольную команду в Sublime Text
На данном этапе рассматривается, как создать из команды, запускаемой в терминале, внутреннюю команду для Sublime Text, которую мы можем вызывать, например из палитры команд или комбинацией горячих клавиш.
Устанавливаем фреймворк Suricate через Package Control, если он ещё не установлен, → Preferences → Browse Packages… → User → создаём файл Default.suricate-profile, если его ещё нет, → добавляем в него следующие настройки:
{
// Выше Ваши прочие настройки
"kira_format_html_or_js_file_use_js_beautify": {
"args": {
"cmd": ["js-beautify", "--editorconfig", "--file", "${file}", "--replace"]
},
"call": "Suricate.lib.process.popen_print_output",
"caption": "Format This File꞉ JS-Beautify for HTML or JS"
},
// Ниже Ваши прочие настройки
}
${file} — абсолютный путь к открытому в данный момент файлу; см. список доступных к использованию в Sublime переменных
Мы получили внутреннюю команду Sublime kira_format_html_or_js_file_use_js_beautify (строго говоря, мы получили команду suricate с аргументом kira_format_html_or_js_file_use_js_beautify), которая должна форматировать файлы также, как и команда js-beautify --editorconfig --file ${file} --replace, запущенная в командной строке.
Открываем в Sublime файл KiraExampleHTML.html → открываем палитру команд → набираем Format This File꞉ JS-Beautify for HTML or JS → Enter. Неотформатированный файл KiraExampleHTML.html должен отформатироваться так же, как тогда, когда мы запускали команду js-beautify из терминала.
Примечание: по причине 2.5 этого ответа я запускаю редко используемые внутренние команды Sublime из палитры команд, но Suricate также позволяет быстро настроить их запуск через сочетания горячих клавиш, контекстное меню или меню.
4.1. Отладка запуска консольной команды через Suricate
Если вы всё правильно настроили в файле Default.suricate-profile, но при запуске kira_format_html_or_js_file_use_js_beautify ничего не происходит или поведение отличается от ожидаемого, приступаем к отладке.
4.1.1. Логирование в консоли Sublime
Для отладки не будет лишним включить логирование в консоли Sublime. Открываем консоль Sublime → вставляем следующий код:
sublime.log_input(True); sublime.log_commands(True)
→ нажимаем Enter.
sublime.log_input(True)выводит в консоль нажатые в Sublime клавиши и хоткеи, пример:key evt: ctrl+ssublime.log_commands(True)выводит в консоль запущенные в Sublime команды, пример:command: suricate {"key": "kira_format_html_or_js_file_use_js_beautify"}
Ожидаемое поведение в консоли Sublime после запуска команды kira_format_html_or_js_file_use_js_beautify для моего примера выглядит так:
command: suricate {"key": "kira_format_html_or_js_file_use_js_beautify"}
beautified D:\SashaDebugging\KiraFormatFileBySave\KiraExampleHTML.html
reloading /D/SashaDebugging/KiraFormatFileBySave/KiraExampleHTML.html
4.1.2. Поведение функции “popen_print_output()”
В отличие от функции popen(), не выводящей ничего, как если бы мы запускали команду с аргументом --quiet, функция popen_print_output() фреймворка Suricate выводит стандартные потоки вывода (stderr и stdout) в консоль Sublime, а также выводит stderr в диалоговое окно с сообщением об ошибке. Например, если мы неправильно указали абсолютный путь к файлу js-beautify.cmd (см. пункт 4.1.4 данного ответа), при запуске команды kira_format_html_or_js_file_use_js_beautify Sublime показывает такое диалоговое окно:

command: suricate {"key": "kira_format_html_or_js_file_use_js_beautify"}
error: The system cannot find the path specified.
4.1.3. Sublime не находит путь к исполняемому файлу
Описанное в данном подразделе решение работает у меня в Windows. Если кто-то сталкивался с проблемой в другой ОС и успешно решил её, пожалуйста, дополните ответ.
Sublime может не распознать команду (в нашем примере js-beautify), которая успешно работает в терминале:
command: suricate {"key": "kira_format_html_or_js_file_use_js_beautify"}
error: 'js-beautify' is not recognized as an internal or external command,
operable program or batch file.
И эта ошибка остаётся после перезапуска Sublime.
Если Вы столкнулись с таким поведением Sublime, оно, вероятно, вызвано тем, что Sublime не получил обновлённые переменные среды. Такое случается, когда консольные программы установлены после последнего перезапуска операционной системы.
Sublime, как и в целом программы в Windows, наследует переменные среды от родительского процесса. Чтобы Sublime получил обновлённые переменные, необходимо, чтобы их получил родительский процесс, откуда он запускается.
Для этого можно запустить Sublime из терминала с обновлёнными переменными. Открываем командную строку от имени администратора → вводим команды:
# Обновляем переменные среды для текущей сессии
C:\Users\SashaChernykh>refreshenv
Refreshing environment variables from registry for cmd.exe. Please wait…Finished..
# Переходим в папку с установленным Sublime
C:\Users\SashaChernykh>g:
G:\>cd "Sublime Text 3 x64"
# Запускаем Sublime в командной строке
G:\Sublime Text 3 x64>subl
refreshenv— консольная утилита для Windows, обновляющая переменные среды.subl— команда для запуска Sublime из терминала, см. её использование.
Запущенный таким образом Sublime получает новейшие версии переменных среды.
4.1.4. Конфликты консольных команд
Консольная команда может работать некорректно, потому что в другой папке, добавленной в переменную среды PATH, может содержаться исполняемый файл с таким же названием. Для js-beautify этот вопрос актуален, поскольку существует одноимённый пакет для Python, форматирующий только JavaScript, но не HTML. Он может установиться, когда Вы установили через pip или его альтернативы пакет для Python, использующий js-beautify в качестве зависимости.
Чтобы наверняка быть уверенным, что мы запускаем js-beautify, установленный через npm, а не pip, вписываем в настройках Suricate абсолютный путь к файлу js-beautify.cmd в формате, как ниже, с экранированными обратными слэшами:
- "cmd": ["js-beautify", "--editorconfig", "--file", "${file}", "--replace"]
+ "cmd": ["C:\\Users\\SashaChernykh\\AppData\\Roaming\\npm\\js-beautify.cmd", "--editorconfig", "--file", "${file}", "--replace"]
Примечание: похоже, нет простого способа использовать переменные среды в файлах настроек Sublime. Например, такой синтаксис не работает:
- "cmd": ["C:\\Users\\SashaChernykh\\AppData\\Roaming\\npm\\js-beautify.cmd", "--editorconfig", "--file", "${file}", "--replace"]
+ "cmd": ["${APPDATA}\\npm\\js-beautify.cmd", "--editorconfig", "--file", "${file}", "--replace"]
5. Шаг 3 — Настройка запуска команды при сохранении файла
Полученную на предыдущем этапе внутреннюю команду Sublime kira_format_html_or_js_file_use_js_beautify можно запускать по определённому событию как то открытие, закрытие или сохранение файла.
Устанавливаем, если он ещё не установлен, через Package Control плагин Hooks, упрощающий настройку хуков → открываем в Sublime Text файл KiraExampleHTML.html → Preferences → Settings — Syntax Specific → в открывшийся файл HTML.sublime-settings (если Вы не меняли дефолтный синтаксис для HTML-файлов, в противном случае у Вас откроется другой файл) добавляем следующие настройки:
{
// Выше Ваши прочие настройки
"on_pre_save_async_language": [{
"args":
{
"key": "kira_format_html_or_js_file_use_js_beautify"
},
"command": "suricate"
}],
// Ниже Ваши прочие настройки
}
Чтобы активировать хук для JavaScript-файлов, проделываем то же самое: открываем какой-нибудь файл с расширением .js → Preferences → Settings — Syntax Specific → вставляем в открывшийся файл JavaScript.sublime-settings (если Вы не меняли синтаксис по умолчанию для JS-файлов, в противном случае у Вас откроется другой файл) приведённые выше настройки и сохраняем его.
on_pre_save_async— выбранное нами событие для запуска командыkira_format_html_or_js_file_use_js_beautify.on_pre_saveозначает, что команда запускается непосредственно перед сохранением файла,_async— что она выполняется в отдельном потоке, не притормаживая работу Sublime. Вместоon_pre_save_asyncмы можем также использоватьon_pre_save,on_post_save_asyncиon_post_save._language— выбираем из возможных пространств имён это, поскольку нам не нужно, чтобы командаkira_format_html_or_js_file_use_js_beautifyвыполнялась при сохранении файлов с синтаксисами отличными отHTMLиJavaScript. В других синтаксисах хук функционировать не будет, равно как он не будет работать, если мы решим поменять синтаксис для файлов HTML и JS.
Всё, любые файлы с синтаксисами HTML и JS должны успешно форматироваться при сохранении.
5.1. Конфликты внутренних команд Sublime при сохранении файла
Если команда kira_format_html_or_js_file_use_js_beautify нормально запускается через палитру команд или нажатие горячих клавиш, но после настройки хука что-то пошло не так, возможно, это связано с тем, что какие-то другие пакеты/плагины Sublime запускают свои команды при сохранении файла.
Приступаем к отладке для выявления проблемы: включаем логирование в консоли Sublime → сохраняем файл KiraExampleHTML.html → смотрим в консоль. Ожидаемый вывод в консоль при сохранении файла после настройки хука:
key evt: ctrl+s
command: save
command: suricate {"key": "kira_format_html_or_js_file_use_js_beautify"}
beautified D:\SashaDebugging\KiraFormatFileBySave\KiraExampleHTML.html
reloading /D/SashaDebugging/KiraFormatFileBySave/KiraExampleHTML.html
Если помимо suricate {"key": "kira_format_html_or_js_file_use_js_beautify"} при сохранении запускаются какие-то другие команды, проверяем, не они ли являются причиной проблемы.
Если из имени команды не понятно, какой пакет/плагин её запускает, мы можем вычислить его с помощью плагина CommandsBrowser. Допустим, при сохранении запускается команда
htmlprettify. Устанавливаем CommandsBrowser через Package Control, если он ещё не установлен, → открываем палитру команд →CommandsBrowser: Browse available Plugin/Package commands→ вводимhtmlprettify→ получаем имя плагина, запускающегоhtmlprettify:
Решаем, нужен ли нам конфликтующий плагин.
Если да, пробуем временно отключить его. В палитре команд вводим
Package Control: Disable Package→ выбираем конфликтующий плагин. Вновь сохраняем файлKiraExampleHTML.html, проверяем, действительно ли проблема в этом конфликтующем плагине. Чтобы вновь активировать плагин, вводим в палитре командPackage Control: Enable Package→ выбираем деактивированный ранее плагин.Если да, проблема заключается именно в этом конфликтующем плагине, смотрим в его настройках, есть ли у него опция вроде
run_command_on_save. Если да, устанавливаем для такой опции значениеfalse. Деактивированную таким образом команду мы можем запускать так, чтобы при сохранении файла она не мешала другим командам. Для этого потребуется включить её в последовательную цепочку команд — см. шаг 4.Неоптимальное решение. Если конфликтующий плагин/пакет нужен, запуск какой-то его команды при сохранении файла нельзя отключить в настройках, а отправлять pull request его разработчикам неохота, то в файле настроек синтаксиса (в нашем примере это
HTML.sublime-settings) пробуем заменитьon_pre_save_async_languageнаon_pre_save_language,on_post_save_async_languageилиon_post_save_language. Какой-то из вариантов может сработать для конкретного случая, но остаётся вероятность, что где-то в другом контексте конфликт команд всё равно вызовет нежелательное поведение.
6. Шаг 4 — Запускаем при сохранении более чем одну команду
Мы можем захотеть запускать при сохранении файла не только одну команду. Например, сохраняя HTML-файлы с синтаксисом HTML, я хочу, чтобы сначала HTML Tidy удалил из файла лишние теги, которые наплодил мой генератор сайтов, а затем, чтобы js-beautify привёл разметку файла в красивый вид.
Чтобы команды HTML Tidy и js-beautify не конфликтовали между собой, лучше запускать их последовательно, а не параллельно. Для этой цели служит плагин Multicommand. Устанавливаем его через Package Control, если он ещё не установлен, → тестируем tidy — команду установленного приложения HTML-Tidy — в терминале, как описано в шаге 1, → создаём, как описано в шаге 2, внутреннюю команду Sublime для Tidy, добавляя в файл Default.suricate-profile следующие строки:
{
// Выше Ваши прочие настройки
"kira_format_html_file_use_tidy": {
"args": {
"cmd": ["tidy", "-config", "G:\\Kristinita\\tidy.conf", "-modify", "${file}"]
},
"call": "Suricate.lib.process.popen_print_output",
"caption": "Format This File: HTML Tidy for HTML"
}
// Ниже Ваши прочие настройки
}
Если внутренняя команда kira_format_html_file_use_tidy успешно запускается, открываем заново HTML.sublime-settings → удаляем из него настройки, внесённые во время шага 3, → добавляем вместо них следующие:
{
// Выше Ваши прочие настройки
"on_pre_save_async_language": [
{
"args":
{
"commands": [
{
"args":
{
"key": "kira_format_html_file_use_tidy"
},
"command": "suricate",
},
{
"args":
{
"key": "kira_format_html_or_js_file_use_js_beautify"
},
"command": "suricate",
}]
},
"command": "multicommand"
}],
// Ниже Ваши прочие настройки
}
Ожидаемый вывод в консоль для нашего примера:
key evt: ctrl+s
command: save
command: multicommand {"commands": [{"args": {"key": "kira_format_html_file_use_tidy"}, "command": "suricate"}, {"args": {"key": "kira_format_html_or_js_file_use_js_beautify"}, "command": "suricate"}]}
command: suricate {"key": "kira_format_html_file_use_tidy"}
command: suricate {"key": "kira_format_html_or_js_file_use_js_beautify"}
beautified D:\SashaDebugging\KiraFormatFileBySave\KiraExampleHTML.html
reloading /D/SashaDebugging/KiraFormatFileBySave/KiraExampleHTML.html
Цепочка команд создана. Теперь при сохранении файла с синтаксисом HTML для него сначала будет запущена команда tidy -config "G:\Kristinita\tidy.conf" -modify ${file}, а затем js-beautify --editorconfig --file ${file} --replace.
7. Дополнительные ссылки
- Документация Suricate — плохая, из docstrings в коде фреймворка можно почерпнуть намного больше, чем из документации.
- Документация плагина Hooks.
- Список доступных событий в документации Sublime Text.
8. Актуальность
Ответ актуален для указанной ниже программной среды по состоянию на 24 февраля 2025 года. В будущем содержащаяся в нём информация может устареть.
9. Программная среда
- Microsoft Windows 11 [Version 10.0.22621.3085]
- Sublime Text 4, Stable Channel, Build 4192
- js-beautify 1.15.3
- HTML Tidy for Windows version 5.6.0
- Suricate v0.4.2
- Hooks v0.3.2
- Multicommand v1.0.1
- CommandsBrowser v1.5.0