diff options
| author | Stefan Monnier | 2010-11-26 16:33:21 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2010-11-26 16:33:21 -0500 |
| commit | 09ffa822f8c0ff82d7a277d1bc673cc0831010b6 (patch) | |
| tree | 0840bfa1c9abeba2a86b88a32e6ecb2bb767781c | |
| parent | afde451abef73d7b4b21af427c48621dedc60f4b (diff) | |
| download | emacs-09ffa822f8c0ff82d7a277d1bc673cc0831010b6.tar.gz emacs-09ffa822f8c0ff82d7a277d1bc673cc0831010b6.zip | |
* emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling
of :smie-open/close-alist.
(smie-next-sexp): Make it accept a "start token" as argument.
(smie-indent-keyword): Be careful not to misidentify tokens that span
more than one line, as empty lines. Add argument `token'.
| -rw-r--r-- | lisp/ChangeLog | 8 | ||||
| -rw-r--r-- | lisp/emacs-lisp/smie.el | 120 |
2 files changed, 74 insertions, 54 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1b35c13377c..3ac8fd7a270 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2010-11-26 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * emacs-lisp/smie.el (smie-prec2->grammar): Simplify handling | ||
| 4 | of :smie-open/close-alist. | ||
| 5 | (smie-next-sexp): Make it accept a "start token" as argument. | ||
| 6 | (smie-indent-keyword): Be careful not to misidentify tokens that span | ||
| 7 | more than one line, as empty lines. Add argument `token'. | ||
| 8 | |||
| 1 | 2010-11-26 Kenichi Handa <handa@m17n.org> | 9 | 2010-11-26 Kenichi Handa <handa@m17n.org> |
| 2 | 10 | ||
| 3 | * mail/rmailmm.el (rmail-mime-insert-multipart): For unsupported | 11 | * mail/rmailmm.el (rmail-mime-insert-multipart): For unsupported |
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el index 179e0a9f094..a7021b3cf7b 100644 --- a/lisp/emacs-lisp/smie.el +++ b/lisp/emacs-lisp/smie.el | |||
| @@ -76,8 +76,6 @@ | |||
| 76 | 76 | ||
| 77 | ;; TODO & BUGS: | 77 | ;; TODO & BUGS: |
| 78 | ;; | 78 | ;; |
| 79 | ;; - FIXME: I think the behavior on empty lines is wrong. It shouldn't | ||
| 80 | ;; look at the next token on subsequent lines. | ||
| 81 | ;; - Using the structural information SMIE gives us, it should be possible to | 79 | ;; - Using the structural information SMIE gives us, it should be possible to |
| 82 | ;; implement a `smie-align' command that would automatically figure out what | 80 | ;; implement a `smie-align' command that would automatically figure out what |
| 83 | ;; there is to align and how to do it (something like: align the token of | 81 | ;; there is to align and how to do it (something like: align the token of |
| @@ -470,7 +468,7 @@ PREC2 is a table as returned by `smie-precs->prec2' or | |||
| 470 | (to (cdar eqs))) | 468 | (to (cdar eqs))) |
| 471 | (setq eqs (cdr eqs)) | 469 | (setq eqs (cdr eqs)) |
| 472 | (if (eq to from) | 470 | (if (eq to from) |
| 473 | nil ;Nothing to do. | 471 | nil ;Nothing to do. |
| 474 | (dolist (other-eq eqs) | 472 | (dolist (other-eq eqs) |
| 475 | (if (eq from (cdr other-eq)) (setcdr other-eq to)) | 473 | (if (eq from (cdr other-eq)) (setcdr other-eq to)) |
| 476 | (when (eq from (car other-eq)) | 474 | (when (eq from (car other-eq)) |
| @@ -523,24 +521,23 @@ PREC2 is a table as returned by `smie-precs->prec2' or | |||
| 523 | (setcar (car eq) (cadr eq)) | 521 | (setcar (car eq) (cadr eq)) |
| 524 | ;; (smie-check-grammar table prec2 'step2) | 522 | ;; (smie-check-grammar table prec2 'step2) |
| 525 | ) | 523 | ) |
| 526 | ;; Finally, fill in the remaining vars (which only appeared on the | 524 | ;; Finally, fill in the remaining vars (which did not appear on the |
| 527 | ;; right side of the < constraints). | 525 | ;; left side of any < constraint). |
| 528 | (let ((classification-table (gethash :smie-open/close-alist prec2))) | 526 | (dolist (x table) |
| 529 | (dolist (x table) | 527 | (unless (nth 1 x) |
| 530 | ;; When both sides are nil, it means this operator binds very | 528 | (setf (nth 1 x) i) |
| 531 | ;; very tight, but it's still just an operator, so we give it | 529 | (incf i)) ;See other (incf i) above. |
| 532 | ;; the highest precedence. | 530 | (unless (nth 2 x) |
| 533 | ;; OTOH if only one side is nil, it usually means it's like an | 531 | (setf (nth 2 x) i) |
| 534 | ;; open-paren, which is very important for indentation purposes, | 532 | (incf i)))) ;See other (incf i) above. |
| 535 | ;; so we keep it nil if so, to make it easier to recognize. | 533 | ;; Mark closers and openers. |
| 536 | (unless (or (nth 1 x) | 534 | (dolist (x (gethash :smie-open/close-alist prec2)) |
| 537 | (eq 'opener (cdr (assoc (car x) classification-table)))) | 535 | (let* ((token (car x)) |
| 538 | (setf (nth 1 x) i) | 536 | (cons (case (cdr x) |
| 539 | (incf i)) ;See other (incf i) above. | 537 | (closer (cddr (assoc token table))) |
| 540 | (unless (or (nth 2 x) | 538 | (opener (cdr (assoc token table)))))) |
| 541 | (eq 'closer (cdr (assoc (car x) classification-table)))) | 539 | (assert (numberp (car cons))) |
| 542 | (setf (nth 2 x) i) | 540 | (setf (car cons) (list (car cons))))) |
| 543 | (incf i))))) ;See other (incf i) above. | ||
| 544 | (let ((ca (gethash :smie-closer-alist prec2))) | 541 | (let ((ca (gethash :smie-closer-alist prec2))) |
| 545 | (when ca (push (cons :smie-closer-alist ca) table))) | 542 | (when ca (push (cons :smie-closer-alist ca) table))) |
| 546 | ;; (smie-check-grammar table prec2 'step3) | 543 | ;; (smie-check-grammar table prec2 'step3) |
| @@ -611,6 +608,8 @@ OP-FORW is the accessor to the forward level of the level data. | |||
| 611 | OP-BACK is the accessor to the backward level of the level data. | 608 | OP-BACK is the accessor to the backward level of the level data. |
| 612 | HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the | 609 | HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the |
| 613 | first token we see is an operator, skip over its left-hand-side argument. | 610 | first token we see is an operator, skip over its left-hand-side argument. |
| 611 | HALFSEXP can also be a token, in which case it means to parse as if | ||
| 612 | we had just successfully passed this token. | ||
| 614 | Possible return values: | 613 | Possible return values: |
| 615 | (FORW-LEVEL POS TOKEN): we couldn't skip TOKEN because its back-level | 614 | (FORW-LEVEL POS TOKEN): we couldn't skip TOKEN because its back-level |
| 616 | is too high. FORW-LEVEL is the forw-level of TOKEN, | 615 | is too high. FORW-LEVEL is the forw-level of TOKEN, |
| @@ -619,7 +618,10 @@ Possible return values: | |||
| 619 | (nil POS TOKEN): we skipped over a paren-like pair. | 618 | (nil POS TOKEN): we skipped over a paren-like pair. |
| 620 | nil: we skipped over an identifier, matched parentheses, ..." | 619 | nil: we skipped over an identifier, matched parentheses, ..." |
| 621 | (catch 'return | 620 | (catch 'return |
| 622 | (let ((levels ())) | 621 | (let ((levels |
| 622 | (if (stringp halfsexp) | ||
| 623 | (prog1 (list (cdr (assoc halfsexp smie-grammar))) | ||
| 624 | (setq halfsexp nil))))) | ||
| 623 | (while | 625 | (while |
| 624 | (let* ((pos (point)) | 626 | (let* ((pos (point)) |
| 625 | (token (funcall next-token)) | 627 | (token (funcall next-token)) |
| @@ -697,6 +699,8 @@ Possible return values: | |||
| 697 | "Skip over one sexp. | 699 | "Skip over one sexp. |
| 698 | HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the | 700 | HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the |
| 699 | first token we see is an operator, skip over its left-hand-side argument. | 701 | first token we see is an operator, skip over its left-hand-side argument. |
| 702 | HALFSEXP can also be a token, in which case we should skip the text | ||
| 703 | assuming it is the left-hand-side argument of that token. | ||
| 700 | Possible return values: | 704 | Possible return values: |
| 701 | (LEFT-LEVEL POS TOKEN): we couldn't skip TOKEN because its right-level | 705 | (LEFT-LEVEL POS TOKEN): we couldn't skip TOKEN because its right-level |
| 702 | is too high. LEFT-LEVEL is the left-level of TOKEN, | 706 | is too high. LEFT-LEVEL is the left-level of TOKEN, |
| @@ -714,7 +718,9 @@ Possible return values: | |||
| 714 | (defun smie-forward-sexp (&optional halfsexp) | 718 | (defun smie-forward-sexp (&optional halfsexp) |
| 715 | "Skip over one sexp. | 719 | "Skip over one sexp. |
| 716 | HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the | 720 | HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the |
| 717 | first token we see is an operator, skip over its left-hand-side argument. | 721 | first token we see is an operator, skip over its right-hand-side argument. |
| 722 | HALFSEXP can also be a token, in which case we should skip the text | ||
| 723 | assuming it is the right-hand-side argument of that token. | ||
| 718 | Possible return values: | 724 | Possible return values: |
| 719 | (RIGHT-LEVEL POS TOKEN): we couldn't skip TOKEN because its left-level | 725 | (RIGHT-LEVEL POS TOKEN): we couldn't skip TOKEN because its left-level |
| 720 | is too high. RIGHT-LEVEL is the right-level of TOKEN, | 726 | is too high. RIGHT-LEVEL is the right-level of TOKEN, |
| @@ -791,7 +797,7 @@ Possible return values: | |||
| 791 | (push (car other) found)))))) | 797 | (push (car other) found)))))) |
| 792 | (cond | 798 | (cond |
| 793 | ((null found) (error "No known closer for opener %s" open)) | 799 | ((null found) (error "No known closer for opener %s" open)) |
| 794 | ;; FIXME: what should we do if there are various closers? | 800 | ;; What should we do if there are various closers? |
| 795 | (t (car found)))))))))) | 801 | (t (car found)))))))))) |
| 796 | (unless (save-excursion (skip-chars-backward " \t") (bolp)) | 802 | (unless (save-excursion (skip-chars-backward " \t") (bolp)) |
| 797 | (newline)) | 803 | (newline)) |
| @@ -1094,9 +1100,6 @@ Only meaningful when called from within `smie-rules-function'." | |||
| 1094 | ;; line, in which case we want to align it with its enclosing parent. | 1100 | ;; line, in which case we want to align it with its enclosing parent. |
| 1095 | (cond | 1101 | (cond |
| 1096 | ((and (eq method :before) (smie-rule-bolp) (not (smie-rule-sibling-p))) | 1102 | ((and (eq method :before) (smie-rule-bolp) (not (smie-rule-sibling-p))) |
| 1097 | ;; FIXME: Rather than consult the number of spaces, we could *set* the | ||
| 1098 | ;; number of spaces so as to align the separator with the close-paren | ||
| 1099 | ;; while aligning the content with the rest. | ||
| 1100 | (let ((parent-col (cdr (smie-rule-parent))) | 1103 | (let ((parent-col (cdr (smie-rule-parent))) |
| 1101 | (parent-pos-col ;FIXME: we knew this when computing smie--parent. | 1104 | (parent-pos-col ;FIXME: we knew this when computing smie--parent. |
| 1102 | (save-excursion | 1105 | (save-excursion |
| @@ -1225,39 +1228,48 @@ in order to figure out the indentation of some other (further down) point." | |||
| 1225 | (smie-indent-virtual)) ;:not-hanging | 1228 | (smie-indent-virtual)) ;:not-hanging |
| 1226 | (scan-error nil))))) | 1229 | (scan-error nil))))) |
| 1227 | 1230 | ||
| 1228 | (defun smie-indent-keyword () | 1231 | (defun smie-indent-keyword (&optional token) |
| 1229 | ;; Align closing token with the corresponding opening one. | 1232 | "Indent point based on the token that follows it immediately. |
| 1230 | ;; (e.g. "of" with "case", or "in" with "let"). | 1233 | If TOKEN is non-nil, assume that that is the token that follows point. |
| 1234 | Returns either a column number or nil if it considers that indentation | ||
| 1235 | should not be computed on the basis of the following token." | ||
| 1231 | (save-excursion | 1236 | (save-excursion |
| 1232 | (let* ((pos (point)) | 1237 | (let* ((pos (point)) |
| 1233 | (toklevels (smie-indent-forward-token)) | 1238 | (toklevels |
| 1234 | (token (pop toklevels))) | 1239 | (if token |
| 1240 | (assoc token smie-grammar) | ||
| 1241 | (let* ((res (smie-indent-forward-token))) | ||
| 1242 | ;; Ignore tokens on subsequent lines. | ||
| 1243 | (if (and (< pos (line-beginning-position)) | ||
| 1244 | ;; Make sure `token' also *starts* on another line. | ||
| 1245 | (save-excursion | ||
| 1246 | (smie-indent-backward-token) | ||
| 1247 | (< pos (line-beginning-position)))) | ||
| 1248 | nil | ||
| 1249 | (goto-char pos) | ||
| 1250 | res))))) | ||
| 1251 | (setq token (pop toklevels)) | ||
| 1235 | (cond | 1252 | (cond |
| 1236 | ((< pos (line-beginning-position)) | 1253 | ((null (cdr toklevels)) nil) ;Not a keyword. |
| 1237 | ;; The token we just read is actually not on the line where we started. | ||
| 1238 | nil) | ||
| 1239 | ((not (numberp (car toklevels))) | 1254 | ((not (numberp (car toklevels))) |
| 1240 | (save-excursion | 1255 | ;; Different cases: |
| 1241 | (goto-char pos) | 1256 | ;; - smie-indent--bolp: "indent according to others". |
| 1242 | ;; Different cases: | 1257 | ;; - common hanging: "indent according to others". |
| 1243 | ;; - smie-indent--bolp: "indent according to others". | 1258 | ;; - SML-let hanging: "indent like parent". |
| 1244 | ;; - common hanging: "indent according to others". | 1259 | ;; - if-after-else: "indent-like parent". |
| 1245 | ;; - SML-let hanging: "indent like parent". | 1260 | ;; - middle-of-line: "trust current position". |
| 1246 | ;; - if-after-else: "indent-like parent". | 1261 | (cond |
| 1247 | ;; - middle-of-line: "trust current position". | 1262 | ((smie-indent--rule :before token)) |
| 1248 | (cond | 1263 | ((smie-indent--bolp) ;I.e. non-virtual indent. |
| 1249 | ((null (cdr toklevels)) nil) ;Not a keyword. | 1264 | ;; For an open-paren-like thingy at BOL, always indent only |
| 1250 | ((smie-indent--rule :before token)) | 1265 | ;; based on other rules (typically smie-indent-after-keyword). |
| 1251 | ((smie-indent--bolp) ;I.e. non-virtual indent. | 1266 | nil) |
| 1252 | ;; For an open-paren-like thingy at BOL, always indent only | 1267 | (t |
| 1253 | ;; based on other rules (typically smie-indent-after-keyword). | 1268 | ;; By default use point unless we're hanging. |
| 1254 | nil) | 1269 | (unless (smie-indent--hanging-p) (current-column))))) |
| 1255 | (t | ||
| 1256 | ;; By default use point unless we're hanging. | ||
| 1257 | (unless (smie-indent--hanging-p) (current-column)))))) | ||
| 1258 | (t | 1270 | (t |
| 1259 | ;; FIXME: This still looks too much like black magic!! | 1271 | ;; FIXME: This still looks too much like black magic!! |
| 1260 | (let* ((parent (smie-backward-sexp 'halfsexp))) | 1272 | (let* ((parent (smie-backward-sexp token))) |
| 1261 | ;; Different behaviors: | 1273 | ;; Different behaviors: |
| 1262 | ;; - align with parent. | 1274 | ;; - align with parent. |
| 1263 | ;; - parent + offset. | 1275 | ;; - parent + offset. |