aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohsin Kaleem <mohkale@kisara.moe>2021-11-21 18:45:50 +0000
committerGitHub <noreply@github.com>2021-11-21 10:45:50 -0800
commit2cf903e9a2faa3b50c97896b59361960472330f9 (patch)
tree1c470ea9956abec52b248ebeb9932efcb247072a
parent8e0605cc29732ec889b7318dd57921bf3f5ba06c (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.md2
-rw-r--r--README.md12
-rw-r--r--apheleia.el45
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
diff --git a/README.md b/README.md
index c4f7241..00fa7f1 100644
--- a/README.md
+++ b/README.md
@@ -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