Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1226 lines
44 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. ;;; format-all.el --- Auto-format C, C++, JS, Python, Ruby and 50 other languages -*- lexical-binding: t -*-
  2. ;;
  3. ;; Author: Lassi Kortela <lassi@lassi.io>
  4. ;; URL: https://github.com/lassik/emacs-format-all-the-code
  5. ;; Package-Version: 0.4.0
  6. ;; Package-Commit: caa0269ce89789a702823041ca7b309ddaffb5ce
  7. ;; Version: 0.4.0
  8. ;; Package-Requires: ((emacs "24.3") (inheritenv "0.1") (language-id "0.12"))
  9. ;; Keywords: languages util
  10. ;; SPDX-License-Identifier: MIT
  11. ;;
  12. ;; This file is not part of GNU Emacs.
  13. ;;
  14. ;;; Commentary:
  15. ;;
  16. ;; Lets you auto-format source code in many languages using the same
  17. ;; command for all languages, instead of learning a different Emacs
  18. ;; package and formatting command for each language.
  19. ;;
  20. ;; Just do M-x format-all-buffer and it will try its best to do the
  21. ;; right thing. To auto-format code on save, use the minor mode
  22. ;; format-all-mode. Please see the documentation for that function
  23. ;; for instructions.
  24. ;;
  25. ;; Supported languages:
  26. ;;
  27. ;; - Angular/Vue (prettier)
  28. ;; - Assembly (asmfmt)
  29. ;; - ATS (atsfmt)
  30. ;; - Bazel Starlark (buildifier)
  31. ;; - BibTeX (Emacs)
  32. ;; - C/C++/Objective-C (clang-format, astyle)
  33. ;; - C# (clang-format, astyle)
  34. ;; - Cabal (cabal-fmt)
  35. ;; - Clojure/ClojureScript (node-cljfmt)
  36. ;; - CMake (cmake-format)
  37. ;; - Crystal (crystal tool format)
  38. ;; - CSS/Less/SCSS (prettier)
  39. ;; - D (dfmt)
  40. ;; - Dart (dartfmt)
  41. ;; - Dhall (dhall format)
  42. ;; - Dockerfile (dockfmt)
  43. ;; - Elixir (mix format)
  44. ;; - Elm (elm-format)
  45. ;; - Emacs Lisp (Emacs)
  46. ;; - Fish Shell (fish_indent)
  47. ;; - Fortran 90 (fprettify)
  48. ;; - Gleam (gleam format)
  49. ;; - GLSL (clang-format)
  50. ;; - Go (gofmt, goimports)
  51. ;; - GraphQL (prettier)
  52. ;; - Haskell (brittany, hindent, ormolu, stylish-haskell)
  53. ;; - HTML/XHTML/XML (tidy)
  54. ;; - Java (clang-format, astyle)
  55. ;; - JavaScript/JSON/JSX (prettier, standard)
  56. ;; - Jsonnet (jsonnetfmt)
  57. ;; - Kotlin (ktlint)
  58. ;; - LaTeX (latexindent)
  59. ;; - Ledger (ledger-mode)
  60. ;; - Lua (lua-fmt, prettier plugin-lua)
  61. ;; - Markdown (prettier)
  62. ;; - Nix (nixpkgs-fmt, nixfmt)
  63. ;; - OCaml (ocp-indent)
  64. ;; - Perl (perltidy)
  65. ;; - PHP (prettier plugin-php)
  66. ;; - Protocol Buffers (clang-format)
  67. ;; - PureScript (purty)
  68. ;; - Python (black, yapf)
  69. ;; - R (styler)
  70. ;; - Reason (bsrefmt)
  71. ;; - ReScript (resfmt)
  72. ;; - Ruby (rufo)
  73. ;; - Rust (rustfmt)
  74. ;; - Scala (scalafmt)
  75. ;; - Shell script (beautysh, shfmt)
  76. ;; - Snakemake (snakefmt)
  77. ;; - Solidity (prettier prettier-plugin-solidity)
  78. ;; - SQL (pgformatter, sqlformat)
  79. ;; - Swift (swiftformat)
  80. ;; - Terraform (terraform fmt)
  81. ;; - TOML (prettier prettier-plugin-toml)
  82. ;; - TypeScript/TSX (prettier)
  83. ;; - Verilog (iStyle)
  84. ;; - YAML (prettier)
  85. ;;
  86. ;; You will need to install external programs to do the formatting.
  87. ;; If `format-all-buffer` can't find the right program, it will try to
  88. ;; tell you how to install it.
  89. ;;
  90. ;; Many of the external formatters support configuration files in the
  91. ;; source code directory to control their formatting. Please see the
  92. ;; documentation for each formatter.
  93. ;;
  94. ;; New external formatters can be added easily if they can read code
  95. ;; from standard input and format it to standard output. Feel free to
  96. ;; submit a pull request or ask for help in GitHub issues.
  97. ;;
  98. ;;; Code:
  99. (require 'cl-lib)
  100. (require 'inheritenv)
  101. (require 'language-id)
  102. (defgroup format-all nil
  103. "Lets you auto-format source code."
  104. :group 'format-all)
  105. (defcustom format-all-debug nil
  106. "When non-nil, troubleshooting info is written into the *Messages* buffer."
  107. :type 'boolean
  108. :group 'format-all)
  109. (defcustom format-all-default-formatters
  110. '(("Assembly" asmfmt)
  111. ("ATS" atsfmt)
  112. ("Bazel" buildifier)
  113. ("BibTeX" bibtex-mode)
  114. ("C" clang-format)
  115. ("C#" clang-format)
  116. ("C++" clang-format)
  117. ("Cabal Config" cabal-fmt)
  118. ("Clojure" cljfmt)
  119. ("CMake" cmake-format)
  120. ("Crystal" crystal)
  121. ("CSS" prettier)
  122. ("D" dfmt)
  123. ("Dart" dartfmt)
  124. ("Dhall" dhall)
  125. ("Dockerfile" dockfmt)
  126. ("Elixir" mix-format)
  127. ("Elm" elm-format)
  128. ("Emacs Lisp" emacs-lisp)
  129. ("Fish" fish-indent)
  130. ("GLSL" clang-format)
  131. ("Go" gofmt)
  132. ("GraphQL" prettier)
  133. ("Haskell" brittany)
  134. ("HTML" html-tidy)
  135. ("Java" clang-format)
  136. ("JavaScript" prettier)
  137. ("JSON" prettier)
  138. ("Jsonnet" jsonnetfmt)
  139. ("JSX" prettier)
  140. ("Kotlin" ktlint)
  141. ("LaTeX" latexindent)
  142. ("Less" prettier)
  143. ("Literate Haskell" brittany)
  144. ("Lua" lua-fmt)
  145. ("Markdown" prettier)
  146. ("Nix" nixpkgs-fmt)
  147. ("Objective-C" clang-format)
  148. ("OCaml" ocp-indent)
  149. ("Perl" perltidy)
  150. ("PHP" prettier)
  151. ("Protocol Buffer" clang-format)
  152. ("PureScript" purty)
  153. ("Python" black)
  154. ("R" styler)
  155. ("Reason" bsrefmt)
  156. ("ReScript" resfmt)
  157. ("Ruby" rufo)
  158. ("Rust" rustfmt)
  159. ("Scala" scalafmt)
  160. ("SCSS" prettier)
  161. ("Shell" shfmt)
  162. ("Solidity" prettier)
  163. ("SQL" sqlformat)
  164. ("Swift" swiftformat)
  165. ("Terraform" terraform-fmt)
  166. ("TOML" prettier)
  167. ("TSX" prettier)
  168. ("TypeScript" prettier)
  169. ("Verilog" istyle-verilog)
  170. ("Vue" prettier)
  171. ("XML" html-tidy)
  172. ("YAML" prettier)
  173. ("_Angular" prettier)
  174. ("_Flow" prettier)
  175. ("_Fortran 90" fprettify)
  176. ("_Gleam" gleam)
  177. ("_Ledger" ledger-mode)
  178. ("_Snakemake" snakefmt))
  179. "Default formatter to use for each language."
  180. :type '(repeat (list string symbol))
  181. :group 'format-all)
  182. (defcustom format-all-always-show-errors nil
  183. "When non-nil, warnings are shown even when formatting is successful."
  184. :type 'boolean
  185. :group 'format-all)
  186. (defvar format-all-after-format-functions nil
  187. "Hook run after each time `format-all-buffer' has formatted a buffer.
  188. The value is a list of hook functions. Use `add-hook' to add a
  189. function. The function is called with two arguments: (FORMATTER
  190. STATUS). FORMATTER is a symbol naming the formatter, as given to
  191. `define-format-all-formatter'. STATUS is one of the following
  192. keywords:
  193. * :reformatted -- The formatter made changes to the buffer.
  194. * :already-formatted -- The buffer was already formatted
  195. correctly so the formatter didn't make any changes to it.
  196. * :error -- The formatter encountered an error (usually a syntax
  197. error). The buffer contents are the same as before formatting.
  198. The current buffer is the buffer that was just formatted. Point
  199. is not guaranteed to be in any particular place, so `goto-char'
  200. before editing the buffer. Narrowing may be in effect unless
  201. STATUS is :reformatted.")
  202. (defvar format-all--user-args nil
  203. "Internal variable to temporarily store arguments for formatters.")
  204. (defvar-local format-all-formatters nil
  205. "Rules to select which formatter format-all uses.
  206. The value is an association list.
  207. The first item of each association is the name of a programming
  208. language. (GitHub Linguist names are used.)
  209. The remaining items are one or more formatters to use for that
  210. language. Each formatter is either:
  211. * a symbol (e.g. black, clang-format, rufo)
  212. * a list whose first item is that symbol, and any remaining items
  213. are extra command line arguments to pass to the formatter
  214. If more than one formatter is given for the same language, all of
  215. them are run as a chain, with the code from each formatter passed
  216. to the next. The final code is from the last formatter. In case
  217. any formatter in the chain is missing or fails to format the
  218. code, the entire chain fails and the old code before formatting
  219. is preserved.
  220. You'll probably want to set this in a \".dir-locals.el\" file or
  221. in a hook function. Any number of buffers can share the same
  222. association list. Using \".dir-locals.el\" is convenient since
  223. the rules for an entire source tree can be given in one file.")
  224. (defun format-all--proper-list-p (object)
  225. "Return t if OBJECT is a proper list, nil otherwise."
  226. ;; If we could depend on Emacs 27.1 this function would be built in.
  227. (and (listp object) (not (null (cl-list-length object)))))
  228. (defun format-all--normalize-formatter (formatter)
  229. "Internal function to convert FORMATTER spec into normal form."
  230. (let ((formatter (if (listp formatter) formatter (list formatter))))
  231. (when (cdr (last formatter))
  232. (error "Formatter is not a proper list: %S" formatter))
  233. (when (null formatter)
  234. (error "Formatter name missing"))
  235. (unless (symbolp (car formatter))
  236. (error "Formatter name is not a symbol: %S" (car formatter)))
  237. (unless (cl-every #'stringp (cdr formatter))
  238. (error "Formatter command line arguments are not all strings: %S"
  239. formatter))
  240. formatter))
  241. (defun format-all--normalize-chain (chain)
  242. "Internal function to convert CHAIN spec into normal form."
  243. (when (or (not (listp chain)) (cdr (last chain)))
  244. (error "Formatter chain is not a proper list: %S" chain))
  245. (mapcar #'format-all--normalize-formatter chain))
  246. (defun format-all-valid-formatters-p (formatters)
  247. "Return t if FORMATTERS is a valid value for `format-all-formatters'."
  248. (and (format-all--proper-list-p formatters)
  249. (cl-every
  250. (lambda (chain)
  251. (and (not (null chain))
  252. (format-all--proper-list-p chain)
  253. (stringp (car chain))
  254. (cl-every
  255. (lambda (formatter)
  256. (and (not (null formatter))
  257. (or (symbolp formatter)
  258. (and (format-all--proper-list-p formatter)
  259. (and (symbolp (car formatter))
  260. (not (null (car formatter))))
  261. (cl-every #'stringp (cdr formatter))))))
  262. (cdr chain))))
  263. formatters)))
  264. (put 'format-all-formatters 'safe-local-variable
  265. 'format-all-valid-formatters-p)
  266. (eval-and-compile
  267. (defconst format-all--system-type
  268. (cl-case system-type
  269. (windows-nt 'windows)
  270. (cygwin 'windows)
  271. (darwin 'macos)
  272. (gnu/linux 'linux)
  273. (berkeley-unix
  274. (save-match-data
  275. (let ((case-fold-search t))
  276. (cond ((string-match "freebsd" system-configuration) 'freebsd)
  277. ((string-match "openbsd" system-configuration) 'openbsd)
  278. ((string-match "netbsd" system-configuration) 'netbsd))))))
  279. "Current operating system according to the format-all package."))
  280. (eval-and-compile
  281. (defun format-all--resolve-system (choices)
  282. "Get first choice matching `format-all--system-type' from CHOICES."
  283. (cl-dolist (choice choices)
  284. (cond ((atom choice)
  285. (cl-return choice))
  286. ((eql format-all--system-type (car choice))
  287. (cl-return (cadr choice)))))))
  288. (defun format-all--fix-trailing-whitespace ()
  289. "Fix trailing whitespace since some formatters don't do that."
  290. (save-match-data
  291. (goto-char (point-min))
  292. (while (re-search-forward "[ \t]+$" nil t)
  293. (replace-match ""))
  294. (goto-char (point-max))
  295. (delete-region
  296. (if (re-search-backward "[^ \t\n]" nil t) (match-end 0) (point-min))
  297. (point-max))
  298. (unless (= (point-min) (point-max))
  299. (goto-char (point-max))
  300. (insert "\n"))))
  301. (defun format-all--remove-ansi-color (string)
  302. "Internal helper function to remove terminal color codes from STRING."
  303. (save-match-data (replace-regexp-in-string "\x1b\\[[0-9]+m" "" string t)))
  304. (defun format-all--flatten-once (list)
  305. "Internal helper function to remove nested lists in LIST."
  306. (cl-mapcan (lambda (x) (if (listp x) x (list x)))
  307. list))
  308. (defun format-all--buffer-extension-p (&rest extensions)
  309. "Internal helper function to test file name EXTENSIONS."
  310. (and (buffer-file-name)
  311. (save-match-data
  312. (let ((case-fold-search t))
  313. (cl-some (lambda (ext)
  314. (string-match (concat "\\." (regexp-quote ext) "\\'")
  315. (buffer-file-name)))
  316. extensions)))))
  317. (defun format-all--buffer-thunk (thunk)
  318. "Internal helper function to implement formatters.
  319. THUNK is a function that implements a particular formatter. It
  320. takes INPUT (the unformatted source code as a string). THUNK is
  321. invoked such that the current buffer is an empty temp buffer. It
  322. should call the formatter on INPUT and write the formatted source
  323. code output to the temp buffer. It should return (ERRORP
  324. ERROR-OUTPUT). ERRORP is a boolean indicating whether the formatter
  325. caused an error and hence the contents of the temp buffer should
  326. be discarded. ERROR-OUTPUT is a string containing all error/warning
  327. output from the formatter.
  328. Note that in some cases we can use the output of the formatter
  329. even if it produced warnings. Not all warnings are errors."
  330. (save-excursion
  331. (save-restriction
  332. (widen)
  333. (let ((inbuf (current-buffer))
  334. (input (buffer-string)))
  335. (inheritenv
  336. (with-temp-buffer
  337. (cl-destructuring-bind (errorp error-output) (funcall thunk input)
  338. (let* ((no-chg (or errorp
  339. (= 0 (let ((case-fold-search nil))
  340. (compare-buffer-substrings
  341. inbuf nil nil nil nil nil)))))
  342. (output (cond (errorp nil)
  343. (no-chg t)
  344. (t (buffer-string)))))
  345. (list output error-output)))))))))
  346. (defun format-all--buffer-native (mode &rest funcs)
  347. "Internal helper function to implement formatters.
  348. In a new temp buffer, switches to MODE then calls FUNCS in order
  349. to format the code. MODE and FUNCS should be symbols instead of
  350. functions to avoid warnings from the Emacs byte compiler."
  351. (format-all--buffer-thunk
  352. (lambda (input)
  353. (funcall mode)
  354. (insert input)
  355. (mapc #'funcall funcs)
  356. (format-all--fix-trailing-whitespace)
  357. (list nil ""))))
  358. (defun format-all--locate-file (filename)
  359. "Internal helper to locate dominating copy of FILENAME for current buffer."
  360. (let* ((dir (and (buffer-file-name)
  361. (locate-dominating-file (buffer-file-name) filename))))
  362. (when dir (expand-file-name (concat dir filename)))))
  363. (defun format-all--locate-default-directory (root-files)
  364. "Internal helper function to find working directory for formatter.
  365. ROOT-FILES is a list of strings which are the filenames to look
  366. for using `locate-dominating-file'. Details in documentation for
  367. `format-all--buffer-hard'."
  368. (let ((found-dirs
  369. (when (and root-files (buffer-file-name))
  370. (mapcan (lambda (root-file)
  371. (let ((found-file (locate-dominating-file
  372. (buffer-file-name) root-file)))
  373. (when found-file
  374. (list (file-name-directory found-file)))))
  375. root-files))))
  376. (or (car (sort found-dirs (lambda (a b) (> (length a) (length b)))))
  377. (and (buffer-file-name) (file-name-directory (buffer-file-name)))
  378. default-directory)))
  379. (defun format-all--buffer-hard
  380. (ok-statuses error-regexp root-files executable &rest args)
  381. "Internal helper function to implement formatters.
  382. Runs the external program EXECUTABLE. The program shall read
  383. unformatted code from stdin, write its formatted equivalent to
  384. stdout, and write errors/warnings to stderr.
  385. The program should exit with status zero for the formatting to be
  386. considered successful. If a list of OK-STATUSES is given, all of
  387. those are actually considered successful. But if ERROR-REGEXP is
  388. given, and the program's stderr contains that regexp, then the
  389. formatting is considered failed even if the exit status is in
  390. OK-STATUSES. OK-STATUSES and ERROR-REGEXP are hacks to work
  391. around formatter programs that don't make sensible use of their
  392. exit status.
  393. If ARGS are given, those are arguments to EXECUTABLE. They should
  394. not be shell-quoted.
  395. If ROOT-FILES are given, the working directory of the formatter
  396. will be the deepest directory (starting from the file being
  397. formatted) containing one of these files. If ROOT-FILES is nil,
  398. or none of ROOT-FILES are found in any parent directories, the
  399. working directory will be the one where the formatted file is.
  400. ROOT-FILES is ignored for buffers that are not visiting a file."
  401. (let ((ok-statuses (or ok-statuses '(0)))
  402. (args (append format-all--user-args (format-all--flatten-once args)))
  403. (default-directory (format-all--locate-default-directory root-files)))
  404. (when format-all-debug
  405. (message "Format-All: Running: %s"
  406. (mapconcat #'shell-quote-argument (cons executable args) " "))
  407. (message "Format-All: Directory: %s" default-directory))
  408. (format-all--buffer-thunk
  409. (lambda (input)
  410. (let* ((errfile (make-temp-file "format-all-"))
  411. (status (apply #'call-process-region input nil
  412. executable nil (list t errfile)
  413. nil args))
  414. (error-output (with-temp-buffer
  415. (insert-file-contents errfile)
  416. (delete-file errfile)
  417. (buffer-string)))
  418. (errorp (or (not (member status ok-statuses))
  419. (and error-regexp
  420. (save-match-data
  421. (string-match error-regexp error-output))))))
  422. (list errorp error-output))))))
  423. (defun format-all--buffer-easy (executable &rest args)
  424. "Internal helper function to implement formatters.
  425. Runs the external program EXECUTABLE. The program shall read
  426. unformatted code from stdin, write its formatted equivalent to
  427. stdout, write errors/warnings to stderr, and exit zero/non-zero
  428. on success/failure.
  429. If ARGS are given, those are arguments to EXECUTABLE. They don't
  430. need to be shell-quoted."
  431. (apply 'format-all--buffer-hard nil nil nil executable args))
  432. (defvar format-all--executable-table (make-hash-table)
  433. "Internal table of formatter executable names for format-all.")
  434. (defvar format-all--install-table (make-hash-table)
  435. "Internal table of formatter install commands for format-all.")
  436. (defvar format-all--language-table (make-hash-table :test 'equal)
  437. "Internal table of major mode formatter lists for format-all.")
  438. (defvar format-all--format-table (make-hash-table)
  439. "Internal table of formatter formatting functions for format-all.")
  440. (defun format-all--pushhash (key value table)
  441. "Push VALUE onto the list under KEY in hash table TABLE."
  442. (puthash key (cons value (remove value (gethash key table))) table))
  443. (defmacro define-format-all-formatter (formatter &rest body)
  444. "Define a new source code formatter for use with format-all.
  445. FORMATTER is a symbol naming the formatter. The name of the
  446. command used to run the formatter is usually a good choice.
  447. Consult the existing formatters for examples of BODY."
  448. (let (executable install languages format)
  449. (cl-assert
  450. (equal (mapcar 'car body) '(:executable :install :languages :format)))
  451. (cl-dolist (part body)
  452. (cl-ecase (car part)
  453. (:executable
  454. (setq executable
  455. (unless (null (cdr part))
  456. (or (format-all--resolve-system (cdr part))
  457. (error "Executable not specified for %S system %S"
  458. formatter format-all--system-type)))))
  459. (:install
  460. (setq install (format-all--resolve-system (cdr part))))
  461. (:languages
  462. (setq languages
  463. (mapcar (lambda (language)
  464. `(format-all--pushhash
  465. ',language ',formatter format-all--language-table))
  466. (cdr part))))
  467. (:format
  468. (setq format `(lambda (executable language)
  469. (ignore language ,@(unless executable '(executable)))
  470. ,(cadr part))))))
  471. `(progn (puthash ',formatter ,executable format-all--executable-table)
  472. (puthash ',formatter ,install format-all--install-table)
  473. ,@languages
  474. (puthash ',formatter ,format format-all--format-table)
  475. ',formatter)))
  476. (define-format-all-formatter asmfmt
  477. (:executable "asmfmt")
  478. (:install)
  479. (:languages "Assembly")
  480. (:format (format-all--buffer-easy executable)))
  481. (define-format-all-formatter astyle
  482. (:executable "astyle")
  483. (:install (macos "brew install astyle"))
  484. (:languages "C" "C++" "C#" "Java")
  485. (:format (format-all--buffer-easy
  486. executable
  487. (let ((astylerc (format-all--locate-file ".astylerc")))
  488. (when astylerc (concat "--options=" astylerc))))))
  489. (define-format-all-formatter atsfmt
  490. (:executable "atsfmt")
  491. (:install "cabal new-install ats-format --happy-options='-gcsa' -O2")
  492. (:languages "ATS")
  493. (:format (format-all--buffer-easy executable)))
  494. (define-format-all-formatter beautysh
  495. (:executable "beautysh")
  496. (:install "pip install beautysh")
  497. (:languages "Shell")
  498. (:format (format-all--buffer-easy executable "-")))
  499. (define-format-all-formatter bibtex-mode
  500. (:executable)
  501. (:install)
  502. (:languages "BibTeX")
  503. (:format (format-all--buffer-native
  504. 'bibtex-mode 'bibtex-reformat 'bibtex-sort-buffer)))
  505. (define-format-all-formatter black
  506. (:executable "black")
  507. (:install "pip install black")
  508. (:languages "Python")
  509. (:format (format-all--buffer-easy
  510. executable "-q"
  511. (when (format-all--buffer-extension-p "pyi") "--pyi")
  512. "-")))
  513. (define-format-all-formatter brittany
  514. (:executable "brittany")
  515. (:install "stack install brittany")
  516. (:languages "Haskell" "Literate Haskell")
  517. (:format (format-all--buffer-easy executable)))
  518. (define-format-all-formatter bsrefmt
  519. (:executable "bsrefmt")
  520. (:install "npm install --global bs-platform")
  521. (:languages "Reason")
  522. (:format (format-all--buffer-easy executable)))
  523. (define-format-all-formatter buildifier
  524. (:executable "buildifier")
  525. (:install
  526. (macos "brew install buildifier")
  527. "go get github.com/bazelbuild/buildtools/buildifier")
  528. (:languages "Bazel")
  529. (:format (format-all--buffer-easy executable)))
  530. (define-format-all-formatter cabal-fmt
  531. (:executable "cabal-fmt")
  532. (:install "cabal install cabal-fmt")
  533. (:languages "Cabal Config")
  534. (:format (format-all--buffer-easy executable)))
  535. (define-format-all-formatter clang-format
  536. (:executable "clang-format")
  537. (:install
  538. (macos "brew install clang-format")
  539. (windows "scoop install llvm"))
  540. (:languages "C" "C#" "C++" "GLSL" "Java" "Objective-C" "Protocol Buffer")
  541. (:format
  542. (format-all--buffer-easy
  543. executable
  544. (concat "-assume-filename="
  545. (or (buffer-file-name)
  546. (cdr (assoc language
  547. '(("C" . ".c")
  548. ("C#" . ".cs")
  549. ("C++" . ".cpp")
  550. ("GLSL" . ".glsl")
  551. ("Java" . ".java")
  552. ("Objective-C" . ".m")
  553. ("Protocol Buffer" . ".proto")))))))))
  554. (define-format-all-formatter cljfmt
  555. (:executable "cljfmt")
  556. (:install "npm install --global node-cljfmt")
  557. (:languages "Clojure")
  558. (:format (format-all--buffer-easy executable)))
  559. (define-format-all-formatter cmake-format
  560. (:executable "cmake-format")
  561. (:install "pip install cmake-format")
  562. (:languages "CMake")
  563. (:format (format-all--buffer-easy executable "-")))
  564. (define-format-all-formatter crystal
  565. (:executable "crystal")
  566. (:install (macos "brew install crystal"))
  567. (:languages "Crystal")
  568. (:format (format-all--buffer-easy executable "tool" "format" "-")))
  569. (define-format-all-formatter dartfmt
  570. (:executable "dartfmt")
  571. (:install (macos "brew tap dart-lang/dart && brew install dart"))
  572. (:languages "Dart")
  573. (:format
  574. (format-all--buffer-easy
  575. executable
  576. (when (buffer-file-name)
  577. (list "--stdin-name" (buffer-file-name))))))
  578. (define-format-all-formatter dfmt
  579. (:executable "dfmt")
  580. (:install (macos "brew install dfmt"))
  581. (:languages "D")
  582. (:format
  583. (format-all--buffer-hard nil (regexp-quote "[error]") nil executable)))
  584. (define-format-all-formatter dhall
  585. (:executable "dhall")
  586. (:install (macos "brew install dhall"))
  587. (:languages "Dhall")
  588. (:format (format-all--buffer-easy executable "format")))
  589. (define-format-all-formatter dockfmt
  590. (:executable "dockfmt")
  591. (:install "go get github.com/jessfraz/dockfmt")
  592. (:languages "Dockerfile")
  593. (:format (format-all--buffer-easy executable "fmt")))
  594. (define-format-all-formatter elm-format
  595. (:executable "elm-format")
  596. (:install (macos "brew install elm"))
  597. (:languages "Elm")
  598. (:format
  599. (cl-destructuring-bind (output error-output)
  600. (format-all--buffer-hard nil nil '("elm.json" "elm-package.json")
  601. executable "--yes" "--stdin")
  602. (let ((error-output (format-all--remove-ansi-color error-output)))
  603. (list output error-output)))))
  604. (define-format-all-formatter emacs-lisp
  605. (:executable)
  606. (:install)
  607. (:languages "Emacs Lisp")
  608. (:format
  609. (format-all--buffer-native
  610. 'emacs-lisp-mode
  611. (lambda () (indent-region (point-min) (point-max))))))
  612. (define-format-all-formatter fish-indent
  613. (:executable "fish_indent")
  614. (:install (macos "brew install fish OR port install fish"))
  615. (:languages "Fish")
  616. (:format (format-all--buffer-easy executable)))
  617. (define-format-all-formatter fprettify
  618. (:executable "fprettify")
  619. (:install "pip install fprettify")
  620. (:languages "_Fortran 90")
  621. (:format (format-all--buffer-easy executable "--silent")))
  622. (define-format-all-formatter gleam
  623. (:executable "gleam")
  624. (:install (macos "brew install gleam"))
  625. (:languages "_Gleam")
  626. (:format (format-all--buffer-easy executable "format" "--stdin")))
  627. (define-format-all-formatter gofmt
  628. (:executable "gofmt")
  629. (:install
  630. (macos "brew install go")
  631. (windows "scoop install go"))
  632. (:languages "Go")
  633. (:format (format-all--buffer-easy executable)))
  634. (define-format-all-formatter goimports
  635. (:executable "goimports")
  636. (:install "go get golang.org/x/tools/cmd/goimports")
  637. (:languages "Go")
  638. (:format (format-all--buffer-easy executable)))
  639. (define-format-all-formatter hindent
  640. (:executable "hindent")
  641. (:install "stack install hindent")
  642. (:languages "Haskell" "Literate Haskell")
  643. (:format (format-all--buffer-easy executable)))
  644. (define-format-all-formatter html-tidy
  645. (:executable "tidy")
  646. (:install
  647. (macos "brew install tidy-html5")
  648. (windows "scoop install tidy"))
  649. (:languages "HTML" "XML")
  650. (:format
  651. (format-all--buffer-hard
  652. '(0 1) nil nil
  653. executable
  654. "-q"
  655. "--tidy-mark" "no"
  656. "-indent"
  657. (when (equal language "XML") "-xml"))))
  658. (define-format-all-formatter istyle-verilog
  659. (:executable "iStyle")
  660. (:install)
  661. (:languages "Verilog")
  662. (:format (format-all--buffer-easy executable)))
  663. (define-format-all-formatter jsonnetfmt
  664. (:executable "jsonnetfmt")
  665. (:install (macos "brew install jsonnet"))
  666. (:languages "Jsonnet")
  667. (:format (format-all--buffer-easy executable "-")))
  668. (define-format-all-formatter ktlint
  669. (:executable "ktlint")
  670. (:install (macos "brew install ktlint"))
  671. (:languages "Kotlin")
  672. (:format (format-all--buffer-easy executable "--format" "--stdin")))
  673. (define-format-all-formatter latexindent
  674. (:executable "latexindent")
  675. (:install)
  676. (:languages "LaTeX")
  677. (:format (format-all--buffer-easy executable)))
  678. (define-format-all-formatter ledger-mode
  679. (:executable)
  680. (:install)
  681. (:languages "_Ledger")
  682. (:format
  683. (format-all--buffer-native 'ledger-mode 'ledger-mode-clean-buffer)))
  684. (define-format-all-formatter lua-fmt
  685. (:executable "luafmt")
  686. (:install "npm install --global lua-fmt")
  687. (:languages "Lua")
  688. (:format (format-all--buffer-easy executable "--stdin")))
  689. (define-format-all-formatter mix-format
  690. (:executable "mix")
  691. (:install (macos "brew install elixir"))
  692. (:languages "Elixir")
  693. (:format
  694. (format-all--buffer-hard
  695. nil nil '("mix.exs")
  696. executable
  697. "format"
  698. (let ((config-file (format-all--locate-file ".formatter.exs")))
  699. (when config-file (list "--dot-formatter" config-file)))
  700. "-")))
  701. (define-format-all-formatter nixfmt
  702. (:executable "nixfmt")
  703. (:install "nix-env -f https://github.com/serokell/nixfmt/archive/master.tar.gz -i")
  704. (:languages "Nix")
  705. (:format (format-all--buffer-easy executable)))
  706. (define-format-all-formatter nixpkgs-fmt
  707. (:executable "nixpkgs-fmt")
  708. (:install "nix-env -f https://github.com/nix-community/nixpkgs-fmt/archive/master.tar.gz -i")
  709. (:languages "Nix")
  710. (:format (format-all--buffer-easy executable)))
  711. (define-format-all-formatter ocp-indent
  712. (:executable "ocp-indent")
  713. (:install "opam install ocp-indent")
  714. (:languages "OCaml")
  715. (:format (format-all--buffer-easy executable)))
  716. (define-format-all-formatter ormolu
  717. (:executable "ormolu")
  718. (:install "stack install ormolu")
  719. (:languages "Haskell" "Literate Haskell")
  720. (:format (format-all--buffer-easy executable)))
  721. (define-format-all-formatter perltidy
  722. (:executable "perltidy")
  723. (:install "cpan install Perl::Tidy")
  724. (:languages "Perl")
  725. (:format (format-all--buffer-easy executable)))
  726. (define-format-all-formatter pgformatter
  727. (:executable "pg_format")
  728. (:install)
  729. (:languages "SQL")
  730. (:format (format-all--buffer-easy executable)))
  731. (define-format-all-formatter prettier
  732. (:executable "prettier")
  733. (:install "npm install --global prettier @prettier/plugin-lua @prettier/plugin-php prettier-plugin-solidity prettier-plugin-toml")
  734. (:languages
  735. "CSS" "GraphQL" "HTML" "JavaScript" "JSON" "JSX" "Less" "Lua" "Markdown"
  736. "PHP" "SCSS" "Solidity" "TOML" "TSX" "TypeScript" "Vue" "YAML"
  737. "_Angular" "_Flow")
  738. (:format
  739. (format-all--buffer-easy
  740. executable
  741. "--parser" (let ((pair (assoc language
  742. '(("_Angular" . "angular")
  743. ("_Flow" . "flow")
  744. ("JavaScript" . "babel")
  745. ("JSX" . "babel")
  746. ("Solidity" . "solidity-parse")
  747. ("TSX" . "typescript")))))
  748. (if pair (cdr pair) (downcase language)))
  749. (when (buffer-file-name) (list "--stdin-filepath" (buffer-file-name)))
  750. (let ((ignore-file (format-all--locate-file ".prettierignore")))
  751. (when ignore-file (list "--ignore-path" ignore-file))))))
  752. (define-format-all-formatter purty
  753. (:executable "purty")
  754. (:install "npm install --global purty")
  755. (:languages "PureScript")
  756. (:format (format-all--buffer-easy executable "-")))
  757. (define-format-all-formatter resfmt
  758. (:executable "resfmt")
  759. (:install "pip install resfmt")
  760. (:languages "ReScript")
  761. (:format (format-all--buffer-easy executable)))
  762. (define-format-all-formatter rufo
  763. (:executable "rufo")
  764. (:install "gem install rufo")
  765. (:languages "Ruby")
  766. (:format
  767. (format-all--buffer-easy
  768. executable
  769. "--simple-exit"
  770. (when (buffer-file-name)
  771. (list "--filename" (buffer-file-name))))))
  772. (define-format-all-formatter rustfmt
  773. (:executable "rustfmt")
  774. (:install "rustup component add rustfmt")
  775. (:languages "Rust")
  776. (:format (format-all--buffer-easy executable)))
  777. (define-format-all-formatter scalafmt
  778. (:executable "scalafmt")
  779. (:install "coursier bootstrap org.scalameta:scalafmt-cli_2.12:2.4.0-RC1 -r sonatype:snapshots -o /usr/local/bin/scalafmt --standalone --main org.scalafmt.cli.Cli")
  780. (:languages "Scala")
  781. (:format
  782. (format-all--buffer-easy
  783. executable "--stdin" "--non-interactive" "--quiet")))
  784. (define-format-all-formatter shfmt
  785. (:executable "shfmt")
  786. (:install
  787. (macos "brew install shfmt")
  788. (windows "scoop install shfmt"))
  789. (:languages "Shell")
  790. (:format
  791. (format-all--buffer-easy
  792. executable
  793. (if (buffer-file-name)
  794. (list "-filename" (buffer-file-name))
  795. (list "-ln" (cl-case (and (eql major-mode 'sh-mode)
  796. (boundp 'sh-shell)
  797. (symbol-value 'sh-shell))
  798. (bash "bash")
  799. (mksh "mksh")
  800. (t "posix")))))))
  801. (define-format-all-formatter snakefmt
  802. (:executable "snakefmt")
  803. (:install)
  804. (:languages "_Snakemake")
  805. (:format (format-all--buffer-easy executable "-")))
  806. (define-format-all-formatter sqlformat
  807. (:executable "sqlformat")
  808. (:install "pip install sqlparse")
  809. (:languages "SQL")
  810. (:format
  811. (let* ((ic (car default-process-coding-system))
  812. (oc (cdr default-process-coding-system))
  813. (ienc (symbol-name (or (coding-system-get ic :mime-charset)
  814. 'utf-8)))
  815. (oenc (symbol-name (or (coding-system-get oc :mime-charset)
  816. 'utf-8)))
  817. (process-environment (cons (concat "PYTHONIOENCODING=" oenc)
  818. process-environment)))
  819. (format-all--buffer-easy executable "--encoding" ienc "-"))))
  820. (define-format-all-formatter standard
  821. (:executable "standard")
  822. (:install "npm install --global standard")
  823. (:languages "JavaScript" "JSX")
  824. (:format
  825. ;; `standard --stdin` properly uses zero vs non-zero exit codes to
  826. ;; indicate success vs error. However, it checks for quite a broad
  827. ;; range of errors, all the way up to undeclared identifiers and
  828. ;; such. To catch only syntax errors, we need to look specifically
  829. ;; for the text "Parsing error:".
  830. (format-all--buffer-hard
  831. '(0 1) ".*?:.*?:[0-9]+:[0-9]+: Parsing error:" nil
  832. executable "--fix" "--stdin")))
  833. (define-format-all-formatter styler
  834. (:executable "Rscript")
  835. (:install "Rscript -e 'install.packages(\"styler\")'")
  836. (:languages "R")
  837. (:format
  838. (format-all--buffer-easy
  839. executable "--vanilla"
  840. "-e" (concat
  841. "options(styler.colored_print.vertical=FALSE);"
  842. " con <- file(\"stdin\");"
  843. " out <- styler::style_text(readLines(con));"
  844. " close(con);"
  845. " out"))))
  846. (define-format-all-formatter stylish-haskell
  847. (:executable "stylish-haskell")
  848. (:install "stack install stylish-haskell")
  849. (:languages "Haskell")
  850. (:format (format-all--buffer-easy executable)))
  851. (define-format-all-formatter swiftformat
  852. (:executable "swiftformat")
  853. (:install (macos "brew install swiftformat"))
  854. (:languages "Swift")
  855. (:format
  856. (format-all--buffer-easy
  857. executable "--quiet"
  858. (let ((config (format-all--locate-file ".swiftformat")))
  859. (when config (list "--config" config))))))
  860. (define-format-all-formatter terraform-fmt
  861. (:executable "terraform")
  862. (:install (macos "brew install terraform"))
  863. (:languages "Terraform")
  864. (:format (format-all--buffer-easy executable "fmt" "-no-color" "-")))
  865. (define-format-all-formatter yapf
  866. (:executable "yapf")
  867. (:install "pip install yapf")
  868. (:languages "Python")
  869. (:format (format-all--buffer-easy executable)))
  870. (defun format-all--language-id-buffer ()
  871. "Return the language used in the current buffer, or NIL.
  872. Prefer getting the ID from the language-id library. Some
  873. languages do not yet have official GitHub Linguist identifiers,
  874. yet format-all needs to know about them anyway. That's why we
  875. have this custom language-id function in format-all. The
  876. unofficial languages IDs are prefixed with \"_\"."
  877. (or (and (or (equal major-mode 'angular-html-mode)
  878. (and (equal major-mode 'web-mode)
  879. (equal (symbol-value 'web-mode-content-type) "html")
  880. (equal (symbol-value 'web-mode-engine) "angular")))
  881. "_Angular")
  882. (and (member major-mode '(js-mode js2-mode js3-mode))
  883. (boundp 'flow-minor-mode)
  884. (not (null (symbol-value 'flow-minor-mode)))
  885. "_Flow")
  886. (and (equal major-mode 'f90-mode) "_Fortran 90")
  887. (and (equal major-mode 'gleam-mode) "_Gleam")
  888. (and (equal major-mode 'ledger-mode) "_Ledger")
  889. (and (equal major-mode 'snakemake-mode) "_Snakemake")
  890. (language-id-buffer)))
  891. (defun format-all--please-install (executable installer)
  892. "Internal helper function for error about missing EXECUTABLE and INSTALLER."
  893. (concat (format "You need the %S command." executable)
  894. (if (not installer) ""
  895. (format " You may be able to install it via %S." installer))))
  896. (defun format-all--formatter-executable (formatter)
  897. "Internal helper function to get the external program for FORMATTER."
  898. (let ((executable (gethash formatter format-all--executable-table)))
  899. (when executable
  900. (or (executable-find executable)
  901. (error (format-all--please-install
  902. executable
  903. (gethash formatter format-all--install-table)))))))
  904. (defun format-all--update-errors-buffer (status error-output)
  905. "Internal helper function to update *format-all-errors*.
  906. STATUS and ERROR-OUTPUT come from the formatter."
  907. (let ((show-errors-p (and (not (= 0 (length error-output)))
  908. (or format-all-always-show-errors
  909. (eq status :error)))))
  910. (save-selected-window
  911. (with-current-buffer (get-buffer-create "*format-all-errors*")
  912. (erase-buffer)
  913. (insert error-output)
  914. (if show-errors-p
  915. (display-buffer (current-buffer))
  916. (let ((error-window (get-buffer-window (current-buffer))))
  917. (when error-window (quit-window nil error-window))))))))
  918. (defun format-all--save-line-number (thunk)
  919. "Internal helper function to run THUNK and go back to the same line."
  920. (let ((old-line-number (line-number-at-pos))
  921. (old-column (current-column)))
  922. (funcall thunk)
  923. (goto-char (point-min))
  924. (forward-line (1- old-line-number))
  925. (let ((line-length (- (point-at-eol) (point-at-bol))))
  926. (goto-char (+ (point) (min old-column line-length))))))
  927. (defun format-all--run-chain (language chain)
  928. "Internal function to run a formatter CHAIN on the current buffer.
  929. LANGUAGE is the language ID of the current buffer, from
  930. `format-all--language-id-buffer`."
  931. (let* ((chain (format-all--normalize-chain chain))
  932. (chain-tail chain)
  933. (error-output "")
  934. (reformatted-by '()))
  935. (format-all--save-line-number
  936. (lambda ()
  937. (cl-loop
  938. (unless (and chain-tail (= 0 (length error-output)))
  939. (cl-return))
  940. (let* ((formatter (car chain-tail))
  941. (f-name (car formatter))
  942. (f-args (cdr formatter))
  943. (f-function (gethash f-name format-all--format-table))
  944. (f-executable (format-all--formatter-executable f-name)))
  945. (when format-all-debug
  946. (message
  947. "Format-All: Formatting %s as %s using %S%s"
  948. (buffer-name) language f-name
  949. (with-temp-buffer
  950. (dolist (arg f-args) (insert " " (shell-quote-argument arg)))
  951. (buffer-string))))
  952. (cl-destructuring-bind (f-output f-error-output)
  953. (let ((format-all--user-args f-args))
  954. (funcall f-function f-executable language))
  955. (let ((f-status :already-formatted))
  956. (cond ((null f-output)
  957. (setq error-output f-error-output)
  958. (setq f-status :error))
  959. ((not (equal f-output t))
  960. (setq reformatted-by
  961. (append reformatted-by (list f-name)))
  962. (let ((inhibit-read-only t))
  963. (erase-buffer)
  964. (insert f-output))
  965. (setq f-status :reformatted)))
  966. (run-hook-with-args 'format-all-after-format-functions
  967. f-name f-status)
  968. (format-all--update-errors-buffer f-status f-error-output))))
  969. (setq chain-tail (cdr chain-tail)))
  970. (message "%s"
  971. (cond ((not (= 0 (length error-output))) "Formatting error")
  972. ((not reformatted-by) "Already formatted")
  973. (t "Reformatted!")))))))
  974. (defun format-all--get-default-chain (language)
  975. "Internal function to get the default formatter chain for LANGUAGE."
  976. (when language (cdr (assoc language format-all-default-formatters))))
  977. (defun format-all--get-chain (language)
  978. "Internal function to get LANGUAGE formatter chain for current buffer."
  979. (when language (cdr (assoc language format-all-formatters))))
  980. (defun format-all--set-chain (language chain)
  981. "Internal function to set LANGUAGE formatter CHAIN for current buffer."
  982. (cl-assert (stringp language))
  983. (cl-assert (listp chain))
  984. (setq format-all-formatters
  985. (append (cl-remove-if (lambda (pair) (equal language (car pair)))
  986. format-all-formatters)
  987. (when chain (list (cons language chain))))))
  988. (defun format-all--prompt-for-formatter (language)
  989. "Internal function to choose a formatter for LANGUAGE."
  990. (let ((f-names (gethash language format-all--language-table)))
  991. (cond ((null f-names) (error "No supported formatters for %s" language))
  992. ((null (cdr f-names)) (car f-names))
  993. (t (let ((f-string (completing-read
  994. (format "Formatter for %s: " language)
  995. (mapcar #'list f-names) nil t)))
  996. (and (not (= 0 (length f-string)))
  997. (intern f-string)))))))
  998. (defun format-all--buffer-from-hook ()
  999. "Internal helper function to auto-format current buffer from a hook.
  1000. Format-All installs this function into `before-save-hook' to
  1001. format buffers on save. This is a lenient version of
  1002. `format-all-buffer' that silently succeeds instead of signaling
  1003. an error if the current buffer has no formatter."
  1004. (let ((language (format-all--language-id-buffer)))
  1005. (format-all--run-chain language (format-all--get-chain language))))
  1006. ;;;###autoload
  1007. (defun format-all-buffer (&optional prompt)
  1008. "Auto-format the source code in the current buffer.
  1009. No disk files are touched - the buffer doesn't even need to be
  1010. saved. If you don't like the results of the formatting, you can
  1011. use ordinary undo to get your code back to its previous state.
  1012. You will need to install external programs to do the formatting.
  1013. If the command can't find the program that it needs, it will try
  1014. to tell you how you might be able to install it on your operating
  1015. system. Only BibTeX, Emacs Lisp and Ledger are formatted without an
  1016. external program.
  1017. A suitable formatter is selected according to the `major-mode' of
  1018. the buffer. Many popular programming languages are supported.
  1019. It is fairly easy to add new languages that have an external
  1020. formatter. When called interactively or PROMPT-P is non-nil, a
  1021. missing formatter is prompted in the minibuffer.
  1022. If PROMPT is non-nil (or the function is called as an interactive
  1023. command), a missing formatter is prompted in the minibuffer. If
  1024. PROMPT is the symbol `always' (or a prefix argument is given),
  1025. the formatter is prompted for even if one has already been set.
  1026. If any errors or warnings were encountered during formatting,
  1027. they are shown in a buffer called *format-all-errors*."
  1028. (interactive (list (if current-prefix-arg 'always t)))
  1029. (let* ((language (format-all--language-id-buffer))
  1030. (chain (format-all--get-chain language)))
  1031. (when (or (equal 'always prompt) (and prompt (not chain)))
  1032. (let ((f-name (format-all--prompt-for-formatter language)))
  1033. (when f-name
  1034. (message "Setting formatter to %S" f-name)
  1035. (setq chain (list f-name))
  1036. (format-all--set-chain language chain))))
  1037. (unless chain (error "No formatter"))
  1038. (format-all--run-chain language chain)))
  1039. (defun format-all-ensure-formatter ()
  1040. "Ensure current buffer has a formatter, using default if not."
  1041. (interactive)
  1042. (let ((language (format-all--language-id-buffer)))
  1043. (unless (format-all--get-chain language)
  1044. (cond ((not language)
  1045. (message "No formatter for this language"))
  1046. ((not (gethash language format-all--language-table))
  1047. (message "No formatter for %s" language))
  1048. (t
  1049. (let ((default (format-all--get-default-chain language)))
  1050. (cond ((not default)
  1051. (message "No default formatter for %s" language))
  1052. (t
  1053. (message "Using default formatter%s"
  1054. (with-temp-buffer
  1055. (dolist (formatter default (buffer-string))
  1056. (insert (format " %S" formatter)))))
  1057. (format-all--set-chain language default)))))))))
  1058. ;;;###autoload
  1059. (define-minor-mode format-all-mode
  1060. "Toggle automatic source code formatting before save.
  1061. When this minor mode (FmtAll) is enabled, `format-all-buffer' is
  1062. automatically called to format your code each time before you
  1063. save the buffer.
  1064. The mode is buffer-local and needs to be enabled separately each
  1065. time a file is visited. You may want to use `add-hook' in your
  1066. `user-init-file' to enable the mode based on buffer modes. E.g.:
  1067. (add-hook 'prog-mode-hook 'format-all-mode)
  1068. To use a default formatter for projects that don't have one, add
  1069. this too:
  1070. (add-hook 'prog-mode-hook 'format-all-ensure-formatter)
  1071. When `format-all-mode' is called as a Lisp function, the mode is
  1072. toggled if ARG is toggle, disabled if ARG is a negative integer
  1073. or zero, and enabled otherwise."
  1074. :lighter " FmtAll"
  1075. :global nil
  1076. (if format-all-mode
  1077. (add-hook 'before-save-hook
  1078. 'format-all--buffer-from-hook
  1079. nil 'local)
  1080. (remove-hook 'before-save-hook
  1081. 'format-all--buffer-from-hook
  1082. 'local)))
  1083. (provide 'format-all)
  1084. ;;; format-all.el ends here