Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 50 additions & 15 deletions format-all.el
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,11 @@ language. Each formatter is either:
* a symbol (e.g. black, clang-format, rufo)

* a list whose first item is that symbol, and any remaining items
are extra command line arguments to pass to the formatter
are extra command line arguments to pass to the formatter; if
it starts with the symbol `:executable' the following item is
the program name that overrides EXECUTABLE and can be a
relative path from the project root, and the rest items are its
arguments. Those arguments should not be shell-quoted.

If more than one formatter is given for the same language, all of
them are run as a chain, with the code from each formatter passed
Expand Down Expand Up @@ -305,7 +309,9 @@ the rules for an entire source tree can be given in one file.")
(error "Formatter name missing"))
(unless (symbolp (car formatter))
(error "Formatter name is not a symbol: %S" (car formatter)))
(unless (cl-every #'stringp (cdr formatter))
(unless (or (and (eq (cadr formatter) :executable)
(cl-every #'stringp (cddr formatter)))
(cl-every #'stringp (cdr formatter)))
(error "Formatter command line arguments are not all strings: %S"
formatter))
formatter))
Expand All @@ -326,12 +332,9 @@ the rules for an entire source tree can be given in one file.")
(stringp (car chain))
(cl-every
(lambda (formatter)
(and (not (null formatter))
(or (symbolp formatter)
(and (format-all--proper-list-p formatter)
(and (symbolp (car formatter))
(not (null (car formatter))))
(cl-every #'stringp (cdr formatter))))))
(condition-case nil
(format-all--normalize-formatter formatter)
(error nil)))
(cdr chain))))
formatters)))

Expand Down Expand Up @@ -482,8 +485,11 @@ OK-STATUSES. OK-STATUSES and ERROR-REGEXP are hacks to work
around formatter programs that don't make sensible use of their
exit status.

If ARGS are given, those are arguments to EXECUTABLE. They should
not be shell-quoted.
If ARGS are given, those are arguments to EXECUTABLE. If it
starts with the symbol `:executable' the following item is the
program name that overrides EXECUTABLE and can be a relative path
from the project root, and the rest items are its arguments.
Those arguments should not be shell-quoted.

If ROOT-FILES are given, the working directory of the formatter
will be the deepest directory (starting from the file being
Expand Down Expand Up @@ -522,8 +528,11 @@ unformatted code from stdin, write its formatted equivalent to
stdout, write errors/warnings to stderr, and exit zero/non-zero
on success/failure.

If ARGS are given, those are arguments to EXECUTABLE. They don't
need to be shell-quoted."
If ARGS are given, those are arguments to EXECUTABLE. If it
starts with the symbol `:executable' the following item is the
program name that overrides EXECUTABLE and can be a relative path
from the project root, and the rest items are its arguments.
Those arguments should not be shell-quoted."
(apply 'format-all--buffer-hard nil nil nil executable args))

(defun format-all--ruby-gem-bundled-p (gem-name)
Expand Down Expand Up @@ -1578,6 +1587,31 @@ STATUS and ERROR-OUTPUT come from the formatter."
(set-marker (mark-marker) old-mark (current-buffer))
(setq mark-ring (mapcar #'copy-marker old-mark-ring))))

(defun format-all--project-root ()
"Internal function to get the project root for the current buffer."
(or (and (fboundp 'projectile-project-root)
(ignore-errors (projectile-project-root)))
(ignore-errors (project-root (project-current)))
default-directory))

(defun format-all--command-args (formatter)
"Internal function to get the full command line arguments for FORMATTER."
(let* ((name (car formatter))
(args (cdr formatter)))
(if (eq (car args) :executable)
(let* ((executable (cadr args))
(args (cddr args))
(executable
(or (let ((project-executable (expand-file-name executable (format-all--project-root))))
(and (file-executable-p project-executable)
(file-regular-p project-executable)
project-executable))
(executable-find executable)
(signal 'format-all-executable-not-found
(list (format "You need the %s command." executable))))))
(cons executable args))
(cons (format-all--formatter-executable name) args))))

(defun format-all--run-chain (language chain region)
"Internal function to run a formatter CHAIN on the current buffer.

Expand Down Expand Up @@ -1608,9 +1642,10 @@ entire buffer."
(cl-return))
(let* ((formatter (car chain-tail))
(f-name (car formatter))
(f-args (cdr formatter))
(f-function (gethash f-name format-all--format-table))
(f-executable (format-all--formatter-executable f-name)))
(f-command-args (format-all--command-args formatter))
(f-executable (car f-command-args))
(f-args (cdr f-command-args))
(f-function (gethash f-name format-all--format-table)))
(when format-all-debug
(message
"Format-All: Formatting %s as %s using %S%s"
Expand Down