diff options
| author | Stefan Monnier | 2010-06-07 15:37:50 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2010-06-07 15:37:50 -0400 |
| commit | 83156c183f94404a1eabfe6d8a5f0b6bc5582fdf (patch) | |
| tree | 234595a12138e31950ee8bc51901e0a17550c19d | |
| parent | 13b5221f4df08dd203b36cc444aab7e825dd29f8 (diff) | |
| download | emacs-83156c183f94404a1eabfe6d8a5f0b6bc5582fdf.tar.gz emacs-83156c183f94404a1eabfe6d8a5f0b6bc5582fdf.zip | |
* lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
smie-indent-offset-after. Add :prev case. Make a bit more generic.
(smie-indent-virtual): Remove `virtual' arg. Update callers.
(smie-indent-keyword): Add handling of open-paren keywords.
(smie-indent-comment-continue): Don't assume comment-continue.
| -rw-r--r-- | lisp/ChangeLog | 8 | ||||
| -rw-r--r-- | lisp/emacs-lisp/smie.el | 139 |
2 files changed, 97 insertions, 50 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 04d914422e7..fd2f42c7b00 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2010-06-07 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * emacs-lisp/smie.el (smie-indent-offset-rule): Rename from | ||
| 4 | smie-indent-offset-after. Add :prev case. Make a bit more generic. | ||
| 5 | (smie-indent-virtual): Remove `virtual' arg. Update callers. | ||
| 6 | (smie-indent-keyword): Add handling of open-paren keywords. | ||
| 7 | (smie-indent-comment-continue): Don't assume comment-continue. | ||
| 8 | |||
| 1 | 2010-06-07 Martin Rudalics <rudalics@gmx.at> | 9 | 2010-06-07 Martin Rudalics <rudalics@gmx.at> |
| 2 | 10 | ||
| 3 | * window.el (pop-to-buffer): Remove the conditional that | 11 | * window.el (pop-to-buffer): Remove the conditional that |
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el index ee016e48555..0dc58ef7a28 100644 --- a/lisp/emacs-lisp/smie.el +++ b/lisp/emacs-lisp/smie.el | |||
| @@ -500,6 +500,7 @@ Possible return values: | |||
| 500 | ;; I.e. the indentation after "=" depends on the parent ("structure") | 500 | ;; I.e. the indentation after "=" depends on the parent ("structure") |
| 501 | ;; as well as on the following token ("struct"). | 501 | ;; as well as on the following token ("struct"). |
| 502 | "Rules of the following form. | 502 | "Rules of the following form. |
| 503 | \((:before . TOK) . OFFSET-RULES) how to indent TOK itself. | ||
| 503 | \(TOK . OFFSET-RULES) how to indent right after TOK. | 504 | \(TOK . OFFSET-RULES) how to indent right after TOK. |
| 504 | \((T1 . T2) . OFFSET) how to indent token T2 w.r.t T1. | 505 | \((T1 . T2) . OFFSET) how to indent token T2 w.r.t T1. |
| 505 | \((t . TOK) . OFFSET) how to indent TOK with respect to its parent. | 506 | \((t . TOK) . OFFSET) how to indent TOK with respect to its parent. |
| @@ -508,12 +509,17 @@ Possible return values: | |||
| 508 | \(t . OFFSET) basic indentation step. | 509 | \(t . OFFSET) basic indentation step. |
| 509 | \(args . OFFSET) indentation of arguments. | 510 | \(args . OFFSET) indentation of arguments. |
| 510 | 511 | ||
| 511 | OFFSET-RULES is list of elements which can either be an integer (the offset to | 512 | OFFSET-RULES is a list of elements which can each either be: |
| 512 | use), or a cons of the form | 513 | |
| 513 | \(:hanging . OFFSET-RULES) if TOK is hanging, use OFFSET-RULES. | 514 | \(:hanging . OFFSET-RULES) if TOK is hanging, use OFFSET-RULES. |
| 514 | \(:parent PARENT . OFFSET-RULES) if TOK's parent is PARENT, use OFFSET-RULES. | 515 | \(:parent PARENT . OFFSET-RULES) if TOK's parent is PARENT, use OFFSET-RULES. |
| 515 | \(:next TOKEN . OFFSET-RULES) if TOK is followed by TOKEN, use OFFSET-RULES. | 516 | \(:next TOKEN . OFFSET-RULES) if TOK is followed by TOKEN, use OFFSET-RULES. |
| 516 | A nil offset defaults to `smie-indent-basic'.") | 517 | \(:prev TOKEN . OFFSET-RULES) if TOK is preceded by TOKEN, use OFFSET-RULES. |
| 518 | a number the offset to use. | ||
| 519 | `point' align with the token. | ||
| 520 | `parent' align with the parent. | ||
| 521 | |||
| 522 | A nil offset for indentation after a token defaults to `smie-indent-basic'.") | ||
| 517 | 523 | ||
| 518 | (defun smie-indent-hanging-p () | 524 | (defun smie-indent-hanging-p () |
| 519 | ;; A hanging keyword is one that's at the end of a line except it's not at | 525 | ;; A hanging keyword is one that's at the end of a line except it's not at |
| @@ -534,45 +540,46 @@ A nil offset defaults to `smie-indent-basic'.") | |||
| 534 | (cdr (assq t smie-indent-rules)) | 540 | (cdr (assq t smie-indent-rules)) |
| 535 | smie-indent-basic)) | 541 | smie-indent-basic)) |
| 536 | 542 | ||
| 537 | (defun smie-indent-offset-after (tokinfo after) | 543 | (defun smie-indent-offset-rule (tokinfo &optional after) |
| 538 | ;; Presumes we're right before the token corresponding to `tokinfo' | 544 | "Apply the OFFSET-RULES in TOKINFO. |
| 539 | ;; and `after' is the position that we're trying to indent. | 545 | Point is expected to be right in front of the token corresponding to TOKINFO. |
| 546 | If computing the indentation after the token, then AFTER is the position | ||
| 547 | after the token." | ||
| 540 | (let ((rules (cdr tokinfo)) | 548 | (let ((rules (cdr tokinfo)) |
| 541 | parent next offset) | 549 | parent next prev |
| 550 | offset) | ||
| 542 | (while (consp rules) | 551 | (while (consp rules) |
| 543 | (let ((rule (pop rules))) | 552 | (let ((rule (pop rules))) |
| 544 | (cond | 553 | (cond |
| 545 | ((not (consp rule)) (setq offset rule)) | 554 | ((not (consp rule)) (setq offset rule)) |
| 546 | ;; Using this `:hanging' is often "wrong", in that the hangingness | ||
| 547 | ;; of a keyword should usually not affect the indentation of the | ||
| 548 | ;; immediately following expression, but rather should affect the | ||
| 549 | ;; virtual indentation of that keyword (which in turn will affect not | ||
| 550 | ;; only indentation of the immediately following expression, but also | ||
| 551 | ;; other dependent expressions). | ||
| 552 | ;; But there are cases where it's useful: you may want to use it to | ||
| 553 | ;; make the indentation inside parentheses different depending on the | ||
| 554 | ;; hangingness of the open-paren, but without affecting the | ||
| 555 | ;; indentation of the paren-close. | ||
| 556 | ((eq (car rule) :hanging) | 555 | ((eq (car rule) :hanging) |
| 557 | (when (smie-indent-hanging-p) | 556 | (when (smie-indent-hanging-p) |
| 558 | (setq rules (cdr rule)))) | 557 | (setq rules (cdr rule)))) |
| 558 | ((eq (car rule) :prev) | ||
| 559 | (unless prev | ||
| 560 | (save-excursion | ||
| 561 | (setq prev (smie-indent-backward-token)))) | ||
| 562 | (when (equal (car prev) (cadr rule)) | ||
| 563 | (setq rules (cddr rule)))) | ||
| 559 | ((eq (car rule) :next) | 564 | ((eq (car rule) :next) |
| 560 | (unless next | 565 | (unless next |
| 566 | (unless after | ||
| 567 | (error "Can't use :next in :before indentation rules")) | ||
| 561 | (save-excursion | 568 | (save-excursion |
| 562 | (goto-char after) | 569 | (goto-char after) |
| 563 | (setq next (funcall smie-forward-token-function)))) | 570 | (setq next (smie-indent-forward-token)))) |
| 564 | (when (equal next (cadr rule)) | 571 | (when (equal (car next) (cadr rule)) |
| 565 | (setq rules (cddr rule)))) | 572 | (setq rules (cddr rule)))) |
| 566 | ((eq (car rule) :parent) | 573 | ((eq (car rule) :parent) |
| 567 | (unless parent | 574 | (unless parent |
| 568 | (save-excursion | 575 | (save-excursion |
| 569 | (goto-char after) | 576 | (if after (goto-char after)) |
| 570 | (setq parent (smie-backward-sexp 'halfsexp)))) | 577 | (setq parent (smie-backward-sexp 'halfsexp)))) |
| 571 | (when (equal (nth 2 parent) (cadr rule)) | 578 | (when (equal (nth 2 parent) (cadr rule)) |
| 572 | (setq rules (cddr rule)))) | 579 | (setq rules (cddr rule)))) |
| 573 | (t (error "Unknown rule %s for indentation after %s" | 580 | (t (error "Unknown rule %s for indentation of %s" |
| 574 | rule (car tokinfo)))))) | 581 | rule (car tokinfo)))))) |
| 575 | (or offset (smie-indent-offset t)))) | 582 | offset)) |
| 576 | 583 | ||
| 577 | (defun smie-indent-forward-token () | 584 | (defun smie-indent-forward-token () |
| 578 | "Skip token forward and return it, along with its levels." | 585 | "Skip token forward and return it, along with its levels." |
| @@ -593,24 +600,18 @@ A nil offset defaults to `smie-indent-basic'.") | |||
| 593 | (forward-char -1) | 600 | (forward-char -1) |
| 594 | (list (buffer-substring (point) (1+ (point))) nil 0))))) | 601 | (list (buffer-substring (point) (1+ (point))) nil 0))))) |
| 595 | 602 | ||
| 596 | ;; FIXME: The `virtual' arg is fundamentally wrong: the virtual indent | 603 | (defun smie-indent-virtual () |
| 597 | ;; of a position should not depend on the caller, since it leads to situations | 604 | ;; We used to take an optional arg (with value :not-hanging) to specify that |
| 598 | ;; where two dependent indentations get indented differently. | 605 | ;; we should only use (smie-indent-calculate) if we're looking at a hanging |
| 599 | (defun smie-indent-virtual (virtual) | 606 | ;; keyword. This was a bad idea, because the virtual indent of a position |
| 607 | ;; should not depend on the caller, since it leads to situations where two | ||
| 608 | ;; dependent indentations get indented differently. | ||
| 600 | "Compute the virtual indentation to use for point. | 609 | "Compute the virtual indentation to use for point. |
| 601 | This is used when we're not trying to indent point but just | 610 | This is used when we're not trying to indent point but just |
| 602 | need to compute the column at which point should be indented | 611 | need to compute the column at which point should be indented |
| 603 | in order to figure out the indentation of some other (further down) point. | 612 | in order to figure out the indentation of some other (further down) point." |
| 604 | VIRTUAL can take two different values: | ||
| 605 | - :bolp: means that the current indentation of point can be trusted | ||
| 606 | to be good only if it follows a line break. | ||
| 607 | - :not-hanging: means that the current indentation of point can be | ||
| 608 | trusted to be good except if the following token is hanging." | ||
| 609 | ;; Trust pre-existing indentation on other lines. | 613 | ;; Trust pre-existing indentation on other lines. |
| 610 | (assert virtual) | 614 | (if (smie-bolp) (current-column) (smie-indent-calculate))) |
| 611 | (if (if (eq virtual :not-hanging) (not (smie-indent-hanging-p)) (smie-bolp)) | ||
| 612 | (current-column) | ||
| 613 | (smie-indent-calculate))) | ||
| 614 | 615 | ||
| 615 | (defun smie-indent-fixindent () | 616 | (defun smie-indent-fixindent () |
| 616 | ;; Obey the `fixindent' special comment. | 617 | ;; Obey the `fixindent' special comment. |
| @@ -640,20 +641,49 @@ VIRTUAL can take two different values: | |||
| 640 | (condition-case nil | 641 | (condition-case nil |
| 641 | (progn | 642 | (progn |
| 642 | (backward-sexp 1) | 643 | (backward-sexp 1) |
| 643 | (smie-indent-virtual :not-hanging)) | 644 | (smie-indent-virtual)) ;:not-hanging |
| 644 | (scan-error nil))))) | 645 | (scan-error nil))))) |
| 645 | 646 | ||
| 646 | (defun smie-indent-keyword () | 647 | (defun smie-indent-keyword () |
| 647 | ;; Align closing token with the corresponding opening one. | 648 | ;; Align closing token with the corresponding opening one. |
| 648 | ;; (e.g. "of" with "case", or "in" with "let"). | 649 | ;; (e.g. "of" with "case", or "in" with "let"). |
| 649 | ;; FIXME: This still looks too much like black magic!! | ||
| 650 | ;; FIXME: Rather than a bunch of rules like (PARENT . TOKEN), we | ||
| 651 | ;; want a single rule for TOKEN with different cases for each PARENT. | ||
| 652 | (save-excursion | 650 | (save-excursion |
| 653 | (let* ((pos (point)) | 651 | (let* ((pos (point)) |
| 654 | (toklevels (smie-indent-forward-token)) | 652 | (toklevels (smie-indent-forward-token)) |
| 655 | (token (pop toklevels))) | 653 | (token (pop toklevels))) |
| 656 | (when (car toklevels) | 654 | (if (null (car toklevels)) |
| 655 | ;; Different case: | ||
| 656 | ;; - smie-bolp: "indent according to others". | ||
| 657 | ;; - common hanging: "indent according to others". | ||
| 658 | ;; - SML-let hanging: "indent like parent". | ||
| 659 | ;; - if-after-else: "indent-like parent". | ||
| 660 | ;; - middle-of-line: "trust current position". | ||
| 661 | (cond | ||
| 662 | ((null (cdr toklevels)) nil) ;Not a keyword. | ||
| 663 | ((smie-bolp) | ||
| 664 | ;; For an open-paren-like thingy at BOL, always indent only | ||
| 665 | ;; based on other rules (typically smie-indent-after-keyword). | ||
| 666 | nil) | ||
| 667 | (t | ||
| 668 | (let* ((tokinfo (or (assoc (cons :before token) smie-indent-rules) | ||
| 669 | ;; By default use point unless we're hanging. | ||
| 670 | (cons (cons :before token) | ||
| 671 | '((:hanging nil) point)))) | ||
| 672 | (after (prog1 (point) (goto-char pos))) | ||
| 673 | (offset (smie-indent-offset-rule tokinfo))) | ||
| 674 | (cond | ||
| 675 | ((eq offset 'point) (current-column)) | ||
| 676 | ((eq offset 'parent) | ||
| 677 | (let ((parent (smie-backward-sexp 'halfsexp))) | ||
| 678 | (if parent (goto-char (cadr parent)))) | ||
| 679 | (smie-indent-virtual)) | ||
| 680 | ((eq offset nil) nil) | ||
| 681 | (t (error "Unhandled offset %s in %s" | ||
| 682 | offset (cons :before token))))))) | ||
| 683 | |||
| 684 | ;; FIXME: This still looks too much like black magic!! | ||
| 685 | ;; FIXME: Rather than a bunch of rules like (PARENT . TOKEN), we | ||
| 686 | ;; want a single rule for TOKEN with different cases for each PARENT. | ||
| 657 | (let ((res (smie-backward-sexp 'halfsexp)) tmp) | 687 | (let ((res (smie-backward-sexp 'halfsexp)) tmp) |
| 658 | (cond | 688 | (cond |
| 659 | ((not (or (< (point) pos) | 689 | ((not (or (< (point) pos) |
| @@ -669,17 +699,17 @@ VIRTUAL can take two different values: | |||
| 669 | ;; a -> b -> c | 699 | ;; a -> b -> c |
| 670 | ;; -> d | 700 | ;; -> d |
| 671 | ;; So as to align with the earliest appropriate place. | 701 | ;; So as to align with the earliest appropriate place. |
| 672 | (smie-indent-virtual :bolp)) | 702 | (smie-indent-virtual)) |
| 673 | ((equal token (save-excursion | 703 | ((equal token (save-excursion |
| 674 | (funcall smie-backward-token-function))) | 704 | (funcall smie-backward-token-function))) |
| 675 | ;; in cases such as "fn x => fn y => fn z =>", | 705 | ;; in cases such as "fn x => fn y => fn z =>", |
| 676 | ;; jump back to the very first fn. | 706 | ;; jump back to the very first fn. |
| 677 | ;; FIXME: should we only do that for special tokens like "=>"? | 707 | ;; FIXME: should we only do that for special tokens like "=>"? |
| 678 | (smie-indent-virtual :bolp)) | 708 | (smie-indent-virtual)) |
| 679 | ((setq tmp (assoc (cons (caddr res) token) | 709 | ((setq tmp (assoc (cons (caddr res) token) |
| 680 | smie-indent-rules)) | 710 | smie-indent-rules)) |
| 681 | (goto-char (cadr res)) | 711 | (goto-char (cadr res)) |
| 682 | (+ (cdr tmp) (smie-indent-virtual :not-hanging))) | 712 | (+ (cdr tmp) (smie-indent-virtual))) ;:not-hanging |
| 683 | ;; FIXME: The rules ((t . TOK) . OFFSET) either indent | 713 | ;; FIXME: The rules ((t . TOK) . OFFSET) either indent |
| 684 | ;; relative to "before the parent" or "after the parent", | 714 | ;; relative to "before the parent" or "after the parent", |
| 685 | ;; depending on details of the grammar. | 715 | ;; depending on details of the grammar. |
| @@ -687,8 +717,15 @@ VIRTUAL can take two different values: | |||
| 687 | (assert (eq (point) (cadr res))) | 717 | (assert (eq (point) (cadr res))) |
| 688 | (goto-char (cadr res)) | 718 | (goto-char (cadr res)) |
| 689 | (+ (or (cdr (assoc (cons t token) smie-indent-rules)) 0) | 719 | (+ (or (cdr (assoc (cons t token) smie-indent-rules)) 0) |
| 690 | (smie-indent-virtual :not-hanging))) | 720 | (smie-indent-virtual))) ;:not-hanging |
| 691 | ((smie-bolp) | 721 | ((and (= (point) pos) (smie-bolp)) |
| 722 | ;; Since we started at BOL, we're not computing a virtual | ||
| 723 | ;; indentation, and we're still at the starting point, so the | ||
| 724 | ;; next (default) rule can't be used since it uses `current-column' | ||
| 725 | ;; which would cause. indentation to depend on itself. | ||
| 726 | ;; We could just return nil, but OTOH that's not good enough in | ||
| 727 | ;; some cases. Instead, we want to combine the offset-rules for | ||
| 728 | ;; the current token with the offset-rules of the previous one. | ||
| 692 | (+ (or (cdr (assoc (cons t token) smie-indent-rules)) 0) | 729 | (+ (or (cdr (assoc (cons t token) smie-indent-rules)) 0) |
| 693 | ;; FIXME: This is odd. Can't we make it use | 730 | ;; FIXME: This is odd. Can't we make it use |
| 694 | ;; smie-indent-(calculate|virtual) somehow? | 731 | ;; smie-indent-(calculate|virtual) somehow? |
| @@ -707,7 +744,8 @@ VIRTUAL can take two different values: | |||
| 707 | 744 | ||
| 708 | (defun smie-indent-comment-continue () | 745 | (defun smie-indent-comment-continue () |
| 709 | ;; indentation of comment-continue lines. | 746 | ;; indentation of comment-continue lines. |
| 710 | (let ((continue (comment-string-strip comment-continue t t))) | 747 | (let ((continue (and comment-continue |
| 748 | (comment-string-strip comment-continue t t)))) | ||
| 711 | (and (< 0 (length continue)) | 749 | (and (< 0 (length continue)) |
| 712 | (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss)) | 750 | (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss)) |
| 713 | (let ((ppss (syntax-ppss))) | 751 | (let ((ppss (syntax-ppss))) |
| @@ -733,7 +771,8 @@ VIRTUAL can take two different values: | |||
| 733 | (when toklevel | 771 | (when toklevel |
| 734 | (let ((offset | 772 | (let ((offset |
| 735 | (cond | 773 | (cond |
| 736 | (tokinfo (smie-indent-offset-after tokinfo pos)) | 774 | (tokinfo (or (smie-indent-offset-rule tokinfo pos) |
| 775 | (smie-indent-offset t))) | ||
| 737 | ;; The default indentation after a keyword/operator | 776 | ;; The default indentation after a keyword/operator |
| 738 | ;; is 0 for infix and t for prefix. | 777 | ;; is 0 for infix and t for prefix. |
| 739 | ;; Using the BNF syntax, we could come up with | 778 | ;; Using the BNF syntax, we could come up with |
| @@ -744,7 +783,7 @@ VIRTUAL can take two different values: | |||
| 744 | ;; For indentation after "(let" in SML-mode, we end up accumulating | 783 | ;; For indentation after "(let" in SML-mode, we end up accumulating |
| 745 | ;; the offset of "(" and the offset of "let", so we use `min' to try | 784 | ;; the offset of "(" and the offset of "let", so we use `min' to try |
| 746 | ;; and get it right either way. | 785 | ;; and get it right either way. |
| 747 | (+ (min (smie-indent-virtual :bolp) (current-column)) offset)))))) | 786 | (+ (min (smie-indent-virtual) (current-column)) offset)))))) |
| 748 | 787 | ||
| 749 | (defun smie-indent-exps () | 788 | (defun smie-indent-exps () |
| 750 | ;; Indentation of sequences of simple expressions without | 789 | ;; Indentation of sequences of simple expressions without |
| @@ -793,7 +832,7 @@ VIRTUAL can take two different values: | |||
| 793 | ;; We're the first arg. | 832 | ;; We're the first arg. |
| 794 | (goto-char (car positions)) | 833 | (goto-char (car positions)) |
| 795 | (+ (smie-indent-offset 'args) | 834 | (+ (smie-indent-offset 'args) |
| 796 | ;; We used to use (smie-indent-virtual :bolp), but that | 835 | ;; We used to use (smie-indent-virtual), but that |
| 797 | ;; doesn't seem right since it might then indent args less than | 836 | ;; doesn't seem right since it might then indent args less than |
| 798 | ;; the function itself. | 837 | ;; the function itself. |
| 799 | (current-column))))))) | 838 | (current-column))))))) |