annotate lisp/emacs-lisp/smie.el @ 111304:0c36e585b866

* lisp/emacs-lisp/smie.el (smie): New custom group. (smie-blink-matching-inners, smie-indent-basic): Add :group.
author Glenn Morris <rgm@gnu.org>
date Sun, 31 Oct 2010 23:44:54 -0700
parents a9904c1962db
children b72ff43b041f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1 ;;; smie.el --- Simple Minded Indentation Engine
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
2
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
3 ;; Copyright (C) 2010 Free Software Foundation, Inc.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
4
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
5 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
6 ;; Keywords: languages, lisp, internal, parsing, indentation
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
7
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
8 ;; This file is part of GNU Emacs.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
9
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
11 ;; it under the terms of the GNU General Public License as published by
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
12 ;; the Free Software Foundation, either version 3 of the License, or
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
13 ;; (at your option) any later version.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
14
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
15 ;; GNU Emacs is distributed in the hope that it will be useful,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
18 ;; GNU General Public License for more details.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
19
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
20 ;; You should have received a copy of the GNU General Public License
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
21 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
22
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
23 ;;; Commentary:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
24
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
25 ;; While working on the SML indentation code, the idea grew that maybe
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
26 ;; I could write something generic to do the same thing, and at the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
27 ;; end of working on the SML code, I had a pretty good idea of what it
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
28 ;; could look like. That idea grew stronger after working on
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
29 ;; LaTeX indentation.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
30 ;;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
31 ;; So at some point I decided to try it out, by writing a new
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
32 ;; indentation code for Coq while trying to keep most of the code
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
33 ;; "table driven", where only the tables are Coq-specific. The result
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
34 ;; (which was used for Beluga-mode as well) turned out to be based on
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
35 ;; something pretty close to an operator precedence parser.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
36
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
37 ;; So here is another rewrite, this time following the actual principles of
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
38 ;; operator precedence grammars. Why OPG? Even though they're among the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
39 ;; weakest kinds of parsers, these parsers have some very desirable properties
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
40 ;; for Emacs:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
41 ;; - most importantly for indentation, they work equally well in either
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
42 ;; direction, so you can use them to parse backward from the indentation
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
43 ;; point to learn the syntactic context;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
44 ;; - they work locally, so there's no need to keep a cache of
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
45 ;; the parser's state;
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
46 ;; - because of that locality, indentation also works just fine when earlier
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
47 ;; parts of the buffer are syntactically incorrect since the indentation
108912
c7e85ff4bca6 * lisp/emacs-lisp/smie.el (smie-indent-keyword): Remove special case that
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108897
diff changeset
48 ;; looks at "as little as possible" of the buffer to make an indentation
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
49 ;; decision.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
50 ;; - they typically have no error handling and can't even detect a parsing
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
51 ;; error, so we don't have to worry about what to do in case of a syntax
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
52 ;; error because the parser just automatically does something. Better yet,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
53 ;; we can afford to use a sloppy grammar.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
54
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
55 ;; The development (especially the parts building the 2D precedence
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
56 ;; tables and then computing the precedence levels from it) is largely
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
57 ;; inspired from page 187-194 of "Parsing techniques" by Dick Grune
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
58 ;; and Ceriel Jacobs (BookBody.pdf available at
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
59 ;; http://www.cs.vu.nl/~dick/PTAPG.html).
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
60 ;;
108912
c7e85ff4bca6 * lisp/emacs-lisp/smie.el (smie-indent-keyword): Remove special case that
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108897
diff changeset
61 ;; OTOH we had to kill many chickens, read many coffee grounds, and practice
c7e85ff4bca6 * lisp/emacs-lisp/smie.el (smie-indent-keyword): Remove special case that
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108897
diff changeset
62 ;; untold numbers of black magic spells, to come up with the indentation code.
c7e85ff4bca6 * lisp/emacs-lisp/smie.el (smie-indent-keyword): Remove special case that
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108897
diff changeset
63 ;; Since then, some of that code has been beaten into submission, but the
c7e85ff4bca6 * lisp/emacs-lisp/smie.el (smie-indent-keyword): Remove special case that
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108897
diff changeset
64 ;; smie-indent-keyword is still pretty obscure.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
65
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
66 ;;; Code:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
67
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
68 ;; FIXME: I think the behavior on empty lines is wrong. It shouldn't
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
69 ;; look at the next token on subsequent lines.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
70
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
71 (eval-when-compile (require 'cl))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
72
111304
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
73 (defgroup smie nil
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
74 "Simple Minded Indentation Engine."
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
75 :group 'languages)
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
76
108878
c3cbf94d10f1 * emacs-lisp/smie.el (comment-continue): Declare for byte-compiler.
Juanma Barranquero <lekktu@gmail.com>
parents: 108865
diff changeset
77 (defvar comment-continue)
108923
5173ad363d4b * emacs-lisp/smie.el (comment-string-strip): Declare function.
Juanma Barranquero <lekktu@gmail.com>
parents: 108912
diff changeset
78 (declare-function comment-string-strip "newcomment" (str beforep afterp))
108878
c3cbf94d10f1 * emacs-lisp/smie.el (comment-continue): Declare for byte-compiler.
Juanma Barranquero <lekktu@gmail.com>
parents: 108865
diff changeset
79
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
80 ;;; Building precedence level tables from BNF specs.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
81
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
82 ;; We have 4 different representations of a "grammar":
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
83 ;; - a BNF table, which is a list of BNF rules of the form
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
84 ;; (NONTERM RHS1 ... RHSn) where each RHS is a list of terminals (tokens)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
85 ;; or nonterminals. Any element in these lists which does not appear as
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
86 ;; the `car' of a BNF rule is taken to be a terminal.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
87 ;; - A list of precedences (key word "precs"), is a list, sorted
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
88 ;; from lowest to highest precedence, of precedence classes that
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
89 ;; have the form (ASSOCIATIVITY TERMINAL1 .. TERMINALn), where
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
90 ;; ASSOCIATIVITY can be `assoc', `left', `right' or `nonassoc'.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
91 ;; - a 2 dimensional precedence table (key word "prec2"), is a 2D
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
92 ;; table recording the precedence relation (can be `<', `=', `>', or
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
93 ;; nil) between each pair of tokens.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
94 ;; - a precedence-level table (key word "levels"), while is a alist
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
95 ;; giving for each token its left and right precedence level (a
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
96 ;; number or nil). This is used in `smie-op-levels'.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
97 ;; The prec2 tables are only intermediate data structures: the source
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
98 ;; code normally provides a mix of BNF and precs tables, and then
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
99 ;; turns them into a levels table, which is what's used by the rest of
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
100 ;; the SMIE code.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
101
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
102 (defun smie-set-prec2tab (table x y val &optional override)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
103 (assert (and x y))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
104 (let* ((key (cons x y))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
105 (old (gethash key table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
106 (if (and old (not (eq old val)))
108766
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
107 (if (and override (gethash key override))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
108 ;; FIXME: The override is meant to resolve ambiguities,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
109 ;; but it also hides real conflicts. It would be great to
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
110 ;; be able to distinguish the two cases so that overrides
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
111 ;; don't hide real conflicts.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
112 (puthash key (gethash key override) table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
113 (display-warning 'smie (format "Conflict: %s %s/%s %s" x old val y)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
114 (puthash key val table))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
115
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
116 (put 'smie-precs-precedence-table 'pure t)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
117 (defun smie-precs-precedence-table (precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
118 "Compute a 2D precedence table from a list of precedences.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
119 PRECS should be a list, sorted by precedence (e.g. \"+\" will
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
120 come before \"*\"), of elements of the form \(left OP ...)
108923
5173ad363d4b * emacs-lisp/smie.el (comment-string-strip): Declare function.
Juanma Barranquero <lekktu@gmail.com>
parents: 108912
diff changeset
121 or (right OP ...) or (nonassoc OP ...) or (assoc OP ...). All operators in
108642
66f3c521df14 * emacs-lisp/smie.el: Fix typos in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents: 108632
diff changeset
122 one of those elements share the same precedence level and associativity."
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
123 (let ((prec2-table (make-hash-table :test 'equal)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
124 (dolist (prec precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
125 (dolist (op (cdr prec))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
126 (let ((selfrule (cdr (assq (car prec)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
127 '((left . >) (right . <) (assoc . =))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
128 (when selfrule
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
129 (dolist (other-op (cdr prec))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
130 (smie-set-prec2tab prec2-table op other-op selfrule))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
131 (let ((op1 '<) (op2 '>))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
132 (dolist (other-prec precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
133 (if (eq prec other-prec)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
134 (setq op1 '> op2 '<)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
135 (dolist (other-op (cdr other-prec))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
136 (smie-set-prec2tab prec2-table op other-op op2)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
137 (smie-set-prec2tab prec2-table other-op op op1)))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
138 prec2-table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
139
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
140 (put 'smie-merge-prec2s 'pure t)
108766
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
141 (defun smie-merge-prec2s (&rest tables)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
142 (if (null (cdr tables))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
143 (car tables)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
144 (let ((prec2 (make-hash-table :test 'equal)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
145 (dolist (table tables)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
146 (maphash (lambda (k v)
110802
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
147 (if (consp k)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
148 (smie-set-prec2tab prec2 (car k) (cdr k) v)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
149 (if (and (gethash k prec2)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
150 (not (equal (gethash k prec2) v)))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
151 (error "Conflicting values for %s property" k)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
152 (puthash k v prec2))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
153 table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
154 prec2)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
155
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
156 (put 'smie-bnf-precedence-table 'pure t)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
157 (defun smie-bnf-precedence-table (bnf &rest precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
158 (let ((nts (mapcar 'car bnf)) ;Non-terminals
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
159 (first-ops-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
160 (last-ops-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
161 (first-nts-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
162 (last-nts-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
163 (prec2 (make-hash-table :test 'equal))
108766
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
164 (override (apply 'smie-merge-prec2s
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
165 (mapcar 'smie-precs-precedence-table precs)))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
166 again)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
167 (dolist (rules bnf)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
168 (let ((nt (car rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
169 (last-ops ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
170 (first-ops ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
171 (last-nts ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
172 (first-nts ()))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
173 (dolist (rhs (cdr rules))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
174 (unless (consp rhs)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
175 (signal 'wrong-type-argument `(consp ,rhs)))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
176 (if (not (member (car rhs) nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
177 (pushnew (car rhs) first-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
178 (pushnew (car rhs) first-nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
179 (when (consp (cdr rhs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
180 ;; If the first is not an OP we add the second (which
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
181 ;; should be an OP if BNF is an "operator grammar").
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
182 ;; Strictly speaking, this should only be done if the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
183 ;; first is a non-terminal which can expand to a phrase
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
184 ;; without any OP in it, but checking doesn't seem worth
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
185 ;; the trouble, and it lets the writer of the BNF
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
186 ;; be a bit more sloppy by skipping uninteresting base
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
187 ;; cases which are terminals but not OPs.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
188 (assert (not (member (cadr rhs) nts)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
189 (pushnew (cadr rhs) first-ops)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
190 (let ((shr (reverse rhs)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
191 (if (not (member (car shr) nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
192 (pushnew (car shr) last-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
193 (pushnew (car shr) last-nts)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
194 (when (consp (cdr shr))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
195 (assert (not (member (cadr shr) nts)))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
196 (pushnew (cadr shr) last-ops)))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
197 (push (cons nt first-ops) first-ops-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
198 (push (cons nt last-ops) last-ops-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
199 (push (cons nt first-nts) first-nts-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
200 (push (cons nt last-nts) last-nts-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
201 ;; Compute all first-ops by propagating the initial ones we have
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
202 ;; now, according to first-nts.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
203 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
204 (while (prog1 again (setq again nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
205 (dolist (first-nts first-nts-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
206 (let* ((nt (pop first-nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
207 (first-ops (assoc nt first-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
208 (dolist (first-nt first-nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
209 (dolist (op (cdr (assoc first-nt first-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
210 (unless (member op first-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
211 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
212 (push op (cdr first-ops))))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
213 ;; Same thing for last-ops.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
214 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
215 (while (prog1 again (setq again nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
216 (dolist (last-nts last-nts-table)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
217 (let* ((nt (pop last-nts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
218 (last-ops (assoc nt last-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
219 (dolist (last-nt last-nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
220 (dolist (op (cdr (assoc last-nt last-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
221 (unless (member op last-ops)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
222 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
223 (push op (cdr last-ops))))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
224 ;; Now generate the 2D precedence table.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
225 (dolist (rules bnf)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
226 (dolist (rhs (cdr rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
227 (while (cdr rhs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
228 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
229 ((member (car rhs) nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
230 (dolist (last (cdr (assoc (car rhs) last-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
231 (smie-set-prec2tab prec2 last (cadr rhs) '> override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
232 ((member (cadr rhs) nts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
233 (dolist (first (cdr (assoc (cadr rhs) first-ops-table)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
234 (smie-set-prec2tab prec2 (car rhs) first '< override))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
235 (if (and (cddr rhs) (not (member (car (cddr rhs)) nts)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
236 (smie-set-prec2tab prec2 (car rhs) (car (cddr rhs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
237 '= override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
238 (t (smie-set-prec2tab prec2 (car rhs) (cadr rhs) '= override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
239 (setq rhs (cdr rhs)))))
110802
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
240 ;; Keep track of which tokens are openers/closer, so they can get a nil
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
241 ;; precedence in smie-prec2-levels.
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
242 (puthash :smie-open/close-alist (smie-bnf-classify bnf) prec2)
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
243 (puthash :smie-closer-alist (smie-bnf-closer-alist bnf) prec2)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
244 prec2))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
245
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
246 ;; (defun smie-prec2-closer-alist (prec2 include-inners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
247 ;; "Build a closer-alist from a PREC2 table.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
248 ;; The return value is in the same form as `smie-closer-alist'.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
249 ;; INCLUDE-INNERS if non-nil means that inner keywords will be included
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
250 ;; in the table, e.g. the table will include things like (\"if\" . \"else\")."
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
251 ;; (let* ((non-openers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
252 ;; (non-closers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
253 ;; ;; For each keyword, this gives the matching openers, if any.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
254 ;; (openers (make-hash-table :test 'equal))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
255 ;; (closers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
256 ;; (done nil))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
257 ;; ;; First, find the non-openers and non-closers.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
258 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
259 ;; (unless (or (eq v '<) (member (cdr k) non-openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
260 ;; (push (cdr k) non-openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
261 ;; (unless (or (eq v '>) (member (car k) non-closers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
262 ;; (push (car k) non-closers)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
263 ;; prec2)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
264 ;; ;; Then find the openers and closers.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
265 ;; (maphash (lambda (k _)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
266 ;; (unless (member (car k) non-openers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
267 ;; (puthash (car k) (list (car k)) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
268 ;; (unless (or (member (cdr k) non-closers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
269 ;; (member (cdr k) closers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
270 ;; (push (cdr k) closers)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
271 ;; prec2)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
272 ;; ;; Then collect the matching elements.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
273 ;; (while (not done)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
274 ;; (setq done t)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
275 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
276 ;; (when (eq v '=)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
277 ;; (let ((aopeners (gethash (car k) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
278 ;; (dopeners (gethash (cdr k) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
279 ;; (new nil))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
280 ;; (dolist (o aopeners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
281 ;; (unless (member o dopeners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
282 ;; (setq new t)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
283 ;; (push o dopeners)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
284 ;; (when new
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
285 ;; (setq done nil)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
286 ;; (puthash (cdr k) dopeners openers)))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
287 ;; prec2))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
288 ;; ;; Finally, dump the resulting table.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
289 ;; (let ((alist '()))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
290 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
291 ;; (when (or include-inners (member k closers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
292 ;; (dolist (opener v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
293 ;; (unless (equal opener k)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
294 ;; (push (cons opener k) alist)))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
295 ;; openers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
296 ;; alist)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
297
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
298 (defun smie-bnf-closer-alist (bnf &optional no-inners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
299 ;; We can also build this closer-alist table from a prec2 table,
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
300 ;; but it takes more work, and the order is unpredictable, which
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
301 ;; is a problem for smie-close-block.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
302 ;; More convenient would be to build it from a levels table since we
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
303 ;; always have this table (contrary to the BNF), but it has all the
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
304 ;; disadvantages of the prec2 case plus the disadvantage that the levels
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
305 ;; table has lost some info which would result in extra invalid pairs.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
306 "Build a closer-alist from a BNF table.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
307 The return value is in the same form as `smie-closer-alist'.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
308 NO-INNERS if non-nil means that inner keywords will be excluded
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
309 from the table, e.g. the table will not include things like (\"if\" . \"else\")."
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
310 (let ((nts (mapcar #'car bnf)) ;non terminals.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
311 (alist '()))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
312 (dolist (nt bnf)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
313 (dolist (rhs (cdr nt))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
314 (unless (or (< (length rhs) 2) (member (car rhs) nts))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
315 (if no-inners
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
316 (let ((last (car (last rhs))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
317 (unless (member last nts)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
318 (pushnew (cons (car rhs) last) alist :test #'equal)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
319 ;; Reverse so that the "real" closer gets there first,
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
320 ;; which is important for smie-close-block.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
321 (dolist (term (reverse (cdr rhs)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
322 (unless (member term nts)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
323 (pushnew (cons (car rhs) term) alist :test #'equal)))))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
324 (nreverse alist)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
325
110802
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
326 (defun smie-bnf-classify (bnf)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
327 "Return a table classifying terminals.
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
328 Each terminal can either be an `opener', a `closer', or neither."
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
329 (let ((table (make-hash-table :test #'equal))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
330 (alist '()))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
331 (dolist (category bnf)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
332 (puthash (car category) 'neither table) ;Remove non-terminals.
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
333 (dolist (rhs (cdr category))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
334 (if (null (cdr rhs))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
335 (puthash (pop rhs) 'neither table)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
336 (let ((first (pop rhs)))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
337 (puthash first
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
338 (if (memq (gethash first table) '(nil opener))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
339 'opener 'neither)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
340 table))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
341 (while (cdr rhs)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
342 (puthash (pop rhs) 'neither table)) ;Remove internals.
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
343 (let ((last (pop rhs)))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
344 (puthash last
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
345 (if (memq (gethash last table) '(nil closer))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
346 'closer 'neither)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
347 table)))))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
348 (maphash (lambda (tok v)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
349 (when (memq v '(closer opener))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
350 (push (cons tok v) alist)))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
351 table)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
352 alist))
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
353
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
354 (defun smie-debug--prec2-cycle (csts)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
355 "Return a cycle in CSTS, assuming there's one.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
356 CSTS is a list of pairs representing arcs in a graph."
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
357 ;; A PATH is of the form (START . REST) where REST is a reverse
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
358 ;; list of nodes through which the path goes.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
359 (let ((paths (mapcar (lambda (pair) (list (car pair) (cdr pair))) csts))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
360 (cycle nil))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
361 (while (null cycle)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
362 (dolist (path (prog1 paths (setq paths nil)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
363 (dolist (cst csts)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
364 (when (eq (car cst) (nth 1 path))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
365 (if (eq (cdr cst) (car path))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
366 (setq cycle path)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
367 (push (cons (car path) (cons (cdr cst) (cdr path)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
368 paths))))))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
369 (cons (car cycle) (nreverse (cdr cycle)))))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
370
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
371 (defun smie-debug--describe-cycle (table cycle)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
372 (let ((names
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
373 (mapcar (lambda (val)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
374 (let ((res nil))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
375 (dolist (elem table)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
376 (if (eq (cdr elem) val)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
377 (push (concat "." (car elem)) res))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
378 (if (eq (cddr elem) val)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
379 (push (concat (car elem) ".") res)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
380 (assert res)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
381 res))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
382 cycle)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
383 (mapconcat
110464
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
384 (lambda (elems) (mapconcat 'identity elems "="))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
385 (append names (list (car names)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
386 " < ")))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
387
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
388 (put 'smie-prec2-levels 'pure t)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
389 (defun smie-prec2-levels (prec2)
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
390 ;; FIXME: Rather than only return an alist of precedence levels, we should
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
391 ;; also extract other useful data from it:
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
392 ;; - better default indentation rules (i.e. non-zero indentation after inner
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
393 ;; keywords like the "in" of "let..in..end") for smie-indent-after-keyword.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
394 ;; Of course, maybe those things would be even better handled in the
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
395 ;; bnf->prec function.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
396 "Take a 2D precedence table and turn it into an alist of precedence levels.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
397 PREC2 is a table as returned by `smie-precs-precedence-table' or
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
398 `smie-bnf-precedence-table'."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
399 ;; For each operator, we create two "variables" (corresponding to
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
400 ;; the left and right precedence level), which are represented by
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
401 ;; cons cells. Those are the very cons cells that appear in the
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
402 ;; final `table'. The value of each "variable" is kept in the `car'.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
403 (let ((table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
404 (csts ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
405 (eqs ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
406 tmp x y)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
407 ;; From `prec2' we construct a list of constraints between
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
408 ;; variables (aka "precedence levels"). These can be either
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
409 ;; equality constraints (in `eqs') or `<' constraints (in `csts').
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
410 (maphash (lambda (k v)
110802
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
411 (when (consp k)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
412 (if (setq tmp (assoc (car k) table))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
413 (setq x (cddr tmp))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
414 (setq x (cons nil nil))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
415 (push (cons (car k) (cons nil x)) table))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
416 (if (setq tmp (assoc (cdr k) table))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
417 (setq y (cdr tmp))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
418 (setq y (cons nil (cons nil nil)))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
419 (push (cons (cdr k) y) table))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
420 (ecase v
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
421 (= (push (cons x y) eqs))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
422 (< (push (cons x y) csts))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
423 (> (push (cons y x) csts)))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
424 prec2)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
425 ;; First process the equality constraints.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
426 (let ((eqs eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
427 (while eqs
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
428 (let ((from (caar eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
429 (to (cdar eqs)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
430 (setq eqs (cdr eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
431 (if (eq to from)
108766
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
432 nil ;Nothing to do.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
433 (dolist (other-eq eqs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
434 (if (eq from (cdr other-eq)) (setcdr other-eq to))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
435 (when (eq from (car other-eq))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
436 ;; This can happen because of `assoc' settings in precs
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
437 ;; or because of a rhs like ("op" foo "op").
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
438 (setcar other-eq to)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
439 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
440 (if (eq from (cdr cst)) (setcdr cst to))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
441 (if (eq from (car cst)) (setcar cst to)))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
442 ;; Then eliminate trivial constraints iteratively.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
443 (let ((i 0))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
444 (while csts
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
445 (let ((rhvs (mapcar 'cdr csts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
446 (progress nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
447 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
448 (unless (memq (car cst) rhvs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
449 (setq progress t)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
450 ;; We could give each var in a given iteration the same value,
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
451 ;; but we can also give them arbitrarily different values.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
452 ;; Basically, these are vars between which there is no
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
453 ;; constraint (neither equality nor inequality), so
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
454 ;; anything will do.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
455 ;; We give them arbitrary values, which means that we
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
456 ;; replace the "no constraint" case with either > or <
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
457 ;; but not =. The reason we do that is so as to try and
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
458 ;; distinguish associative operators (which will have
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
459 ;; left = right).
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
460 (unless (caar cst)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
461 (setcar (car cst) i)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
462 (incf i))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
463 (setq csts (delq cst csts))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
464 (unless progress
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
465 (error "Can't resolve the precedence cycle: %s"
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
466 (smie-debug--describe-cycle
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
467 table (smie-debug--prec2-cycle csts)))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
468 (incf i 10))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
469 ;; Propagate equalities back to their source.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
470 (dolist (eq (nreverse eqs))
108766
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
471 (assert (or (null (caar eq)) (eq (car eq) (cdr eq))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
472 (setcar (car eq) (cadr eq)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
473 ;; Finally, fill in the remaining vars (which only appeared on the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
474 ;; right side of the < constraints).
110802
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
475 (let ((classification-table (gethash :smie-open/close-alist prec2)))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
476 (dolist (x table)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
477 ;; When both sides are nil, it means this operator binds very
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
478 ;; very tight, but it's still just an operator, so we give it
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
479 ;; the highest precedence.
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
480 ;; OTOH if only one side is nil, it usually means it's like an
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
481 ;; open-paren, which is very important for indentation purposes,
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
482 ;; so we keep it nil if so, to make it easier to recognize.
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
483 (unless (or (nth 1 x)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
484 (eq 'opener (cdr (assoc (car x) classification-table))))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
485 (setf (nth 1 x) i)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
486 (incf i)) ;See other (incf i) above.
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
487 (unless (or (nth 2 x)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
488 (eq 'closer (cdr (assoc (car x) classification-table))))
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
489 (setf (nth 2 x) i)
e544f6cc2447 SMIE: Reliably distinguish openers/closers in smie-prec2-levels
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110464
diff changeset
490 (incf i))))) ;See other (incf i) above.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
491 (let ((ca (gethash :smie-closer-alist prec2)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
492 (when ca (push (cons :smie-closer-alist ca) table)))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
493 table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
494
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
495 ;;; Parsing using a precedence level table.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
496
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
497 (defvar smie-op-levels 'unset
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
498 "List of token parsing info.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
499 Each element is of the form (TOKEN LEFT-LEVEL RIGHT-LEVEL).
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
500 Parsing is done using an operator precedence parser.
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
501 LEFT-LEVEL and RIGHT-LEVEL can be either numbers or nil, where nil
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
502 means that this operator does not bind on the corresponding side,
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
503 i.e. a LEFT-LEVEL of nil means this is a token that behaves somewhat like
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
504 an open-paren, whereas a RIGHT-LEVEL of nil would correspond to something
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
505 like a close-paren.")
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
506
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
507 (defvar smie-forward-token-function 'smie-default-forward-token
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
508 "Function to scan forward for the next token.
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
509 Called with no argument should return a token and move to its end.
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
510 If no token is found, return nil or the empty string.
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
511 It can return nil when bumping into a parenthesis, which lets SMIE
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
512 use syntax-tables to handle them in efficient C code.")
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
513
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
514 (defvar smie-backward-token-function 'smie-default-backward-token
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
515 "Function to scan backward the previous token.
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
516 Same calling convention as `smie-forward-token-function' except
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
517 it should move backward to the beginning of the previous token.")
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
518
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
519 (defalias 'smie-op-left 'car)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
520 (defalias 'smie-op-right 'cadr)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
521
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
522 (defun smie-default-backward-token ()
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
523 (forward-comment (- (point)))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
524 (buffer-substring-no-properties
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
525 (point)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
526 (progn (if (zerop (skip-syntax-backward "."))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
527 (skip-syntax-backward "w_'"))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
528 (point))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
529
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
530 (defun smie-default-forward-token ()
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
531 (forward-comment (point-max))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
532 (buffer-substring-no-properties
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
533 (point)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
534 (progn (if (zerop (skip-syntax-forward "."))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
535 (skip-syntax-forward "w_'"))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
536 (point))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
537
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
538 (defun smie--associative-p (toklevels)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
539 ;; in "a + b + c" we want to stop at each +, but in
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
540 ;; "if a then b elsif c then d else c" we don't want to stop at each keyword.
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
541 ;; To distinguish the two cases, we made smie-prec2-levels choose
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
542 ;; different levels for each part of "if a then b else c", so that
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
543 ;; by checking if the left-level is equal to the right level, we can
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
544 ;; figure out that it's an associative operator.
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
545 ;; This is not 100% foolproof, tho, since the "elsif" will have to have
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
546 ;; equal left and right levels (since it's optional), so smie-next-sexp
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
547 ;; has to be careful to distinguish those different cases.
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
548 (eq (smie-op-left toklevels) (smie-op-right toklevels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
549
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
550 (defun smie-next-sexp (next-token next-sexp op-forw op-back halfsexp)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
551 "Skip over one sexp.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
552 NEXT-TOKEN is a function of no argument that moves forward by one
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
553 token (after skipping comments if needed) and returns it.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
554 NEXT-SEXP is a lower-level function to skip one sexp.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
555 OP-FORW is the accessor to the forward level of the level data.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
556 OP-BACK is the accessor to the backward level of the level data.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
557 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
558 first token we see is an operator, skip over its left-hand-side argument.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
559 Possible return values:
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
560 (FORW-LEVEL POS TOKEN): we couldn't skip TOKEN because its back-level
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
561 is too high. FORW-LEVEL is the forw-level of TOKEN,
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
562 POS is its start position in the buffer.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
563 (t POS TOKEN): same thing when we bump on the wrong side of a paren.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
564 (nil POS TOKEN): we skipped over a paren-like pair.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
565 nil: we skipped over an identifier, matched parentheses, ..."
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
566 (catch 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
567 (let ((levels ()))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
568 (while
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
569 (let* ((pos (point))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
570 (token (funcall next-token))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
571 (toklevels (cdr (assoc token smie-op-levels))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
572 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
573 ((null toklevels)
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
574 (when (zerop (length token))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
575 (condition-case err
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
576 (progn (goto-char pos) (funcall next-sexp 1) nil)
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
577 (scan-error (throw 'return
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
578 (list t (caddr err)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
579 (buffer-substring-no-properties
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
580 (caddr err)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
581 (+ (caddr err)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
582 (if (< (point) (caddr err))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
583 -1 1)))))))
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
584 (if (eq pos (point))
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
585 ;; We did not move, so let's abort the loop.
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
586 (throw 'return (list t (point))))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
587 ((null (funcall op-back toklevels))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
588 ;; A token like a paren-close.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
589 (assert (funcall op-forw toklevels)) ;Otherwise, why mention it?
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
590 (push toklevels levels))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
591 (t
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
592 (while (and levels (< (funcall op-back toklevels)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
593 (funcall op-forw (car levels))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
594 (setq levels (cdr levels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
595 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
596 ((null levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
597 (if (and halfsexp (funcall op-forw toklevels))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
598 (push toklevels levels)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
599 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
600 (prog1 (list (or (car toklevels) t) (point) token)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
601 (goto-char pos)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
602 (t
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
603 (let ((lastlevels levels))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
604 (if (and levels (= (funcall op-back toklevels)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
605 (funcall op-forw (car levels))))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
606 (setq levels (cdr levels)))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
607 ;; We may have found a match for the previously pending
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
608 ;; operator. Is this the end?
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
609 (cond
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
610 ;; Keep looking as long as we haven't matched the
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
611 ;; topmost operator.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
612 (levels
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
613 (if (funcall op-forw toklevels)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
614 (push toklevels levels)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
615 ;; We matched the topmost operator. If the new operator
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
616 ;; is the last in the corresponding BNF rule, we're done.
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
617 ((null (funcall op-forw toklevels))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
618 ;; It is the last element, let's stop here.
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
619 (throw 'return (list nil (point) token)))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
620 ;; If the new operator is not the last in the BNF rule,
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
621 ;; ans is not associative, it's one of the inner operators
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
622 ;; (like the "in" in "let .. in .. end"), so keep looking.
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
623 ((not (smie--associative-p toklevels))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
624 (push toklevels levels))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
625 ;; The new operator is associative. Two cases:
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
626 ;; - it's really just an associative operator (like + or ;)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
627 ;; in which case we should have stopped right before.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
628 ((and lastlevels
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
629 (smie--associative-p (car lastlevels)))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
630 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
631 (prog1 (list (or (car toklevels) t) (point) token)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
632 (goto-char pos))))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
633 ;; - it's an associative operator within a larger construct
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
634 ;; (e.g. an "elsif"), so we should just ignore it and keep
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
635 ;; looking for the closing element.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
636 (t (setq levels lastlevels))))))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
637 levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
638 (setq halfsexp nil)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
639
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
640 (defun smie-backward-sexp (&optional halfsexp)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
641 "Skip over one sexp.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
642 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
643 first token we see is an operator, skip over its left-hand-side argument.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
644 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
645 (LEFT-LEVEL POS TOKEN): we couldn't skip TOKEN because its right-level
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
646 is too high. LEFT-LEVEL is the left-level of TOKEN,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
647 POS is its start position in the buffer.
108642
66f3c521df14 * emacs-lisp/smie.el: Fix typos in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents: 108632
diff changeset
648 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
649 (nil POS TOKEN): we skipped over a paren-like pair.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
650 nil: we skipped over an identifier, matched parentheses, ..."
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
651 (smie-next-sexp
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
652 (indirect-function smie-backward-token-function)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
653 (indirect-function 'backward-sexp)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
654 (indirect-function 'smie-op-left)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
655 (indirect-function 'smie-op-right)
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
656 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
657
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
658 (defun smie-forward-sexp (&optional halfsexp)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
659 "Skip over one sexp.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
660 HALFSEXP if non-nil, means skip over a partial sexp if needed. I.e. if the
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
661 first token we see is an operator, skip over its left-hand-side argument.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
662 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
663 (RIGHT-LEVEL POS TOKEN): we couldn't skip TOKEN because its left-level
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
664 is too high. RIGHT-LEVEL is the right-level of TOKEN,
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
665 POS is its end position in the buffer.
108642
66f3c521df14 * emacs-lisp/smie.el: Fix typos in docstrings.
Juanma Barranquero <lekktu@gmail.com>
parents: 108632
diff changeset
666 (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
667 (nil POS TOKEN): we skipped over a paren-like pair.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
668 nil: we skipped over an identifier, matched parentheses, ..."
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
669 (smie-next-sexp
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
670 (indirect-function smie-forward-token-function)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
671 (indirect-function 'forward-sexp)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
672 (indirect-function 'smie-op-right)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
673 (indirect-function 'smie-op-left)
108652
79ce86edba9f * emacs-lisp/smie.el (smie-next-sexp): Break inf-loop at BOB.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108649
diff changeset
674 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
675
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
676 ;;; Miscellanous commands using the precedence parser.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
677
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
678 (defun smie-backward-sexp-command (&optional n)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
679 "Move backward through N logical elements."
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
680 (interactive "^p")
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
681 (smie-forward-sexp-command (- n)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
682
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
683 (defun smie-forward-sexp-command (&optional n)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
684 "Move forward through N logical elements."
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
685 (interactive "^p")
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
686 (let ((forw (> n 0))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
687 (forward-sexp-function nil))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
688 (while (/= n 0)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
689 (setq n (- n (if forw 1 -1)))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
690 (let ((pos (point))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
691 (res (if forw
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
692 (smie-forward-sexp 'halfsexp)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
693 (smie-backward-sexp 'halfsexp))))
109840
51f5fd9b5515 * smie.el (smie-forward-sexp-command): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109838
diff changeset
694 (if (and (car res) (= pos (point)) (not (if forw (eobp) (bobp))))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
695 (signal 'scan-error
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
696 (list "Containing expression ends prematurely"
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
697 (cadr res) (cadr res)))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
698 nil)))))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
699
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
700 (defvar smie-closer-alist nil
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
701 "Alist giving the closer corresponding to an opener.")
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
702
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
703 (defun smie-close-block ()
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
704 "Close the closest surrounding block."
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
705 (interactive)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
706 (let ((closer
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
707 (save-excursion
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
708 (backward-up-list 1)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
709 (if (looking-at "\\s(")
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
710 (string (cdr (syntax-after (point))))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
711 (let* ((open (funcall smie-forward-token-function))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
712 (closer (cdr (assoc open smie-closer-alist)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
713 (levels (list (assoc open smie-op-levels)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
714 (seen '())
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
715 (found '()))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
716 (cond
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
717 ;; Even if we improve the auto-computation of closers,
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
718 ;; there are still cases where we need manual
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
719 ;; intervention, e.g. for Octave's use of `until'
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
720 ;; as a pseudo-closer of `do'.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
721 (closer)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
722 ((or (equal levels '(nil)) (nth 1 (car levels)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
723 (error "Doesn't look like a block"))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
724 (t
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
725 ;; FIXME: With grammars like Octave's, every closer ("end",
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
726 ;; "endif", "endwhile", ...) has the same level, so we'd need
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
727 ;; to look at the BNF or at least at the 2D prec-table, in
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
728 ;; order to find the right closer for a given opener.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
729 (while levels
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
730 (let ((level (pop levels)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
731 (dolist (other smie-op-levels)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
732 (when (and (eq (nth 2 level) (nth 1 other))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
733 (not (memq other seen)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
734 (push other seen)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
735 (if (nth 2 other)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
736 (push other levels)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
737 (push (car other) found))))))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
738 (cond
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
739 ((null found) (error "No known closer for opener %s" open))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
740 ;; FIXME: what should we do if there are various closers?
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
741 (t (car found))))))))))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
742 (unless (save-excursion (skip-chars-backward " \t") (bolp))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
743 (newline))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
744 (insert closer)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
745 (if (save-excursion (skip-chars-forward " \t") (eolp))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
746 (indent-according-to-mode)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
747 (reindent-then-newline-and-indent))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
748
110067
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
749 (defun smie-down-list (&optional arg)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
750 "Move forward down one level paren-like blocks. Like `down-list'.
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
751 With argument ARG, do this that many times.
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
752 A negative argument means move backward but still go down a level.
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
753 This command assumes point is not in a string or comment."
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
754 (interactive "p")
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
755 (let ((start (point))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
756 (inc (if (< arg 0) -1 1))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
757 (offset (if (< arg 0) 1 0))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
758 (next-token (if (< arg 0)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
759 smie-backward-token-function
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
760 smie-forward-token-function)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
761 (while (/= arg 0)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
762 (setq arg (- arg inc))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
763 (while
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
764 (let* ((pos (point))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
765 (token (funcall next-token))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
766 (levels (assoc token smie-op-levels)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
767 (cond
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
768 ((zerop (length token))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
769 (if (if (< inc 0) (looking-back "\\s(\\|\\s)" (1- (point)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
770 (looking-at "\\s(\\|\\s)"))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
771 ;; Go back to `start' in case of an error. This presumes
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
772 ;; none of the token we've found until now include a ( or ).
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
773 (progn (goto-char start) (down-list inc) nil)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
774 (forward-sexp inc)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
775 (/= (point) pos)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
776 ((and levels (null (nth (+ 1 offset) levels))) nil)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
777 ((and levels (null (nth (- 2 offset) levels)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
778 (let ((end (point)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
779 (goto-char start)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
780 (signal 'scan-error
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
781 (list "Containing expression ends prematurely"
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
782 pos end))))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
783 (t)))))))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
784
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
785 (defvar smie-blink-matching-triggers '(?\s ?\n)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
786 "Chars which might trigger `blink-matching-open'.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
787 These can include the final chars of end-tokens, or chars that are
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
788 typically inserted right after an end token.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
789 I.e. a good choice can be:
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
790 (delete-dups
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
791 (mapcar (lambda (kw) (aref (cdr kw) (1- (length (cdr kw)))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
792 smie-closer-alist))")
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
793
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
794 (defcustom smie-blink-matching-inners t
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
795 "Whether SMIE should blink to matching opener for inner keywords.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
796 If non-nil, it will blink not only for \"begin..end\" but also for \"if...else\"."
111304
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
797 :type 'boolean
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
798 :group 'smie)
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
799
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
800 (defun smie-blink-matching-check (start end)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
801 (save-excursion
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
802 (goto-char end)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
803 (let ((ender (funcall smie-backward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
804 (cond
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
805 ((not (and ender (rassoc ender smie-closer-alist)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
806 ;; This not is one of the begin..end we know how to check.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
807 (blink-matching-check-mismatch start end))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
808 ((not start) t)
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
809 ((eq t (car (rassoc ender smie-closer-alist))) nil)
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
810 (t
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
811 (goto-char start)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
812 (let ((starter (funcall smie-forward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
813 (not (member (cons starter ender) smie-closer-alist))))))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
814
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
815 (defun smie-blink-matching-open ()
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
816 "Blink the matching opener when applicable.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
817 This uses SMIE's tables and is expected to be placed on `post-self-insert-hook'."
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
818 (let ((pos (point)) ;Position after the close token.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
819 token)
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
820 (when (and blink-matching-paren
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
821 smie-closer-alist ; Optimization.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
822 (or (eq (char-before) last-command-event) ;; Sanity check.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
823 (save-excursion
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
824 (or (progn (skip-chars-backward " \t")
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
825 (setq pos (point))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
826 (eq (char-before) last-command-event))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
827 (progn (skip-chars-backward " \n\t")
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
828 (setq pos (point))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
829 (eq (char-before) last-command-event)))))
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
830 (memq last-command-event smie-blink-matching-triggers)
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
831 (not (nth 8 (syntax-ppss))))
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
832 (save-excursion
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
833 (setq token (funcall smie-backward-token-function))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
834 (when (and (eq (point) (1- pos))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
835 (= 1 (length token))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
836 (not (rassoc token smie-closer-alist)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
837 ;; The trigger char is itself a token but is not one of the
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
838 ;; closers (e.g. ?\; in Octave mode), so go back to the
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
839 ;; previous token.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
840 (setq pos (point))
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
841 (setq token (funcall smie-backward-token-function)))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
842 (when (rassoc token smie-closer-alist)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
843 ;; We're after a close token. Let's still make sure we
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
844 ;; didn't skip a comment to find that token.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
845 (funcall smie-forward-token-function)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
846 (when (and (save-excursion
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
847 ;; Skip the trigger char, if applicable.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
848 (if (eq (char-after) last-command-event)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
849 (forward-char 1))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
850 (if (eq ?\n last-command-event)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
851 ;; Skip any auto-indentation, if applicable.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
852 (skip-chars-forward " \t"))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
853 (>= (point) pos))
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
854 ;; If token ends with a trigger char, don't blink for
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
855 ;; anything else than this trigger char, lest we'd blink
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
856 ;; both when inserting the trigger char and when
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
857 ;; inserting a subsequent trigger char like SPC.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
858 (or (eq (point) pos)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
859 (not (memq (char-before)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
860 smie-blink-matching-triggers)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
861 (or smie-blink-matching-inners
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
862 (null (nth 2 (assoc token smie-op-levels)))))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
863 ;; The major mode might set blink-matching-check-function
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
864 ;; buffer-locally so that interactive calls to
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
865 ;; blink-matching-open work right, but let's not presume
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
866 ;; that's the case.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
867 (let ((blink-matching-check-function #'smie-blink-matching-check))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
868 (blink-matching-open))))))))
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
869
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
870 ;;; The indentation engine.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
871
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
872 (defcustom smie-indent-basic 4
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
873 "Basic amount of indentation."
111304
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
874 :type 'integer
0c36e585b866 * lisp/emacs-lisp/smie.el (smie): New custom group.
Glenn Morris <rgm@gnu.org>
parents: 111232
diff changeset
875 :group 'smie)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
876
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
877 (defvar smie-rules-function 'ignore
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
878 "Function providing the indentation rules.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
879 It takes two arguments METHOD and ARG where the meaning of ARG
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
880 and the expected return value depends on METHOD.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
881 METHOD can be:
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
882 - :after, in which case ARG is a token and the function should return the
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
883 OFFSET to use for indentation after ARG.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
884 - :before, in which case ARG is a token and the function should return the
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
885 OFFSET to use to indent ARG itself.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
886 - :elem, in which case the function should return either:
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
887 - the offset to use to indent function arguments (ARG = `arg')
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
888 - the basic indentation step (ARG = `basic').
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
889 - :list-intro, in which case ARG is a token and the function should return
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
890 non-nil if TOKEN is followed by a list of expressions (not separated by any
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
891 token) rather than an expression.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
892
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
893 When ARG is a token, the function is called with point just before that token.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
894 A return value of nil always means to fallback on the default behavior, so the
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
895 function should return nil for arguments it does not expect.
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
896
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
897 OFFSET can be of the form:
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
898 `point' align with the token.
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
899 `parent' align with the parent.
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
900 NUMBER offset by NUMBER.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
901 \(+ OFFSETS...) use the sum of OFFSETS.
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
902 VARIABLE use the value of VARIABLE as offset.
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
903
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
904 This function will often use some of the following functions designed
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
905 specifically for it:
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
906 `smie-bolp', `smie-hanging-p', `smie-parent-p', `smie-next-p', `smie-prev-p'.")
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
907
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
908 (defun smie-hanging-p ()
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
909 "Return non-nil if the current token is \"hanging\".
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
910 A hanging keyword is one that's at the end of a line except it's not at
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
911 the beginning of a line."
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
912 (and (not (smie-bolp))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
913 (save-excursion
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
914 (when (zerop (length (funcall smie-forward-token-function)))
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
915 ;; Could be an open-paren.
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
916 (forward-char 1))
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
917 (skip-chars-forward " \t")
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
918 (eolp))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
919
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
920 (defun smie-bolp ()
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
921 "Return non-nil if the current token is the first on the line."
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
922 (save-excursion (skip-chars-backward " \t") (bolp)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
923
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
924 (defvar smie--parent) (defvar smie--after) ;Dynamically scoped.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
925
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
926 (defun smie-parent-p (&rest parents)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
927 "Return non-nil if the current token's parent is among PARENTS.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
928 Only meaningful when called from within `smie-rules-function'."
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
929 (member (nth 2 (or smie--parent
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
930 (save-excursion
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
931 (let* ((pos (point))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
932 (tok (funcall smie-forward-token-function)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
933 (unless (cadr (assoc tok smie-op-levels))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
934 (goto-char pos))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
935 (setq smie--parent
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
936 (smie-backward-sexp 'halfsexp))))))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
937 parents))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
938
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
939 (defun smie-next-p (&rest tokens)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
940 "Return non-nil if the next token is among TOKENS.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
941 Only meaningful when called from within `smie-rules-function'."
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
942 (let ((next
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
943 (save-excursion
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
944 (unless smie--after
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
945 (smie-indent-forward-token) (setq smie--after (point)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
946 (goto-char smie--after)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
947 (smie-indent-forward-token))))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
948 (member (car next) tokens)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
949
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
950 (defun smie-prev-p (&rest tokens)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
951 "Return non-nil if the previous token is among TOKENS."
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
952 (let ((prev (save-excursion
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
953 (smie-indent-backward-token))))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
954 (member (car prev) tokens)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
955
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
956
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
957 (defun smie-indent--offset (elem)
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
958 (or (funcall smie-rules-function :elem elem)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
959 (if (not (eq elem 'basic))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
960 (funcall smie-rules-function :elem 'basic))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
961 smie-indent-basic))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
962
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
963 (defun smie-indent--rule (kind token &optional after parent)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
964 (let ((smie--parent parent)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
965 (smie--after after))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
966 (funcall smie-rules-function kind token)))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
967
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
968 (defun smie-indent--column (offset &optional base parent virtual-point)
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
969 "Compute the actual column to use for a given OFFSET.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
970 BASE is the base position to use, and PARENT is the parent info, if any.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
971 If VIRTUAL-POINT is non-nil, then `point' is virtual."
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
972 (cond
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
973 ((eq (car-safe offset) '+)
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
974 (apply '+ (mapcar (lambda (offset) (smie-indent--column offset nil parent))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
975 (cdr offset))))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
976 ((integerp offset)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
977 (+ offset
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
978 (case base
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
979 ((nil) 0)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
980 (parent (goto-char (cadr parent))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
981 (smie-indent-virtual))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
982 (t
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
983 (goto-char base)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
984 ;; For indentation after "(let" in SML-mode, we end up accumulating
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
985 ;; the offset of "(" and the offset of "let", so we use `min' to try
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
986 ;; and get it right either way.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
987 (min (smie-indent-virtual) (current-column))))))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
988 ((eq offset 'point)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
989 ;; In indent-keyword, if we're indenting `then' wrt `if', we want to use
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
990 ;; indent-virtual rather than use just current-column, so that we can
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
991 ;; apply the (:before . "if") rule which does the "else if" dance in SML.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
992 ;; But in other cases, we do not want to use indent-virtual
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
993 ;; (e.g. indentation of "*" w.r.t "+", or ";" wrt "("). We could just
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
994 ;; always use indent-virtual and then have indent-rules say explicitly
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
995 ;; to use `point' after things like "(" or "+" when they're not at EOL,
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
996 ;; but you'd end up with lots of those rules.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
997 ;; So we use a heuristic here, which is that we only use virtual if
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
998 ;; the parent is tightly linked to the child token (they're part of
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
999 ;; the same BNF rule).
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1000 (if (and virtual-point (null (car parent))) ;Black magic :-(
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1001 (smie-indent-virtual) (current-column)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1002 ((eq offset 'parent)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1003 (unless parent
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1004 (setq parent (or (smie-backward-sexp 'halfsexp) :notfound)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1005 (if (consp parent) (goto-char (cadr parent)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1006 (smie-indent-virtual))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1007 ((eq offset nil) nil)
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1008 ;; FIXME: would be good to get rid of this since smie-rules-function
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1009 ;; can usually do the lookup trivially, but in cases where
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1010 ;; smie-rules-function returns (+ point VAR) it's not nearly as trivial.
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
1011 ((and (symbolp offset) (boundp 'offset))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1012 (smie-indent--column (symbol-value offset) base parent virtual-point))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1013 (t (error "Unknown indentation offset %s" offset))))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1014
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1015 (defun smie-indent-forward-token ()
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1016 "Skip token forward and return it, along with its levels."
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1017 (let ((tok (funcall smie-forward-token-function)))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1018 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1019 ((< 0 (length tok)) (assoc tok smie-op-levels))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1020 ((looking-at "\\s(")
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1021 (forward-char 1)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1022 (list (buffer-substring (1- (point)) (point)) nil 0)))))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1023
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1024 (defun smie-indent-backward-token ()
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1025 "Skip token backward and return it, along with its levels."
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1026 (let ((tok (funcall smie-backward-token-function)))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1027 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1028 ((< 0 (length tok)) (assoc tok smie-op-levels))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1029 ;; 4 == Open paren syntax.
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1030 ((eq 4 (syntax-class (syntax-after (1- (point)))))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1031 (forward-char -1)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1032 (list (buffer-substring (point) (1+ (point))) nil 0)))))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1033
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1034 (defun smie-indent-virtual ()
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1035 ;; We used to take an optional arg (with value :not-hanging) to specify that
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1036 ;; we should only use (smie-indent-calculate) if we're looking at a hanging
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1037 ;; keyword. This was a bad idea, because the virtual indent of a position
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1038 ;; should not depend on the caller, since it leads to situations where two
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1039 ;; dependent indentations get indented differently.
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1040 "Compute the virtual indentation to use for point.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1041 This is used when we're not trying to indent point but just
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1042 need to compute the column at which point should be indented
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1043 in order to figure out the indentation of some other (further down) point."
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1044 ;; Trust pre-existing indentation on other lines.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1045 (if (smie-bolp) (current-column) (smie-indent-calculate)))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1046
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1047 (defun smie-indent-fixindent ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1048 ;; Obey the `fixindent' special comment.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1049 (and (smie-bolp)
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1050 (save-excursion
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1051 (comment-normalize-vars)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1052 (re-search-forward (concat comment-start-skip
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1053 "fixindent"
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1054 comment-end-skip)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1055 ;; 1+ to account for the \n comment termination.
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1056 (1+ (line-end-position)) t))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1057 (current-column)))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1058
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1059 (defun smie-indent-bob ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1060 ;; Start the file at column 0.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1061 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1062 (forward-comment (- (point)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1063 (if (bobp) 0)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1064
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1065 (defun smie-indent-close ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1066 ;; Align close paren with opening paren.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1067 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1068 ;; (forward-comment (point-max))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1069 (when (looking-at "\\s)")
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1070 (while (not (zerop (skip-syntax-forward ")")))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1071 (skip-chars-forward " \t"))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1072 (condition-case nil
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1073 (progn
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1074 (backward-sexp 1)
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1075 (smie-indent-virtual)) ;:not-hanging
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1076 (scan-error nil)))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1077
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1078 (defun smie-indent-keyword ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1079 ;; Align closing token with the corresponding opening one.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1080 ;; (e.g. "of" with "case", or "in" with "let").
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1081 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1082 (let* ((pos (point))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1083 (toklevels (smie-indent-forward-token))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1084 (token (pop toklevels)))
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1085 (if (null (car toklevels))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1086 (save-excursion
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1087 (goto-char pos)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1088 ;; Different cases:
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1089 ;; - smie-bolp: "indent according to others".
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1090 ;; - common hanging: "indent according to others".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1091 ;; - SML-let hanging: "indent like parent".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1092 ;; - if-after-else: "indent-like parent".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1093 ;; - middle-of-line: "trust current position".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1094 (cond
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1095 ((null (cdr toklevels)) nil) ;Not a keyword.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1096 ((smie-bolp)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1097 ;; For an open-paren-like thingy at BOL, always indent only
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1098 ;; based on other rules (typically smie-indent-after-keyword).
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1099 nil)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1100 (t
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1101 ;; We're only ever here for virtual-indent, which is why
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1102 ;; we can use (current-column) as answer for `point'.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1103 (let* ((offset (or (smie-indent--rule :before token)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1104 ;; By default use point unless we're hanging.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1105 (unless (smie-hanging-p) 'point))))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1106 (smie-indent--column offset)))))
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1107
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1108 ;; FIXME: This still looks too much like black magic!!
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1109 (let* ((parent (smie-backward-sexp 'halfsexp))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1110 (offset (save-excursion
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1111 (goto-char pos)
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1112 (or (smie-indent--rule :before token nil parent)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1113 'point))))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1114 ;; Different behaviors:
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1115 ;; - align with parent.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1116 ;; - parent + offset.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1117 ;; - after parent's column + offset (actually, after or before
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1118 ;; depending on where backward-sexp stopped).
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1119 ;; ? let it drop to some other indentation function (almost never).
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1120 ;; ? parent + offset + parent's own offset.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1121 ;; Different cases:
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1122 ;; - bump into a same-level operator.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1123 ;; - bump into a specific known parent.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1124 ;; - find a matching open-paren thingy.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1125 ;; - bump into some random parent.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1126 ;; ? borderline case (almost never).
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1127 ;; ? bump immediately into a parent.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1128 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1129 ((not (or (< (point) pos)
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1130 (and (cadr parent) (< (cadr parent) pos))))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1131 ;; If we didn't move at all, that means we didn't really skip
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1132 ;; what we wanted. Should almost never happen, other than
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1133 ;; maybe when an infix or close-paren is at the beginning
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1134 ;; of a buffer.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1135 nil)
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1136 ((eq (car parent) (car toklevels))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1137 ;; We bumped into a same-level operator. align with it.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1138 (if (and (smie-bolp) (/= (point) pos)
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1139 (save-excursion
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1140 (goto-char (goto-char (cadr parent)))
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1141 (not (smie-bolp)))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1142 ;; Check the offset of `token' rather then its parent
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1143 ;; because its parent may have used a special rule. E.g.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1144 ;; function foo;
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1145 ;; line2;
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1146 ;; line3;
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1147 ;; The ; on the first line had a special rule, but when
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1148 ;; indenting line3, we don't care about it and want to
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1149 ;; align with line2.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1150 (memq offset '(point nil)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1151 ;; If the parent is at EOL and its children are indented like
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1152 ;; itself, then we can just obey the indentation chosen for the
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1153 ;; child.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1154 ;; This is important for operators like ";" which
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1155 ;; are usually at EOL (and have an offset of 0): otherwise we'd
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1156 ;; always go back over all the statements, which is
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1157 ;; a performance problem and would also mean that fixindents
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1158 ;; in the middle of such a sequence would be ignored.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1159 ;;
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1160 ;; This is a delicate point!
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1161 ;; Even if the offset is not 0, we could follow the same logic
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1162 ;; and subtract the offset from the child's indentation.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1163 ;; But that would more often be a bad idea: OT1H we generally
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1164 ;; want to reuse the closest similar indentation point, so that
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1165 ;; the user's choice (or the fixindents) are obeyed. But OTOH
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1166 ;; we don't want this to affect "unrelated" parts of the code.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1167 ;; E.g. a fixindent in the body of a "begin..end" should not
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1168 ;; affect the indentation of the "end".
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1169 (current-column)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1170 (goto-char (cadr parent))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1171 ;; Don't use (smie-indent-virtual :not-hanging) here, because we
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1172 ;; want to jump back over a sequence of same-level ops such as
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1173 ;; a -> b -> c
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1174 ;; -> d
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1175 ;; So as to align with the earliest appropriate place.
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1176 (smie-indent-virtual)))
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1177 (t
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1178 (if (and (= (point) pos) (smie-bolp)
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1179 (or (eq offset 'point)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1180 (and (consp offset) (memq 'point offset))))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1181 ;; Since we started at BOL, we're not computing a virtual
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1182 ;; indentation, and we're still at the starting point, so
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1183 ;; we can't use `current-column' which would cause
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1184 ;; indentation to depend on itself.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1185 nil
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1186 (smie-indent--column offset 'parent parent
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1187 ;; If we're still at pos, indent-virtual
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1188 ;; will inf-loop.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1189 (unless (= (point) pos) 'virtual))))))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1190
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1191 (defun smie-indent-comment ()
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1192 "Compute indentation of a comment."
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1193 ;; Don't do it for virtual indentations. We should normally never be "in
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1194 ;; front of a comment" when doing virtual-indentation anyway. And if we are
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1195 ;; (as can happen in octave-mode), moving forward can lead to inf-loops.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1196 (and (smie-bolp)
110464
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1197 (let ((pos (point)))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1198 (save-excursion
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1199 (beginning-of-line)
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1200 (and (re-search-forward comment-start-skip (line-end-position) t)
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1201 (eq pos (or (match-end 1) (match-beginning 0))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1202 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1203 (forward-comment (point-max))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1204 (skip-chars-forward " \t\r\n")
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1205 (smie-indent-calculate))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1206
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1207 (defun smie-indent-comment-continue ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1208 ;; indentation of comment-continue lines.
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1209 (let ((continue (and comment-continue
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1210 (comment-string-strip comment-continue t t))))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1211 (and (< 0 (length continue))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1212 (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1213 (let ((ppss (syntax-ppss)))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1214 (save-excursion
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1215 (forward-line -1)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1216 (if (<= (point) (nth 8 ppss))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1217 (progn (goto-char (1+ (nth 8 ppss))) (current-column))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1218 (skip-chars-forward " \t")
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1219 (if (looking-at (regexp-quote continue))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1220 (current-column))))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1221
110464
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1222 (defun smie-indent-comment-close ()
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1223 (and (boundp 'comment-end-skip)
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1224 comment-end-skip
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1225 (not (looking-at " \t*$")) ;Not just a \n comment-closer.
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1226 (looking-at comment-end-skip)
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1227 (nth 4 (syntax-ppss))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1228 (save-excursion
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1229 (goto-char (nth 8 (syntax-ppss)))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1230 (current-column))))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1231
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1232 (defun smie-indent-comment-inside ()
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1233 (and (nth 4 (syntax-ppss))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1234 'noindent))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1235
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1236 (defun smie-indent-after-keyword ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1237 ;; Indentation right after a special keyword.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1238 (save-excursion
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1239 (let* ((pos (point))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1240 (toklevel (smie-indent-backward-token))
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1241 (tok (car toklevel)))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1242 (when toklevel
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1243 (let ((offset
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1244 (or (smie-indent--rule :after tok pos)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1245 ;; The default indentation after a keyword/operator is
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1246 ;; 0 for infix and t for prefix.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1247 (if (or (null (cadr toklevel))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1248 (rassoc tok smie-closer-alist))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1249 (smie-indent--offset 'basic) 0)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1250 (before (point)))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1251 (goto-char pos)
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1252 (smie-indent--column offset before))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1253
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1254 (defun smie-indent-exps ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1255 ;; Indentation of sequences of simple expressions without
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1256 ;; intervening keywords or operators. E.g. "a b c" or "g (balbla) f".
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1257 ;; Can be a list of expressions or a function call.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1258 ;; If it's a function call, the first element is special (it's the
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1259 ;; function). We distinguish function calls from mere lists of
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1260 ;; expressions based on whether the preceding token is listed in
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1261 ;; the `list-intro' entry of smie-indent-rules.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1262 ;;
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1263 ;; TODO: to indent Lisp code, we should add a way to specify
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1264 ;; particular indentation for particular args depending on the
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1265 ;; function (which would require always skipping back until the
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1266 ;; function).
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1267 ;; TODO: to indent C code, such as "if (...) {...}" we might need
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1268 ;; to add similar indentation hooks for particular positions, but
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1269 ;; based on the preceding token rather than based on the first exp.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1270 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1271 (let ((positions nil)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1272 arg)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1273 (while (and (null (car (smie-backward-sexp)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1274 (push (point) positions)
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1275 (not (smie-bolp))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1276 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1277 ;; Figure out if the atom we just skipped is an argument rather
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1278 ;; than a function.
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1279 (setq arg
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1280 (or (null (car (smie-backward-sexp)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1281 (funcall smie-rules-function :list-intro
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1282 (funcall smie-backward-token-function)))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1283 (cond
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1284 ((null positions)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1285 ;; We're the first expression of the list. In that case, the
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1286 ;; indentation should be (have been) determined by its context.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1287 nil)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1288 (arg
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1289 ;; There's a previous element, and it's not special (it's not
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1290 ;; the function), so let's just align with that one.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1291 (goto-char (car positions))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1292 (current-column))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1293 ((cdr positions)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1294 ;; We skipped some args plus the function and bumped into something.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1295 ;; Align with the first arg.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1296 (goto-char (cadr positions))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1297 (current-column))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1298 (positions
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1299 ;; We're the first arg.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1300 (goto-char (car positions))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1301 ;; FIXME: Use smie-indent--column.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1302 (+ (smie-indent--offset 'args)
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1303 ;; We used to use (smie-indent-virtual), but that
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1304 ;; doesn't seem right since it might then indent args less than
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1305 ;; the function itself.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1306 (current-column)))))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1307
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1308 (defvar smie-indent-functions
110464
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1309 '(smie-indent-fixindent smie-indent-bob smie-indent-close
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1310 smie-indent-comment smie-indent-comment-continue smie-indent-comment-close
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1311 smie-indent-comment-inside smie-indent-keyword smie-indent-after-keyword
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1312 smie-indent-exps)
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1313 "Functions to compute the indentation.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1314 Each function is called with no argument, shouldn't move point, and should
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1315 return either nil if it has no opinion, or an integer representing the column
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1316 to which that point should be aligned, if we were to reindent it.")
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1317
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1318 (defun smie-indent-calculate ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1319 "Compute the indentation to use for point."
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1320 (run-hook-with-args-until-success 'smie-indent-functions))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1321
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1322 (defun smie-indent-line ()
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1323 "Indent current line using the SMIE indentation engine."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1324 (interactive)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1325 (let* ((savep (point))
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1326 (indent (condition-case-no-debug nil
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1327 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1328 (forward-line 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1329 (skip-chars-forward " \t")
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1330 (if (>= (point) savep) (setq savep nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1331 (or (smie-indent-calculate) 0))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1332 (error 0))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1333 (if (not (numberp indent))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1334 ;; If something funny is used (e.g. `noindent'), return it.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1335 indent
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1336 (if (< indent 0) (setq indent 0)) ;Just in case.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1337 (if savep
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1338 (save-excursion (indent-line-to indent))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1339 (indent-line-to indent)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1340
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1341 (defun smie-setup (op-levels rules-function &rest keywords)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1342 "Setup SMIE navigation and indentation.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1343 OP-LEVELS is a grammar table generated by `smie-prec2-levels'.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1344 RULES-FUNCTION is a set of indentation rules for use on `smie-rules-function'.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1345 KEYWORDS are additional arguments, which can use the following keywords:
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1346 - :forward-token FUN
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1347 - :backward-token FUN"
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1348 (set (make-local-variable 'smie-rules-function) rules-function)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1349 (set (make-local-variable 'smie-op-levels) op-levels)
111232
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1350 (set (make-local-variable 'indent-line-function) 'smie-indent-line)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1351 (set (make-local-variable 'forward-sexp-function)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1352 'smie-forward-sexp-command)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1353 (while keywords
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1354 (let ((k (pop keywords))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1355 (v (pop keywords)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1356 (case k
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1357 (:forward-token
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1358 (set (make-local-variable 'smie-forward-token-function) v))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1359 (:backward-token
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1360 (set (make-local-variable 'smie-backward-token-function) v))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1361 (t (message "smie-setup: ignoring unknown keyword %s" k)))))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1362 (let ((ca (cdr (assq :smie-closer-alist op-levels))))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1363 (when ca
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1364 (set (make-local-variable 'smie-closer-alist) ca)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1365 ;; Only needed for interactive calls to blink-matching-open.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1366 (set (make-local-variable 'blink-matching-check-function)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1367 #'smie-blink-matching-check)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1368 (add-hook 'post-self-insert-hook
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1369 #'smie-blink-matching-open 'append 'local)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1370 (set (make-local-variable 'smie-blink-matching-triggers)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1371 (append smie-blink-matching-triggers
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1372 ;; Rather than wait for SPC to blink, try to blink as
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1373 ;; soon as we type the last char of a block ender.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1374 (let ((closers (sort (mapcar #'cdr smie-closer-alist)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1375 #'string-lessp))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1376 (triggers ())
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1377 closer)
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1378 (while (setq closer (pop closers))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1379 (unless (and closers
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1380 ;; FIXME: this eliminates prefixes of other
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1381 ;; closers, but we should probably elimnate
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1382 ;; prefixes of other keywords as well.
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1383 (string-prefix-p closer (car closers)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1384 (push (aref closer (1- (length closer))) triggers)))
a9904c1962db SMIE: change indent rules format, improve smie-setup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110802
diff changeset
1385 (delete-dups triggers)))))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1386
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1387
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1388 (provide 'smie)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1389 ;;; smie.el ends here