diff options
| author | Stefan Monnier | 2010-10-29 15:20:28 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2010-10-29 15:20:28 -0400 |
| commit | c4d17d50ea180c405fc58f9ffe693b6c633571ac (patch) | |
| tree | f1bf3bbd1d417fa9853b6a98260e25a42083b638 | |
| parent | 2ec4c9665d3766eea7bf2d131cabbc177d049b6b (diff) | |
| download | emacs-c4d17d50ea180c405fc58f9ffe693b6c633571ac.tar.gz emacs-c4d17d50ea180c405fc58f9ffe693b6c633571ac.zip | |
SMIE: change indent rules format, improve smie-setup.
* lisp/emacs-lisp/smie.el (smie-precs-precedence-table)
(smie-merge-prec2s, smie-bnf-precedence-table, smie-prec2-levels):
Mark them pure so the tables gets built at compile time.
(smie-bnf-precedence-table): Store the closer-alist in the table.
(smie-prec2-levels): Preserve the closer-alist.
(smie-blink-matching-open): Be more forgiving in case of indentation.
(smie-hanging-p): Rename from smie-indent--hanging-p.
(smie-bolp): Rename from smie-indent--bolp.
(smie--parent, smie--after): New dynamic vars.
(smie-parent-p, smie-next-p, smie-prev-p): New funs.
(smie-indent-rules): Remove.
(smie-indent--offset-rule): Remove fun.
(smie-rules-function): New var.
(smie-indent--rule): New fun.
(smie-indent--offset, smie-indent-keyword, smie-indent-after-keyword)
(smie-indent-exps): Use it.
(smie-setup): Setup paren blinking; add keyword args for token
functions; extract closer-alist from op-levels.
(smie-indent-debug-log): Remove var.
(smie-indent-debug): Remove fun.
* lisp/progmodes/prolog.el (prolog-smie-indent-rules): Remove.
(prolog-smie-rules): New fun to replace it.
(prolog-mode-variables): Simplify.
* lisp/progmodes/octave-mod.el (octave-smie-closer-alist): Remove, now that
it's setup automatically.
(octave-smie-indent-rules): Remove.
(octave-smie-rules): New fun to replace it.
(octave-mode): Simplify.
| -rw-r--r-- | etc/NEWS | 2 | ||||
| -rw-r--r-- | lisp/ChangeLog | 32 | ||||
| -rw-r--r-- | lisp/emacs-lisp/smie.el | 339 | ||||
| -rw-r--r-- | lisp/progmodes/octave-mod.el | 55 | ||||
| -rw-r--r-- | lisp/progmodes/prolog.el | 23 |
5 files changed, 235 insertions, 216 deletions
| @@ -587,6 +587,8 @@ Notifications API. It requires D-Bus for communication. | |||
| 587 | 587 | ||
| 588 | * Incompatible Lisp Changes in Emacs 24.1 | 588 | * Incompatible Lisp Changes in Emacs 24.1 |
| 589 | 589 | ||
| 590 | ** Remove obsolete name `e' (use `float-e' instead). | ||
| 591 | |||
| 590 | ** A backquote not followed by a space is now always treated as new-style. | 592 | ** A backquote not followed by a space is now always treated as new-style. |
| 591 | 593 | ||
| 592 | ** Test for special mode-class was moved from view-file to view-buffer. | 594 | ** Test for special mode-class was moved from view-file to view-buffer. |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4842d677fb4..0fb702e7f66 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,35 @@ | |||
| 1 | 2010-10-29 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | SMIE: change indent rules format, improve smie-setup. | ||
| 4 | * emacs-lisp/smie.el (smie-precs-precedence-table) | ||
| 5 | (smie-merge-prec2s, smie-bnf-precedence-table, smie-prec2-levels): | ||
| 6 | Mark them pure so the tables gets built at compile time. | ||
| 7 | (smie-bnf-precedence-table): Store the closer-alist in the table. | ||
| 8 | (smie-prec2-levels): Preserve the closer-alist. | ||
| 9 | (smie-blink-matching-open): Be more forgiving in case of indentation. | ||
| 10 | (smie-hanging-p): Rename from smie-indent--hanging-p. | ||
| 11 | (smie-bolp): Rename from smie-indent--bolp. | ||
| 12 | (smie--parent, smie--after): New dynamic vars. | ||
| 13 | (smie-parent-p, smie-next-p, smie-prev-p): New funs. | ||
| 14 | (smie-indent-rules): Remove. | ||
| 15 | (smie-indent--offset-rule): Remove fun. | ||
| 16 | (smie-rules-function): New var. | ||
| 17 | (smie-indent--rule): New fun. | ||
| 18 | (smie-indent--offset, smie-indent-keyword, smie-indent-after-keyword) | ||
| 19 | (smie-indent-exps): Use it. | ||
| 20 | (smie-setup): Setup paren blinking; add keyword args for token | ||
| 21 | functions; extract closer-alist from op-levels. | ||
| 22 | (smie-indent-debug-log): Remove var. | ||
| 23 | (smie-indent-debug): Remove fun. | ||
| 24 | * progmodes/prolog.el (prolog-smie-indent-rules): Remove. | ||
| 25 | (prolog-smie-rules): New fun to replace it. | ||
| 26 | (prolog-mode-variables): Simplify. | ||
| 27 | * progmodes/octave-mod.el (octave-smie-closer-alist): Remove, now that | ||
| 28 | it's setup automatically. | ||
| 29 | (octave-smie-indent-rules): Remove. | ||
| 30 | (octave-smie-rules): New fun to replace it. | ||
| 31 | (octave-mode): Simplify. | ||
| 32 | |||
| 1 | 2010-10-29 Glenn Morris <rgm@gnu.org> | 33 | 2010-10-29 Glenn Morris <rgm@gnu.org> |
| 2 | 34 | ||
| 3 | * files.el (temporary-file-directory): Remove (already defined in C). | 35 | * files.el (temporary-file-directory): Remove (already defined in C). |
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el index 4f5b2046150..6cd434ff790 100644 --- a/lisp/emacs-lisp/smie.el +++ b/lisp/emacs-lisp/smie.el | |||
| @@ -109,6 +109,7 @@ | |||
| 109 | (display-warning 'smie (format "Conflict: %s %s/%s %s" x old val y))) | 109 | (display-warning 'smie (format "Conflict: %s %s/%s %s" x old val y))) |
| 110 | (puthash key val table)))) | 110 | (puthash key val table)))) |
| 111 | 111 | ||
| 112 | (put 'smie-precs-precedence-table 'pure t) | ||
| 112 | (defun smie-precs-precedence-table (precs) | 113 | (defun smie-precs-precedence-table (precs) |
| 113 | "Compute a 2D precedence table from a list of precedences. | 114 | "Compute a 2D precedence table from a list of precedences. |
| 114 | PRECS should be a list, sorted by precedence (e.g. \"+\" will | 115 | PRECS should be a list, sorted by precedence (e.g. \"+\" will |
| @@ -132,6 +133,7 @@ one of those elements share the same precedence level and associativity." | |||
| 132 | (smie-set-prec2tab prec2-table other-op op op1))))))) | 133 | (smie-set-prec2tab prec2-table other-op op op1))))))) |
| 133 | prec2-table)) | 134 | prec2-table)) |
| 134 | 135 | ||
| 136 | (put 'smie-merge-prec2s 'pure t) | ||
| 135 | (defun smie-merge-prec2s (&rest tables) | 137 | (defun smie-merge-prec2s (&rest tables) |
| 136 | (if (null (cdr tables)) | 138 | (if (null (cdr tables)) |
| 137 | (car tables) | 139 | (car tables) |
| @@ -147,6 +149,7 @@ one of those elements share the same precedence level and associativity." | |||
| 147 | table)) | 149 | table)) |
| 148 | prec2))) | 150 | prec2))) |
| 149 | 151 | ||
| 152 | (put 'smie-bnf-precedence-table 'pure t) | ||
| 150 | (defun smie-bnf-precedence-table (bnf &rest precs) | 153 | (defun smie-bnf-precedence-table (bnf &rest precs) |
| 151 | (let ((nts (mapcar 'car bnf)) ;Non-terminals | 154 | (let ((nts (mapcar 'car bnf)) ;Non-terminals |
| 152 | (first-ops-table ()) | 155 | (first-ops-table ()) |
| @@ -233,6 +236,7 @@ one of those elements share the same precedence level and associativity." | |||
| 233 | ;; Keep track of which tokens are openers/closer, so they can get a nil | 236 | ;; Keep track of which tokens are openers/closer, so they can get a nil |
| 234 | ;; precedence in smie-prec2-levels. | 237 | ;; precedence in smie-prec2-levels. |
| 235 | (puthash :smie-open/close-alist (smie-bnf-classify bnf) prec2) | 238 | (puthash :smie-open/close-alist (smie-bnf-classify bnf) prec2) |
| 239 | (puthash :smie-closer-alist (smie-bnf-closer-alist bnf) prec2) | ||
| 236 | prec2)) | 240 | prec2)) |
| 237 | 241 | ||
| 238 | ;; (defun smie-prec2-closer-alist (prec2 include-inners) | 242 | ;; (defun smie-prec2-closer-alist (prec2 include-inners) |
| @@ -377,6 +381,7 @@ CSTS is a list of pairs representing arcs in a graph." | |||
| 377 | (append names (list (car names))) | 381 | (append names (list (car names))) |
| 378 | " < "))) | 382 | " < "))) |
| 379 | 383 | ||
| 384 | (put 'smie-prec2-levels 'pure t) | ||
| 380 | (defun smie-prec2-levels (prec2) | 385 | (defun smie-prec2-levels (prec2) |
| 381 | ;; FIXME: Rather than only return an alist of precedence levels, we should | 386 | ;; FIXME: Rather than only return an alist of precedence levels, we should |
| 382 | ;; also extract other useful data from it: | 387 | ;; also extract other useful data from it: |
| @@ -479,6 +484,8 @@ PREC2 is a table as returned by `smie-precs-precedence-table' or | |||
| 479 | (eq 'closer (cdr (assoc (car x) classification-table)))) | 484 | (eq 'closer (cdr (assoc (car x) classification-table)))) |
| 480 | (setf (nth 2 x) i) | 485 | (setf (nth 2 x) i) |
| 481 | (incf i))))) ;See other (incf i) above. | 486 | (incf i))))) ;See other (incf i) above. |
| 487 | (let ((ca (gethash :smie-closer-alist prec2))) | ||
| 488 | (when ca (push (cons :smie-closer-alist ca) table))) | ||
| 482 | table)) | 489 | table)) |
| 483 | 490 | ||
| 484 | ;;; Parsing using a precedence level table. | 491 | ;;; Parsing using a precedence level table. |
| @@ -803,14 +810,22 @@ If non-nil, it will blink not only for \"begin..end\" but also for \"if...else\" | |||
| 803 | (defun smie-blink-matching-open () | 810 | (defun smie-blink-matching-open () |
| 804 | "Blink the matching opener when applicable. | 811 | "Blink the matching opener when applicable. |
| 805 | This uses SMIE's tables and is expected to be placed on `post-self-insert-hook'." | 812 | This uses SMIE's tables and is expected to be placed on `post-self-insert-hook'." |
| 813 | (let ((pos (point)) ;Position after the close token. | ||
| 814 | token) | ||
| 806 | (when (and blink-matching-paren | 815 | (when (and blink-matching-paren |
| 807 | smie-closer-alist ; Optimization. | 816 | smie-closer-alist ; Optimization. |
| 808 | (eq (char-before) last-command-event) ; Sanity check. | 817 | (or (eq (char-before) last-command-event) ;; Sanity check. |
| 818 | (save-excursion | ||
| 819 | (or (progn (skip-chars-backward " \t") | ||
| 820 | (setq pos (point)) | ||
| 821 | (eq (char-before) last-command-event)) | ||
| 822 | (progn (skip-chars-backward " \n\t") | ||
| 823 | (setq pos (point)) | ||
| 824 | (eq (char-before) last-command-event))))) | ||
| 809 | (memq last-command-event smie-blink-matching-triggers) | 825 | (memq last-command-event smie-blink-matching-triggers) |
| 810 | (not (nth 8 (syntax-ppss)))) | 826 | (not (nth 8 (syntax-ppss)))) |
| 811 | (save-excursion | 827 | (save-excursion |
| 812 | (let ((pos (point)) | 828 | (setq token (funcall smie-backward-token-function)) |
| 813 | (token (funcall smie-backward-token-function))) | ||
| 814 | (when (and (eq (point) (1- pos)) | 829 | (when (and (eq (point) (1- pos)) |
| 815 | (= 1 (length token)) | 830 | (= 1 (length token)) |
| 816 | (not (rassoc token smie-closer-alist))) | 831 | (not (rassoc token smie-closer-alist))) |
| @@ -818,17 +833,20 @@ This uses SMIE's tables and is expected to be placed on `post-self-insert-hook'. | |||
| 818 | ;; closers (e.g. ?\; in Octave mode), so go back to the | 833 | ;; closers (e.g. ?\; in Octave mode), so go back to the |
| 819 | ;; previous token. | 834 | ;; previous token. |
| 820 | (setq pos (point)) | 835 | (setq pos (point)) |
| 821 | (setq token (save-excursion | 836 | (setq token (funcall smie-backward-token-function))) |
| 822 | (funcall smie-backward-token-function)))) | ||
| 823 | (when (rassoc token smie-closer-alist) | 837 | (when (rassoc token smie-closer-alist) |
| 824 | ;; We're after a close token. Let's still make sure we | 838 | ;; We're after a close token. Let's still make sure we |
| 825 | ;; didn't skip a comment to find that token. | 839 | ;; didn't skip a comment to find that token. |
| 826 | (funcall smie-forward-token-function) | 840 | (funcall smie-forward-token-function) |
| 827 | (when (and (save-excursion | 841 | (when (and (save-excursion |
| 828 | ;; Trigger can be SPC, or reindent. | 842 | ;; Skip the trigger char, if applicable. |
| 829 | (skip-chars-forward " \n\t") | 843 | (if (eq (char-after) last-command-event) |
| 844 | (forward-char 1)) | ||
| 845 | (if (eq ?\n last-command-event) | ||
| 846 | ;; Skip any auto-indentation, if applicable. | ||
| 847 | (skip-chars-forward " \t")) | ||
| 830 | (>= (point) pos)) | 848 | (>= (point) pos)) |
| 831 | ;; If token ends with a trigger char, so don't blink for | 849 | ;; If token ends with a trigger char, don't blink for |
| 832 | ;; anything else than this trigger char, lest we'd blink | 850 | ;; anything else than this trigger char, lest we'd blink |
| 833 | ;; both when inserting the trigger char and when | 851 | ;; both when inserting the trigger char and when |
| 834 | ;; inserting a subsequent trigger char like SPC. | 852 | ;; inserting a subsequent trigger char like SPC. |
| @@ -850,34 +868,25 @@ This uses SMIE's tables and is expected to be placed on `post-self-insert-hook'. | |||
| 850 | "Basic amount of indentation." | 868 | "Basic amount of indentation." |
| 851 | :type 'integer) | 869 | :type 'integer) |
| 852 | 870 | ||
| 853 | (defvar smie-indent-rules 'unset | 871 | (defvar smie-rules-function 'ignore |
| 854 | ;; TODO: For SML, we need more rule formats, so as to handle | 872 | "Function providing the indentation rules. |
| 855 | ;; structure Foo = | 873 | It takes two arguments METHOD and ARG where the meaning of ARG |
| 856 | ;; Bar (toto) | 874 | and the expected return value depends on METHOD. |
| 857 | ;; and | 875 | METHOD can be: |
| 858 | ;; structure Foo = | 876 | - :after, in which case ARG is a token and the function should return the |
| 859 | ;; struct ... end | 877 | OFFSET to use for indentation after ARG. |
| 860 | ;; I.e. the indentation after "=" depends on the parent ("structure") | 878 | - :before, in which case ARG is a token and the function should return the |
| 861 | ;; as well as on the following token ("struct"). | 879 | OFFSET to use to indent ARG itself. |
| 862 | "Rules of the following form. | 880 | - :elem, in which case the function should return either: |
| 863 | \((:before . TOK) . OFFSET-RULES) how to indent TOK itself. | 881 | - the offset to use to indent function arguments (ARG = `arg') |
| 864 | \(TOK . OFFSET-RULES) how to indent right after TOK. | 882 | - the basic indentation step (ARG = `basic'). |
| 865 | \(list-intro . TOKENS) declare TOKENS as being followed by what may look like | 883 | - :list-intro, in which case ARG is a token and the function should return |
| 866 | a funcall but is just a sequence of expressions. | 884 | non-nil if TOKEN is followed by a list of expressions (not separated by any |
| 867 | \(t . OFFSET) basic indentation step. | 885 | token) rather than an expression. |
| 868 | \(args . OFFSET) indentation of arguments. | 886 | |
| 869 | \((T1 . T2) OFFSET) like ((:before . T2) (:parent T1 OFFSET)). | 887 | When ARG is a token, the function is called with point just before that token. |
| 870 | 888 | A return value of nil always means to fallback on the default behavior, so the | |
| 871 | OFFSET-RULES is a list of elements which can each either be: | 889 | function should return nil for arguments it does not expect. |
| 872 | |||
| 873 | \(:hanging . OFFSET-RULES) if TOK is hanging, use OFFSET-RULES. | ||
| 874 | \(:parent PARENT . OFFSET-RULES) if TOK's parent is PARENT, use OFFSET-RULES. | ||
| 875 | \(:next TOKEN . OFFSET-RULES) if TOK is followed by TOKEN, use OFFSET-RULES. | ||
| 876 | \(:prev TOKEN . OFFSET-RULES) if TOK is preceded by TOKEN, use | ||
| 877 | \(:bolp . OFFSET-RULES) If TOK is first on a line, use OFFSET-RULES. | ||
| 878 | OFFSET the offset to use. | ||
| 879 | |||
| 880 | PARENT can be either the name of the parent or a list of such names. | ||
| 881 | 890 | ||
| 882 | OFFSET can be of the form: | 891 | OFFSET can be of the form: |
| 883 | `point' align with the token. | 892 | `point' align with the token. |
| @@ -886,91 +895,69 @@ NUMBER offset by NUMBER. | |||
| 886 | \(+ OFFSETS...) use the sum of OFFSETS. | 895 | \(+ OFFSETS...) use the sum of OFFSETS. |
| 887 | VARIABLE use the value of VARIABLE as offset. | 896 | VARIABLE use the value of VARIABLE as offset. |
| 888 | 897 | ||
| 889 | The precise meaning of `point' depends on various details: it can | 898 | This function will often use some of the following functions designed |
| 890 | either mean the position of the token we're indenting, or the | 899 | specifically for it: |
| 891 | position of its parent, or the position right after its parent. | 900 | `smie-bolp', `smie-hanging-p', `smie-parent-p', `smie-next-p', `smie-prev-p'.") |
| 892 | |||
| 893 | A nil offset for indentation after an opening token defaults | ||
| 894 | to `smie-indent-basic'.") | ||
| 895 | 901 | ||
| 896 | (defun smie-indent--hanging-p () | 902 | (defun smie-hanging-p () |
| 897 | ;; A hanging keyword is one that's at the end of a line except it's not at | 903 | "Return non-nil if the current token is \"hanging\". |
| 898 | ;; the beginning of a line. | 904 | A hanging keyword is one that's at the end of a line except it's not at |
| 899 | (and (save-excursion | 905 | the beginning of a line." |
| 906 | (and (not (smie-bolp)) | ||
| 907 | (save-excursion | ||
| 900 | (when (zerop (length (funcall smie-forward-token-function))) | 908 | (when (zerop (length (funcall smie-forward-token-function))) |
| 901 | ;; Could be an open-paren. | 909 | ;; Could be an open-paren. |
| 902 | (forward-char 1)) | 910 | (forward-char 1)) |
| 903 | (skip-chars-forward " \t") | 911 | (skip-chars-forward " \t") |
| 904 | (eolp)) | 912 | (eolp)))) |
| 905 | (not (smie-indent--bolp)))) | ||
| 906 | 913 | ||
| 907 | (defun smie-indent--bolp () | 914 | (defun smie-bolp () |
| 915 | "Return non-nil if the current token is the first on the line." | ||
| 908 | (save-excursion (skip-chars-backward " \t") (bolp))) | 916 | (save-excursion (skip-chars-backward " \t") (bolp))) |
| 909 | 917 | ||
| 918 | (defvar smie--parent) (defvar smie--after) ;Dynamically scoped. | ||
| 919 | |||
| 920 | (defun smie-parent-p (&rest parents) | ||
| 921 | "Return non-nil if the current token's parent is among PARENTS. | ||
| 922 | Only meaningful when called from within `smie-rules-function'." | ||
| 923 | (member (nth 2 (or smie--parent | ||
| 924 | (save-excursion | ||
| 925 | (let* ((pos (point)) | ||
| 926 | (tok (funcall smie-forward-token-function))) | ||
| 927 | (unless (cadr (assoc tok smie-op-levels)) | ||
| 928 | (goto-char pos)) | ||
| 929 | (setq smie--parent | ||
| 930 | (smie-backward-sexp 'halfsexp)))))) | ||
| 931 | parents)) | ||
| 932 | |||
| 933 | (defun smie-next-p (&rest tokens) | ||
| 934 | "Return non-nil if the next token is among TOKENS. | ||
| 935 | Only meaningful when called from within `smie-rules-function'." | ||
| 936 | (let ((next | ||
| 937 | (save-excursion | ||
| 938 | (unless smie--after | ||
| 939 | (smie-indent-forward-token) (setq smie--after (point))) | ||
| 940 | (goto-char smie--after) | ||
| 941 | (smie-indent-forward-token)))) | ||
| 942 | (member (car next) tokens))) | ||
| 943 | |||
| 944 | (defun smie-prev-p (&rest tokens) | ||
| 945 | "Return non-nil if the previous token is among TOKENS." | ||
| 946 | (let ((prev (save-excursion | ||
| 947 | (smie-indent-backward-token)))) | ||
| 948 | (member (car prev) tokens))) | ||
| 949 | |||
| 950 | |||
| 910 | (defun smie-indent--offset (elem) | 951 | (defun smie-indent--offset (elem) |
| 911 | (or (cdr (assq elem smie-indent-rules)) | 952 | (or (funcall smie-rules-function :elem elem) |
| 912 | (cdr (assq t smie-indent-rules)) | 953 | (if (not (eq elem 'basic)) |
| 954 | (funcall smie-rules-function :elem 'basic)) | ||
| 913 | smie-indent-basic)) | 955 | smie-indent-basic)) |
| 914 | 956 | ||
| 915 | (defvar smie-indent-debug-log) | 957 | (defun smie-indent--rule (kind token &optional after parent) |
| 916 | 958 | (let ((smie--parent parent) | |
| 917 | (defun smie-indent--offset-rule (tokinfo &optional after parent) | 959 | (smie--after after)) |
| 918 | "Apply the OFFSET-RULES in TOKINFO. | 960 | (funcall smie-rules-function kind token))) |
| 919 | Point is expected to be right in front of the token corresponding to TOKINFO. | ||
| 920 | If computing the indentation after the token, then AFTER is the position | ||
| 921 | after the token, otherwise it should be nil. | ||
| 922 | PARENT if non-nil should be the parent info returned by `smie-backward-sexp'." | ||
| 923 | (let ((rules (cdr tokinfo)) | ||
| 924 | next prev | ||
| 925 | offset) | ||
| 926 | (while (consp rules) | ||
| 927 | (let ((rule (pop rules))) | ||
| 928 | (cond | ||
| 929 | ((not (consp rule)) (setq offset rule)) | ||
| 930 | ((eq (car rule) '+) (setq offset rule)) | ||
| 931 | ((eq (car rule) :hanging) | ||
| 932 | (when (smie-indent--hanging-p) | ||
| 933 | (setq rules (cdr rule)))) | ||
| 934 | ((eq (car rule) :bolp) | ||
| 935 | (when (smie-indent--bolp) | ||
| 936 | (setq rules (cdr rule)))) | ||
| 937 | ((eq (car rule) :eolp) | ||
| 938 | (unless after | ||
| 939 | (error "Can't use :eolp in :before indentation rules")) | ||
| 940 | (when (> after (line-end-position)) | ||
| 941 | (setq rules (cdr rule)))) | ||
| 942 | ((eq (car rule) :prev) | ||
| 943 | (unless prev | ||
| 944 | (save-excursion | ||
| 945 | (setq prev (smie-indent-backward-token)))) | ||
| 946 | (when (equal (car prev) (cadr rule)) | ||
| 947 | (setq rules (cddr rule)))) | ||
| 948 | ((eq (car rule) :next) | ||
| 949 | (unless next | ||
| 950 | (unless after | ||
| 951 | (error "Can't use :next in :before indentation rules")) | ||
| 952 | (save-excursion | ||
| 953 | (goto-char after) | ||
| 954 | (setq next (smie-indent-forward-token)))) | ||
| 955 | (when (equal (car next) (cadr rule)) | ||
| 956 | (setq rules (cddr rule)))) | ||
| 957 | ((eq (car rule) :parent) | ||
| 958 | (unless parent | ||
| 959 | (save-excursion | ||
| 960 | (if after (goto-char after)) | ||
| 961 | (setq parent (smie-backward-sexp 'halfsexp)))) | ||
| 962 | (when (if (listp (cadr rule)) | ||
| 963 | (member (nth 2 parent) (cadr rule)) | ||
| 964 | (equal (nth 2 parent) (cadr rule))) | ||
| 965 | (setq rules (cddr rule)))) | ||
| 966 | (t (error "Unknown rule %s for indentation of %s" | ||
| 967 | rule (car tokinfo)))))) | ||
| 968 | ;; If `offset' is not set yet, use `rules' to handle the case where | ||
| 969 | ;; the tokinfo uses the old-style ((PARENT . TOK). OFFSET). | ||
| 970 | (unless offset (setq offset rules)) | ||
| 971 | (when (boundp 'smie-indent-debug-log) | ||
| 972 | (push (list (point) offset tokinfo) smie-indent-debug-log)) | ||
| 973 | offset)) | ||
| 974 | 961 | ||
| 975 | (defun smie-indent--column (offset &optional base parent virtual-point) | 962 | (defun smie-indent--column (offset &optional base parent virtual-point) |
| 976 | "Compute the actual column to use for a given OFFSET. | 963 | "Compute the actual column to use for a given OFFSET. |
| @@ -1012,6 +999,9 @@ If VIRTUAL-POINT is non-nil, then `point' is virtual." | |||
| 1012 | (if (consp parent) (goto-char (cadr parent))) | 999 | (if (consp parent) (goto-char (cadr parent))) |
| 1013 | (smie-indent-virtual)) | 1000 | (smie-indent-virtual)) |
| 1014 | ((eq offset nil) nil) | 1001 | ((eq offset nil) nil) |
| 1002 | ;; FIXME: would be good to get rid of this since smie-rules-function | ||
| 1003 | ;; can usually do the lookup trivially, but in cases where | ||
| 1004 | ;; smie-rules-function returns (+ point VAR) it's not nearly as trivial. | ||
| 1015 | ((and (symbolp offset) (boundp 'offset)) | 1005 | ((and (symbolp offset) (boundp 'offset)) |
| 1016 | (smie-indent--column (symbol-value offset) base parent virtual-point)) | 1006 | (smie-indent--column (symbol-value offset) base parent virtual-point)) |
| 1017 | (t (error "Unknown indentation offset %s" offset)))) | 1007 | (t (error "Unknown indentation offset %s" offset)))) |
| @@ -1046,11 +1036,11 @@ This is used when we're not trying to indent point but just | |||
| 1046 | need to compute the column at which point should be indented | 1036 | need to compute the column at which point should be indented |
| 1047 | in order to figure out the indentation of some other (further down) point." | 1037 | in order to figure out the indentation of some other (further down) point." |
| 1048 | ;; Trust pre-existing indentation on other lines. | 1038 | ;; Trust pre-existing indentation on other lines. |
| 1049 | (if (smie-indent--bolp) (current-column) (smie-indent-calculate))) | 1039 | (if (smie-bolp) (current-column) (smie-indent-calculate))) |
| 1050 | 1040 | ||
| 1051 | (defun smie-indent-fixindent () | 1041 | (defun smie-indent-fixindent () |
| 1052 | ;; Obey the `fixindent' special comment. | 1042 | ;; Obey the `fixindent' special comment. |
| 1053 | (and (smie-indent--bolp) | 1043 | (and (smie-bolp) |
| 1054 | (save-excursion | 1044 | (save-excursion |
| 1055 | (comment-normalize-vars) | 1045 | (comment-normalize-vars) |
| 1056 | (re-search-forward (concat comment-start-skip | 1046 | (re-search-forward (concat comment-start-skip |
| @@ -1090,43 +1080,31 @@ in order to figure out the indentation of some other (further down) point." | |||
| 1090 | (save-excursion | 1080 | (save-excursion |
| 1091 | (goto-char pos) | 1081 | (goto-char pos) |
| 1092 | ;; Different cases: | 1082 | ;; Different cases: |
| 1093 | ;; - smie-indent--bolp: "indent according to others". | 1083 | ;; - smie-bolp: "indent according to others". |
| 1094 | ;; - common hanging: "indent according to others". | 1084 | ;; - common hanging: "indent according to others". |
| 1095 | ;; - SML-let hanging: "indent like parent". | 1085 | ;; - SML-let hanging: "indent like parent". |
| 1096 | ;; - if-after-else: "indent-like parent". | 1086 | ;; - if-after-else: "indent-like parent". |
| 1097 | ;; - middle-of-line: "trust current position". | 1087 | ;; - middle-of-line: "trust current position". |
| 1098 | (cond | 1088 | (cond |
| 1099 | ((null (cdr toklevels)) nil) ;Not a keyword. | 1089 | ((null (cdr toklevels)) nil) ;Not a keyword. |
| 1100 | ((smie-indent--bolp) | 1090 | ((smie-bolp) |
| 1101 | ;; For an open-paren-like thingy at BOL, always indent only | 1091 | ;; For an open-paren-like thingy at BOL, always indent only |
| 1102 | ;; based on other rules (typically smie-indent-after-keyword). | 1092 | ;; based on other rules (typically smie-indent-after-keyword). |
| 1103 | nil) | 1093 | nil) |
| 1104 | (t | 1094 | (t |
| 1105 | ;; We're only ever here for virtual-indent, which is why | 1095 | ;; We're only ever here for virtual-indent, which is why |
| 1106 | ;; we can use (current-column) as answer for `point'. | 1096 | ;; we can use (current-column) as answer for `point'. |
| 1107 | (let* ((tokinfo (or (assoc (cons :before token) | 1097 | (let* ((offset (or (smie-indent--rule :before token) |
| 1108 | smie-indent-rules) | ||
| 1109 | ;; By default use point unless we're hanging. | 1098 | ;; By default use point unless we're hanging. |
| 1110 | `((:before . ,token) (:hanging nil) point))) | 1099 | (unless (smie-hanging-p) 'point)))) |
| 1111 | ;; (after (prog1 (point) (goto-char pos))) | ||
| 1112 | (offset (smie-indent--offset-rule tokinfo))) | ||
| 1113 | (smie-indent--column offset))))) | 1100 | (smie-indent--column offset))))) |
| 1114 | 1101 | ||
| 1115 | ;; FIXME: This still looks too much like black magic!! | 1102 | ;; FIXME: This still looks too much like black magic!! |
| 1116 | ;; FIXME: Rather than a bunch of rules like (PARENT . TOKEN), we | ||
| 1117 | ;; want a single rule for TOKEN with different cases for each PARENT. | ||
| 1118 | (let* ((parent (smie-backward-sexp 'halfsexp)) | 1103 | (let* ((parent (smie-backward-sexp 'halfsexp)) |
| 1119 | (tokinfo | ||
| 1120 | (or (assoc (cons (caddr parent) token) | ||
| 1121 | smie-indent-rules) | ||
| 1122 | (assoc (cons :before token) smie-indent-rules) | ||
| 1123 | ;; Default rule. | ||
| 1124 | `((:before . ,token) | ||
| 1125 | ;; (:parent open 0) | ||
| 1126 | point))) | ||
| 1127 | (offset (save-excursion | 1104 | (offset (save-excursion |
| 1128 | (goto-char pos) | 1105 | (goto-char pos) |
| 1129 | (smie-indent--offset-rule tokinfo nil parent)))) | 1106 | (or (smie-indent--rule :before token nil parent) |
| 1107 | 'point)))) | ||
| 1130 | ;; Different behaviors: | 1108 | ;; Different behaviors: |
| 1131 | ;; - align with parent. | 1109 | ;; - align with parent. |
| 1132 | ;; - parent + offset. | 1110 | ;; - parent + offset. |
| @@ -1151,10 +1129,10 @@ in order to figure out the indentation of some other (further down) point." | |||
| 1151 | nil) | 1129 | nil) |
| 1152 | ((eq (car parent) (car toklevels)) | 1130 | ((eq (car parent) (car toklevels)) |
| 1153 | ;; We bumped into a same-level operator. align with it. | 1131 | ;; We bumped into a same-level operator. align with it. |
| 1154 | (if (and (smie-indent--bolp) (/= (point) pos) | 1132 | (if (and (smie-bolp) (/= (point) pos) |
| 1155 | (save-excursion | 1133 | (save-excursion |
| 1156 | (goto-char (goto-char (cadr parent))) | 1134 | (goto-char (goto-char (cadr parent))) |
| 1157 | (not (smie-indent--bolp))) | 1135 | (not (smie-bolp))) |
| 1158 | ;; Check the offset of `token' rather then its parent | 1136 | ;; Check the offset of `token' rather then its parent |
| 1159 | ;; because its parent may have used a special rule. E.g. | 1137 | ;; because its parent may have used a special rule. E.g. |
| 1160 | ;; function foo; | 1138 | ;; function foo; |
| @@ -1190,8 +1168,8 @@ in order to figure out the indentation of some other (further down) point." | |||
| 1190 | ;; -> d | 1168 | ;; -> d |
| 1191 | ;; So as to align with the earliest appropriate place. | 1169 | ;; So as to align with the earliest appropriate place. |
| 1192 | (smie-indent-virtual))) | 1170 | (smie-indent-virtual))) |
| 1193 | (tokinfo | 1171 | (t |
| 1194 | (if (and (= (point) pos) (smie-indent--bolp) | 1172 | (if (and (= (point) pos) (smie-bolp) |
| 1195 | (or (eq offset 'point) | 1173 | (or (eq offset 'point) |
| 1196 | (and (consp offset) (memq 'point offset)))) | 1174 | (and (consp offset) (memq 'point offset)))) |
| 1197 | ;; Since we started at BOL, we're not computing a virtual | 1175 | ;; Since we started at BOL, we're not computing a virtual |
| @@ -1209,7 +1187,7 @@ in order to figure out the indentation of some other (further down) point." | |||
| 1209 | ;; Don't do it for virtual indentations. We should normally never be "in | 1187 | ;; Don't do it for virtual indentations. We should normally never be "in |
| 1210 | ;; front of a comment" when doing virtual-indentation anyway. And if we are | 1188 | ;; front of a comment" when doing virtual-indentation anyway. And if we are |
| 1211 | ;; (as can happen in octave-mode), moving forward can lead to inf-loops. | 1189 | ;; (as can happen in octave-mode), moving forward can lead to inf-loops. |
| 1212 | (and (smie-indent--bolp) | 1190 | (and (smie-bolp) |
| 1213 | (let ((pos (point))) | 1191 | (let ((pos (point))) |
| 1214 | (save-excursion | 1192 | (save-excursion |
| 1215 | (beginning-of-line) | 1193 | (beginning-of-line) |
| @@ -1254,27 +1232,18 @@ in order to figure out the indentation of some other (further down) point." | |||
| 1254 | (save-excursion | 1232 | (save-excursion |
| 1255 | (let* ((pos (point)) | 1233 | (let* ((pos (point)) |
| 1256 | (toklevel (smie-indent-backward-token)) | 1234 | (toklevel (smie-indent-backward-token)) |
| 1257 | (tok (car toklevel)) | 1235 | (tok (car toklevel))) |
| 1258 | (tokinfo (assoc tok smie-indent-rules))) | ||
| 1259 | ;; Set some default indent rules. | ||
| 1260 | (if (and toklevel (null (cadr toklevel)) (null tokinfo)) | ||
| 1261 | (setq tokinfo (list (car toklevel)))) | ||
| 1262 | ;; (if (and tokinfo (null toklevel)) | ||
| 1263 | ;; (error "Token %S has indent rule but has no parsing info" tok)) | ||
| 1264 | (when toklevel | 1236 | (when toklevel |
| 1265 | (unless tokinfo | ||
| 1266 | ;; The default indentation after a keyword/operator is 0 for | ||
| 1267 | ;; infix and t for prefix. | ||
| 1268 | ;; Using the BNF syntax, we could come up with better | ||
| 1269 | ;; defaults, but we only have the precedence levels here. | ||
| 1270 | (setq tokinfo (list tok 'default-rule | ||
| 1271 | (if (cadr toklevel) 0 (smie-indent--offset t))))) | ||
| 1272 | (let ((offset | 1237 | (let ((offset |
| 1273 | (or (smie-indent--offset-rule tokinfo pos) | 1238 | (or (smie-indent--rule :after tok pos) |
| 1274 | (smie-indent--offset t)))) | 1239 | ;; The default indentation after a keyword/operator is |
| 1275 | (let ((before (point))) | 1240 | ;; 0 for infix and t for prefix. |
| 1241 | (if (or (null (cadr toklevel)) | ||
| 1242 | (rassoc tok smie-closer-alist)) | ||
| 1243 | (smie-indent--offset 'basic) 0))) | ||
| 1244 | (before (point))) | ||
| 1276 | (goto-char pos) | 1245 | (goto-char pos) |
| 1277 | (smie-indent--column offset before))))))) | 1246 | (smie-indent--column offset before)))))) |
| 1278 | 1247 | ||
| 1279 | (defun smie-indent-exps () | 1248 | (defun smie-indent-exps () |
| 1280 | ;; Indentation of sequences of simple expressions without | 1249 | ;; Indentation of sequences of simple expressions without |
| @@ -1297,13 +1266,14 @@ in order to figure out the indentation of some other (further down) point." | |||
| 1297 | arg) | 1266 | arg) |
| 1298 | (while (and (null (car (smie-backward-sexp))) | 1267 | (while (and (null (car (smie-backward-sexp))) |
| 1299 | (push (point) positions) | 1268 | (push (point) positions) |
| 1300 | (not (smie-indent--bolp)))) | 1269 | (not (smie-bolp)))) |
| 1301 | (save-excursion | 1270 | (save-excursion |
| 1302 | ;; Figure out if the atom we just skipped is an argument rather | 1271 | ;; Figure out if the atom we just skipped is an argument rather |
| 1303 | ;; than a function. | 1272 | ;; than a function. |
| 1304 | (setq arg (or (null (car (smie-backward-sexp))) | 1273 | (setq arg |
| 1305 | (member (funcall smie-backward-token-function) | 1274 | (or (null (car (smie-backward-sexp))) |
| 1306 | (cdr (assoc 'list-intro smie-indent-rules)))))) | 1275 | (funcall smie-rules-function :list-intro |
| 1276 | (funcall smie-backward-token-function))))) | ||
| 1307 | (cond | 1277 | (cond |
| 1308 | ((null positions) | 1278 | ((null positions) |
| 1309 | ;; We're the first expression of the list. In that case, the | 1279 | ;; We're the first expression of the list. In that case, the |
| @@ -1362,18 +1332,51 @@ to which that point should be aligned, if we were to reindent it.") | |||
| 1362 | (save-excursion (indent-line-to indent)) | 1332 | (save-excursion (indent-line-to indent)) |
| 1363 | (indent-line-to indent))))) | 1333 | (indent-line-to indent))))) |
| 1364 | 1334 | ||
| 1365 | (defun smie-indent-debug () | 1335 | (defun smie-setup (op-levels rules-function &rest keywords) |
| 1366 | "Show the rules used to compute indentation of current line." | 1336 | "Setup SMIE navigation and indentation. |
| 1367 | (interactive) | 1337 | OP-LEVELS is a grammar table generated by `smie-prec2-levels'. |
| 1368 | (let ((smie-indent-debug-log '())) | 1338 | RULES-FUNCTION is a set of indentation rules for use on `smie-rules-function'. |
| 1369 | (smie-indent-calculate) | 1339 | KEYWORDS are additional arguments, which can use the following keywords: |
| 1370 | ;; FIXME: please improve! | 1340 | - :forward-token FUN |
| 1371 | (message "%S" smie-indent-debug-log))) | 1341 | - :backward-token FUN" |
| 1372 | 1342 | (set (make-local-variable 'smie-rules-function) rules-function) | |
| 1373 | (defun smie-setup (op-levels indent-rules) | ||
| 1374 | (set (make-local-variable 'smie-indent-rules) indent-rules) | ||
| 1375 | (set (make-local-variable 'smie-op-levels) op-levels) | 1343 | (set (make-local-variable 'smie-op-levels) op-levels) |
| 1376 | (set (make-local-variable 'indent-line-function) 'smie-indent-line)) | 1344 | (set (make-local-variable 'indent-line-function) 'smie-indent-line) |
| 1345 | (set (make-local-variable 'forward-sexp-function) | ||
| 1346 | 'smie-forward-sexp-command) | ||
| 1347 | (while keywords | ||
| 1348 | (let ((k (pop keywords)) | ||
| 1349 | (v (pop keywords))) | ||
| 1350 | (case k | ||
| 1351 | (:forward-token | ||
| 1352 | (set (make-local-variable 'smie-forward-token-function) v)) | ||
| 1353 | (:backward-token | ||
| 1354 | (set (make-local-variable 'smie-backward-token-function) v)) | ||
| 1355 | (t (message "smie-setup: ignoring unknown keyword %s" k))))) | ||
| 1356 | (let ((ca (cdr (assq :smie-closer-alist op-levels)))) | ||
| 1357 | (when ca | ||
| 1358 | (set (make-local-variable 'smie-closer-alist) ca) | ||
| 1359 | ;; Only needed for interactive calls to blink-matching-open. | ||
| 1360 | (set (make-local-variable 'blink-matching-check-function) | ||
| 1361 | #'smie-blink-matching-check) | ||
| 1362 | (add-hook 'post-self-insert-hook | ||
| 1363 | #'smie-blink-matching-open 'append 'local) | ||
| 1364 | (set (make-local-variable 'smie-blink-matching-triggers) | ||
| 1365 | (append smie-blink-matching-triggers | ||
| 1366 | ;; Rather than wait for SPC to blink, try to blink as | ||
| 1367 | ;; soon as we type the last char of a block ender. | ||
| 1368 | (let ((closers (sort (mapcar #'cdr smie-closer-alist) | ||
| 1369 | #'string-lessp)) | ||
| 1370 | (triggers ()) | ||
| 1371 | closer) | ||
| 1372 | (while (setq closer (pop closers)) | ||
| 1373 | (unless (and closers | ||
| 1374 | ;; FIXME: this eliminates prefixes of other | ||
| 1375 | ;; closers, but we should probably elimnate | ||
| 1376 | ;; prefixes of other keywords as well. | ||
| 1377 | (string-prefix-p closer (car closers))) | ||
| 1378 | (push (aref closer (1- (length closer))) triggers))) | ||
| 1379 | (delete-dups triggers))))))) | ||
| 1377 | 1380 | ||
| 1378 | 1381 | ||
| 1379 | (provide 'smie) | 1382 | (provide 'smie) |
diff --git a/lisp/progmodes/octave-mod.el b/lisp/progmodes/octave-mod.el index 40931c3d54d..fdd5e867b7b 100644 --- a/lisp/progmodes/octave-mod.el +++ b/lisp/progmodes/octave-mod.el | |||
| @@ -446,9 +446,6 @@ Non-nil means always go to the next Octave code line after sending." | |||
| 446 | ;; (fundesc (atom "=" atom)) | 446 | ;; (fundesc (atom "=" atom)) |
| 447 | )) | 447 | )) |
| 448 | 448 | ||
| 449 | (defconst octave-smie-closer-alist | ||
| 450 | (smie-bnf-closer-alist octave-smie-bnf-table)) | ||
| 451 | |||
| 452 | (defconst octave-smie-op-levels | 449 | (defconst octave-smie-op-levels |
| 453 | (smie-prec2-levels | 450 | (smie-prec2-levels |
| 454 | (smie-merge-prec2s | 451 | (smie-merge-prec2s |
| @@ -521,15 +518,18 @@ Non-nil means always go to the next Octave code line after sending." | |||
| 521 | (t | 518 | (t |
| 522 | (smie-default-forward-token)))) | 519 | (smie-default-forward-token)))) |
| 523 | 520 | ||
| 524 | (defconst octave-smie-indent-rules | 521 | (defun octave-smie-rules (kind token) |
| 525 | '((";" | 522 | (pcase (cons kind token) |
| 526 | (:parent ("function" "if" "while" "else" "elseif" "for" "otherwise" | 523 | (`(:elem . basic) octave-block-offset) |
| 527 | "case" "try" "catch" "unwind_protect" "unwind_protect_cleanup") | 524 | (`(:before . "case") octave-block-offset) |
| 528 | ;; FIXME: don't hardcode 2. | 525 | (`(:after . ";") |
| 529 | (+ parent octave-block-offset)) | 526 | (if (smie-parent-p "function" "if" "while" "else" "elseif" "for" |
| 530 | ;; (:parent "switch" 4) ;For (invalid) code between switch and case. | 527 | "otherwise" "case" "try" "catch" "unwind_protect" |
| 531 | 0) | 528 | "unwind_protect_cleanup") |
| 532 | ((:before . "case") octave-block-offset))) | 529 | '(+ parent octave-block-offset) |
| 530 | ;; For (invalid) code between switch and case. | ||
| 531 | ;; (if (smie-parent-p "switch") 4) | ||
| 532 | 0)))) | ||
| 533 | 533 | ||
| 534 | (defvar electric-indent-chars) | 534 | (defvar electric-indent-chars) |
| 535 | 535 | ||
| @@ -619,32 +619,15 @@ already added. You just need to add a description of the problem, | |||
| 619 | including a reproducible test case and send the message." | 619 | including a reproducible test case and send the message." |
| 620 | (setq local-abbrev-table octave-abbrev-table) | 620 | (setq local-abbrev-table octave-abbrev-table) |
| 621 | 621 | ||
| 622 | (smie-setup octave-smie-op-levels octave-smie-indent-rules) | 622 | (smie-setup octave-smie-op-levels #'octave-smie-rules |
| 623 | :forward-token #'octave-smie-forward-token | ||
| 624 | :backward-token #'octave-smie-backward-token) | ||
| 623 | (set (make-local-variable 'smie-indent-basic) 'octave-block-offset) | 625 | (set (make-local-variable 'smie-indent-basic) 'octave-block-offset) |
| 624 | (set (make-local-variable 'smie-backward-token-function) | 626 | |
| 625 | 'octave-smie-backward-token) | ||
| 626 | (set (make-local-variable 'smie-forward-token-function) | ||
| 627 | 'octave-smie-forward-token) | ||
| 628 | (set (make-local-variable 'forward-sexp-function) | ||
| 629 | 'smie-forward-sexp-command) | ||
| 630 | (set (make-local-variable 'smie-closer-alist) octave-smie-closer-alist) | ||
| 631 | ;; Only needed for interactive calls to blink-matching-open. | ||
| 632 | (set (make-local-variable 'blink-matching-check-function) | ||
| 633 | #'smie-blink-matching-check) | ||
| 634 | |||
| 635 | (when octave-blink-matching-block | ||
| 636 | (add-hook 'post-self-insert-hook #'smie-blink-matching-open 'append 'local) | ||
| 637 | (set (make-local-variable 'smie-blink-matching-triggers) | 627 | (set (make-local-variable 'smie-blink-matching-triggers) |
| 638 | (append smie-blink-matching-triggers '(\;) | 628 | (cons ?\; smie-blink-matching-triggers)) |
| 639 | ;; Rather than wait for SPC or ; to blink, try to blink as | 629 | (unless octave-blink-matching-block |
| 640 | ;; soon as we type the last char of a block ender. | 630 | (remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local)) |
| 641 | ;; But strip ?d from this list so that we don't blink twice | ||
| 642 | ;; when the user writes "endif" (once at "end" and another | ||
| 643 | ;; time at "endif"). | ||
| 644 | (delq ?d (delete-dups | ||
| 645 | (mapcar (lambda (kw) | ||
| 646 | (aref (cdr kw) (1- (length (cdr kw))))) | ||
| 647 | smie-closer-alist)))))) | ||
| 648 | 631 | ||
| 649 | (set (make-local-variable 'electric-indent-chars) | 632 | (set (make-local-variable 'electric-indent-chars) |
| 650 | (cons ?\; electric-indent-chars)) | 633 | (cons ?\; electric-indent-chars)) |
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el index f3db7fad135..3e388dac56d 100644 --- a/lisp/progmodes/prolog.el +++ b/lisp/progmodes/prolog.el | |||
| @@ -173,10 +173,11 @@ When nil, send actual operating system end of file." | |||
| 173 | ) | 173 | ) |
| 174 | "Precedence levels of infix operators.") | 174 | "Precedence levels of infix operators.") |
| 175 | 175 | ||
| 176 | (defconst prolog-smie-indent-rules | 176 | (defun prolog-smie-rules (kind token) |
| 177 | '((":-") | 177 | (pcase (cons kind token) |
| 178 | ("->")) | 178 | (`(:elem . basic) prolog-indent-width) |
| 179 | "Prolog indentation rules.") | 179 | (`(:after . ".") 0) ;; To work around smie-closer-alist. |
| 180 | (`(:after . ,(or `":-" `"->")) prolog-indent-width))) | ||
| 180 | 181 | ||
| 181 | (defun prolog-mode-variables () | 182 | (defun prolog-mode-variables () |
| 182 | (make-local-variable 'paragraph-separate) | 183 | (make-local-variable 'paragraph-separate) |
| @@ -185,19 +186,17 @@ When nil, send actual operating system end of file." | |||
| 185 | (setq paragraph-ignore-fill-prefix t) | 186 | (setq paragraph-ignore-fill-prefix t) |
| 186 | (make-local-variable 'imenu-generic-expression) | 187 | (make-local-variable 'imenu-generic-expression) |
| 187 | (setq imenu-generic-expression '((nil "^\\sw+" 0))) | 188 | (setq imenu-generic-expression '((nil "^\\sw+" 0))) |
| 188 | (smie-setup prolog-smie-op-levels prolog-smie-indent-rules) | 189 | |
| 189 | (set (make-local-variable 'smie-forward-token-function) | 190 | ;; Setup SMIE. |
| 190 | #'prolog-smie-forward-token) | 191 | (smie-setup prolog-smie-op-levels #'prolog-smie-rules |
| 191 | (set (make-local-variable 'smie-backward-token-function) | 192 | :forward-token #'prolog-smie-forward-token |
| 192 | #'prolog-smie-backward-token) | 193 | :backward-token #'prolog-smie-backward-token) |
| 193 | (set (make-local-variable 'forward-sexp-function) | ||
| 194 | 'smie-forward-sexp-command) | ||
| 195 | (set (make-local-variable 'smie-indent-basic) prolog-indent-width) | ||
| 196 | (set (make-local-variable 'smie-blink-matching-triggers) '(?.)) | 194 | (set (make-local-variable 'smie-blink-matching-triggers) '(?.)) |
| 197 | (set (make-local-variable 'smie-closer-alist) '((t . "."))) | 195 | (set (make-local-variable 'smie-closer-alist) '((t . "."))) |
| 198 | (add-hook 'post-self-insert-hook #'smie-blink-matching-open 'append 'local) | 196 | (add-hook 'post-self-insert-hook #'smie-blink-matching-open 'append 'local) |
| 199 | ;; There's no real closer in Prolog anyway. | 197 | ;; There's no real closer in Prolog anyway. |
| 200 | (set (make-local-variable 'smie-blink-matching-inners) t) | 198 | (set (make-local-variable 'smie-blink-matching-inners) t) |
| 199 | |||
| 201 | (make-local-variable 'comment-start) | 200 | (make-local-variable 'comment-start) |
| 202 | (setq comment-start "%") | 201 | (setq comment-start "%") |
| 203 | (make-local-variable 'comment-start-skip) | 202 | (make-local-variable 'comment-start-skip) |