diff options
| author | Stefan Monnier | 2010-11-16 16:14:46 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2010-11-16 16:14:46 -0500 |
| commit | 7100ff98443a6d433bbce9de8771983eb13f03c0 (patch) | |
| tree | 8bda0da705eb00067770483a40a00a0396441840 | |
| parent | 77cd1a622a5d365eba4f686bb52f92357cadfcf9 (diff) | |
| download | emacs-7100ff98443a6d433bbce9de8771983eb13f03c0.tar.gz emacs-7100ff98443a6d433bbce9de8771983eb13f03c0.zip | |
* lisp/electric.el (electric-layout-mode): New minor mode.
(electric--after-char-pos): New function.
(electric-indent-post-self-insert-function): Use it.
(electric-layout-rules): New var.
(electric-layout-post-self-insert-function): New function.
(electric-indent-mode): Make them interact better.
| -rw-r--r-- | etc/NEWS | 3 | ||||
| -rw-r--r-- | lisp/ChangeLog | 9 | ||||
| -rw-r--r-- | lisp/electric.el | 127 |
3 files changed, 107 insertions, 32 deletions
| @@ -543,7 +543,8 @@ system or session bus. | |||
| 543 | 543 | ||
| 544 | * New Modes and Packages in Emacs 24.1 | 544 | * New Modes and Packages in Emacs 24.1 |
| 545 | 545 | ||
| 546 | ** New global minor modes electric-pair-mode and electric-indent-mode. | 546 | ** New global minor modes electric-pair-mode, electric-indent-mode, |
| 547 | and electric-layout-mode. | ||
| 547 | 548 | ||
| 548 | ** pcase.el provides the ML-style pattern matching macro `pcase'. | 549 | ** pcase.el provides the ML-style pattern matching macro `pcase'. |
| 549 | 550 | ||
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index bf31d51c2d1..b5be8544e5a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2010-11-16 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * electric.el (electric-layout-mode): New minor mode. | ||
| 4 | (electric--after-char-pos): New function. | ||
| 5 | (electric-indent-post-self-insert-function): Use it. | ||
| 6 | (electric-layout-rules): New var. | ||
| 7 | (electric-layout-post-self-insert-function): New function. | ||
| 8 | (electric-indent-mode): Make them interact better. | ||
| 9 | |||
| 1 | 2010-11-15 Stefan Monnier <monnier@iro.umontreal.ca> | 10 | 2010-11-15 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 11 | ||
| 3 | * emacs-lisp/checkdoc.el (checkdoc-syntax-table): Fix last change. | 12 | * emacs-lisp/checkdoc.el (checkdoc-syntax-table): Fix last change. |
diff --git a/lisp/electric.el b/lisp/electric.el index a0d849bbcca..b34d327c4f2 100644 --- a/lisp/electric.el +++ b/lisp/electric.el | |||
| @@ -176,6 +176,20 @@ | |||
| 176 | "Electric behavior for self inserting keys." | 176 | "Electric behavior for self inserting keys." |
| 177 | :group 'editing) | 177 | :group 'editing) |
| 178 | 178 | ||
| 179 | (defun electric--after-char-pos () | ||
| 180 | "Return the position after the char we just inserted. | ||
| 181 | Returns nil when we can't find this char." | ||
| 182 | (let ((pos (point))) | ||
| 183 | (when (or (eq (char-before) last-command-event) ;; Sanity check. | ||
| 184 | (save-excursion | ||
| 185 | (or (progn (skip-chars-backward " \t") | ||
| 186 | (setq pos (point)) | ||
| 187 | (eq (char-before) last-command-event)) | ||
| 188 | (progn (skip-chars-backward " \n\t") | ||
| 189 | (setq pos (point)) | ||
| 190 | (eq (char-before) last-command-event))))) | ||
| 191 | pos))) | ||
| 192 | |||
| 179 | ;; Electric indentation. | 193 | ;; Electric indentation. |
| 180 | 194 | ||
| 181 | ;; Autoloading variables is generally undesirable, but major modes | 195 | ;; Autoloading variables is generally undesirable, but major modes |
| @@ -193,35 +207,35 @@ | |||
| 193 | ;; electric-pair-mode wrapping a region with a pair of parens. | 207 | ;; electric-pair-mode wrapping a region with a pair of parens. |
| 194 | ;; There might be a way to get it working by analyzing buffer-undo-list, but | 208 | ;; There might be a way to get it working by analyzing buffer-undo-list, but |
| 195 | ;; it looks challenging. | 209 | ;; it looks challenging. |
| 196 | (when (and (memq last-command-event electric-indent-chars) | 210 | (let (pos) |
| 197 | ;; Don't reindent while inserting spaces at beginning of line. | 211 | (when (and (memq last-command-event electric-indent-chars) |
| 198 | (or (not (memq last-command-event '(?\s ?\t))) | 212 | ;; Don't reindent while inserting spaces at beginning of line. |
| 199 | (save-excursion (skip-chars-backward " \t") (not (bolp)))) | 213 | (or (not (memq last-command-event '(?\s ?\t))) |
| 200 | ;; Not in a string or comment. | 214 | (save-excursion (skip-chars-backward " \t") (not (bolp)))) |
| 201 | (not (nth 8 (syntax-ppss)))) | 215 | (setq pos (electric--after-char-pos)) |
| 202 | ;; For newline, we want to reindent both lines and basically behave like | 216 | ;; Not in a string or comment. |
| 203 | ;; reindent-then-newline-and-indent (whose code we hence copied). | 217 | (not (nth 8 (save-excursion (syntax-ppss pos))))) |
| 204 | (when (and (eq last-command-event ?\n) | 218 | ;; For newline, we want to reindent both lines and basically behave like |
| 205 | ;; Don't reindent the previous line if the indentation function | 219 | ;; reindent-then-newline-and-indent (whose code we hence copied). |
| 206 | ;; is not a real one. | 220 | (when (and (< (1- pos) (line-beginning-position)) |
| 207 | (not (memq indent-line-function | 221 | ;; Don't reindent the previous line if the indentation |
| 208 | '(indent-relative indent-relative-maybe))) | 222 | ;; function is not a real one. |
| 209 | ;; Sanity check. | 223 | (not (memq indent-line-function |
| 210 | (eq (char-before) last-command-event)) | 224 | '(indent-relative indent-relative-maybe)))) |
| 211 | (let ((pos (copy-marker (1- (point)) t))) | 225 | (let ((before (copy-marker (1- pos) t))) |
| 212 | (save-excursion | 226 | (save-excursion |
| 213 | (goto-char pos) | 227 | (goto-char before) |
| 214 | (indent-according-to-mode) | 228 | (indent-according-to-mode) |
| 215 | ;; We are at EOL before the call to indent-according-to-mode, and | 229 | ;; We are at EOL before the call to indent-according-to-mode, and |
| 216 | ;; after it we usually are as well, but not always. We tried to | 230 | ;; after it we usually are as well, but not always. We tried to |
| 217 | ;; address it with `save-excursion' but that uses a normal marker | 231 | ;; address it with `save-excursion' but that uses a normal marker |
| 218 | ;; whereas we need `move after insertion', so we do the | 232 | ;; whereas we need `move after insertion', so we do the |
| 219 | ;; save/restore by hand. | 233 | ;; save/restore by hand. |
| 220 | (goto-char pos) | 234 | (goto-char before) |
| 221 | ;; Remove the trailing whitespace after indentation because | 235 | ;; Remove the trailing whitespace after indentation because |
| 222 | ;; indentation may (re)introduce the whitespace. | 236 | ;; indentation may (re)introduce the whitespace. |
| 223 | (delete-horizontal-space t)))) | 237 | (delete-horizontal-space t)))) |
| 224 | (indent-according-to-mode))) | 238 | (indent-according-to-mode)))) |
| 225 | 239 | ||
| 226 | ;;;###autoload | 240 | ;;;###autoload |
| 227 | (define-minor-mode electric-indent-mode | 241 | (define-minor-mode electric-indent-mode |
| @@ -233,7 +247,17 @@ | |||
| 233 | (add-hook 'post-self-insert-hook | 247 | (add-hook 'post-self-insert-hook |
| 234 | #'electric-indent-post-self-insert-function) | 248 | #'electric-indent-post-self-insert-function) |
| 235 | (remove-hook 'post-self-insert-hook | 249 | (remove-hook 'post-self-insert-hook |
| 236 | #'electric-indent-post-self-insert-function))) | 250 | #'electric-indent-post-self-insert-function)) |
| 251 | ;; FIXME: electric-indent-mode and electric-layout-mode interact | ||
| 252 | ;; in non-trivial ways. It turns out that electric-indent-mode works | ||
| 253 | ;; better if it is run *after* electric-layout-mode's hook. | ||
| 254 | (when (memq #'electric-layout-post-self-insert-function | ||
| 255 | (memq #'electric-indent-post-self-insert-function | ||
| 256 | (default-value 'post-self-insert-hook))) | ||
| 257 | (remove-hook 'post-self-insert-hook | ||
| 258 | #'electric-layout-post-self-insert-function) | ||
| 259 | (add-hook 'post-self-insert-hook | ||
| 260 | #'electric-layout-post-self-insert-function))) | ||
| 237 | 261 | ||
| 238 | ;; Electric pairing. | 262 | ;; Electric pairing. |
| 239 | 263 | ||
| @@ -302,7 +326,48 @@ This can be convenient for people who find it easier to hit ) than C-f." | |||
| 302 | #'electric-pair-post-self-insert-function) | 326 | #'electric-pair-post-self-insert-function) |
| 303 | (remove-hook 'post-self-insert-hook | 327 | (remove-hook 'post-self-insert-hook |
| 304 | #'electric-pair-post-self-insert-function))) | 328 | #'electric-pair-post-self-insert-function))) |
| 305 | 329 | ||
| 330 | ;; Automatically add newlines after/before/around some chars. | ||
| 331 | |||
| 332 | (defvar electric-layout-rules '() | ||
| 333 | "List of rules saying where to automatically insert newlines. | ||
| 334 | Each rule has the form (CHAR . WHERE) where CHAR is the char | ||
| 335 | that was just inserted and WHERE specifies where to insert newlines | ||
| 336 | and can be: nil, `before', `after', `around', or a function that returns | ||
| 337 | one of those symbols.") | ||
| 338 | |||
| 339 | (defun electric-layout-post-self-insert-function () | ||
| 340 | (let* ((rule (cdr (assq last-command-event electric-layout-rules))) | ||
| 341 | pos) | ||
| 342 | (when (and rule | ||
| 343 | (setq pos (electric--after-char-pos)) | ||
| 344 | ;; Not in a string or comment. | ||
| 345 | (not (nth 8 (save-excursion (syntax-ppss pos))))) | ||
| 346 | (let ((end (copy-marker (point) t))) | ||
| 347 | (goto-char pos) | ||
| 348 | (case (if (functionp rule) (funcall rule) rule) | ||
| 349 | ;; FIXME: we used `newline' down here which called | ||
| 350 | ;; self-insert-command and ran post-self-insert-hook recursively. | ||
| 351 | ;; It happened to make electric-indent-mode work automatically with | ||
| 352 | ;; electric-layout-mode (at the cost of re-indenting lines | ||
| 353 | ;; multiple times), but I'm not sure it's what we want. | ||
| 354 | (before (goto-char (1- pos)) (insert "\n")) | ||
| 355 | (after (insert "\n")) | ||
| 356 | (around (goto-char (1- pos)) (insert "\n") | ||
| 357 | (forward-char 1) (insert "\n"))) | ||
| 358 | (goto-char end))))) | ||
| 359 | |||
| 360 | ;;;###autoload | ||
| 361 | (define-minor-mode electric-layout-mode | ||
| 362 | "Automatically insert newlines around some chars." | ||
| 363 | :global t | ||
| 364 | :group 'electricity | ||
| 365 | (if electric-layout-mode | ||
| 366 | (add-hook 'post-self-insert-hook | ||
| 367 | #'electric-layout-post-self-insert-function) | ||
| 368 | (remove-hook 'post-self-insert-hook | ||
| 369 | #'electric-layout-post-self-insert-function))) | ||
| 370 | |||
| 306 | (provide 'electric) | 371 | (provide 'electric) |
| 307 | 372 | ||
| 308 | ;; arch-tag: dae045eb-dc2d-4fb7-9f27-9cc2ce277be8 | 373 | ;; arch-tag: dae045eb-dc2d-4fb7-9f27-9cc2ce277be8 |