diff options
| author | Elías Gabriel Pérez | 2025-09-11 19:13:21 -0600 |
|---|---|---|
| committer | Stefan Monnier | 2025-09-23 16:16:54 -0400 |
| commit | 2a782c8d2803edeb01aef592c2b89fc8bcd80660 (patch) | |
| tree | 28920d4f1071db2532b43b7b257cc7faf8c64b11 /lisp/electric.el | |
| parent | 578aeedbe986efbae63382a7b9ba1a94372df659 (diff) | |
| download | emacs-2a782c8d2803edeb01aef592c2b89fc8bcd80660.tar.gz emacs-2a782c8d2803edeb01aef592c2b89fc8bcd80660.zip | |
Add electric-indent actions to reindent (bug#79371)
* lisp/electric.el (electric-indent-actions)
(electric-indent-function): New user options.
(electric-indent-should-reindent-p, electric-indent--yank-advice)
(electric-indent-save-hook): New functions.
(electric-indent-post-self-insert-function): Use them.
Diffstat (limited to 'lisp/electric.el')
| -rw-r--r-- | lisp/electric.el | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/lisp/electric.el b/lisp/electric.el index 302fb8d08bc..7825bbe43ec 100644 --- a/lisp/electric.el +++ b/lisp/electric.el | |||
| @@ -192,6 +192,29 @@ Returns nil when we can't find this char." | |||
| 192 | 192 | ||
| 193 | ;;; Electric indentation. | 193 | ;;; Electric indentation. |
| 194 | 194 | ||
| 195 | (defcustom electric-indent-actions nil | ||
| 196 | "List of actions to indent. | ||
| 197 | |||
| 198 | The valid elements of this list can be: | ||
| 199 | - yank: Indent the yanked text only if point is not in a string or | ||
| 200 | comment and yanked region is longer than 1 line. | ||
| 201 | - save: Indent the whole buffer before saving it. | ||
| 202 | |||
| 203 | The indentation will not happen when the major mode is unable to | ||
| 204 | reindent code reliably, such as in buffers where indentation is | ||
| 205 | significant." | ||
| 206 | :type '(repeat (choice (const :tag "After yanking" yank) | ||
| 207 | (const :tag "Before saving" before-save))) | ||
| 208 | :set (lambda (var val) | ||
| 209 | (set-default var val) | ||
| 210 | (when electric-indent-mode | ||
| 211 | (electric-indent-mode -1) | ||
| 212 | (electric-indent-mode +1))) | ||
| 213 | :safe (lambda (v) | ||
| 214 | (and (proper-list-p v) | ||
| 215 | (null (seq-filter (lambda (e) (not (symbolp e)) ) v)))) | ||
| 216 | :version "31.1") | ||
| 217 | |||
| 195 | ;; Autoloading variables is generally undesirable, but major modes | 218 | ;; Autoloading variables is generally undesirable, but major modes |
| 196 | ;; should usually set this variable by adding elements to the default | 219 | ;; should usually set this variable by adding elements to the default |
| 197 | ;; value, which only works well if the variable is preloaded. | 220 | ;; value, which only works well if the variable is preloaded. |
| @@ -218,6 +241,50 @@ If `indent-line-function' is one of those, then `electric-indent-mode' will | |||
| 218 | not try to reindent lines. It is normally better to make the major | 241 | not try to reindent lines. It is normally better to make the major |
| 219 | mode set `electric-indent-inhibit', but this can be used as a workaround.") | 242 | mode set `electric-indent-inhibit', but this can be used as a workaround.") |
| 220 | 243 | ||
| 244 | (defun electric-indent-can-reindent-p () | ||
| 245 | "Return t if `electric-indent-mode' can performs reindentation." | ||
| 246 | (not (or (memq indent-line-function | ||
| 247 | electric-indent-functions-without-reindent) | ||
| 248 | electric-indent-inhibit))) | ||
| 249 | |||
| 250 | (defun electric-indent--yank-advice (fn &rest r) | ||
| 251 | (let ((p (point)) | ||
| 252 | (end (line-beginning-position))) | ||
| 253 | (apply fn r) | ||
| 254 | (when (and electric-indent-mode | ||
| 255 | (memq 'yank electric-indent-actions) | ||
| 256 | (electric-indent-can-reindent-p) | ||
| 257 | ;; Ensure yanked text is longer than 1 line | ||
| 258 | (> (point) p) | ||
| 259 | (not (= end (line-beginning-position)))) | ||
| 260 | (undo-boundary) | ||
| 261 | (save-excursion | ||
| 262 | (with-demoted-errors "Error reindenting: %S" | ||
| 263 | (indent-region p (point))))))) | ||
| 264 | |||
| 265 | (defun electric-indent-save-hook () | ||
| 266 | (when (and electric-indent-mode | ||
| 267 | ;; Ensure this hook is called interactively | ||
| 268 | (memq real-this-command '(save-buffer basic-save-buffer)) | ||
| 269 | (memq 'before-save electric-indent-actions) | ||
| 270 | (not buffer-read-only) | ||
| 271 | (electric-indent-can-reindent-p)) | ||
| 272 | (save-excursion | ||
| 273 | (with-demoted-errors "Error reindenting: %S" | ||
| 274 | (indent-region (point-min) (point-max)))))) | ||
| 275 | |||
| 276 | (defun electric-indent-toggle-indent-actions (enable) | ||
| 277 | "Enable the actions specified in `electric-indent-actions'." | ||
| 278 | (cond | ||
| 279 | ((memq 'yank electric-indent-actions) | ||
| 280 | (if enable | ||
| 281 | (advice-add #'yank :around #'electric-indent--yank-advice) | ||
| 282 | (advice-remove #'yank #'electric-indent--yank-advice))) | ||
| 283 | ((memq 'before-save electric-indent-actions) | ||
| 284 | (if enable | ||
| 285 | (add-hook 'before-save-hook #'electric-indent-save-hook) | ||
| 286 | (remove-hook 'before-save-hook #'electric-indent-save-hook))))) | ||
| 287 | |||
| 221 | (defun electric-indent-post-self-insert-function () | 288 | (defun electric-indent-post-self-insert-function () |
| 222 | "Function that `electric-indent-mode' adds to `post-self-insert-hook'. | 289 | "Function that `electric-indent-mode' adds to `post-self-insert-hook'. |
| 223 | This indents if the hook `electric-indent-functions' returns non-nil, | 290 | This indents if the hook `electric-indent-functions' returns non-nil, |
| @@ -256,10 +323,7 @@ or comment." | |||
| 256 | (when at-newline | 323 | (when at-newline |
| 257 | (let ((before (copy-marker (1- pos) t))) | 324 | (let ((before (copy-marker (1- pos) t))) |
| 258 | (save-excursion | 325 | (save-excursion |
| 259 | (unless | 326 | (when (electric-indent-can-reindent-p) |
| 260 | (or (memq indent-line-function | ||
| 261 | electric-indent-functions-without-reindent) | ||
| 262 | electric-indent-inhibit) | ||
| 263 | ;; Don't reindent the previous line if the | 327 | ;; Don't reindent the previous line if the |
| 264 | ;; indentation function is not a real one. | 328 | ;; indentation function is not a real one. |
| 265 | (goto-char before) | 329 | (goto-char before) |
| @@ -331,9 +395,13 @@ use `electric-indent-local-mode'." | |||
| 331 | (if electric-indent-mode (throw 'found t))))) | 395 | (if electric-indent-mode (throw 'found t))))) |
| 332 | (remove-hook 'post-self-insert-hook | 396 | (remove-hook 'post-self-insert-hook |
| 333 | #'electric-indent-post-self-insert-function)) | 397 | #'electric-indent-post-self-insert-function)) |
| 398 | |||
| 334 | (add-hook 'post-self-insert-hook | 399 | (add-hook 'post-self-insert-hook |
| 335 | #'electric-indent-post-self-insert-function | 400 | #'electric-indent-post-self-insert-function |
| 336 | 60))) | 401 | 60)) |
| 402 | |||
| 403 | ;; Toggle the reindentation on actions | ||
| 404 | (electric-indent-toggle-indent-actions electric-indent-mode)) | ||
| 337 | 405 | ||
| 338 | ;;;###autoload | 406 | ;;;###autoload |
| 339 | (define-minor-mode electric-indent-local-mode | 407 | (define-minor-mode electric-indent-local-mode |