Mercurial > emacs
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 |