aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2010-06-07 15:37:50 -0400
committerStefan Monnier2010-06-07 15:37:50 -0400
commit83156c183f94404a1eabfe6d8a5f0b6bc5582fdf (patch)
tree234595a12138e31950ee8bc51901e0a17550c19d
parent13b5221f4df08dd203b36cc444aab7e825dd29f8 (diff)
downloademacs-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/ChangeLog8
-rw-r--r--lisp/emacs-lisp/smie.el139
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 @@
12010-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
12010-06-07 Martin Rudalics <rudalics@gmx.at> 92010-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
511OFFSET-RULES is list of elements which can either be an integer (the offset to 512OFFSET-RULES is a list of elements which can each either be:
512use), 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.
516A nil offset defaults to `smie-indent-basic'.") 517\(:prev TOKEN . OFFSET-RULES) if TOK is preceded by TOKEN, use OFFSET-RULES.
518a number the offset to use.
519`point' align with the token.
520`parent' align with the parent.
521
522A 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. 545Point is expected to be right in front of the token corresponding to TOKINFO.
546If computing the indentation after the token, then AFTER is the position
547after 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.
601This is used when we're not trying to indent point but just 610This is used when we're not trying to indent point but just
602need to compute the column at which point should be indented 611need to compute the column at which point should be indented
603in order to figure out the indentation of some other (further down) point. 612in order to figure out the indentation of some other (further down) point."
604VIRTUAL 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)))))))