annotate lisp/emacs-lisp/smie.el @ 110682:ba6a1c230532

gnus-html.el (gnus-html-prefetch-images): Adjust regexp to avoid regexp backtrace overflows.
author Katsumi Yamaoka <yamaoka@jpl.org>
date Fri, 01 Oct 2010 13:33:03 +0000
parents 27917ce150c1
children e544f6cc2447
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
108878
c3cbf94d10f1 * emacs-lisp/smie.el (comment-continue): Declare for byte-compiler.
Juanma Barranquero <lekktu@gmail.com>
parents: 108865
diff changeset
73 (defvar comment-continue)
108923
5173ad363d4b * emacs-lisp/smie.el (comment-string-strip): Declare function.
Juanma Barranquero <lekktu@gmail.com>
parents: 108912
diff changeset
74 (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
75
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
76 ;;; 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
77
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
78 ;; 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
79 ;; - 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
80 ;; (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
81 ;; 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
82 ;; 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
83 ;; - 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
84 ;; 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
85 ;; have the form (ASSOCIATIVITY TERMINAL1 .. TERMINALn), where
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
86 ;; 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
87 ;; - 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
88 ;; 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
89 ;; nil) between each pair of tokens.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
90 ;; - 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
91 ;; 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
92 ;; 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
93 ;; 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
94 ;; 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
95 ;; 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
96 ;; the SMIE code.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
97
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
98 (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
99 (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
100 (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
101 (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
102 (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
103 (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
104 ;; 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
105 ;; 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
106 ;; 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
107 ;; 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
108 (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
109 (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
110 (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
111
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
112 (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
113 "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
114 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
115 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
116 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
117 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
118 (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
119 (dolist (prec precs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
120 (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
121 (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
122 '((left . >) (right . <) (assoc . =))))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
123 (when selfrule
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
124 (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
125 (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
126 (let ((op1 '<) (op2 '>))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
127 (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
128 (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
129 (setq op1 '> op2 '<)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
130 (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
131 (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
132 (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
133 prec2-table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
134
108766
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
135 (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
136 (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
137 (car tables)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
138 (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
139 (dolist (table tables)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
140 (maphash (lambda (k v)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
141 (smie-set-prec2tab prec2 (car k) (cdr k) v))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
142 table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
143 prec2)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
144
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
145 (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
146 (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
147 (first-ops-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
148 (last-ops-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
149 (first-nts-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
150 (last-nts-table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
151 (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
152 (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
153 (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
154 again)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
155 (dolist (rules bnf)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
156 (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
157 (last-ops ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
158 (first-ops ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
159 (last-nts ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
160 (first-nts ()))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
161 (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
162 (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
163 (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
164 (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
165 (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
166 (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
167 (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
168 ;; 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
169 ;; 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
170 ;; 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
171 ;; 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
172 ;; 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
173 ;; 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
174 ;; 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
175 ;; 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
176 (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
177 (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
178 (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
179 (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
180 (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
181 (pushnew (car shr) last-nts)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
182 (when (consp (cdr shr))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
183 (assert (not (member (cadr shr) nts)))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
184 (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
185 (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
186 (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
187 (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
188 (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
189 ;; 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
190 ;; 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
191 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
192 (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
193 (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
194 (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
195 (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
196 (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
197 (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
198 (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
199 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
200 (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
201 ;; 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
202 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
203 (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
204 (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
205 (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
206 (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
207 (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
208 (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
209 (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
210 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
211 (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
212 ;; 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
213 (dolist (rules bnf)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
214 (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
215 (while (cdr rhs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
216 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
217 ((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
218 (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
219 (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
220 ((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
221 (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
222 (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
223 (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
224 (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
225 '= override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
226 (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
227 (setq rhs (cdr rhs)))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
228 prec2))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
229
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
230 ;; (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
231 ;; "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
232 ;; 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
233 ;; 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
234 ;; 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
235 ;; (let* ((non-openers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
236 ;; (non-closers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
237 ;; ;; 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
238 ;; (openers (make-hash-table :test 'equal))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
239 ;; (closers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
240 ;; (done nil))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
241 ;; ;; 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
242 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
243 ;; (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
244 ;; (push (cdr k) non-openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
245 ;; (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
246 ;; (push (car k) non-closers)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
247 ;; prec2)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
248 ;; ;; Then find the openers and closers.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
249 ;; (maphash (lambda (k _)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
250 ;; (unless (member (car k) non-openers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
251 ;; (puthash (car k) (list (car k)) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
252 ;; (unless (or (member (cdr k) non-closers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
253 ;; (member (cdr k) closers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
254 ;; (push (cdr k) closers)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
255 ;; prec2)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
256 ;; ;; Then collect the matching elements.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
257 ;; (while (not done)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
258 ;; (setq done t)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
259 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
260 ;; (when (eq v '=)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
261 ;; (let ((aopeners (gethash (car k) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
262 ;; (dopeners (gethash (cdr k) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
263 ;; (new nil))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
264 ;; (dolist (o aopeners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
265 ;; (unless (member o dopeners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
266 ;; (setq new t)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
267 ;; (push o dopeners)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
268 ;; (when new
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
269 ;; (setq done nil)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
270 ;; (puthash (cdr k) dopeners openers)))))
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 ;; ;; Finally, dump the resulting table.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
273 ;; (let ((alist '()))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
274 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
275 ;; (when (or include-inners (member k closers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
276 ;; (dolist (opener v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
277 ;; (unless (equal opener k)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
278 ;; (push (cons opener k) alist)))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
279 ;; openers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
280 ;; alist)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
281
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
282 (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
283 ;; 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
284 ;; 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
285 ;; is a problem for smie-close-block.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
286 ;; 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
287 ;; 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
288 ;; 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
289 ;; 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
290 "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
291 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
292 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
293 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
294 (let ((nts (mapcar #'car bnf)) ;non terminals.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
295 (alist '()))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
296 (dolist (nt bnf)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
297 (dolist (rhs (cdr nt))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
298 (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
299 (if no-inners
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
300 (let ((last (car (last rhs))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
301 (unless (member last nts)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
302 (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
303 ;; 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
304 ;; which is important for smie-close-block.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
305 (dolist (term (reverse (cdr rhs)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
306 (unless (member term nts)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
307 (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
308 (nreverse alist)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
309
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
310
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
311 (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
312 "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
313 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
314 ;; 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
315 ;; 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
316 (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
317 (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
318 (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
319 (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
320 (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
321 (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
322 (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
323 (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
324 (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
325 paths))))))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
326 (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
327
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
328 (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
329 (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
330 (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
331 (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
332 (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
333 (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
334 (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
335 (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
336 (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
337 (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
338 res))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
339 cycle)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
340 (mapconcat
110464
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
341 (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
342 (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
343 " < ")))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
344
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
345 (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
346 ;; 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
347 ;; 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
348 ;; - matching sets of block openers&closers (which can otherwise become
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
349 ;; collapsed into a single equivalence class in smie-op-levels) for
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
350 ;; smie-close-block as well as to detect mismatches in 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
351 ;; or in blink-paren (as well as to do the blink-paren for 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
352 ;; keywords like the "in" of "let..in..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
353 ;; - 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
354 ;; 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
355 ;; 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
356 ;; 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
357 "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
358 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
359 `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
360 ;; 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
361 ;; 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
362 ;; 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
363 ;; 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
364 (let ((table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
365 (csts ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
366 (eqs ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
367 tmp x y)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
368 ;; 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
369 ;; 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
370 ;; 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
371 (maphash (lambda (k v)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
372 (if (setq tmp (assoc (car k) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
373 (setq x (cddr tmp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
374 (setq x (cons nil nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
375 (push (cons (car k) (cons nil x)) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
376 (if (setq tmp (assoc (cdr k) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
377 (setq y (cdr tmp))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
378 (setq y (cons nil (cons nil nil)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
379 (push (cons (cdr k) y) table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
380 (ecase v
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
381 (= (push (cons x y) eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
382 (< (push (cons x y) csts))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
383 (> (push (cons y x) csts))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
384 prec2)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
385 ;; 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
386 (let ((eqs eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
387 (while eqs
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
388 (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
389 (to (cdar eqs)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
390 (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
391 (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
392 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
393 (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
394 (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
395 (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
396 ;; 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
397 ;; 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
398 (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
399 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
400 (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
401 (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
402 ;; 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
403 (let ((i 0))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
404 (while csts
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
405 (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
406 (progress nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
407 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
408 (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
409 (setq progress t)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
410 ;; 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
411 ;; 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
412 ;; 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
413 ;; constraint (neither equality nor inequality), so
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
414 ;; anything will do.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
415 ;; 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
416 ;; 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
417 ;; 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
418 ;; distinguish associative operators (which will have
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
419 ;; left = right).
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
420 (unless (caar cst)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
421 (setcar (car cst) i)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
422 (incf i))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
423 (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
424 (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
425 (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
426 (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
427 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
428 (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
429 ;; 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
430 (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
431 (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
432 (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
433 ;; 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
434 ;; right side of the < constraints).
108766
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
435 (dolist (x table)
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
436 ;; When both sides are nil, it means this operator binds very
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
437 ;; very tight, but it's still just an operator, so we give it
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
438 ;; the highest precedence.
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
439 ;; OTOH if only one side is nil, it usually means it's like an
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
440 ;; open-paren, which is very important for indentation purposes,
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
441 ;; so we keep it nil, to make it easier to recognize.
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
442 (unless (or (nth 1 x) (nth 2 x))
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
443 (setf (nth 1 x) i)
2f547b05b620 * emacs-lisp/smie.el (smie-set-prec2tab): Check override before use.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108652
diff changeset
444 (setf (nth 2 x) i))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
445 table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
446
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
447 ;;; 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
448
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
449 (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
450 "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
451 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
452 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
453 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
454 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
455 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
456 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
457 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
458
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
459 (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
460 "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
461 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
462 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
463 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
464 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
465
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
466 (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
467 "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
468 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
469 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
470
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
471 (defalias 'smie-op-left 'car)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
472 (defalias 'smie-op-right 'cadr)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
473
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
474 (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
475 (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
476 (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
477 (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
478 (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
479 (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
480 (point))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
481
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
482 (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
483 (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
484 (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
485 (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
486 (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
487 (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
488 (point))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
489
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
490 (defun smie--associative-p (toklevels)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
491 ;; 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
492 ;; "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
493 ;; 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
494 ;; 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
495 ;; 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
496 ;; 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
497 ;; 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
498 ;; 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
499 ;; 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
500 (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
501
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
502 (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
503 "Skip over one sexp.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
504 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
505 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
506 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
507 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
508 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
509 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
510 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
511 Possible return values:
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
512 (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
513 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
514 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
515 (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
516 (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
517 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
518 (catch 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
519 (let ((levels ()))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
520 (while
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
521 (let* ((pos (point))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
522 (token (funcall next-token))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
523 (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
524 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
525 ((null toklevels)
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
526 (when (zerop (length token))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
527 (condition-case err
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
528 (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
529 (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
530 (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
531 (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
532 (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
533 (+ (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
534 (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
535 -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
536 (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
537 ;; 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
538 (throw 'return (list t (point))))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
539 ((null (funcall op-back toklevels))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
540 ;; A token like a paren-close.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
541 (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
542 (push toklevels levels))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
543 (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
544 (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
545 (funcall op-forw (car levels))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
546 (setq levels (cdr levels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
547 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
548 ((null levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
549 (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
550 (push toklevels levels)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
551 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
552 (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
553 (goto-char pos)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
554 (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
555 (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
556 (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
557 (funcall op-forw (car levels))))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
558 (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
559 ;; 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
560 ;; operator. Is this the end?
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
561 (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
562 ;; 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
563 ;; 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
564 (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
565 (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
566 (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
567 ;; 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
568 ;; 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
569 ((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
570 ;; 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
571 (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
572 ;; 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
573 ;; 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
574 ;; (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
575 ((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
576 (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
577 ;; 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
578 ;; - 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
579 ;; 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
580 ((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
581 (smie--associative-p (car lastlevels)))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
582 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
583 (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
584 (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
585 ;; - 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
586 ;; (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
587 ;; 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
588 (t (setq levels lastlevels))))))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
589 levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
590 (setq halfsexp nil)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
591
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
592 (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
593 "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
594 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
595 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
596 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
597 (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
598 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
599 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
600 (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
601 (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
602 nil: we skipped over an identifier, matched parentheses, ..."
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
603 (smie-next-sexp
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
604 (indirect-function smie-backward-token-function)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
605 (indirect-function 'backward-sexp)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
606 (indirect-function 'smie-op-left)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
607 (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
608 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
609
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
610 (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
611 "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
612 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
613 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
614 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
615 (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
616 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
617 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
618 (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
619 (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
620 nil: we skipped over an identifier, matched parentheses, ..."
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
621 (smie-next-sexp
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
622 (indirect-function smie-forward-token-function)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
623 (indirect-function 'forward-sexp)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
624 (indirect-function 'smie-op-right)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
625 (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
626 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
627
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
628 ;;; 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
629
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
630 (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
631 "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
632 (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
633 (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
634
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 (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
636 "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
637 (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
638 (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
639 (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
640 (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
641 (setq n (- n (if forw 1 -1)))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
642 (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
643 (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
644 (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
645 (smie-backward-sexp 'halfsexp))))
109840
51f5fd9b5515 * smie.el (smie-forward-sexp-command): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109838
diff changeset
646 (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
647 (signal 'scan-error
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
648 (list "Containing expression ends prematurely"
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
649 (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
650 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
651
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
652 (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
653 "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
654
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
655 (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
656 "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
657 (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
658 (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
659 (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
660 (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
661 (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
662 (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
663 (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
664 (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
665 (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
666 (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
667 (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
668 (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
669 ;; 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
670 ;; 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
671 ;; 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
672 ;; 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
673 (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
674 ((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
675 (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
676 (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
677 ;; 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
678 ;; "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
679 ;; 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
680 ;; 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
681 (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
682 (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
683 (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
684 (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
685 (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
686 (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
687 (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
688 (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
689 (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
690 (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
691 ((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
692 ;; 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
693 (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
694 (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
695 (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
696 (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
697 (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
698 (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
699 (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
700
110067
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
701 (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
702 "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
703 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
704 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
705 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
706 (interactive "p")
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
707 (let ((start (point))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
708 (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
709 (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
710 (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
711 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
712 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
713 (while (/= arg 0)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
714 (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
715 (while
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
716 (let* ((pos (point))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
717 (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
718 (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
719 (cond
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
720 ((zerop (length token))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
721 (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
722 (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
723 ;; 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
724 ;; 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
725 (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
726 (forward-sexp inc)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
727 (/= (point) pos)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
728 ((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
729 ((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
730 (let ((end (point)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
731 (goto-char start)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
732 (signal 'scan-error
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
733 (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
734 pos end))))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
735 (t)))))))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
736
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
737 (defvar smie-blink-matching-triggers '(?\s ?\n)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
738 "Chars which might trigger `blink-matching-open'.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
739 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
740 typically inserted right after an end token.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
741 I.e. a good choice can be:
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
742 (delete-dups
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
743 (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
744 smie-closer-alist))")
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
745
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
746 (defcustom smie-blink-matching-inners t
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
747 "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
748 If non-nil, it will blink not only for \"begin..end\" but also for \"if...else\"."
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
749 :type 'boolean)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
750
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
751 (defun smie-blink-matching-check (start end)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
752 (save-excursion
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
753 (goto-char end)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
754 (let ((ender (funcall smie-backward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
755 (cond
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
756 ((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
757 ;; 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
758 (blink-matching-check-mismatch start end))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
759 ((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
760 ((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
761 (t
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
762 (goto-char start)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
763 (let ((starter (funcall smie-forward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
764 (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
765
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
766 (defun smie-blink-matching-open ()
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
767 "Blink the matching opener when applicable.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
768 This uses SMIE's tables and is expected to be placed on `post-self-insert-hook'."
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
769 (when (and blink-matching-paren
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
770 smie-closer-alist ; Optimization.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
771 (eq (char-before) last-command-event) ; Sanity check.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
772 (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
773 (not (nth 8 (syntax-ppss))))
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
774 (save-excursion
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
775 (let ((pos (point))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
776 (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
777 (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
778 (= 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
779 (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
780 ;; 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
781 ;; 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
782 ;; 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
783 (setq pos (point))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
784 (setq token (save-excursion
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
785 (funcall smie-backward-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
786 (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
787 ;; 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
788 ;; 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
789 (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
790 (when (and (save-excursion
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
791 ;; Trigger can be SPC, or reindent.
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
792 (skip-chars-forward " \n\t")
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
793 (>= (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
794 ;; If token ends with a trigger char, so don't blink for
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
795 ;; 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
796 ;; 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
797 ;; 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
798 (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
799 (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
800 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
801 (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
802 (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
803 ;; 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
804 ;; 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
805 ;; 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
806 ;; 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
807 (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
808 (blink-matching-open))))))))
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
809
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
810 ;;; The indentation engine.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
811
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
812 (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
813 "Basic amount of indentation."
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
814 :type 'integer)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
815
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
816 (defvar smie-indent-rules 'unset
108864
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
817 ;; TODO: For SML, we need more rule formats, so as to handle
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
818 ;; structure Foo =
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
819 ;; Bar (toto)
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
820 ;; and
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
821 ;; structure Foo =
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
822 ;; struct ... end
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
823 ;; I.e. the indentation after "=" depends on the parent ("structure")
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
824 ;; as well as on the following token ("struct").
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
825 "Rules of the following form.
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
826 \((:before . TOK) . OFFSET-RULES) how to indent TOK itself.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
827 \(TOK . OFFSET-RULES) how to indent right after TOK.
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
828 \(list-intro . TOKENS) declare TOKENS as being followed by what may look like
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
829 a funcall but is just a sequence of expressions.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
830 \(t . OFFSET) basic indentation step.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
831 \(args . OFFSET) indentation of arguments.
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
832 \((T1 . T2) OFFSET) like ((:before . T2) (:parent T1 OFFSET)).
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
833
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
834 OFFSET-RULES is a list of elements which can each either be:
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
835
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
836 \(:hanging . OFFSET-RULES) if TOK is hanging, use OFFSET-RULES.
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
837 \(:parent PARENT . OFFSET-RULES) if TOK's parent is PARENT, use OFFSET-RULES.
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
838 \(:next TOKEN . OFFSET-RULES) if TOK is followed by TOKEN, use OFFSET-RULES.
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
839 \(:prev TOKEN . OFFSET-RULES) if TOK is preceded by TOKEN, 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
840 \(:bolp . OFFSET-RULES) If TOK is first on a line, use OFFSET-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
841 OFFSET the offset 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
842
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
843 PARENT can be either the name of the parent or a list of such names.
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
844
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
845 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
846 `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
847 `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
848 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
849 \(+ 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
850 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
851
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
852 The precise meaning of `point' depends on various details: it 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
853 either mean the position of the token we're indenting, or 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
854 position of its parent, or the position right after its parent.
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
855
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
856 A nil offset for indentation after an opening token defaults
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
857 to `smie-indent-basic'.")
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
858
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
859 (defun smie-indent--hanging-p ()
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
860 ;; A hanging keyword is one that's at the end of a line except it's not at
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
861 ;; the beginning of a line.
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
862 (and (save-excursion
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
863 (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
864 ;; 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
865 (forward-char 1))
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
866 (skip-chars-forward " \t")
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
867 (eolp))
110432
6b2714f6bd1f * emacs-lisp/smie.el (smie-indent--hanging-p): Use `smie-indent--bolp'.
Juanma Barranquero <lekktu@gmail.com>
parents: 110429
diff changeset
868 (not (smie-indent--bolp))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
869
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
870 (defun smie-indent--bolp ()
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
871 (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
872
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
873 (defun smie-indent--offset (elem)
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
874 (or (cdr (assq elem smie-indent-rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
875 (cdr (assq t smie-indent-rules))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
876 smie-indent-basic))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
877
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
878 (defvar smie-indent-debug-log)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
879
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
880 (defun smie-indent--offset-rule (tokinfo &optional after parent)
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
881 "Apply the OFFSET-RULES in TOKINFO.
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
882 Point is expected to be right in front of the token corresponding to TOKINFO.
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
883 If computing the indentation after the token, then AFTER is the position
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
884 after the token, otherwise it should be 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
885 PARENT if non-nil should be the parent info returned by `smie-backward-sexp'."
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
886 (let ((rules (cdr tokinfo))
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
887 next prev
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
888 offset)
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
889 (while (consp rules)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
890 (let ((rule (pop rules)))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
891 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
892 ((not (consp rule)) (setq offset rule))
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
893 ((eq (car rule) '+) (setq offset rule))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
894 ((eq (car rule) :hanging)
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
895 (when (smie-indent--hanging-p)
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
896 (setq rules (cdr rule))))
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
897 ((eq (car rule) :bolp)
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
898 (when (smie-indent--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
899 (setq rules (cdr 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
900 ((eq (car rule) :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
901 (unless after
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
902 (error "Can't use :eolp in :before indentation 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
903 (when (> after (line-end-position))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
904 (setq rules (cdr rule))))
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
905 ((eq (car rule) :prev)
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
906 (unless prev
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
907 (save-excursion
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
908 (setq prev (smie-indent-backward-token))))
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
909 (when (equal (car prev) (cadr rule))
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
910 (setq rules (cddr rule))))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
911 ((eq (car rule) :next)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
912 (unless next
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
913 (unless after
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
914 (error "Can't use :next in :before indentation rules"))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
915 (save-excursion
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
916 (goto-char after)
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
917 (setq next (smie-indent-forward-token))))
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
918 (when (equal (car next) (cadr rule))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
919 (setq rules (cddr rule))))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
920 ((eq (car rule) :parent)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
921 (unless parent
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
922 (save-excursion
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
923 (if after (goto-char after))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
924 (setq parent (smie-backward-sexp 'halfsexp))))
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
925 (when (if (listp (cadr rule))
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
926 (member (nth 2 parent) (cadr rule))
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
927 (equal (nth 2 parent) (cadr rule)))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
928 (setq rules (cddr rule))))
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
929 (t (error "Unknown rule %s for indentation of %s"
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
930 rule (car tokinfo))))))
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
931 ;; If `offset' is not set yet, use `rules' to handle the case where
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
932 ;; the tokinfo uses the old-style ((PARENT . TOK). 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
933 (unless offset (setq offset 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
934 (when (boundp 'smie-indent-debug-log)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
935 (push (list (point) offset tokinfo) smie-indent-debug-log))
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
936 offset))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
937
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
938 (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
939 "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
940 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
941 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
942 (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
943 ((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
944 (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
945 (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
946 ((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
947 (+ 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
948 (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
949 ((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
950 (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
951 (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
952 (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
953 (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
954 ;; 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
955 ;; 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
956 ;; 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
957 (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
958 ((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
959 ;; 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
960 ;; 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
961 ;; 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
962 ;; 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
963 ;; (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
964 ;; 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
965 ;; 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
966 ;; 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
967 ;; 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
968 ;; 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
969 ;; 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
970 (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
971 (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
972 ((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
973 (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
974 (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
975 (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
976 (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
977 ((eq offset nil) nil)
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
978 ((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
979 (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
980 (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
981
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
982 (defun smie-indent-forward-token ()
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
983 "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
984 (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
985 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
986 ((< 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
987 ((looking-at "\\s(")
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
988 (forward-char 1)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
989 (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
990
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
991 (defun smie-indent-backward-token ()
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
992 "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
993 (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
994 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
995 ((< 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
996 ;; 4 == Open paren syntax.
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
997 ((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
998 (forward-char -1)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
999 (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
1000
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1001 (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
1002 ;; 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
1003 ;; 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
1004 ;; 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
1005 ;; 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
1006 ;; 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
1007 "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
1008 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
1009 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
1010 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
1011 ;; Trust pre-existing indentation on other lines.
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 (if (smie-indent--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
1013
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1014 (defun smie-indent-fixindent ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1015 ;; Obey the `fixindent' special comment.
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1016 (and (smie-indent--bolp)
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1017 (save-excursion
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1018 (comment-normalize-vars)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1019 (re-search-forward (concat comment-start-skip
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1020 "fixindent"
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1021 comment-end-skip)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1022 ;; 1+ to account for the \n comment termination.
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1023 (1+ (line-end-position)) t))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1024 (current-column)))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1025
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1026 (defun smie-indent-bob ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1027 ;; 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
1028 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1029 (forward-comment (- (point)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1030 (if (bobp) 0)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1031
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1032 (defun smie-indent-close ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1033 ;; 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
1034 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1035 ;; (forward-comment (point-max))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1036 (when (looking-at "\\s)")
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1037 (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
1038 (skip-chars-forward " \t"))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1039 (condition-case nil
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1040 (progn
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1041 (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
1042 (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
1043 (scan-error nil)))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1044
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1045 (defun smie-indent-keyword ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1046 ;; 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
1047 ;; (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
1048 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1049 (let* ((pos (point))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1050 (toklevels (smie-indent-forward-token))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1051 (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
1052 (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
1053 (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
1054 (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
1055 ;; Different cases:
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1056 ;; - smie-indent--bolp: "indent according to others".
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1057 ;; - common hanging: "indent according to others".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1058 ;; - SML-let hanging: "indent like parent".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1059 ;; - if-after-else: "indent-like parent".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1060 ;; - middle-of-line: "trust current position".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1061 (cond
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1062 ((null (cdr toklevels)) nil) ;Not a keyword.
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1063 ((smie-indent--bolp)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1064 ;; 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
1065 ;; based on other rules (typically smie-indent-after-keyword).
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1066 nil)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1067 (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
1068 ;; 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
1069 ;; we can use (current-column) as answer for `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
1070 (let* ((tokinfo (or (assoc (cons :before token)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1071 smie-indent-rules)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1072 ;; By default use point unless we're hanging.
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
1073 `((:before . ,token) (:hanging nil) 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
1074 ;; (after (prog1 (point) (goto-char pos)))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1075 (offset (smie-indent--offset-rule tokinfo)))
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1076 (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
1077
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1078 ;; FIXME: This still looks too much like black magic!!
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1079 ;; FIXME: Rather than a bunch of rules like (PARENT . TOKEN), we
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1080 ;; want a single rule for TOKEN with different cases for each 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
1081 (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
1082 (tokinfo
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1083 (or (assoc (cons (caddr parent) token)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1084 smie-indent-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
1085 (assoc (cons :before token) smie-indent-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
1086 ;; Default 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
1087 `((:before . ,token)
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 ;; (:parent open 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
1089 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
1090 (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
1091 (goto-char pos)
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1092 (smie-indent--offset-rule tokinfo 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
1093 ;; 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
1094 ;; - 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
1095 ;; - 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
1096 ;; - 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
1097 ;; 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
1098 ;; ? 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
1099 ;; ? 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
1100 ;; 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
1101 ;; - 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
1102 ;; - 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
1103 ;; - 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
1104 ;; - 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
1105 ;; ? 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
1106 ;; ? bump immediately into a parent.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1107 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1108 ((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
1109 (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
1110 ;; 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
1111 ;; 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
1112 ;; 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
1113 ;; of a buffer.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1114 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
1115 ((eq (car parent) (car toklevels))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1116 ;; We bumped into a same-level operator. align with it.
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1117 (if (and (smie-indent--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
1118 (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
1119 (goto-char (goto-char (cadr parent)))
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1120 (not (smie-indent--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
1121 ;; 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
1122 ;; 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
1123 ;; 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
1124 ;; 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
1125 ;; 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
1126 ;; 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
1127 ;; 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
1128 ;; 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
1129 (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
1130 ;; 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
1131 ;; 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
1132 ;; 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
1133 ;; 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
1134 ;; 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
1135 ;; 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
1136 ;; 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
1137 ;; 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
1138 ;;
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 ;; 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
1140 ;; 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
1141 ;; 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
1142 ;; 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
1143 ;; 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
1144 ;; 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
1145 ;; 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
1146 ;; 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
1147 ;; 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
1148 (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
1149 (goto-char (cadr parent))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1150 ;; 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
1151 ;; 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
1152 ;; a -> b -> c
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1153 ;; -> d
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1154 ;; 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
1155 (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
1156 (tokinfo
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1157 (if (and (= (point) pos) (smie-indent--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
1158 (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
1159 (and (consp offset) (memq 'point offset))))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1160 ;; 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
1161 ;; 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
1162 ;; 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
1163 ;; 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
1164 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
1165 (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
1166 ;; 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
1167 ;; 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
1168 (unless (= (point) pos) 'virtual))))))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1169
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1170 (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
1171 "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
1172 ;; 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
1173 ;; 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
1174 ;; (as can happen in octave-mode), moving forward can lead to inf-loops.
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1175 (and (smie-indent--bolp)
110464
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1176 (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
1177 (save-excursion
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1178 (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
1179 (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
1180 (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
1181 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1182 (forward-comment (point-max))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1183 (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
1184 (smie-indent-calculate))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1185
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1186 (defun smie-indent-comment-continue ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1187 ;; 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
1188 (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
1189 (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
1190 (and (< 0 (length continue))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1191 (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1192 (let ((ppss (syntax-ppss)))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1193 (save-excursion
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1194 (forward-line -1)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1195 (if (<= (point) (nth 8 ppss))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1196 (progn (goto-char (1+ (nth 8 ppss))) (current-column))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1197 (skip-chars-forward " \t")
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1198 (if (looking-at (regexp-quote continue))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1199 (current-column))))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1200
110464
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1201 (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
1202 (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
1203 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
1204 (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
1205 (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
1206 (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
1207 (save-excursion
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1208 (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
1209 (current-column))))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1210
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1211 (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
1212 (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
1213 'noindent))
27917ce150c1 * lisp/emacs-lisp/smie.el (smie-debug--describe-cycle): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110432
diff changeset
1214
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1215 (defun smie-indent-after-keyword ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1216 ;; 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
1217 (save-excursion
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1218 (let* ((pos (point))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1219 (toklevel (smie-indent-backward-token))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1220 (tok (car toklevel))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1221 (tokinfo (assoc tok smie-indent-rules)))
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
1222 ;; Set some default indent rules.
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1223 (if (and toklevel (null (cadr toklevel)) (null tokinfo))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1224 (setq tokinfo (list (car toklevel))))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1225 ;; (if (and tokinfo (null toklevel))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1226 ;; (error "Token %S has indent rule but has no parsing info" tok))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1227 (when toklevel
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
1228 (unless tokinfo
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1229 ;; The default indentation after a keyword/operator is 0 for
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1230 ;; infix and t for prefix.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1231 ;; Using the BNF syntax, we could come up with better
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1232 ;; defaults, but we only have the precedence levels here.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1233 (setq tokinfo (list tok 'default-rule
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1234 (if (cadr toklevel) 0 (smie-indent--offset t)))))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1235 (let ((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
1236 (or (smie-indent--offset-rule tokinfo pos)
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1237 (smie-indent--offset 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
1238 (let ((before (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
1239 (goto-char pos)
110429
06323f4d421b * lisp/emacs-lisp/smie.el (smie-bnf-precedence-table): Improve error message.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110161
diff changeset
1240 (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
1241
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1242 (defun smie-indent-exps ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1243 ;; 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
1244 ;; 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
1245 ;; 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
1246 ;; 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
1247 ;; 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
1248 ;; 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
1249 ;; 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
1250 ;;
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1251 ;; 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
1252 ;; 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
1253 ;; 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
1254 ;; function).
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1255 ;; 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
1256 ;; 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
1257 ;; 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
1258 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1259 (let ((positions nil)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1260 arg)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1261 (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
1262 (push (point) 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
1263 (not (smie-indent--bolp))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1264 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1265 ;; 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
1266 ;; than a function.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1267 (setq arg (or (null (car (smie-backward-sexp)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1268 (member (funcall smie-backward-token-function)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1269 (cdr (assoc 'list-intro smie-indent-rules))))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1270 (cond
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1271 ((null positions)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1272 ;; 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
1273 ;; 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
1274 nil)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1275 (arg
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1276 ;; 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
1277 ;; 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
1278 (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
1279 (current-column))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1280 ((cdr positions)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1281 ;; 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
1282 ;; Align with the first arg.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1283 (goto-char (cadr positions))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1284 (current-column))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1285 (positions
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1286 ;; We're the first arg.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1287 (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
1288 ;; 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
1289 (+ (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
1290 ;; 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
1291 ;; 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
1292 ;; the function itself.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1293 (current-column)))))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1294
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1295 (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
1296 '(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
1297 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
1298 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
1299 smie-indent-exps)
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1300 "Functions to compute the indentation.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1301 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
1302 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
1303 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
1304
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1305 (defun smie-indent-calculate ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1306 "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
1307 (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
1308
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1309 (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
1310 "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
1311 (interactive)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1312 (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
1313 (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
1314 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1315 (forward-line 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1316 (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
1317 (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
1318 (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
1319 (error 0))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1320 (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
1321 ;; 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
1322 indent
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1323 (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
1324 (if savep
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1325 (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
1326 (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
1327
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
1328 (defun smie-indent-debug ()
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1329 "Show the rules used to compute indentation of current line."
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1330 (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
1331 (let ((smie-indent-debug-log '()))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1332 (smie-indent-calculate)
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1333 ;; FIXME: please improve!
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1334 (message "%S" smie-indent-debug-log)))
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
1335
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1336 (defun smie-setup (op-levels indent-rules)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1337 (set (make-local-variable 'smie-indent-rules) indent-rules)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1338 (set (make-local-variable 'smie-op-levels) op-levels)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1339 (set (make-local-variable 'indent-line-function) 'smie-indent-line))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1340
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1341
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1342 (provide 'smie)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1343 ;;; smie.el ends here