diff options
| author | Mohsin Kaleem <mohkale@kisara.moe> | 2021-11-21 18:45:50 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-21 10:45:50 -0800 |
| commit | 2cf903e9a2faa3b50c97896b59361960472330f9 (patch) | |
| tree | 1c470ea9956abec52b248ebeb9932efcb247072a | |
| parent | 8e0605cc29732ec889b7318dd57921bf3f5ba06c (diff) | |
Support non-file buffers (#52) (#59)
* Support non-file buffers (#52)
Closes #52
* Apply suggestions from code review
* Oops, my bad
Co-authored-by: Radon Rosborough <radon.neon@gmail.com>
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | README.md | 12 | ||||
| -rw-r--r-- | apheleia.el | 45 |
3 files changed, 45 insertions, 14 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a971d..27dea21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog]. be run in sequence. * Support evaluating items in `apheleia-formatters` to make formatter commands more dynamic ([#50], [#55]). +* Allow apheleia to format buffers without an underlying file ([#52]). ### Formatters * [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) for @@ -46,6 +47,7 @@ The format is based on [Keep a Changelog]. [#48]: https://github.com/raxod502/apheleia/pull/48 [#49]: https://github.com/raxod502/apheleia/pull/49 [#50]: https://github.com/raxod502/apheleia/pull/50 +[#52]: https://github.com/raxod502/apheleia/issues/52 [#54]: https://github.com/raxod502/apheleia/pull/54 [#55]: https://github.com/raxod502/apheleia/issues/55 @@ -107,6 +107,18 @@ variables: only when it is bound. Observe that one of these evaluations returns a list of flags whereas the other returns a single string. These are substituted into the command as you'd expect. + * You can also use Apheleia to format buffers that have no underlying + files. In this case the value of `file` and `filepath` will be + the name of the current buffer with any special characters for + the file-system (such as `*` on windows) being stripped out. + + This is also how the extension for any temporary files apheleia + might create will be determined. If you're using a formatter + that determines the file-type from the extension you should name + such buffers such that their suffixed with the extension. For + example a buffer called `*foo-bar.c*` that has no associated + file will have an implicit file-name of `foo-bar.c` and any + temporary files will be suffixed with a `.c` extension. * `apheleia-mode-alist`: Alist mapping major modes and filename regexps to names of formatters to use in those modes and files. See the docstring for more information. diff --git a/apheleia.el b/apheleia.el index 6fe4b8f..a815a2e 100644 --- a/apheleia.el +++ b/apheleia.el @@ -27,6 +27,9 @@ (require 'map) (require 'subr-x) +(eval-when-compile + (require 'rx)) + (defgroup apheleia nil "Reformat buffer without moving point." :group 'external @@ -394,6 +397,15 @@ as its sole argument." ;; changes, and 2 if error. (memq status '(0 1))))))) +(defun apheleia--safe-buffer-name () + "Return `buffer-name' without special file-system characters." + ;; See https://stackoverflow.com/q/1976007 for a list of supported + ;; characters on all systems. + (replace-regexp-in-string + (rx (or "/" "<" ">" ":" "\"" "\\" "|" "?" "*")) + "" + (buffer-name))) + (defun apheleia--format-command (command &optional stdin-buffer) "Format COMMAND into a shell command and list of file paths. Returns a list with the car being the optional input file-name, the @@ -435,9 +447,10 @@ cmd is to be run." (when (memq 'input command) (let ((input-fname (make-temp-file "apheleia" nil - (and buffer-file-name - (file-name-extension - buffer-file-name 'period))))) + (when-let ((file-name + (or buffer-file-name + (apheleia--safe-buffer-name)))) + (file-name-extension file-name 'period))))) (with-current-buffer stdin (apheleia--write-region-silently nil nil input-fname)) (setq command (mapcar (lambda (arg) @@ -458,15 +471,18 @@ cmd is to be run." (when stdin-buffer (error "Cannot run formatter using `file' or `filepath' in a \ sequence unless it's first in the sequence")) - (setq command (mapcar (lambda (arg) - (when (eq arg 'file) - (setq stdin nil)) - (if (memq arg '(file filepath)) - (prog1 buffer-file-name - (when (buffer-modified-p) - (cl-return))) - arg)) - command))) + (let ((file-name (or buffer-file-name + (concat default-directory + (apheleia--safe-buffer-name))))) + (setq command (mapcar (lambda (arg) + (when (eq arg 'file) + (setq stdin nil)) + (if (memq arg '(file filepath)) + (prog1 file-name + (when (buffer-modified-p) + (cl-return))) + arg)) + command)))) ;; Evaluate each element of arg that isn't a string and replace ;; it with the evaluated value. The result of an evaluation should ;; be a string or a list of strings. If the former its replaced as @@ -772,8 +788,9 @@ operating, to prevent an infinite loop.") commands (lambda () (with-demoted-errors "Apheleia: %s" - (let ((apheleia--format-after-save-in-progress t)) - (apheleia--write-file-silently buffer-file-name)) + (when buffer-file-name + (let ((apheleia--format-after-save-in-progress t)) + (apheleia--write-file-silently buffer-file-name))) (run-hooks 'apheleia-post-format-hook)))))))) ;; Use `progn' to force the entire minor mode definition to be copied |
