[#69] Improvements to Apheleia logging

* Rename apheleia-hide-log-buffer to apheleia-hide-log-buffers.
* Rename apheleia-verbose to apheleia-log-only-errors (note, meaning
  is inverted).
* Add apheleia-hide-old-log-entries.
* Include more information in log and format it more neatly.
* Convert log buffer to special-mode and attempt to keep point at the
  end (although this is not working for an undetermined reason).
This commit is contained in:
Radon Rosborough 2022-01-03 20:07:44 -08:00
parent a606d59c2d
commit 54844c3988
3 changed files with 92 additions and 30 deletions

View file

@ -13,10 +13,12 @@ The format is based on [Keep a Changelog].
## Changes
* Stdout and stderr buffers are no longer retained after running a
formatter. Instead, the stderr is appended into an
`*apheleia-whatever-log*` buffer if it fails, or unconditionally if
the new user option `apheleia-verbose` is set to non-nil. See [#64],
[#65]. The log buffer is not hidden by default, and this can be
changed via the new user option `apheleia-hide-log-buffer` ([#69]).
`*apheleia-cmdname-log*` buffer if it fails, or unconditionally if
the new user option `apheleia-log-only-errors` is set to nil. See
[#64], [#65]. The log buffer is not hidden by default, and shows all
command output rather than just the latest run. These behaviors can
be customized using the new user options `apheleia-hide-log-buffers`
and `apheleia-hide-old-log-entries` ([#69]).
## Formatters
* [fish\_indent](https://fishshell.com/docs/current/cmds/fish_indent.html)

View file

@ -169,6 +169,23 @@ run.
Apheleia does not currently support TRAMP, and is therefore
automatically disabled for remote files.
You can configure error reporting using the following user options:
* `apheleia-hide-log-buffers`: By default, errors from formatters are
put in buffers named like `*apheleia-cmdname-log*`. If you customize
this user option to non-nil then a space is prepended to the names
of these buffers, hiding them by default in `switch-to-buffer` (you
must type a space to see them).
* `apheleia-log-only-errors`: By default, only failed formatter runs
are logged. If you customize this user option to nil then all runs
are logged, along with whether or not they succeeded.
* `apheleia-hide-old-log-entries`: By default, all failed formatter
runs are appended to the log. It is intended that point stay at the
end of the buffer by default, but due to an unknown bug this is not
currently the case. By customizing this user option to non-nil, you
can cause only the most recent failure for a formatter to be
retained in its log buffer.
The following user options are also available:
* `apheleia-post-format-hook`: Normal hook run after Apheleia formats

View file

@ -36,13 +36,24 @@
:link '(url-link :tag "GitHub" "https://github.com/raxod502/apheleia")
:link '(emacs-commentary-link :tag "Commentary" "apheleia"))
(defcustom apheleia-hide-log-buffer nil
(defcustom apheleia-hide-log-buffers nil
"Non-nil means log buffers will be hidden.
Hidden buffers have names that begin with a space, and do not
appear in `switch-to-buffer' unless you type in a space
manually."
:type 'boolean)
(defcustom apheleia-log-only-errors t
"Non-nil means Apheleia will only log when an error occurs.
Otherwise, Apheleia will log every time a formatter is run, even
if it is successful."
:type 'boolean)
(defcustom apheleia-hide-old-log-entries nil
"Non-nil means only the most recent log entry will be retained.
This is on a per-formatter basis."
:type 'boolean)
(cl-defun apheleia--edit-distance-table (s1 s2)
"Align strings S1 and S2 for minimum edit distance.
Return the dynamic programming table as has table which maps cons
@ -261,11 +272,6 @@ contains the patch."
Keeping track of this helps avoid running more than one process
at once.")
(defvar apheleia-verbose nil
"When true `apheleia' produces richer log buffers.
Specifically, formatter stderr is appended to the log buffer even
if there is no error.")
(cl-defun apheleia--make-process
(&key command stdin callback ensure exit-status)
"Wrapper for `make-process' that behaves a bit more nicely.
@ -289,12 +295,11 @@ command succeeds provided that its exit status is 0."
(format " *apheleia-%s-stdout*" name)))
(stderr (generate-new-buffer
(format " *apheleia-%s-stderr*" name)))
(log (get-buffer-create
(format "%s*apheleia-%s-log*"
(if apheleia-hide-log-buffer
" "
"")
name))))
(log-name (format "%s*apheleia-%s-log*"
(if apheleia-hide-log-buffers
" "
"")
name)))
(condition-case-unless-debug e
(progn
(setq apheleia--current-process
@ -308,22 +313,60 @@ command succeeds provided that its exit status is 0."
(lambda (proc _event)
(unless (process-live-p proc)
(let ((exit-ok (funcall
(or exit-status
(lambda (status)
(= 0 status)))
(or exit-status #'zerop)
(process-exit-status proc))))
;; Append standard-error from current formatter
;; to log buffer when `apheleia-verbose' or the
;; to log buffer when
;; `apheleia-log-only-errors' is nil or the
;; formatter failed. Every process output is
;; delimited by a line-feed character.
(with-current-buffer log
(when (or apheleia-verbose
(not exit-ok))
(if (= 0 (with-current-buffer stderr
(buffer-size)))
(insert "[No output received on stderr]")
(insert-buffer-substring stderr))
(insert "\n\C-l\n")))
(unless (and exit-ok apheleia-log-only-errors)
(with-current-buffer (get-buffer-create log-name)
(special-mode)
(save-restriction
(widen)
(let ((inhibit-read-only t)
(orig-point (point))
(keep-at-end (eobp))
(stderr-string
(with-current-buffer stderr
(string-trim (buffer-string)))))
(when apheleia-hide-old-log-entries
(erase-buffer))
(goto-char (point-max))
(skip-chars-backward "\n")
(delete-region (point) (point-max))
(unless (bobp)
(insert
"\n\n\C-l\n"))
(insert
(current-time-string)
" :: "
(buffer-local-value 'default-directory stdout)
"\n$ "
(mapconcat #'shell-quote-argument command " ")
"\n\n"
(if (string-empty-p stderr-string)
"(no output on stderr)"
stderr-string)
"\n\n"
"Command "
(if exit-ok "succeeded" "failed")
" with exit code "
(number-to-string (process-exit-status proc))
".\n")
;; Known issue: this does not actually
;; work; point is left at the end of
;; the previous command output, instead
;; of being moved to the end of the
;; buffer for some reason.
(goto-char
(if keep-at-end
(point-max)
(min
(point-max)
orig-point)))
(goto-char (point-max))))))
(unwind-protect
(if exit-ok
(when callback
@ -334,10 +377,10 @@ command succeeds provided that its exit status is 0."
"(see %s %s)")
(car command)
(process-exit-status proc)
(if (string-prefix-p " " (buffer-name log))
(if (string-prefix-p " " log-name)
"hidden buffer"
"buffer")
(string-trim (buffer-name log))))
(string-trim log-name)))
(when ensure
(funcall ensure))
(kill-buffer stdout)