comparison lisp/emacs-lisp/smie.el @ 109841:3a11454ef7ca

Reindent smie.el
author Stefan Monnier <monnier@iro.umontreal.ca>
date Wed, 18 Aug 2010 14:10:30 +0200
parents 51f5fd9b5515
children af3f1edc363f
comparison
equal deleted inserted replaced
109840:51f5fd9b5515 109841:3a11454ef7ca
156 (pushnew (cadr rhs) first-ops))) 156 (pushnew (cadr rhs) first-ops)))
157 (let ((shr (reverse rhs))) 157 (let ((shr (reverse rhs)))
158 (if (not (member (car shr) nts)) 158 (if (not (member (car shr) nts))
159 (pushnew (car shr) last-ops) 159 (pushnew (car shr) last-ops)
160 (pushnew (car shr) last-nts) 160 (pushnew (car shr) last-nts)
161 (when (consp (cdr shr)) 161 (when (consp (cdr shr))
162 (assert (not (member (cadr shr) nts))) 162 (assert (not (member (cadr shr) nts)))
163 (pushnew (cadr shr) last-ops))))) 163 (pushnew (cadr shr) last-ops)))))
164 (push (cons nt first-ops) first-ops-table) 164 (push (cons nt first-ops) first-ops-table)
165 (push (cons nt last-ops) last-ops-table) 165 (push (cons nt last-ops) last-ops-table)
166 (push (cons nt first-nts) first-nts-table) 166 (push (cons nt first-nts) first-nts-table)
167 (push (cons nt last-nts) last-nts-table))) 167 (push (cons nt last-nts) last-nts-table)))
168 ;; Compute all first-ops by propagating the initial ones we have 168 ;; Compute all first-ops by propagating the initial ones we have
280 ;; replace the "no constraint" case with either > or < 280 ;; replace the "no constraint" case with either > or <
281 ;; but not =. The reason we do that is so as to try and 281 ;; but not =. The reason we do that is so as to try and
282 ;; distinguish associative operators (which will have 282 ;; distinguish associative operators (which will have
283 ;; left = right). 283 ;; left = right).
284 (unless (caar cst) 284 (unless (caar cst)
285 (setcar (car cst) i) 285 (setcar (car cst) i)
286 (incf i)) 286 (incf i))
287 (setq csts (delq cst csts)))) 287 (setq csts (delq cst csts))))
288 (unless progress 288 (unless progress
289 (error "Can't resolve the precedence table to precedence levels"))) 289 (error "Can't resolve the precedence table to precedence levels")))
290 (incf i 10)) 290 (incf i 10))
384 (token (funcall next-token)) 384 (token (funcall next-token))
385 (toklevels (cdr (assoc token smie-op-levels)))) 385 (toklevels (cdr (assoc token smie-op-levels))))
386 (cond 386 (cond
387 ((null toklevels) 387 ((null toklevels)
388 (when (zerop (length token)) 388 (when (zerop (length token))
389 (condition-case err 389 (condition-case err
390 (progn (goto-char pos) (funcall next-sexp 1) nil) 390 (progn (goto-char pos) (funcall next-sexp 1) nil)
391 (scan-error (throw 'return 391 (scan-error (throw 'return
392 (list t (caddr err) 392 (list t (caddr err)
393 (buffer-substring-no-properties 393 (buffer-substring-no-properties
394 (caddr err) 394 (caddr err)
395 (+ (caddr err) 395 (+ (caddr err)
415 (goto-char pos))))) 415 (goto-char pos)))))
416 (t 416 (t
417 (let ((lastlevels levels)) 417 (let ((lastlevels levels))
418 (if (and levels (= (funcall op-back toklevels) 418 (if (and levels (= (funcall op-back toklevels)
419 (funcall op-forw (car levels)))) 419 (funcall op-forw (car levels))))
420 (setq levels (cdr levels))) 420 (setq levels (cdr levels)))
421 ;; We may have found a match for the previously pending 421 ;; We may have found a match for the previously pending
422 ;; operator. Is this the end? 422 ;; operator. Is this the end?
423 (cond 423 (cond
424 ;; Keep looking as long as we haven't matched the 424 ;; Keep looking as long as we haven't matched the
425 ;; topmost operator. 425 ;; topmost operator.
426 (levels 426 (levels
427 (if (funcall op-forw toklevels) 427 (if (funcall op-forw toklevels)
428 (push toklevels levels))) 428 (push toklevels levels)))
460 is too high. LEFT-LEVEL is the left-level of TOKEN, 460 is too high. LEFT-LEVEL is the left-level of TOKEN,
461 POS is its start position in the buffer. 461 POS is its start position in the buffer.
462 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer. 462 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
463 (nil POS TOKEN): we skipped over a paren-like pair. 463 (nil POS TOKEN): we skipped over a paren-like pair.
464 nil: we skipped over an identifier, matched parentheses, ..." 464 nil: we skipped over an identifier, matched parentheses, ..."
465 (smie-next-sexp 465 (smie-next-sexp
466 (indirect-function smie-backward-token-function) 466 (indirect-function smie-backward-token-function)
467 (indirect-function 'backward-sexp) 467 (indirect-function 'backward-sexp)
468 (indirect-function 'smie-op-left) 468 (indirect-function 'smie-op-left)
469 (indirect-function 'smie-op-right) 469 (indirect-function 'smie-op-right)
470 halfsexp)) 470 halfsexp))
471 471
472 (defun smie-forward-sexp (&optional halfsexp) 472 (defun smie-forward-sexp (&optional halfsexp)
473 "Skip over one sexp. 473 "Skip over one sexp.
474 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the 474 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the
478 is too high. RIGHT-LEVEL is the right-level of TOKEN, 478 is too high. RIGHT-LEVEL is the right-level of TOKEN,
479 POS is its end position in the buffer. 479 POS is its end position in the buffer.
480 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer. 480 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
481 (nil POS TOKEN): we skipped over a paren-like pair. 481 (nil POS TOKEN): we skipped over a paren-like pair.
482 nil: we skipped over an identifier, matched parentheses, ..." 482 nil: we skipped over an identifier, matched parentheses, ..."
483 (smie-next-sexp 483 (smie-next-sexp
484 (indirect-function smie-forward-token-function) 484 (indirect-function smie-forward-token-function)
485 (indirect-function 'forward-sexp) 485 (indirect-function 'forward-sexp)
486 (indirect-function 'smie-op-right) 486 (indirect-function 'smie-op-right)
487 (indirect-function 'smie-op-left) 487 (indirect-function 'smie-op-left)
488 halfsexp)) 488 halfsexp))
489 489
490 ;;; Miscellanous commands using the precedence parser. 490 ;;; Miscellanous commands using the precedence parser.
491 491
492 (defun smie-backward-sexp-command (&optional n) 492 (defun smie-backward-sexp-command (&optional n)
499 (interactive "^p") 499 (interactive "^p")
500 (let ((forw (> n 0)) 500 (let ((forw (> n 0))
501 (forward-sexp-function nil)) 501 (forward-sexp-function nil))
502 (while (/= n 0) 502 (while (/= n 0)
503 (setq n (- n (if forw 1 -1))) 503 (setq n (- n (if forw 1 -1)))
504 (let ((pos (point)) 504 (let ((pos (point))
505 (res (if forw 505 (res (if forw
506 (smie-forward-sexp 'halfsexp) 506 (smie-forward-sexp 'halfsexp)
507 (smie-backward-sexp 'halfsexp)))) 507 (smie-backward-sexp 'halfsexp))))
508 (if (and (car res) (= pos (point)) (not (if forw (eobp) (bobp)))) 508 (if (and (car res) (= pos (point)) (not (if forw (eobp) (bobp))))
509 (signal 'scan-error 509 (signal 'scan-error
510 (list "Containing expression ends prematurely" 510 (list "Containing expression ends prematurely"
511 (cadr res) (cadr res))) 511 (cadr res) (cadr res)))
512 nil))))) 512 nil)))))
513 513
514 (defvar smie-closer-alist nil 514 (defvar smie-closer-alist nil
515 "Alist giving the closer corresponding to an opener.") 515 "Alist giving the closer corresponding to an opener.")
516 516
762 762
763 (defun smie-indent-fixindent () 763 (defun smie-indent-fixindent ()
764 ;; Obey the `fixindent' special comment. 764 ;; Obey the `fixindent' special comment.
765 (and (smie-bolp) 765 (and (smie-bolp)
766 (save-excursion 766 (save-excursion
767 (comment-normalize-vars) 767 (comment-normalize-vars)
768 (re-search-forward (concat comment-start-skip 768 (re-search-forward (concat comment-start-skip
769 "fixindent" 769 "fixindent"
770 comment-end-skip) 770 comment-end-skip)
771 ;; 1+ to account for the \n comment termination. 771 ;; 1+ to account for the \n comment termination.
772 (1+ (line-end-position)) t)) 772 (1+ (line-end-position)) t))
773 (current-column))) 773 (current-column)))
774 774
775 (defun smie-indent-bob () 775 (defun smie-indent-bob ()
776 ;; Start the file at column 0. 776 ;; Start the file at column 0.
777 (save-excursion 777 (save-excursion
778 (forward-comment (- (point))) 778 (forward-comment (- (point)))
800 (token (pop toklevels))) 800 (token (pop toklevels)))
801 (if (null (car toklevels)) 801 (if (null (car toklevels))
802 (save-excursion 802 (save-excursion
803 (goto-char pos) 803 (goto-char pos)
804 ;; Different cases: 804 ;; Different cases:
805 ;; - smie-bolp: "indent according to others". 805 ;; - smie-bolp: "indent according to others".
806 ;; - common hanging: "indent according to others". 806 ;; - common hanging: "indent according to others".
807 ;; - SML-let hanging: "indent like parent". 807 ;; - SML-let hanging: "indent like parent".
808 ;; - if-after-else: "indent-like parent". 808 ;; - if-after-else: "indent-like parent".
809 ;; - middle-of-line: "trust current position". 809 ;; - middle-of-line: "trust current position".
810 (cond 810 (cond
811 ((null (cdr toklevels)) nil) ;Not a keyword. 811 ((null (cdr toklevels)) nil) ;Not a keyword.
812 ((smie-bolp) 812 ((smie-bolp)
813 ;; For an open-paren-like thingy at BOL, always indent only 813 ;; For an open-paren-like thingy at BOL, always indent only
814 ;; based on other rules (typically smie-indent-after-keyword). 814 ;; based on other rules (typically smie-indent-after-keyword).
815 nil) 815 nil)
816 (t 816 (t
817 ;; We're only ever here for virtual-indent, which is why 817 ;; We're only ever here for virtual-indent, which is why
818 ;; we can use (current-column) as answer for `point'. 818 ;; we can use (current-column) as answer for `point'.
819 (let* ((tokinfo (or (assoc (cons :before token) 819 (let* ((tokinfo (or (assoc (cons :before token)
820 smie-indent-rules) 820 smie-indent-rules)
821 ;; By default use point unless we're hanging. 821 ;; By default use point unless we're hanging.
822 `((:before . ,token) (:hanging nil) point))) 822 `((:before . ,token) (:hanging nil) point)))
823 ;; (after (prog1 (point) (goto-char pos))) 823 ;; (after (prog1 (point) (goto-char pos)))
824 (offset (smie-indent-offset-rule tokinfo))) 824 (offset (smie-indent-offset-rule tokinfo)))
825 (smie-indent-column offset))))) 825 (smie-indent-column offset)))))
826 826
827 ;; FIXME: This still looks too much like black magic!! 827 ;; FIXME: This still looks too much like black magic!!
828 ;; FIXME: Rather than a bunch of rules like (PARENT . TOKEN), we 828 ;; FIXME: Rather than a bunch of rules like (PARENT . TOKEN), we
829 ;; want a single rule for TOKEN with different cases for each PARENT. 829 ;; want a single rule for TOKEN with different cases for each PARENT.
894 ;; we don't want this to affect "unrelated" parts of the code. 894 ;; we don't want this to affect "unrelated" parts of the code.
895 ;; E.g. a fixindent in the body of a "begin..end" should not 895 ;; E.g. a fixindent in the body of a "begin..end" should not
896 ;; affect the indentation of the "end". 896 ;; affect the indentation of the "end".
897 (current-column) 897 (current-column)
898 (goto-char (cadr parent)) 898 (goto-char (cadr parent))
899 ;; Don't use (smie-indent-virtual :not-hanging) here, because we 899 ;; Don't use (smie-indent-virtual :not-hanging) here, because we
900 ;; want to jump back over a sequence of same-level ops such as 900 ;; want to jump back over a sequence of same-level ops such as
901 ;; a -> b -> c 901 ;; a -> b -> c
902 ;; -> d 902 ;; -> d
903 ;; So as to align with the earliest appropriate place. 903 ;; So as to align with the earliest appropriate place.
904 (smie-indent-virtual))) 904 (smie-indent-virtual)))
905 (tokinfo 905 (tokinfo
906 (if (and (= (point) pos) (smie-bolp) 906 (if (and (= (point) pos) (smie-bolp)
907 (or (eq offset 'point) 907 (or (eq offset 'point)
908 (and (consp offset) (memq 'point offset)))) 908 (and (consp offset) (memq 'point offset))))
909 ;; Since we started at BOL, we're not computing a virtual 909 ;; Since we started at BOL, we're not computing a virtual
910 ;; indentation, and we're still at the starting point, so 910 ;; indentation, and we're still at the starting point, so
911 ;; we can't use `current-column' which would cause 911 ;; we can't use `current-column' which would cause
912 ;; indentation to depend on itself. 912 ;; indentation to depend on itself.
913 nil 913 nil
914 (smie-indent-column offset 'parent parent 914 (smie-indent-column offset 'parent parent
932 ;; indentation of comment-continue lines. 932 ;; indentation of comment-continue lines.
933 (let ((continue (and comment-continue 933 (let ((continue (and comment-continue
934 (comment-string-strip comment-continue t t)))) 934 (comment-string-strip comment-continue t t))))
935 (and (< 0 (length continue)) 935 (and (< 0 (length continue))
936 (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss)) 936 (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss))
937 (let ((ppss (syntax-ppss))) 937 (let ((ppss (syntax-ppss)))
938 (save-excursion 938 (save-excursion
939 (forward-line -1) 939 (forward-line -1)
940 (if (<= (point) (nth 8 ppss)) 940 (if (<= (point) (nth 8 ppss))
941 (progn (goto-char (1+ (nth 8 ppss))) (current-column)) 941 (progn (goto-char (1+ (nth 8 ppss))) (current-column))
942 (skip-chars-forward " \t") 942 (skip-chars-forward " \t")
943 (if (looking-at (regexp-quote continue)) 943 (if (looking-at (regexp-quote continue))
944 (current-column)))))))) 944 (current-column))))))))
945 945
946 (defun smie-indent-after-keyword () 946 (defun smie-indent-after-keyword ()
947 ;; Indentation right after a special keyword. 947 ;; Indentation right after a special keyword.
1022 ;; the function itself. 1022 ;; the function itself.
1023 (current-column))))))) 1023 (current-column)))))))
1024 1024
1025 (defvar smie-indent-functions 1025 (defvar smie-indent-functions
1026 '(smie-indent-fixindent smie-indent-bob smie-indent-close smie-indent-comment 1026 '(smie-indent-fixindent smie-indent-bob smie-indent-close smie-indent-comment
1027 smie-indent-comment-continue smie-indent-keyword smie-indent-after-keyword 1027 smie-indent-comment-continue smie-indent-keyword smie-indent-after-keyword
1028 smie-indent-exps) 1028 smie-indent-exps)
1029 "Functions to compute the indentation. 1029 "Functions to compute the indentation.
1030 Each function is called with no argument, shouldn't move point, and should 1030 Each function is called with no argument, shouldn't move point, and should
1031 return either nil if it has no opinion, or an integer representing the column 1031 return either nil if it has no opinion, or an integer representing the column
1032 to which that point should be aligned, if we were to reindent it.") 1032 to which that point should be aligned, if we were to reindent it.")
1033 1033