Skip to content

Commit

Permalink
fixup! more library friendly cleanup trailing whitespace
Browse files Browse the repository at this point in the history
  • Loading branch information
pkryger committed Dec 12, 2024
1 parent d9e139d commit eb71ad3
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 58 deletions.
133 changes: 79 additions & 54 deletions modules/init-look-and-feel.el
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,68 @@ Set FONT and SIZE if they are passed as arguments."
:ensure vlf
:defer t)

(require 'rx)

(defun exordium--alist-get-derived-mode (alist)
"Return value from ALIST where key matches `derived-mode-p' of current buffer."
(alist-get nil alist nil nil
(lambda (elt _)
(apply #'derived-mode-p
(if (listp elt) elt (list elt))))))

(defun exordium--delete-trailing-whitespace-data-start-and-cleanup ()
"Find beginning of data section start.
Also cleanup trailing lines when `delete-trailing-lines' is
non-nil and insert new line when `require-final-newline' is
non-nil."
(save-excursion
(when-let*
((exordium-delete-trailing-whitespace-skip-data)
(data-keywords (exordium--alist-get-derived-mode
exordium-delete-trailing-whitespace-data-keywords)))
(when (re-search-forward
(rx-to-string
`(seq line-start
(or ,@data-keywords)
(zero-or-more whitespace)
line-end)
t)
nil t)
(let ((point (point)))
;; When this is not a perlpod, clean it too - return nil
(unless (when-let*
((perlpod-keywords
(exordium--alist-get-derived-mode
exordium-delete-trailing-whitespace-data-perlpod-keywords)))
(re-search-forward
(rx-to-string
`(seq "\n" (zero-or-more whitespace)
"\n=" (or ,@perlpod-keywords))
t)
nil t))
;; Otherwise do a minimal cleanup:
;; Delete trailing lines, as `delete-trailing-whitespace' won't
;; handle it
(when-let*
((delete-trailing-lines)
((re-search-forward
(rx line-start
(group (one-or-more (or whitespace "\n")))
string-end)
nil t))
(b (match-beginning 1))
(e (match-end 1))
((region-modifiable-p b e)))
(delete-region b e))
;; Ensure trailing new line is present, as
;; `delete-trailing-whitespace' won't handle it
(when (and require-final-newline
(not (re-search-forward (rx "\n" string-end) nil t)))
(goto-char (point-max))
(insert "\n"))
;; trim whitespace only up to data section
point))))))

(defun exordium-delete-trailing-whitespace-in-buffer (&optional start end)
"Delete trailing whitespace in current buffer.
Like `delete-trailing-whitespace', but any restrictions are
Expand All @@ -297,11 +359,11 @@ non-nil END it will delete trailing whitespace up to END.
If called interactively, START and END are the start/end of the
region if the mark is active, or the whole buffer, up to data
secion (when `exordium-delete-trailing-whitespace-skip-data' is
non-nil), if the mark is inactive.
non-nil) if the mark is inactive.
The function doesn't delete trailing whitespaces when buffer is
in `diff-mode', `exordium-delete-trailing-whitespace-skip-data'
is non-nil, and the function has been called without a prefix argument.
in any of `exordium-delete-trailing-whitespace-inhibit-modes',
and the function has been called without a prefix argument.
Depending on mode a data section starts after a line with a one
of keywords __END__ or __DATA__ or a one of control
Expand All @@ -319,66 +381,27 @@ https://docs.ruby-lang.org/en/3.3/Object.html for more details."
(list nil nil))))
(if (and (not current-prefix-arg)
(apply #'derived-mode-p
'(diff-mode special-mode view-mode comint-mode cider-repl-mode haskell-interactive-mode)))
exordium-delete-trailing-whitespace-inhibit-modes))
(when (called-interactively-p 'any)
(user-error "Not deleting trailing whitespaces in '%s', call with prefix to override"
major-mode))
(without-restriction
(save-mark-and-excursion
(save-match-data
(goto-char (point-min))
(when-let* (((looking-at
(rx string-start (group (zero-or-more (or whitespace "\n")) (or "\n" line-end)))))
(b (match-beginning 1))
(e (match-end 1))
((region-modifiable-p b e)))
(when-let*
(((looking-at
(rx string-start
(group (zero-or-more (or whitespace "\n"))
(or "\n" line-end)))))
(b (match-beginning 1))
(e (match-end 1))
((region-modifiable-p b e)))
(delete-region b e))

(let ((end
(or end
(when-let* ((exordium-delete-trailing-whitespace-skip-data)
(data-keywords (cond
((derived-mode-p 'ruby-mode
'ruby-ts-mode
'enh-ruby-mode)
'("__END__"))
((derived-mode-p 'perl-mode
'perl-ts-mode
'cperl-mode)
'("__END__" "__DATA__" "" ""))))
(perlpod-keywords '("pod" "head1" "head2" "head3"
"head4" "head5" "head6" "over"
"item" "back" "begin" "end"
"for" "encoding" "cut")))
(when (re-search-forward
(rx-to-string
`(seq line-start (or ,@data-keywords) (zero-or-more whitespace) line-end)
t)
nil t)
(let ((point (point)))
(unless (and (derived-mode-p 'perl-mode
'perl-ts-mode
'cperl-mode)
(re-search-forward
(rx-to-string
`(seq "\n" (zero-or-more whitespace) "\n" "=" (or ,@perlpod-keywords)) t)
nil t))
;; delete trailing lines, as `delete-trailing-whitespace' won't handle it
(when-let* ((delete-trailing-lines)
((re-search-forward
(rx line-start (group (one-or-more (or whitespace "\n"))) string-end)
nil t))
(b (match-beginning 1))
(e (match-end 1))
((region-modifiable-p b e)))
(delete-region b e))
;; ensure trailing new line is present, as `delete-trailing-whitespace' won't handle it
(when (and require-final-newline
(not (re-search-forward (rx "\n" string-end) nil t)))
(goto-char (point-max))
(insert "\n")))
;; trim whitespace only up to data section
point))))))
(exordium--delete-trailing-whitespace-data-start-and-cleanup))))
(delete-trailing-whitespace start end)))))))

;; Remove trailing blanks on save
Expand All @@ -387,8 +410,10 @@ https://docs.ruby-lang.org/en/3.3/Object.html for more details."
See `exordium-delete-trailing-whitespace-in-buffer' for more details."
:lighter nil
(if delete-trailing-whitespace-mode
(add-hook 'before-save-hook #'exordium-delete-trailing-whitespace-in-buffer nil t)
(remove-hook 'before-save-hook #'exordium-delete-trailing-whitespace-in-buffer t)))
(add-hook 'before-save-hook
#'exordium-delete-trailing-whitespace-in-buffer nil t)
(remove-hook 'before-save-hook
#'exordium-delete-trailing-whitespace-in-buffer t)))

(define-globalized-minor-mode global-delete-trailing-whitespace-mode
delete-trailing-whitespace-mode
Expand Down
51 changes: 47 additions & 4 deletions modules/init-prefs.el
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,56 @@ a lot of trailing whitespaces."
(defcustom exordium-delete-trailing-whitespace-skip-data t
"When t preserve whitespaces in Data section in Perl and Ruby modes.
This variable is used by
`exordium-delete-trailing-whitespace-in-buffer' (see docstring
for details) and in consequence in
`delete-trailing-whitespace-mode' and
`global-delete-trailing-whitespace-mode'."
`exordium-delete-trailing-whitespace-in-buffer' (which see) and
in consequence in `delete-trailing-whitespace-mode' and
`global-delete-trailing-whitespace-mode'.
See also `exordium-delete-trailing-whitespace-data-keywords'."
:group 'exordium
:type 'boolean)

(defcustom exordium-delete-trailing-whitespace-inhibit-modes
'(diff-mode special-mode view-mode comint-mode cider-repl-mode
haskell-interactive-mode)
"List of modes where deletion of trailing whitespaces is inhibited.
See also docstring for
`exordium-delete-trailing-whitespace-in-buffer' and
`delete-trailing-whitespace-mode'."
:type '(repeat (symbol :tag "Mode"))
:group 'exordium)

(defcustom exordium-delete-trailing-whitespace-data-keywords
'(((ruby-mode ruby-ts-mode enh-ruby-mode) . ("__END__"))
((perl-mode perl-ts-mode cperl-mode) . ("__END__" "__DATA__" "" "")))
"Mapping between modes and keywords that indicate data section for that mode.
Data section will not have its trailing whitespace
deleted, barred for trailing new lines when
`delete-trailing-lines' is non nil and for ensuring ending
newline when `require-final-newline' is non nil.
See also `exordium-delete-trailing-whitespace-data-perlpod-keywords'."
:type '(alist :key-type (choice
(symbol :tag "Mode")
(repeat (symbol :tag "Mode")))
:value-type (repeat (string :tag "Keyword")))
:group 'exordium)

(defcustom exordium-delete-trailing-whitespace-data-perlpod-keywords
'((perl-mode perl-ts-mode cperl-mode) . ("pod" "head1" "head2" "head3"
"head4" "head5" "head6" "over"
"item" "back" "begin" "end"
"for" "encoding" "cut"))
"Mapping between Perl mode and perlpod keywords.
When a data section happens to contain a perlpod as sensed by
existence of a perlpod keyword it will have its trailing
whitespaces deleted, even when
`exordium-delete-trailing-whitespace-skip-data' is non-nil."
:type '(alist :key-type (choice
(symbol :tag "Mode")
(repeat (symbol :tag "Mode")))
:value-type (repeat (string :tag "Keyword")))
:group 'exordium)

(defcustom exordium-enable-electric-pair-mode t
"Whether to enable `electric-pair-mode'."
:group 'exordium
Expand Down

0 comments on commit eb71ad3

Please sign in to comment.