From 26ef9acd0fdc8f43769f1870513a0d70485e5f7f Mon Sep 17 00:00:00 2001 From: Olli Date: Sat, 23 Mar 2024 03:44:33 +0200 Subject: [PATCH] Parse shebangs on Windows (#293) Parses the shebang from formatter scripts on Windows, and inserts the binary in to the command. This fixes https://github.com/radian-software/apheleia/issues/285. Please let me know if there is still something that need more work, thanks. One minor issue I noticed is that errors will now get logged to `*aphleia-bash-log*` instead of `*apheleia-npx-log*`. --- CHANGELOG.md | 3 +++ apheleia-formatters.el | 28 ++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d64ec42..736373d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,11 @@ The format is based on [Keep a Changelog]. ### Bugs fixed * `apheleia-indent-lisp-buffer` updated to apply local variables after calling major-mode. Also includes setting for `indent-tabs-mode` ([#286]). +* [Formatter scripts](scripts/formatters) will now work on Windows if Emacs + can find the executable defined in the shebang. [#286]: https://github.com/radian-software/apheleia/pull/286 +[#285]: https://github.com/radian-software/apheleia/issues/285 ## 4.1 (released 2024-02-25) ### Enhancements diff --git a/apheleia-formatters.el b/apheleia-formatters.el index 21976e7..e24e686 100644 --- a/apheleia-formatters.el +++ b/apheleia-formatters.el @@ -992,6 +992,26 @@ machine from the machine file is available on")) collect val else do (error "Result of command evaluation must be a string \ or list of strings: %S" arg))) + + ;; Windows fails to run formatter scripts. Check whether the + ;; command executable is a script that contains a shebang. Parse + ;; the shebang and insert the binary into the command. + (when (member system-type '(ms-dos windows-nt)) + (when-let ((arg1-file (locate-file (car command) exec-path))) + (with-temp-buffer + (insert-file-contents arg1-file nil 0 2) + (when (string= (buffer-string) "#!") + ;; Assumes that the full shebang is max 200 characters + (insert-file-contents arg1-file nil 2 200 t) + (let* ((shebang-components (split-string (thing-at-point 'line))) + (shebang-binary + (if (string= (car shebang-components) "/usr/bin/env") + (cdr shebang-components) + (last (split-string (car shebang-components) "/"))))) + (setq command (append shebang-binary + (list arg1-file) + (cdr command)))))))) + (setf (apheleia-formatter--arg1 context) (car command) (apheleia-formatter--argv context) (cdr command)) context))) @@ -1009,9 +1029,7 @@ purposes." ;; resolve for the whole formatting process (for example ;; `apheleia--current-process'). (with-current-buffer buffer - (when-let ((ctx - (apheleia--formatter-context formatter command remote stdin)) - (exec-path + (when-let ((exec-path (append `(,(expand-file-name "scripts/formatters" (file-name-directory @@ -1019,7 +1037,9 @@ purposes." ;; Borrowed with love from Magit (let ((load-suffixes '(".el"))) (locate-library "apheleia")))))) - exec-path))) + exec-path)) + (ctx + (apheleia--formatter-context formatter command remote stdin))) (if (executable-find (apheleia-formatter--arg1 ctx) (eq apheleia-remote-algorithm 'remote)) (apheleia--execute-formatter-process