格式化工具
🧜♀️ Sublime Text 插件,用于美化并压缩源代码:CSS,SCSS,Sass,HTML,XML,SVG,JS,JavaScript,JSON,GraphQL,Markdown,TypeScript,Vue,Lua,YAML,Go,Perl,PHP,Python,Ruby,Rust,Haskell,Dart,Swift,Crystal,Bash,Shell,SQL,CSV,C,C++,C#,Objective-C,D,Java,Pawn,Julia,Proto,LaTeX,D2,Graphviz,Mermaid,PlantUML,等等
详细信息
安装量
- 总数 132K
- Win 74K
- Mac 36K
- Linux 21K
8月6日 | 8月5日 | 8月4日 | 8月3日 | 8月2日 | 8月1日 | 7月31日 | 7月30日 | 7月29日 | 7月28日 | 7月27日 | 7月26日 | 7月25日 | 7月24日 | 7月23日 | 7月22日 | 7月21日 | 7月20日 | 7月19日 | 7月18日 | 7月17日 | 7月16日 | 7月15日 | 7月14日 | 7月13日 | 7月12日 | 7月11日 | 7月10日 | 7月9日 | 7月8日 | 7月7日 | 7月6日 | 7月5日 | 7月4日 | 7月3日 | 7月2日 | 7月1日 | 6月30日 | 6月29日 | 6月28日 | 6月27日 | 6月26日 | 6月25日 | 6月24日 | 6月23日 | 6月22日 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Windows | 44 | 51 | 34 | 48 | 58 | 62 | 57 | 50 | 34 | 28 | 43 | 42 | 44 | 65 | 50 | 55 | 31 | 38 | 48 | 53 | 51 | 56 | 34 | 30 | 30 | 48 | 58 | 53 | 45 | 45 | 22 | 32 | 47 | 42 | 56 | 41 | 35 | 26 | 33 | 51 | 53 | 46 | 51 | 37 | 31 | 36 |
Mac | 33 | 46 | 35 | 24 | 39 | 47 | 38 | 47 | 39 | 19 | 17 | 35 | 44 | 35 | 38 | 35 | 24 | 21 | 33 | 29 | 36 | 36 | 43 | 22 | 29 | 38 | 35 | 41 | 28 | 39 | 22 | 25 | 30 | 33 | 38 | 40 | 26 | 26 | 27 | 33 | 30 | 33 | 40 | 37 | 25 | 27 |
Linux | 26 | 35 | 29 | 29 | 22 | 25 | 19 | 22 | 28 | 22 | 15 | 39 | 20 | 26 | 36 | 17 | 14 | 14 | 28 | 34 | 25 | 29 | 32 | 16 | 22 | 22 | 20 | 21 | 24 | 27 | 23 | 16 | 21 | 19 | 30 | 29 | 23 | 20 | 17 | 30 | 33 | 30 | 21 | 31 | 22 | 21 |
自述文件
🧜♀️ 格式化工具
格式化工具是 Sublime Text 3
& 4
的一个简单配置文件驱动插件,用于美化并压缩源代码。
在理论上,它也可以作为一个平台,用于将任何形式的文本转换为美化和压缩,而不仅限于美化与压缩。
主要功能
- 支持超过70种主要编程语言。
- 包括80多个预置适配器,适用于各种 插件。
- 以各种方式格式化文本
- 文本转文本(文本图章,ASCII艺术等)
- 文本转图像(图像图章,二维码图像等)
- 可格式化整个文件,单个或多个选中内容。
- 可递归格式化整个文件夹。
- 基于语法作用域进行格式化,不是基于文件扩展名。
- 可与保存和未保存的文件(缓冲区)一起工作。
- 跨不同系统具有统一的设置。
- 支持自动检测格式化。
- 支持特定项目格式化。
- 支持在保存时格式化。
- 支持在粘贴时格式化。
- 每个第三方插件都提供共享配置文件。
- 显示实时的单词和字符计数。
- 自动记住并恢复文本位置。
- 通过两种方法可定制和扩展,以添加您自己的自定义插件
- 安装无任何依赖。
限制
文本到图像:第三方插件通常依赖于无头浏览器来渲染图像,使过程变得耗时。因此
"recursive_folder_format"
将不会被实现或已禁用。"new_file_on_format"
将不会被实现或已禁用。- 第三方插件必须**支持**导出
PNG
格式,因为Sublime Text只支持PNG
、JPG
和GIF
图像。
插件
- _
eslint_d
:放弃对Eslint v8.57.0+的支持(使用扁平配置文件eslint.config.*
),直到这个上游错误被修复:#281
- _
格式化器在行动:文本到文本…
格式化器在行动:文本到图像…
格式化器在行动:美化打印…使用theme-dosa和color-scheme-two
指南
插件
没有第三方插件,格式化器毫无用处。它依赖于外部插件来格式化代码。这意味着,格式化器不负责
- 格式化代码的质量。
- 格式化的速度。
支持插件的完整列表:需要更多?请参阅配置和开发以添加您自己的。
- 如果您想跟踪最新添加的插件及其发布和记录信息:_summary.txt
- 以下表格不包含每个插件支持的完整语言列表。例如,
prettydiff
支持45种语言,这将导致此列表超长。 - 如
Svelte
或Prisma
之类的语言未在此列出,但可以通过prettier插件使用。deno和dprint应有类似概念。 build-in
= 不需要用户安装。None
= 独立二进制文件。Req.
= 可能需要更新要求。
语言 | 美化 | 压缩 | 图形 | 要求 | 配置 |
---|---|---|---|---|---|
Angular | prettier、prettierd | – | – | Node.js | – |
Arduino | uncrustify [1]、clang-format [2]、artistic style | – | – | 无 | [1], [2] |
汇编 | asmfmt、nasmfmt | – | – | 无 | – |
Astro | prettier、prettierd | – | – | Node.js | – |
BibTeX | bibtex-tidy [1] | – | – | Node.js 12.0+ | [1] |
C, C++, C#, Objective-C | uncrustify [1]、clang-format [2]、artistic style | – | – | 无 | [1], [2] |
Cabal | cabal-fmt | – | – | Haskell | – |
Caddyfile | caddy-fmt | – | – | 无 | – |
Clojure | cljfmt、zprint | – | – | 无,(Java) | – |
CMake | cmake-format | – | – | Python | – |
Crystal | crystal tool format | – | – | 无 | – |
CSS, SCSS, Sass, Less, SugarSS | stylelint [1],js-beautifier,prettier,prettierd,prettydiff [2],csscomb,stylefmt | cleancss CLI,prettydiff [2] | – | Node.js | [1], [2] |
CSV,TSV,DSV,文本 | prettytable (内置) ,prettydiff [1] [2] |
– | – | Python,Node.js [2] | [1] |
D | uncrustify [1] | – | – | 无 | [1] |
D2 | d2 fmt | – | d2 | 无 | – |
Dart | dart-format | – | – | Dart | – |
Dhall | dhall format | – | – | 无 | – |
Dockerfile | dockfmt | – | – | 无 | – |
Drawio | – | – | draw.io | 无 | – |
Elixir | mix format | – | – | Erlang | – |
Elm | elm-format | – | – | 无 | – |
Erlang | erlfmt [1],efmt | – | – | rebar3 [1],None | – |
Fortran | fprettify | – | – | Python | – |
Gleam | gleam format | – | – | 无 | – |
GLSL | clang-format [1] | – | – | 无 | [1] |
Go | gofmt,goimports,gofumpt | – | – | 无 | – |
GraphQL | prettier、prettierd | – | – | Node.js | – |
Graphviz | – | – | graphviz | 无 | – |
Haskell | ormolu,fourmolu [1],hindent,stylish-haskell,floskell | – | – | Haskell | [1] |
HCL | hclfmt | – | – | 无 | – |
HTML,XHTML,XML | js-beautifier,prettier,prettierd,prettydiff [1],html-tidy | html-minifier,prettydiff [1] | – | Node.js | [1] |
Java | google java format [1],uncrustify [2],clang-format [3],artistic style | – | – | Java [1],None | [2], [3] |
JavaScript | eslint,eslint_d,js-beautifier,prettier,prettierd,standard js,standardx js,semistandard js,prettydiff,clang-format [1] [2],deno [2],dprint [2],biome [2] | terser,prettydiff | – | Node.js,None [2] | [1] |
JSON | js-beautifier,prettier,prettierd,prettydiff [1],deno [2],topiary [2],dprint [2],biome [2],jsonmax (内置) |
prettydiff [1],jsonmin (内置) |
– | Node.js,None [2] | [1] |
Julia | juliaformatter | – | – | Julia 0.6+ | – |
Kotlin | ktlint | – | – | Java | – |
LaTeX | latexindent | – | – | Perl,None | – |
Lua | stylua,luaformatter | – | – | 无 | – |
Markdown | prettier,prettierd,deno [1],dprint [1] | – | – | Node.js,None [1] | – |
Mermaid | – | – | mermaid [1] | Node.js | [1] |
Nginx | nginxfmt | – | – | Python 3.4+ | – |
Nickel | topiary | – | – | 无 | – |
OCaml | ocamlformat,ocp-indent,topiary | – | – | 无 | – |
Perl | perltidy | – | – | Perl | – |
Pawn | uncrustify [1] | – | – | 无 | [1] |
PHP | php-cs-fixer [1],php_codesniffer | – | – | PHP 7.4+ [1] | [1] |
Plantuml | plantumlascii | – | plantuml | Java | – |
Proto | clang-format [1] | – | – | None [1] | [1] |
Python | ruff、yapf [1]、black [1]、autopep8、isort、docformatter、pyment | python-minifier [2] | – | Python 3.7+ [1] | [2] |
R | styler、formatR [1] | – | – | R | [1] |
Racket | raco fmt | – | – | Racket 8.0+ | – |
Ruby | rubocop [1]、rubyfmt、standardrb、rufo [1] | – | – | Ruby [1]、None | – |
Rust | rustfmt | – | – | Rust 1.24+ | – |
Scala | scalafmt、scalariform [1] | – | – | None、Java [1] | – |
Shell、Bash | beautysh [1]、shfmt、shellcheck | shfmt | – | Python [1]、None | – |
SQL、SQL方言、PostgreSQL | sql-formatter [1]、pg_format [2]、sqlparse [3] | sqlmin (内置) |
– | Node.js [1]、Perl [2]、Python 3.6+ [3] | [1], [2] |
Swift | apple swift-format、swiftformat | – | – | 无 | – |
SVG | svgo max | svgo min | – | Node.js | – |
TableGen | clang-format [1] | – | – | 无 | [1] |
Terraform | terraform fmt | – | – | 无 | – |
TextProto | clang-format [1] | – | – | 无 | [1] |
TOML | taplo、topiary、dprint | – | – | 无 | – |
TypeScript | prettier、prettierd、js-beautify、ts-standard、prettydiff [1]、tsfmt、deno [2]、dprint [2]、biome [2] | prettydiff [1] | – | Node.js,None [2] | [1] |
VALA | uncrustify [1] | – | – | 无 | [1] |
Verilog | clang-format [1] | – | – | 无 | [1] |
Vue | prettier、prettierd、js-beautify | – | – | Node.js | – |
YAML | prettier、prettierd | – | – | Node.js | – |
Zig | zigfmt | – | – | 无 | – |
💡 提示
prettier 和 stylelint 可协同格式化
CSS
配置示例
stylelint_rc.json: {"extends":["stylelint-config-recommended","stylelint-config-standard"],"plugins":["stylelint-group-selectors","stylelint-no-indistinguishable-colors","@double-great/stylelint-a11y","stylelint-prettier"],"rules":{"plugin/stylelint-group-selectors":true,"plugin/stylelint-no-indistinguishable-colors":true,"a11y/content-property-no-static-value":false,"a11y/font-size-is-readable":false,"a11y/line-height-is-vertical-rhythmed":[true,{"severity":"warning"}],"a11y/media-prefers-color-scheme":false,"a11y/media-prefers-reduced-motion":false,"a11y/no-display-none":false,"a11y/no-obsolete-attribute":[true,{"severity":"warning"}],"a11y/no-obsolete-element":[true,{"severity":"warning"}],"a11y/no-outline-none":false,"a11y/no-spread-text":false,"a11y/no-text-align-justify":false,"a11y/selector-pseudo-class-focus":false,"prettier/prettier":[true,{"parser":"css","printWidth":120,"semi":true,"singleQuote":false,"tabWidth":4,"useTabs":false}]}} Then in Formatter settings > "stylelint": { ... "args": ["--config-basedir", "/absolute/path/to/javascript/node_modules"] ... }
-
配置示例
eslint_rc.json: {"env":{"es2022":true,"node":true,"browser":true},"parserOptions":{"ecmaVersion":13,"sourceType":"module","ecmaFeatures":{"jsx":true}},"extends":["../javascript/node_modules/eslint-config-prettier","../javascript/node_modules/eslint-config-airbnb-base"],"plugins":["eslint-plugin-prettier"],"rules":{"prettier/prettier":["error",{"bracketSpacing":true,"jsxSingleQuote":true,"parser":"babel","printWidth":120,"semi":true,"singleQuote":true,"tabWidth":4,"useTabs":false},{"usePrettierrc":false}],"indent":["error",4]}}
安装
- 使用 Package Control: 运行
Package Control: Install Package
并选择Formatter
- 或 下载: 从 GitHub 下载最新源代码到您的 sublime
Packages
目录,并将其重命名为Formatter
Packages
目录位于
- MacOSX:
~/Library/Application Support/Sublime Text 3/Packages/
- Linux:
~/.config/sublime-text-3/Packages/
- Windows:
%APPDATA%/Sublime Text 3/Packages/
配置
本节是 Formatter 的头部。虽然配置简单且易于理解,但仍需要对底层原理和背景进行详细解释。
Formatter 将第三方插件的 配置文件 存储在
Sublime Text > Packages > User > formatter.assets > config
- 您可以使用这些文件,或者将它们放置在您选择的任何位置。Formatter 提供了一套默认(原始)配置文件,以说明其工作原理。您可能需要对其进行调整和优化,以满足您的需求。完整的支持选项和参数列表可在插件开发者网站上找到。
- 您可以使用与Formatter默认提供的配置文件格式不同的格式。例如,虽然Formatter默认使用JSON或YAML(
prettier_rc.json
),但您可以编写自己的JavaScript格式(prettier_rc.js
)或任何第三方插件支持的格式配置。
注意:请不要使用以.master.
结尾的文件,因为它们作为您最终配置的参考(示例)文件,可能会被任何包更新覆盖。原因:一些奇特的插件不支持输入配置文件,而其他插件不理解stdio。为了克服这个限制,您需要这些示例文件作为配置它们的参考。
建议您探索这个文件夹,因为它可能包含相同插件的附加配置文件。
可以从以下位置访问Formatter设置:首选项 > 包设置 > Formatter > 设置
以下设置细节(包括其默认值和示例)提供指导,以便您了解如何设置。
💡 提示
- 选项是可选的:您不需要整个选项集。只需要您需要的部分,但请保持JSON结构完整。
- 您不必强制使用预设模块。相反,您可以通过以下任一方法创建一个新模块,使用不同的UID键。
- 并非所有特定语言的语法高亮插件都存在;像
"text"
或"plain"
这样的语法同样可以作为解决方案。
- 示例设置选项: Formatter.sublime-settings
{
// Enable debug mode to view errors in the console.
// Accepted values: true (verbose), false, OR "status" (recommended)
"debug": false,
// Auto open the console panel whenever formatting fails.
// This is useful if "debug" is "status" or true
"open_console_on_failure": false,
// The counterpart for success.
"close_console_on_success": false,
// Timeout to abort subprocess in seconds.
// Default to 10 seconds. Set to false to disable the timeout.
"timeout": 10,
// Integrate your custom modules into the Formatter ecosystem.
// Modules can be located either locally or remotely (with or without signing).
// This option must be of type string pointing to the JSON metata file path.
// More about the format of this file, see README.md > Integrating modules
"custom_modules_manifest": "",
// Display results in the status bar with the current settings mode info:
// PUS: Persistent User Settings
// PQO: Persistent Quick Options
// TQO: Temporary Quick Options
"show_statusbar": true,
// Display a real-time word and character count in the status bar.
// By default, whitespace is not included in the character count.
"show_words_count": {
"enable": true,
"use_short_label": false,
"ignore_whitespace_char": true
},
// Remember and restore cursor position, selections and bookmarks
// each time a file is closed and re-opened.
// This is helpful to resume your work from where you left off.
// It does not remember any sublime sessions as name might suggest.
"remember_session": true,
// Configure the layout when opening new files.
// This only takes effect if the "new_file_on_format" option is true.
// Accepted values: "2cols", "2rows", "single" OR false
"layout": {
"enable": "2cols",
"sync_scroll": true
},
// A set of directories where executable programs are located.
// These can be absolute paths to module directories or Python zipfiles.
// Any environment variables like PATH, PYTHONPATH, GEM_PATH, GOPATH,
// GOROOT, GOBIN, TMPDIR, WHATEVER, etc. can be added here.
// This is similar to running 'export PYTHONPATH="/path/to/my/site-packages"'
// from the terminal. It is temporary, your system environment remains untouched.
// On Windows, you can use either escaped backslashes (e.g., "C:\\a\\b\\c") or
// forward slashes (e.g., "C:/a/b/c") as path separators for all other options.
// Tip: Activating "print_on_console" will help to set the correct environment.
"environ": {
"print_on_console": false,
"PATH": ["/path/to/erlang@22/bin:$PATH", "$PATH:/path/to/elixir/bin", "/path/to/.cache/rebar3/bin:$PATH"],
"GEM_PATH": ["${HOME}/to/my/ruby"],
"PYTHONPATH": ["${packages}/User/MyFolder/python/lib/python3.7/site-packages"],
"OLALA": ["$HOME/.cabal/bin:$PATH", "~/.olala/bin:$PATH"]
},
// This option resolves the syntax conflicts described in "format_on_save".
// It acts as an override and only applies to the following options:
// 1. "format_on_save"
// 2. "format_on_paste"
// Syntaxes in this option always take precedence over the syntaxes specified there.
// All syntaxes must be unique without any duplicates.
"format_on_priority": {
"enable": false,
"csscomb": ["css"],
"jsbeautifier": ["js"]
},
// This option enables auto-detect formatting for file.
// Configure it here and/or by using the dot files in your working folder.
// If both methods are used, the config from the dot files will override this embedded one.
// Advantage: The embedded one can handle both saved and unsaved files,
// while the dot files variant only applies to saved file, as unsaved files
// (puffer on view) never has an working dir to contain dot files.
//
// For "format_on_save" and "format_on_paste" you can use a dictionary format to exclude.
// "format_on_save": {
// "exclude_dirs_regex": [".*(\\.git|node_modules|__pycache__|env).*", ".*/project/test"],
// "exclude_files_regex": [".*test_file\\.py\\$", ".*/project/test/config\\.json"],
// "exclude_extensions_regex": ["ya?ml", "mjs", "json"]
// }
// More about this feature, see README.md > Auto-detect Formatting
"auto_format": {
"config": {
"format_on_save": false,
"format_on_paste": false
},
"json": {
"uid": "jsbeautifier"
},
"html": {
"uid": "jsbeautifier",
"exclude_syntaxes": {
"html": ["markdown"]
}
},
"python": {
"uid": "autopep8"
}
},
// THIRD-PARTY PLUGINS LEVEL
// Info: Preferences > Package Settings > Formatter > Modules Info
"formatters": {
"examplemodule": { // MODULE METHOD
// Plugin activation.
// By default, all plugins are disabled.
"enable": false,
// Auto formatting whenever the current file is being saved.
// This option should be used for plugins with unique syntaxes.
// For multi plugins with the same syntaxes, the first plugin takes precedence.
// Remove the identical syntaxes from one of the plugins to avoid conflicts.
// For example:
// Plugin A (enabled): syntaxes ["css", "js"]
// Plugin B (enabled): syntaxes ["html", "css"]
// In the case you want to use Plugin B with "css", then you should remove
// the "css" from plugin A or just disable it, as there is no guarantee of the
// execution order between the two, and determining your favorist is not possible.
// Solution: Use the "format_on_priority" option to workaround this.
//
// By default, this option uses a boolean value: false OR true
// To exclude files or dirs, use a dictionary format:
// "format_on_save": {
// "exclude_dirs_regex": [".*(\\.git|node_modules|__pycache__|env).*", ".*/project/test"],
// "exclude_files_regex": [".*test_file\\.py\\$", ".*/project/test/config\\.json"],
// "exclude_extensions_regex": ["ya?ml", "mjs", "json"]
// }
"format_on_save": false,
// Auto formatting whenever code is pasted into the current file.
// This option affects the same way as "format_on_save".
// So the mentioned syntax conflicts and solutions are the same.
//
// Also you can use the same dictionary format for exclusions:
// "exclude_dirs_regex", "exclude_files_regex", "exclude_extensions_regex"
"format_on_paste": false,
// Create a new file containing formatted code.
// The value of this option is the suffix of the new file being renamed.
// Suffix must be of type string. =true, =false means =false
// Note: It will overwrite any existing file that has the same new name in
// the same location.
// For example:
// "new_file_on_format": "min", will create a new file:
// myfile.raw.js -> myfile.raw.min.js
"new_file_on_format": false,
// Recursive directory formatting, regardless of depth.
// This option requires an existing and currently opened file
// to serve as the starting point.
// - For the sake of convenience, two new folders will be created at
// the same level as the file, which will contain all failed and
// successfully formatted files.
// - The "new_file_on_format" option can be used to rename files
// at the same time if needed.
// - The "format_on_save" option above, which only works in the
// single-file mode, does not take effect here.
// - All none-text files (binary) will be automatically ignored.
// - To STOP the current formatting process, press any of the
// arrow keys (up, down, left, right) on your keyboard.
// Any literal "$" must be escaped to "\\$" to distinguish it from
// the variable expansion "${...}". This important rule applies
// to the entire content of this settings file!
"recursive_folder_format": {
"enable": false,
"exclude_folders_regex": ["Spotlight-V100", "temp", "cache", "logs", "^_.*foo\\$"],
"exclude_files_regex": ["^._.*$", ".*bar.exe"],
"exclude_extensions": ["DS_Store", "localized", "TemporaryItems", "Trashes", "db", "ini", "git", "svn", "tmp", "bak"],
"exclude_syntaxes": []
},
// Syntax support based on the scope name, not file extension.
// Syntax name is part of the scope name and can be retrieved from:
// Tools > Developer > Show Scope Name
// End-users are advised to consult plugin manpages to add more syntaxes.
"syntaxes": ["css", "html", "js", "php"],
// Exclude a list of syntaxes for an individual syntax key.
// A list of excluded syntaxes can be applied to all syntax definitions.
// In this case, the key must be named: "all".
// This option is useful to exclude part of the scope selector.
// For example: text.html.markdown, want html but wish to filter out html.markdown.
"exclude_syntaxes": {
"html": ["markdown"],
"all": ["markdown"]
},
// Path to the interpreter.
// Omit this option will force Formatter to detect interpreter on PATH and
// automatically set them for you.
// Or you can set the basename as the interpreter name to search on PATH or
// locally, similar to how it is done with the "executable_path" option.
"interpreter_path": ["${HOME}/example/path/to\\$my/java.exe"],
// Path to the plugin executable.
// This option can be either a string or a list of executable paths.
// - If this option is omitted or set to null, then the global executable
// on PATH will be used, OR the local executable if automatically found.
// - If this option is exactly the basename, then it will be used as the
// executable name and searched for on the PATH.
// Basename can be with or without dot.extension as both variants are the same.
// For example: "fiLe.exe" (Windows only), "fiLe" (Windows + Unix + Linux)
// System variable expansions like ${HOME}, ${USER} etc. and the Sublime Text
// specific ${packages} can be used to assign paths.
// Note: Again, any literal "$" must be escaped to "\\$" to distinguish
// it from the variable expansion "${...}".
"executable_path": ["${HOME}/example/path/to\\$my/php-cs-fixer.phar"],
// Path to the config file for each individual syntaxes.
// Syntax keys must match those in the "syntaxes" option above.
// A single config file can be used to assign to all syntaxes.
// In this case, the key must be named: "default"
// - You can choose another config file format as the default one
// provided by Formatter if the third-party plugin supports it.
// - Formatter provides a set of default config files under
// "formatter.assets/config" folder for your personal use.
// Do not use the reference files with suffix '.master.' directly.
// These files could be overwritten by any release updates.
// - Options from this config file always have precedence over
// the options from any local project (per-project config dotfile).
// - Disabling this option will force Formatter to auto resolve
// the per-project config dotfile in the file tree to use.
// To disable this option:
// 1. Set the config path of this option to null, OR
// 2. Use the Quick Options: Ignore Config Path, OR
// 3. Place an '.sublimeformatter.cfgignore.json' file inside
// the working root folder. The structure of this file is
// descripted in README.md > Auto-detect Formatting
// Formatter will start to search up the file tree until a
// '.sublimeformatter.cfgignore' file is found to bypass this option.
"config_path": {
"css": "${packages}/User/formatter.assets/config/only_css_rc.json",
"php": "${packages}/User/formatter.assets/config/only_php_rc.json",
"default": "${packages}/User/formatter.assets/config/css_plus_js_plus_php_rc.json"
},
// Array of additional arguments for the command line.
"args": ["--basedir", "./example/my/foo", "--show-bar", "yes"],
// This option is specifically designed for type graphic.
// It enables SVG image generation for saving.
// Enable it if you need SVG image at the cost of processing time.
// Unlike the generic method, this method only supports SVG generation.
"render_extended": false,
// Manipulate hardcoded command-line arguments.
// This option allow you to modify hardcoded parameters, values and
// their positions without digging into the source code.
// This feature is primarily intended to temporarily fix bugs until
// an official solution is implemented.
// Note: Hardcoded args can be changed (rarely) by any release updates.
// Enable debug mode will help to find all current hardcoded args.
// Use "args" option above to add, this option to remove or manipulate.
// Using regex: Again, any literal "$" must be escaped to "\\$" to
// distinguish it from the variable expansion "${...}". Accepted args:
// [search, [replace, [index, count, new position]]], where:
// - search: @type:str (regex)
// - replace: @type:str
// - index: @type:int (the number is known as a list index); required!
// - count: @type:int (the matching occurrences per index, 0 = all); required!
// - position: @type:int (move old index pos. to new/old one, -1 = delete index); required!
"fix_commands": [
["--autocorrect", "--autocorrect-all", 4, 0, 4], // no index pos change
["^.*?auto.*\\$", "--with", 4, 1, 5], // using escaped "\\$" regex, move index 4 to pos 5
["${packages}/to/old", "${packages}/to/new", 3, 0, 3], // variable expansion, no escaped "$"
["css", 5, 0, 7], // replace the value in index 5 with "css", move it to pos 7
[3, 0, 4], // just move index 3 to the new pos 4. (count 0 irrelevant)
[2, 0, -1], // just delete the index 2. (count 0 irrelevant)
["--show-bar", "xxx", 2, 0, -1] // enough bar, pop it out. ("xxx", 2, 0 irrelevant)
]
},
"examplegeneric": { // GENERIC METHOD
// Formatter provides 2 methods to add custom plugins:
// - Generic: this one, you design the bridge yourself. Suitable for simple tasks.
// - Modules: requires writing Python modules for complex tasks.
// Note: The Generic method requires a Sublime Text restart after adding or changing
// the "name" and "type" keys. Also, avoid reusing existing UID keys in JSON.
// The capitalized Plugin name (REQUIRED!)
// This will appear in the Sublime menu and other commands.
"name": "Example Generic",
// The plugin type (REQUIRED!)
// This will categorize the plugin. Accepted values:
// "beautifier", "minifier", "converter", "graphic", or any string of your choice.
"type": "beautifier",
// This will activate the "args_extended" option for the graphic type
// to generate extended files like SVG for saving.
"render_extended": false,
// The exit code for the third-party plugin (optional, default is 0).
"success_code": 0,
// Same as the one in the examplemodule.
"enable": false,
// Same as the one in the examplemodule.
"format_on_save": false,
// Same as the one in the examplemodule.
"format_on_paste": false,
// Same as the one in the examplemodule, but disabled/unused for type graphic.
"new_file_on_format": false,
// Same as the one in the examplemodule, but disabled/unused for type graphic.
"recursive_folder_format": {},
// Same as the one in the examplemodule.
"syntaxes": ["css", "html", "js", "php"],
// Same as the one in the examplemodule.
"exclude_syntaxes": {},
// Same as the one in the examplemodule.
"interpreter_path": ["${HOME}/example/path/to\\$my/php.exe"],
// Same as the one in the examplemodule.
"executable_path": ["${HOME}/example/path/to\\$my/php-cs-fixer.phar"],
// Same as the one in the examplemodule.
"config_path": {
"css": "${packages}/User/formatter.assets/config/only_css_rc.json",
"php": "${packages}/User/formatter.assets/config/only_php_rc.json",
"default": "${packages}/User/formatter.assets/config/css_plus_js_plus_php_rc.json"
},
// Main commands to trigger the formatting process.
// You can either set the qualified paths directly or use variable substitution for:
// - "interpreter_path" : "{{i}}"
// - "executable_path" : "{{e}}", "{{e=node}}" (for local executable auto-resolving with runtime type node)
// - "config_path" : "{{c}}"
// - SPECIAL CASE GRAPHIC : "{{o}}" (output PNG image, e.g: "args": [... "--output", "{{o}}"])
// Variable substitution provides advanced mechanisms such as auto-search path, auto-config, etc.
// SPECIAL CASE GRAPHIC requirements:
// 1. The plugin must support exporting PNG format.
// 2. The hardcoded "{{o}}" MUST ALWAYS be included in "args".
// You might regret using your own path instead of "{{o}}" or daring to omit "{{o}}" in this case.
// In all other cases, output may not be as a file; use "-" or "--" instead.
"args": ["{{i}}", "{{e=node}}", "--config", "{{c}}", "--basedir", "./example/my/foo", "--"],
// This is for the SPECIAL CASE GRAPHIC to saving extended graphic files.
// To use this, the trigger option "render_extended" above must be activated.
// Sublime Text only supports PNG, JPG, and GIF images. Formatter uses PNG to display
// image in view and generates the same image in various formats for you.
// WARNING: Formatter will loop subprocess to render extended files. This means, process
// will takes more time. This option might be useful for the final step to production.
// "key":["value",..], where key is the output file extension, value is the command arguments.
"args_extended": {
"svg": ["{{e}}", "--config", "{{c}}", "--blabla-format", "svgv5", "--output", "{{o}}"],
"pdf": ["{{e}}", "--config", "{{c}}", "--blabla-format", "pdf2001", "--output", "{{o}}"]
}
},
// -- END of explanation --
}
}
- 示例设置插件: Formatter.sublime-settings
{
"debug": true,
"environ": {
"print_on_console": true,
"PATH": ["/path/to/erlang@22/bin:$PATH", "$PATH:/path/to/elixir/bin", "/path/to/.cache/rebar3/bin:$PATH"],
"GEM_PATH": ["${HOME}/to/my/ruby"],
"PYTHONPATH": ["${packages}/User/MyFolder/python/lib/python3.7/site-packages"],
"OLALA": ["$HOME/.cabal/bin:$PATH", "~/.olala/bin:$PATH"]
},
"formatters": {
"stylelint": { // EXAMPLE: MODULE METHOD
"info": "https://github.com/stylelint/stylelint",
"enable": true,
"format_on_paste": false,
"format_on_save": false,
"new_file_on_format": false,
"recursive_folder_format": {
"enable": false,
"exclude_folders_regex": ["Spotlight-V100", "temp", "cache", "logs", "^_.*foo\\$"],
"exclude_files_regex": ["^._.*$", ".*bar.exe"],
"exclude_extensions": ["DS_Store", "localized", "TemporaryItems", "Trashes", "db", "ini", "git", "svn", "tmp", "bak"],
"exclude_syntaxes": []
},
"syntaxes": ["css", "scss", "sass", "less", "sss", "sugarss"],
"executable_path": ["${packages}/User/myjs/node_modules/.bin/stylelint"],
"args": ["--config-basedir", "/path/to/js/node_modules"],
"config_path": {
"default": "${packages}/User/formatter.assets/config/stylelint_rc.json"
}
},
"uncrustify": { // EXAMPLE: GENERIC METHOD: Text-to-Text. Restart ST.
"name": "Uncrustify",
"type": "beautifier",
"success_code": 0,
"args": ["{{e}}", " --style=file:{{c}} ", "--"],
"info": "https://github.com/uncrustify/uncrustify",
"enable": true,
"format_on_save": false,
// "new_file_on_format": false, // Add this, if needed
// "recursive_folder_format": {...} // Add this, if needed
"syntaxes": ["c", "c++", "cs", "objc", "objc++", "d", "java", "pawn", "vala"],
"executable_path": ["${HOME}/path/to/bin/uncrustify"],
"config_path": {
"objc": "${packages}/User/formatter.assets/config/uncrustify_objc_rc.cfg",
"objc++": "${packages}/User/formatter.assets/config/uncrustify_objc_rc.cfg",
"java": "${packages}/User/formatter.assets/config/uncrustify_sun_java_rc.cfg",
"default": "${packages}/User/formatter.assets/config/uncrustify_rc.cfg"
}
},
"d2": { // EXAMPLE: GENERIC METHOD: Text-to-Image. Restart ST.
"name": "D2",
"type": "graphic",
"success_code": 0,
"render_extended": true,
"info": "https://github.com/terrastruct/d2",
"enable": true,
"format_on_save": false,
"format_on_paste": false,
"syntaxes": ["d2"],
"args": ["{{e}}", "--theme", "300", "--dark-theme", "200", "-l", "elk", "--pad", "0", "-", "{{o}}"],
"args_extended": {
"svg": ["{{e}}", "--theme", "300", "--dark-theme", "200", "-l", "elk", "--pad", "0", "-", "{{o}}"],
"pdf": ["{{e}}", "--theme", "300", "--dark-theme", "200", "-l", "elk", "--pad", "0", "-", "{{o}}"]
},
"executable_path": "/path/to/bin/d2",
"config_path": {
"default": "${packages}/User/formatter.assets/config/d2_rc.yaml"
}
}
}
}
自动检测格式化
从版本1.4.0开始,Formatter引入了一种配置机制来自动检测自身的格式化工具(特别感谢@midrare的理念、测试和建议)。有两种方法可以实现这一点:
- 使用User
Formatter.sublime-settings
中的嵌入式设置 - 在工作目录中放置点文件,类似于基于每个项目的。
优点:嵌入式设置可以处理已保存和未保存的文件,而点文件变体仅适用于已保存的文件,因为未保存的文件(视图中的puffer)永远不会有一个工作目录来包含点文件。
- 点文件变体:将在工作目录内的文件树中开始搜索,直到找到以下文件:
.sublimeformatter.json
OR.sublimeformatter
.sublimeformatter.json,.sublimeformatter
{
// Comments are allowed.
"json": {
"uid": "jsbeautifier"
},
"html": {
"uid": "jsbeautifier",
"exclude_syntaxes": {
"html": ["markdown"]
}
},
"python": {
"uid": "autopep8"
}
}
- 可以使用:
.sublimeformatter.user.json
或.sublimeformatter-user
设置用户特定的操作。
.sublimeformatter.user.json,.sublimeformatter-user
{
"format_on_save": true,
"format_on_paste": false
}
或者如果您喜欢字典格式
{
"format_on_save": {
"exclude_dirs_regex": [".*(\\.git|node_modules|__pycache__|env).*", ".*/project/test"],
"exclude_files_regex": [".*test_file\\.py\\$", ".*/project/test/config\\.json"],
"exclude_extensions_regex": ["ya?ml", "mjs", "json"]
},
"format_on_paste": false
}
- 要忽略应用于您的User
"config_path":
设置的特定语法,您可以使用:.sublimeformatter.cfgignore.json
或.sublimeformatter.cfgignore
例如,如果您更喜欢在工作目录中使用默认的.prettierrc而不是使用定制的Formatter"config_path":
.sublimeformatter.cfgignore.json,.sublimeformatter.cfgignore
{
"json": ["jsbeautifier", "deno"],
"python": ["autopep8"],
"default": ["scalafmt", "stylelint"]
}
- 嵌入式变体:将自动检测的配置嵌入到您的User
Formatter.sublime-settings
中。在点文件和嵌入式方法共存的情况下,点文件的配置将优先于嵌入式配置。
Formatter.sublime-settings
{
"debug": "status",
"auto_format": {
"config": {
"format_on_save": false, // or use the dictionary format to exclude
"format_on_paste": false // or use the dictionary format to exclude
},
"json": {
"uid": "jsbeautifier"
},
"html": {
"uid": "jsbeautifier",
"exclude_syntaxes": {
"html": ["markdown"]
}
},
"python": {
"uid": "autopep8"
}
},
"formatters": {}
}
这是一个一键/一键绑定功能。现在应用和上下文菜单将指示当前文件夹是否已准备好使用Formatter,带有新的项目:自动格式化文件
项目特定格式化
Formatter可以使用.sublime-project
文件为每个项目添加和覆盖任何设置。
您可能需要重新启动Sublime Text以将更改应用于.sublime-project
文件。
.sublime-project
{
"folders": [
{
"path": "/path/to/my/project"
}
],
"settings": {
"Formatter": {
"debug": "status",
"formatters": {
"htmltidy": {
"format_on_save": true
},
"jsbeautifier": {
"config_path": {
"default": "${HOME}/path/to/new/jsbeautify_rc.json"
}
}
}
}
}
}
使用
格式化器被设计用来检测不同文件域的语法,而不是文件扩展名。在大多数情况下,当你打开文件时,Sublime Text 已经为你做了这项工作。对其他文件,你必须通过右下角的语法菜单或以下方式显式分配语法。
Sublime Text > View > Syntax
在格式化代码时设置错误的语法会导致错误
Syntax out of the scope.
可以通过多种方式触发格式化操作
- 工具 > 命令面板 (Cmd+Shift+P 或 Ctrl+Shift+P),然后输入
Formatter
。 - 工具 > 格式化器
- 右键单击 > 右键菜单 > 格式化器
- 首选项 > 插件设置 > 格式化器 > 快捷键
快速选项
这个特性旨在帮助用户快速访问和切换选项,而无需导航设置文件。它包含3种模式
- 临时快速选项 (TQO):默认情况下,所有选项都是临时的,只对当前 Sublime 会话有效。当你关闭 Sublime 时,它们将被自动重置。
- 持久用户设置 (PUS):单击
重置
选项将重置所有当前的临时快速选项
并切换到使用你的Formatter.sublime-settings
文件中的用户设置。 - 持久快速选项 (PQO):单击
保存
选项将使所有当前的临时快速选项
持久化。这意味着关闭并重新打开 Sublime 将保留这些选项。要退出此模式,只需单击重置
选项。
总结
重置
选项是退出任何模式的唯一方法。- 单击已选中的相同项目将从列表中删除它。
- 没有哪种模式会修改您的设置文件。
- 当前模式将在状态栏中显示,供您参考。
开发
从版本 1.0.6 开始,你现在可以创建用于尚未集成到格式化器的第三方插件的自定义模块。这允许你扩展你的个别需求。从理论上讲,只要你使用的第三方插件以文本文本方式运行(例如文本到二维码,文本到 ASCII 图像转换),你可以将格式化器用作转换任何形式文本的平台。
1. 先决条件
- 如果有必要,创建一个针对第三方插件的特定配置文件。第三方插件的配置文件必须放置在以下文件夹中
Formatter > config
- 使用你的格式化器设置中的密钥
dev
激活调试模式。不应在生产环境中使用dev
密钥。
Formatter.sublime-settings
{
"debug": true, // printing error messages
"dev": true // updating modified files
...
}
2. 创建模块
开发格式化器的模块很简单。你所需要做的只是创建一个包含几行代码的 Python 文件,如下所示
- 在
Formatter > modules
文件夹内创建一个文件,文件名为formatter_thisismyfirstpluginmodule.py
。确保遵守以下约定
- 在
Formatter > modules
文件夹中,每个插件只创建一个文件- 所有函数和其他必要组件都应该放在这个文件中。
- 文件名全部使用 小写,并且只包含 字母数字 字符(不允许有空格或下划线)
- 前缀:
formatter_
(表示它是第三方插件的模块) - 后缀:
thisismyfirstpluginmodule
(作为独特的格式化器 ID,也称为 uid) - 扩展名:
.py
- 前缀:
- 第三方插件依赖的外部库应该放置在
Formatter > libs
文件夹中- 库不得包含专有元素,包括许可证文件或许可证通知。
- 不要进行互联网通信。
- 此模块文件的文档结构如下
formatter_thisismyfirstpluginmodule.py
INTERPRETERS = [] # optional: fallback list of interpreter names
EXECUTABLES = [] # REQUIRED: fallback list of executable names
DOTFILES = [] # optional: names list of the per-project config dotfiles
MODULE_CONFIG = {} # REQUIRED: template to create several sublime config files
class ThisismyfirstpluginmoduleFormatter(Module): # REQUIRED: the Capitalized of uid and the Capitalized word "Formatter", nothing else!
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # REQUIRED: initialize the module APIs from common.Module
def get_cmd(self): # optional: get commands, e.g get the "config_path", "executable_path" etc...
def format(self): # REQUIRED: the entry point, predefined function name exact as written
以示例的形式提供详细信息
from .. import log # REQUIRED: log to debugging this file
from ..core.common import Module # REQUIRED: a collection of APIs to assist in running this file
INTERPRETERS = ['node'] # optional: case-sensitive fallback names (without extension) if interpreter is not found
EXECUTABLES = ['terser'] # optional: case-sensitive fallback names (without extension) if executable is not found
DOTFILES = ['.terser.json'] # optional: to auto-resolve the per-project config dotfile if "config_path" is disabled
MODULE_CONFIG = { # REQUIRED: template to create several sublime config files
'source': 'https://thirdparty-plugin.com', # REQUIRED: info on where the user can download the plugin
'name': 'My First Plugin', # REQUIRED: a Capitalized plugin name of your choice, preferably short and comprehensive
'uid': 'thisismyfirstpluginmodule', # REQUIRED: must match the suffix of "formatter_thisismyfirstpluginmodule.py"
'type': 'minifier', # REQUIRED: "beautifier" OR "minifier" OR "converter" OR "graphic",
# OR any string of your choice (for private purposes).
'syntaxes': ['js', 'html'], # REQUIRED: array of syntaxes, obtained from: Tools > Developer > Show Scope Name
'exclude_syntaxes': { # optional: blacklist syntaxes per syntax or None to omit it.
'html': ['markdown']
},
"interpreter_path": ["/path/to/bin/node"], # optional: use an empty string "" to include this key in config files or None to omit it
"executable_path": ["/path/to/bin/terser"], # optional: use an empty string "" to include this key in config files or None to omit it
'args': None, # optional: an array ['arg1', 'args2', ...] to include this key in config files or None to omit it
'config_path': { # optional: a dictionary to include this key in config files or None to omit it
'js': 'my_first_plugin_js_rc.json' # optional: a key-value pair or just omit it. See Formatter.sublime-settings for explanation
'default': 'my_first_plugin_rc.json' # optional: a key-value pair or just omit it. See Formatter.sublime-settings for explanation
},
'comment': 'build-in, no executable' # optional: a single short comment, limited to 200 chars or just omit it
}
class ThisismyfirstpluginmoduleFormatter(Module): # REQUIRED: the Capitalized of uid and the Capitalized word "Formatter", nothing else!
def __init__(self, *args, **kwargs): # REQUIRED: initialization
super().__init__(*args, **kwargs) # REQUIRED: initialize the module APIs from common.Module
def get_cmd(self): # optional: get commands e.g get the "config_path", "executable_path" etc...
cmd = self.get_combo_cmd(runtime_type='node') # See API below
if not cmd:
return None
path = self.get_config_path() # See API below
if path:
cmd.extend(['--config-file', path]) # an array of args to run the third-party plugin
cmd.extend(['--compress', '--mangle', '--'])
# cmd.extend(['--output', self.get_output_image()]) # REQUIRED: only for special case of "type": "graphic"
return cmd
def format(self): # REQUIRED: the entry point, predefined function name exact as written
cmd = self.get_cmd()
try:
exitcode, stdout, stderr = self.exec_cmd(cmd) # REQUIRED: process command
if exitcode > 0: # REQUIRED: please consult the plugin documentation for the exit codes
self.print_exiterr(exitcode, stderr)
else:
# if self.is_render_extended(): # is render extended mode activated?
# cmd = self.all_png_to_svg_cmd(cmd)
# try:
# self.exec_cmd(cmd) # REQUIRED: only for special case of "type": "graphic" to generate SVG image.
# except Exception as e:
# log.error('Error: %s', e)
return stdout # REQUIRED: return the formatted code on success
except OSError:
self.print_oserr(cmd)
return None # REQUIRED: return None to indicate failure
这就完了。简洁易用。快乐编码 🤪
重启 Sublime Text。
新的键将自动创建在 默认 设置中。
别忘了更新/调整你的 用户 设置
首选项 > 包设置 > 格式化 > 设置
3. 模块集成
你可以选择提交一个拉取请求,或者通过配置自己集成你的模块
Formatter.sublime-settings
{
"custom_modules_manifest": "/path/to/local/metadata.json", // or
"custom_modules_manifest": "https://raw.githubusercontent.com/you/repo/main/metadata.json",
}
元数据 JSON 文件的结构应遵循以下格式
{
"version": "0.0.1", // tells to update
"ca_cert": "/path/to/ca_cert.pem", // optional, CA Certificate path for ssl
"public_key": "/path/to/public_key.asc", // optional, but required for .sig file
"gpg": "gpg.exe (on PATH) or /path/to/gpg.exe", // optional, omit this to auto-detect gpg on PATH
"local": {
"config": ["/path/to/dir", "/path/to/file"],
"libs": ["/path/to/dir", "/path/to/file"],
"modules": ["/path/to/dir", "/path/to/file"]
},
"remote": [
"http|s|ftp://example.com/archive/refs/heads/myproject1.zip", // only zip or tar.gz
"http|s|ftp://example.com/archive/refs/heads/myproject1.zip.sig", // optional, but pattern: filename + '.sig'
"http|s|ftp://example.com/archive/refs/heads/myproject2.tar.gz",
"http|s|ftp://example.com/archive/refs/heads/myproject2.tar.gz.sig"
]
}
- 每个远程存档文件(myproject.zip)必须包含以下固定文件夹中的一个:
config
、libs
、modules
- 所有文件都必须放在这 3 个 预定义 文件夹内。
- 要更新你的代码,只需重置格式化根文件夹中的
.custom
文件。 - 以下格式化模块不能替换:
prettytable
、sqlmin
、toml
、wcswidth
、yaml
Python 不是 JS。你负责处理所有互联网上的操作。
4. API
整个格式化 API 可以在文件中找到:core > common.py
负责与插件模块交互的是类:class Module:
- 主要是对
def get_cmd(self)
函数
# This alias method combines get_interpreter() and get_executable().
# Set runtime_type=(None|'node'|'python'|'perl'|'ruby') to enable local executable search.
# Currently, only None and 'node' are functional. All others are placeholders for future use.
cmd = self.get_iprexe_cmd(runtime_type=None)
# This alias method just extends get_iprexe_cmd() with get_args().
cmd = self.get_combo_cmd(runtime_type=None)
# Get the interpreter path or None.
interpreter = self.get_interpreter()
# Get the executable path or None.
# Set runtime_type=(None|'node'|'python'|'perl'|'ruby') to enable local executable search.
executable = self.get_executable(runtime_type=None)
# Get the input arguments "args" from the User settings or None.
args = self.get_args()
# Get the input "config_path" from the User settings or
# the path of the per-project config dotfile if found or None.
path = self.get_config_path()
# Get the current text content in view or the current selected text.
text = self.get_text_from_region(self.region)
# Get the detected syntax of the current file or None.
syntax = self.get_assigned_syntax()
# Get the path to the output PNG image. Applicable only to the special case of type: graphic
output_image = self.get_output_image()
# Get a dictionary of file path components:
# {'path':, 'cwd':, 'base':, 'stem':, 'suffix':, 'ext':} or None.
components = self.get_pathinfo()
# Create and get the temp file path.
# Useful for plugins lacking a built-in mechanism to fix files inplace.
tmp_file = self.create_tmp_file(suffix=None)
# Remove temp file.
self.remove_tmp_file(tmp_file)
- 主要是对
def format(self)
函数
# To replace cmd list items to generate SVG file for download.
# It is applicable only to the special case of type: graphic.
# Note: extended_cmd MUST be executed right before return stdout (=success)!
extended_cmd = self.ext_png_to_svg_cmd(cmd) # replace extension .png -> .svg
extended_cmd = self.all_png_to_svg_cmd(cmd) # replace all occurred png -> svg
# To process the formatting with all input (fixed) arguments.
# stdout as PIPE. 99% of plugins use this way.
exitcode, stdout, stderr = self.exec_cmd(cmd)
# stdout as file. 1% are just retarded.
exitcode, stdout, stderr = self.exec_cmd(cmd, outfile='/path/to/save/outfile')
# To print formatting exit error.
self.print_exiterr(exitcode, stderr)
# To print executing commands error.
self.print_oserr(cmd)
已废弃的API和设置
以下 API 和设置已被弃用,将在下一个版本中 移除
自定义模块 API
log = logging.getLogger(__name__)
(建议使用from .. import log
)self.is_valid_cmd(cmd)
self.fix_cmd(cmd)
格式化.sublime-settings 选项
"custom_modules"
(建议使用"custom_modules_manifest"
)"format_on_unique"
(建议使用"format_on_priority"
)"disable"
(建议使用"enable"
)