annotate lisp/emacs-lisp/smie.el @ 110161:eb977e012180

Provide blink-matching support to SMIE. * lisp/emacs-lisp/smie.el (smie-bnf-closer-alist): New function. (smie-blink-matching-triggers, smie-blink-matching-inners): New vars. (smie-blink-matching-check, smie-blink-matching-open): New functions.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Fri, 03 Sep 2010 13:18:45 +0200
parents 5cab4c4229ff
children 06323f4d421b
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))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
162 (assert (consp rhs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
163 (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
164 (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
165 (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
166 (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
167 ;; 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
168 ;; 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
169 ;; 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
170 ;; 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
171 ;; 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
172 ;; 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
173 ;; 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
174 ;; 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
175 (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
176 (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
177 (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
178 (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
179 (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
180 (pushnew (car shr) last-nts)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
181 (when (consp (cdr shr))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
182 (assert (not (member (cadr shr) nts)))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
183 (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
184 (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
185 (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
186 (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
187 (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
188 ;; 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
189 ;; 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
190 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
191 (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
192 (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
193 (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
194 (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
195 (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
196 (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
197 (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
198 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
199 (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
200 ;; 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
201 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
202 (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
203 (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
204 (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
205 (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
206 (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
207 (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
208 (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
209 (setq again t)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
210 (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
211 ;; 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
212 (dolist (rules bnf)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
213 (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
214 (while (cdr rhs)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
215 (cond
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
216 ((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
217 (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
218 (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
219 ((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
220 (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
221 (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
222 (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
223 (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
224 '= override)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
225 (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
226 (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
227 prec2))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
228
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
229 ;; (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
230 ;; "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
231 ;; 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
232 ;; 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
233 ;; 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
234 ;; (let* ((non-openers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
235 ;; (non-closers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
236 ;; ;; 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
237 ;; (openers (make-hash-table :test 'equal))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
238 ;; (closers '())
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
239 ;; (done nil))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
240 ;; ;; 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
241 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
242 ;; (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
243 ;; (push (cdr k) non-openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
244 ;; (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
245 ;; (push (car k) non-closers)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
246 ;; prec2)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
247 ;; ;; Then find the openers and closers.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
248 ;; (maphash (lambda (k _)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
249 ;; (unless (member (car k) non-openers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
250 ;; (puthash (car k) (list (car k)) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
251 ;; (unless (or (member (cdr k) non-closers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
252 ;; (member (cdr k) closers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
253 ;; (push (cdr k) closers)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
254 ;; prec2)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
255 ;; ;; Then collect the matching elements.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
256 ;; (while (not done)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
257 ;; (setq done t)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
258 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
259 ;; (when (eq v '=)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
260 ;; (let ((aopeners (gethash (car k) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
261 ;; (dopeners (gethash (cdr k) openers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
262 ;; (new nil))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
263 ;; (dolist (o aopeners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
264 ;; (unless (member o dopeners)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
265 ;; (setq new t)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
266 ;; (push o dopeners)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
267 ;; (when new
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
268 ;; (setq done nil)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
269 ;; (puthash (cdr k) dopeners openers)))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
270 ;; prec2))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
271 ;; ;; Finally, dump the resulting table.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
272 ;; (let ((alist '()))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
273 ;; (maphash (lambda (k v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
274 ;; (when (or include-inners (member k closers))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
275 ;; (dolist (opener v)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
276 ;; (unless (equal opener k)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
277 ;; (push (cons opener k) alist)))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
278 ;; openers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
279 ;; alist)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
280
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
281 (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
282 ;; 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
283 ;; 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
284 ;; is a problem for smie-close-block.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
285 ;; 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
286 ;; 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
287 ;; 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
288 ;; 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
289 "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
290 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
291 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
292 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
293 (let ((nts (mapcar #'car bnf)) ;non terminals.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
294 (alist '()))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
295 (dolist (nt bnf)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
296 (dolist (rhs (cdr nt))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
297 (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
298 (if no-inners
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
299 (let ((last (car (last rhs))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
300 (unless (member last nts)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
301 (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
302 ;; 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
303 ;; which is important for smie-close-block.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
304 (dolist (term (reverse (cdr rhs)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
305 (unless (member term nts)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
306 (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
307 (nreverse alist)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
308
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
309
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
310 (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
311 ;; 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
312 ;; 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
313 ;; - 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
314 ;; 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
315 ;; 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
316 ;; 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
317 ;; 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
318 ;; - 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
319 ;; 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
320 ;; 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
321 ;; 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
322 "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
323 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
324 `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
325 ;; 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
326 ;; 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
327 ;; 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
328 ;; 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
329 (let ((table ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
330 (csts ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
331 (eqs ())
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
332 tmp x y)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
333 ;; 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
334 ;; 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
335 ;; 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
336 (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
337 (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
338 (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
339 (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
340 (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
341 (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
342 (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
343 (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
344 (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
345 (ecase v
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
346 (= (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
347 (< (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
348 (> (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
349 prec2)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
350 ;; 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
351 (let ((eqs eqs))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
352 (while eqs
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
353 (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
354 (to (cdar eqs)))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
355 (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
356 (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
357 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
358 (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
359 (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
360 (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
361 ;; 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
362 ;; 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
363 (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
364 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
365 (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
366 (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
367 ;; 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
368 (let ((i 0))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
369 (while csts
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
370 (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
371 (progress nil))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
372 (dolist (cst csts)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
373 (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
374 (setq progress t)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
375 ;; 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
376 ;; 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
377 ;; 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
378 ;; constraint (neither equality nor inequality), so
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
379 ;; anything will do.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
380 ;; 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
381 ;; 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
382 ;; 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
383 ;; distinguish associative operators (which will have
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
384 ;; left = right).
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
385 (unless (caar cst)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
386 (setcar (car cst) i)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
387 (incf i))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
388 (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
389 (unless progress
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
390 (error "Can't resolve the precedence table to precedence levels")))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
391 (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
392 ;; 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
393 (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
394 (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
395 (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
396 ;; 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
397 ;; 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
398 (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
399 ;; 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
400 ;; 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
401 ;; 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
402 ;; 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
403 ;; 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
404 ;; 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
405 (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
406 (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
407 (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
408 table))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
409
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
410 ;;; 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
411
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
412 (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
413 "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
414 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
415 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
416 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
417 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
418 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
419 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
420 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
421
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
422 (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
423 "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
424 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
425 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
426 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
427 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
428
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
429 (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
430 "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
431 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
432 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
433
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
434 (defalias 'smie-op-left 'car)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
435 (defalias 'smie-op-right 'cadr)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
436
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
437 (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
438 (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
439 (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
440 (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
441 (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
442 (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
443 (point))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
444
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
445 (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
446 (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
447 (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
448 (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
449 (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
450 (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
451 (point))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
452
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
453 (defun smie-associative-p (toklevels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
454 ;; 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
455 ;; "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
456 ;; 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
457 ;; 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
458 ;; 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
459 ;; 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
460 ;; 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
461 ;; 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
462 ;; 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
463 (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
464
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
465 (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
466 "Skip over one sexp.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
467 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
468 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
469 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
470 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
471 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
472 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
473 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
474 Possible return values:
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
475 (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
476 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
477 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
478 (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
479 (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
480 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
481 (catch 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
482 (let ((levels ()))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
483 (while
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
484 (let* ((pos (point))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
485 (token (funcall next-token))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
486 (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
487 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
488 ((null toklevels)
108797
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
489 (when (zerop (length token))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
490 (condition-case err
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
491 (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
492 (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
493 (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
494 (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
495 (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
496 (+ (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
497 (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
498 -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
499 (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
500 ;; 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
501 (throw 'return (list t (point))))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
502 ((null (funcall op-back toklevels))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
503 ;; A token like a paren-close.
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
504 (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
505 (push toklevels levels))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
506 (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
507 (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
508 (funcall op-forw (car levels))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
509 (setq levels (cdr levels)))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
510 (cond
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
511 ((null levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
512 (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
513 (push toklevels levels)
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
514 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
515 (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
516 (goto-char pos)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
517 (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
518 (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
519 (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
520 (funcall op-forw (car levels))))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
521 (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
522 ;; 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
523 ;; operator. Is this the end?
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
524 (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
525 ;; 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
526 ;; 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
527 (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
528 (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
529 (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
530 ;; 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
531 ;; 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
532 ((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
533 ;; 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
534 (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
535 ;; 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
536 ;; 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
537 ;; (like the "in" in "let .. in .. end"), so keep looking.
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
538 ((not (smie-associative-p 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
539 (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
540 ;; 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
541 ;; - 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
542 ;; 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
543 ((and lastlevels
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 (smie-associative-p (car lastlevels)))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
545 (throw 'return
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
546 (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
547 (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
548 ;; - 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
549 ;; (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
550 ;; 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
551 (t (setq levels lastlevels))))))))
108649
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
552 levels)
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
553 (setq halfsexp nil)))))
c9e786f54683 Fix handling of non-associative equal levels.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108642
diff changeset
554
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
555 (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
556 "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
557 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
558 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
559 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
560 (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
561 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
562 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
563 (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
564 (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
565 nil: we skipped over an identifier, matched parentheses, ..."
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
566 (smie-next-sexp
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
567 (indirect-function smie-backward-token-function)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
568 (indirect-function 'backward-sexp)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
569 (indirect-function 'smie-op-left)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
570 (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
571 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
572
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
573 (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
574 "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
575 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
576 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
577 Possible return values:
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
578 (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
579 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
580 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
581 (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
582 (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
583 nil: we skipped over an identifier, matched parentheses, ..."
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
584 (smie-next-sexp
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
585 (indirect-function smie-forward-token-function)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
586 (indirect-function 'forward-sexp)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
587 (indirect-function 'smie-op-right)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
588 (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
589 halfsexp))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
590
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
591 ;;; 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
592
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
593 (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
594 "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
595 (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
596 (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
597
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
598 (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
599 "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
600 (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
601 (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
602 (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
603 (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
604 (setq n (- n (if forw 1 -1)))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
605 (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
606 (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
607 (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
608 (smie-backward-sexp 'halfsexp))))
109840
51f5fd9b5515 * smie.el (smie-forward-sexp-command): Fix typo.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109838
diff changeset
609 (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
610 (signal 'scan-error
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
611 (list "Containing expression ends prematurely"
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
612 (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
613 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
614
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
615 (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
616 "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
617
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
618 (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
619 "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
620 (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
621 (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
622 (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
623 (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
624 (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
625 (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
626 (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
627 (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
628 (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
629 (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
630 (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
631 (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
632 ;; 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
633 ;; 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
634 ;; 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
635 ;; 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
636 (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
637 ((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
638 (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
639 (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
640 ;; 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
641 ;; "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
642 ;; 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
643 ;; 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
644 (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
645 (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
646 (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
647 (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
648 (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
649 (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
650 (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
651 (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
652 (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
653 (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
654 ((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
655 ;; 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
656 (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
657 (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
658 (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
659 (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
660 (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
661 (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
662 (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
663
110067
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
664 (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
665 "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
666 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
667 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
668 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
669 (interactive "p")
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
670 (let ((start (point))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
671 (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
672 (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
673 (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
674 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
675 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
676 (while (/= arg 0)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
677 (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
678 (while
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
679 (let* ((pos (point))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
680 (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
681 (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
682 (cond
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
683 ((zerop (length token))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
684 (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
685 (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
686 ;; 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
687 ;; 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
688 (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
689 (forward-sexp inc)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
690 (/= (point) pos)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
691 ((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
692 ((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
693 (let ((end (point)))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
694 (goto-char start)
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
695 (signal 'scan-error
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
696 (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
697 pos end))))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
698 (t)))))))
5cab4c4229ff * lisp/emacs-lisp/smie.el (smie-down-list): New command.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110036
diff changeset
699
110161
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
700 (defvar smie-blink-matching-triggers '(?\s ?\n)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
701 "Chars which might trigger `blink-matching-open'.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
702 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
703 typically inserted right after an end token.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
704 I.e. a good choice can be:
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
705 (delete-dups
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
706 (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
707 smie-closer-alist))")
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
708
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
709 (defcustom smie-blink-matching-inners t
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
710 "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
711 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
712 :type 'boolean)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
713
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
714 (defun smie-blink-matching-check (start end)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
715 (save-excursion
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
716 (goto-char end)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
717 (let ((ender (funcall smie-backward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
718 (cond
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
719 ((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
720 ;; 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
721 (blink-matching-check-mismatch start end))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
722 ((not start) t)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
723 (t
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
724 (goto-char start)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
725 (let ((starter (funcall smie-forward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
726 (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
727
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
728 (defun smie-blink-matching-open ()
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
729 "Blink the matching opener when applicable.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
730 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
731 (when (and blink-matching-paren
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
732 smie-closer-alist ; Optimization.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
733 (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
734 (memq last-command-event smie-blink-matching-triggers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
735 (save-excursion
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
736 ;; FIXME: Here we assume that closers all end
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
737 ;; with a word-syntax char.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
738 (unless (eq ?\w (char-syntax last-command-event))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
739 (forward-char -1))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
740 (and (looking-at "\\>")
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
741 (not (nth 8 (syntax-ppss))))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
742 (save-excursion
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
743 (let ((pos (point))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
744 (token (funcall smie-backward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
745 (if (= 1 (length token))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
746 ;; The trigger char is itself a token but is not
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
747 ;; one of the closers (e.g. ?\; in Octave mode),
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
748 ;; so go back to the previous token
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
749 (setq token (save-excursion
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
750 (funcall smie-backward-token-function)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
751 (goto-char pos))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
752 ;; Here we assume that smie-backward-token-function
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
753 ;; returns a token that is a string and whose content
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
754 ;; match the buffer's representation of this token.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
755 (when (and (> (length token) 1) (stringp token)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
756 (memq (aref token (1- (length token)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
757 smie-blink-matching-triggers)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
758 (not (eq (aref token (1- (length token)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
759 last-command-event)))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
760 ;; Token ends with a trigger char, so don't blink for
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
761 ;; anything else than this trigger char, lest we'd blink
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
762 ;; both when inserting the trigger char and when inserting a
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
763 ;; subsequent SPC.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
764 (setq token nil))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
765 (when (and (rassoc token smie-closer-alist)
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
766 (or smie-blink-matching-inners
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
767 (null (nth 2 (assoc token smie-op-levels)))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
768 ;; The major mode might set blink-matching-check-function
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
769 ;; buffer-locally so that interactive calls to
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
770 ;; blink-matching-open work right, but let's not presume
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
771 ;; that's the case.
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
772 (let ((blink-matching-check-function #'smie-blink-matching-check))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
773 (blink-matching-open)))))))
eb977e012180 Provide blink-matching support to SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 110067
diff changeset
774
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
775 ;;; The indentation engine.
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
776
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
777 (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
778 "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
779 :type 'integer)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
780
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
781 (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
782 ;; 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
783 ;; structure Foo =
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
784 ;; Bar (toto)
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
785 ;; and
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
786 ;; structure Foo =
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
787 ;; struct ... end
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
788 ;; 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
789 ;; 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
790 "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
791 \((: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
792 \(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
793 \(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
794 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
795 \(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
796 \(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
797 \((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
798
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
799 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
800
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
801 \(: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
802 \(: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
803 \(: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
804 \(: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
805 \(: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
806 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
807
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
808 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
809
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
810 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
811 `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
812 `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
813 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
814 \(+ 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
815 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
816
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
817 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
818 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
819 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
820
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
821 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
822 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
823
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
824 (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
825 ;; 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
826 ;; 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
827 (and (save-excursion
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
828 (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
829 ;; 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
830 (forward-char 1))
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
831 (skip-chars-forward " \t")
d674108e8753 Provide hooks to use a different tokenizer in SMIE.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108766
diff changeset
832 (eolp))
108864
f241d9fe71fe * lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108797
diff changeset
833 (not (smie-bolp))))
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
834
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
835 (defun smie-bolp ()
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
836 (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
837
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
838 (defun smie-indent-offset (elem)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
839 (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
840 (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
841 smie-indent-basic))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
842
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
843 (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
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 (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
846 "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
847 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
848 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
849 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
850 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
851 (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
852 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
853 offset)
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
854 (while (consp rules)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
855 (let ((rule (pop rules)))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
856 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
857 ((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
858 ((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
859 ((eq (car rule) :hanging)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
860 (when (smie-indent-hanging-p)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
861 (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
862 ((eq (car rule) :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
863 (when (smie-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
864 (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
865 ((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
866 (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
867 (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
868 (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
869 (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
870 ((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
871 (unless prev
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
872 (save-excursion
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
873 (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
874 (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
875 (setq rules (cddr rule))))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
876 ((eq (car rule) :next)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
877 (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
878 (unless after
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
879 (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
880 (save-excursion
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
881 (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
882 (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
883 (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
884 (setq rules (cddr rule))))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
885 ((eq (car rule) :parent)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
886 (unless parent
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
887 (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
888 (if after (goto-char after))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
889 (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
890 (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
891 (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
892 (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
893 (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
894 (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
895 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
896 ;; 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
897 ;; 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
898 (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
899 (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
900 (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
901 offset))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
902
109838
64936c70841e Try and remove some of SMIE's black magic by generalizing some rules.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108923
diff changeset
903 (defun smie-indent-column (offset &optional base parent virtual-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
904 "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
905 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
906 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
907 (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
908 ((eq (car-safe 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
909 (apply '+ (mapcar (lambda (offset) (smie-indent-column offset nil 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
910 (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
911 ((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
912 (+ 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
913 (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
914 ((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
915 (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
916 (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
917 (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
918 (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
919 ;; 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
920 ;; 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
921 ;; 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
922 (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
923 ((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
924 ;; 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
925 ;; 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
926 ;; 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
927 ;; 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
928 ;; (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
929 ;; 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
930 ;; 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
931 ;; 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
932 ;; 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
933 ;; 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
934 ;; 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
935 (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
936 (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
937 ((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
938 (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
939 (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
940 (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
941 (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
942 ((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
943 ((and (symbolp offset) (boundp 'offset))
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
944 (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
945 (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
946
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
947 (defun smie-indent-forward-token ()
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
948 "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
949 (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
950 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
951 ((< 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
952 ((looking-at "\\s(")
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
953 (forward-char 1)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
954 (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
955
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
956 (defun smie-indent-backward-token ()
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
957 "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
958 (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
959 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
960 ((< 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
961 ;; 4 == Open paren syntax.
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
962 ((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
963 (forward-char -1)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
964 (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
965
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
966 (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
967 ;; 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
968 ;; 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
969 ;; 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
970 ;; 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
971 ;; 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
972 "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
973 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
974 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
975 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
976 ;; Trust pre-existing indentation on other lines.
108897
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
977 (if (smie-bolp) (current-column) (smie-indent-calculate)))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
978
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
979 (defun smie-indent-fixindent ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
980 ;; Obey the `fixindent' special comment.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
981 (and (smie-bolp)
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
982 (save-excursion
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
983 (comment-normalize-vars)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
984 (re-search-forward (concat comment-start-skip
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
985 "fixindent"
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
986 comment-end-skip)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
987 ;; 1+ to account for the \n comment termination.
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
988 (1+ (line-end-position)) t))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
989 (current-column)))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
990
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
991 (defun smie-indent-bob ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
992 ;; 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
993 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
994 (forward-comment (- (point)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
995 (if (bobp) 0)))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
996
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
997 (defun smie-indent-close ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
998 ;; 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
999 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1000 ;; (forward-comment (point-max))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1001 (when (looking-at "\\s)")
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1002 (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
1003 (skip-chars-forward " \t"))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1004 (condition-case nil
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1005 (progn
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1006 (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
1007 (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
1008 (scan-error nil)))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1009
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1010 (defun smie-indent-keyword ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1011 ;; 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
1012 ;; (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
1013 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1014 (let* ((pos (point))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1015 (toklevels (smie-indent-forward-token))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1016 (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
1017 (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
1018 (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
1019 (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
1020 ;; Different cases:
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1021 ;; - smie-bolp: "indent according to others".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1022 ;; - common hanging: "indent according to others".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1023 ;; - SML-let hanging: "indent like parent".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1024 ;; - if-after-else: "indent-like parent".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1025 ;; - middle-of-line: "trust current position".
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1026 (cond
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1027 ((null (cdr toklevels)) nil) ;Not a keyword.
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1028 ((smie-bolp)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1029 ;; 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
1030 ;; based on other rules (typically smie-indent-after-keyword).
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1031 nil)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1032 (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
1033 ;; 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
1034 ;; 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
1035 (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
1036 smie-indent-rules)
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1037 ;; 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
1038 `((: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
1039 ;; (after (prog1 (point) (goto-char pos)))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1040 (offset (smie-indent-offset-rule 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
1041 (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
1042
68586a267c40 * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Rename from
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108894
diff changeset
1043 ;; 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
1044 ;; 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
1045 ;; 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
1046 (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
1047 (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
1048 (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
1049 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
1050 (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
1051 ;; 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
1052 `((: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
1053 ;; (: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
1054 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
1055 (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
1056 (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
1057 (smie-indent-offset-rule tokinfo nil 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
1058 ;; 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
1059 ;; - 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
1060 ;; - 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
1061 ;; - 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
1062 ;; 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
1063 ;; ? 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
1064 ;; ? 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
1065 ;; 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
1066 ;; - 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
1067 ;; - 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
1068 ;; - 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
1069 ;; - 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
1070 ;; ? 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
1071 ;; ? bump immediately into a parent.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1072 (cond
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1073 ((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
1074 (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
1075 ;; 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
1076 ;; 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
1077 ;; 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
1078 ;; of a buffer.
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1079 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
1080 ((eq (car parent) (car toklevels))
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1081 ;; We bumped into a same-level operator. align with 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
1082 (if (and (smie-bolp) (/= (point) 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
1083 (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
1084 (goto-char (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
1085 (not (smie-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
1086 ;; 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
1087 ;; 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
1088 ;; 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
1089 ;; 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
1090 ;; 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
1091 ;; 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
1092 ;; 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
1093 ;; 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
1094 (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
1095 ;; 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
1096 ;; 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
1097 ;; 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
1098 ;; 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
1099 ;; 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
1100 ;; 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
1101 ;; 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
1102 ;; 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
1103 ;;
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 ;; 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
1105 ;; 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
1106 ;; 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
1107 ;; 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
1108 ;; 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
1109 ;; 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
1110 ;; 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
1111 ;; 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
1112 ;; 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
1113 (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
1114 (goto-char (cadr parent))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1115 ;; 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
1116 ;; 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
1117 ;; a -> b -> c
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1118 ;; -> d
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1119 ;; 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
1120 (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
1121 (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
1122 (if (and (= (point) pos) (smie-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
1123 (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
1124 (and (consp offset) (memq 'point offset))))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1125 ;; 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
1126 ;; 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
1127 ;; 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
1128 ;; 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
1129 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 (smie-indent-column offset 'parent 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
1131 ;; 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
1132 ;; 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
1133 (unless (= (point) pos) 'virtual))))))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1134
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1135 (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
1136 "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
1137 ;; 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
1138 ;; 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
1139 ;; (as can happen in octave-mode), moving forward can lead to inf-loops.
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 (and (smie-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
1141 (looking-at comment-start-skip)
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1142 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1143 (forward-comment (point-max))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1144 (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
1145 (smie-indent-calculate))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1146
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1147 (defun smie-indent-comment-continue ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1148 ;; 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
1149 (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
1150 (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
1151 (and (< 0 (length continue))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1152 (looking-at (regexp-quote continue)) (nth 4 (syntax-ppss))
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1153 (let ((ppss (syntax-ppss)))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1154 (save-excursion
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1155 (forward-line -1)
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1156 (if (<= (point) (nth 8 ppss))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1157 (progn (goto-char (1+ (nth 8 ppss))) (current-column))
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1158 (skip-chars-forward " \t")
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1159 (if (looking-at (regexp-quote continue))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1160 (current-column))))))))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1161
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1162 (defun smie-indent-after-keyword ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1163 ;; 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
1164 (save-excursion
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1165 (let* ((pos (point))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1166 (toklevel (smie-indent-backward-token))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1167 (tok (car toklevel))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1168 (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
1169 ;; 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
1170 (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
1171 (setq tokinfo (list (car toklevel))))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1172 ;; (if (and tokinfo (null toklevel))
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1173 ;; (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
1174 (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
1175 (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
1176 ;; 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
1177 ;; 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
1178 ;; 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
1179 ;; 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
1180 (setq tokinfo (list tok '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
1181 (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
1182 (let ((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
1183 (or (smie-indent-offset-rule tokinfo 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
1184 (smie-indent-offset 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
1185 (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
1186 (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
1187 (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
1188
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1189 (defun smie-indent-exps ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1190 ;; 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
1191 ;; 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
1192 ;; 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
1193 ;; 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
1194 ;; 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
1195 ;; 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
1196 ;; 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
1197 ;;
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1198 ;; 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
1199 ;; 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
1200 ;; 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
1201 ;; function).
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1202 ;; 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
1203 ;; 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
1204 ;; 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
1205 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1206 (let ((positions nil)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1207 arg)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1208 (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
1209 (push (point) positions)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1210 (not (smie-bolp))))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1211 (save-excursion
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1212 ;; 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
1213 ;; than a function.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1214 (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
1215 (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
1216 (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
1217 (cond
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1218 ((null positions)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1219 ;; 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
1220 ;; 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
1221 nil)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1222 (arg
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1223 ;; 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
1224 ;; 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
1225 (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
1226 (current-column))
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1227 ((cdr positions)
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1228 ;; 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
1229 ;; Align with the first arg.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1230 (goto-char (cadr positions))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1231 (current-column))
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1232 (positions
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1233 ;; We're the first arg.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1234 (goto-char (car positions))
110036
af3f1edc363f * lisp/emacs-lisp/smie.el (smie-indent-offset-rule): Let :parent take
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109841
diff changeset
1235 ;; FIXME: Use smie-indent-column.
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1236 (+ (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
1237 ;; 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
1238 ;; 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
1239 ;; the function itself.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1240 (current-column)))))))
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 (defvar smie-indent-functions
108894
ca3bfaa18e56 Make (after keyword) indent-rules more flexible.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108878
diff changeset
1243 '(smie-indent-fixindent smie-indent-bob smie-indent-close smie-indent-comment
109841
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1244 smie-indent-comment-continue smie-indent-keyword smie-indent-after-keyword
3a11454ef7ca Reindent smie.el
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 109840
diff changeset
1245 smie-indent-exps)
108865
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1246 "Functions to compute the indentation.
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1247 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
1248 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
1249 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
1250
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1251 (defun smie-indent-calculate ()
9d8fb76d6857 Split smie-indent-calculate into more manageable chunks.
Stefan Monnier <monnier@iro.umontreal.ca>
parents: 108864
diff changeset
1252 "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
1253 (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
1254
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1255 (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
1256 "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
1257 (interactive)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1258 (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
1259 (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
1260 (save-excursion
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1261 (forward-line 0)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1262 (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
1263 (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
1264 (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
1265 (error 0))))
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1266 (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
1267 ;; 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
1268 indent
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1269 (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
1270 (if savep
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1271 (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
1272 (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
1273
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
1274 (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
1275 "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
1276 (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
1277 (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
1278 (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
1279 ;; 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
1280 (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
1281
108632
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1282 (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
1283 (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
1284 (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
1285 (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
1286
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1287
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1288 (provide 'smie)
d38b0dd2bdbe Provide a simple generic indentation engine and use it for Prolog.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff changeset
1289 ;;; smie.el ends here