[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/proof-general 20028f7 2/4: New smie grammar + indentation
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/proof-general 20028f7 2/4: New smie grammar + indentation rules + tests. |
Date: |
Fri, 10 Sep 2021 12:57:48 -0400 (EDT) |
branch: elpa/proof-general
commit 20028f74c4197eea6cc22c0093444e188959046f
Author: Pierre Courtieu <Pierre.Courtieu@cnam.fr>
Commit: Pierre Courtieu <Matafou@users.noreply.github.com>
New smie grammar + indentation rules + tests.
Main design choice for this new version: the first word of a command
is now a token "Com start". Together with the "." token for ending a
command this makes the parsing much more "local".
Users may experience a few changes in the indentation. A few special
cases where the old indentation would reduce shifting to the right
have been removed.
Non regression testing have been added.
See comments in coq-smie.el at coq-smie-grammar for more details.
---
CHANGES | 10 +
ci/test-indent/.gitignore | 1 +
ci/test-indent/coq-test-indent.el | 96 +++++
ci/test-indent/coq-test-indent.sh | 37 ++
ci/test-indent/indent-commands-boxed.v | 268 ++++++++++++
ci/test-indent/indent-commands.v | 265 ++++++++++++
ci/test-indent/indent-inside-command-boxed.v | 104 +++++
ci/test-indent/indent-inside-command.v | 93 ++++
ci/test-indent/indent-tac-boxed.v | 164 +++++++
coq/ex/indent.v => ci/test-indent/indent-tac.v | 451 +++++++++++++-------
ci/test-indent/indent_equations.v | 79 ++++
ci/test-indent/indent_monadic.v | 44 ++
ci/test-indent/tests.sh | 8 +
coq/coq-indent.el | 2 +-
coq/coq-smie.el | 568 +++++++++++++------------
coq/coq-syntax.el | 2 +-
coq/ex/indent.v | 2 +-
17 files changed, 1771 insertions(+), 423 deletions(-)
diff --git a/CHANGES b/CHANGES
index 56232b3..56f3da1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -193,6 +193,16 @@ also https://wiki.ubuntu.com/Releases).
- 92: Compile before require from current directory failing
with 8.5
+*** indentation code refactored
+
+ A big refactoring of the code for indentation has been done. You
+ may experience a few changes in indentation results. Mostly small
+ shifts to the right.
+
+ Variable `coq-indent-box-style' only affects indentation after
+ quantifiers (used to affect script braces "{").
+
+
* Changes of Proof General 4.4 from Proof General 4.3
** ProofGeneral has moved to GitHub!
diff --git a/ci/test-indent/.gitignore b/ci/test-indent/.gitignore
new file mode 100644
index 0000000..8e2384a
--- /dev/null
+++ b/ci/test-indent/.gitignore
@@ -0,0 +1 @@
+indented_*
\ No newline at end of file
diff --git a/ci/test-indent/coq-test-indent.el
b/ci/test-indent/coq-test-indent.el
new file mode 100644
index 0000000..2320433
--- /dev/null
+++ b/ci/test-indent/coq-test-indent.el
@@ -0,0 +1,96 @@
+;;; Regression testing of indentation.
+
+;;; Initially the file is indented as it is supposed to be. Each line
+;;; is unindented, then indented. If the new indentation differ a
+;;; comment is added to signal it.
+
+;;; WARNING: there are relative path names, so this currently works
+;;; only frowhen the current directory is the one containin this file.
+
+(defun blank-line-p ()
+ (= (current-indentation)
+ (- (line-end-position) (line-beginning-position))))
+
+
+(defun line-fixindent ()
+ (save-excursion
+ (let ((end (line-end-position)))
+ (re-search-forward "fixindent" end t))))
+
+
+(defun test-indent-line (&optional nocomment)
+ (interactive)
+ (unless (or (blank-line-p) (line-fixindent))
+ (back-to-indentation)
+ (let ((init-col (current-column)))
+ ;; avoid moving comments
+ (unless (proof-inside-comment (point)) (delete-horizontal-space))
+ (indent-according-to-mode)
+ (let ((res (- (current-column) init-col)))
+ (unless (= 0 res)
+ (save-excursion
+ (end-of-line)
+ (unless nocomment
+ (insert (format " (*<=== %s%d INDENT CHANGED *)"
+ (if (< res 0) "" "+")
+ res))))
+ res)
+ 0))))
+
+
+(defun remove-previous-comment ()
+ (interactive)
+ (save-excursion
+ (end-of-line)
+ (let* ((com (re-search-backward " (\\*<===" (line-beginning-position) t))
+ (strt (and com (point)))
+ (end (and com (line-end-position))))
+ (when com (delete-region strt end)))))
+
+
+(defun test--indent-region (beg end boxed &optional nocomment)
+ (let ((line-move-visual nil)
+ ;; we store the last line number rather than the position
+ ;; since by inderting things we shift the end pos, but not the
+ ;; end line.
+ (last-line (line-number-at-pos end))
+ (stop nil))
+ (set (make-local-variable 'coq-indent-box-style) boxed)
+ (goto-char beg)
+ (while (and (<= (line-number-at-pos) last-line)
+ (not stop))
+ (remove-previous-comment)
+ (test-indent-line nocomment)
+ (setq stop (/= (forward-line) 0)))))
+
+(defun remove-comments-region (beg end)
+ (interactive "r")
+ (goto-char beg)
+ (let ((line-move-visual nil))
+ (while (< (point) end);; loops because end position changes.
+ (remove-previous-comment)
+ (forward-line))))
+
+
+(defun test-indent-region (beg end &optional boxed nocomment)
+ (interactive "r\nP")
+ (test--indent-region beg end boxed nocomment))
+
+
+(defun test-indent-region-boxed (beg end &optional nocomment)
+ (interactive "r")
+ (test--indent-region beg end t nocomment))
+
+
+(defun test-indent-buffer (&optional nocomment) (interactive)
+ (test--indent-region (point-min) (point-max) nil nocomment))
+
+(defun test-indent-buffer-boxed (&optional nocomment) (interactive)
+ (test--indent-region (point-min) (point-max) t nocomment))
+
+(defun launch-test (orig indented &optional boxed)
+ (load-file "../../generic/proof-site.el")
+ (find-file orig)
+ (write-file indented)
+ (if boxed (test-indent-buffer-boxed t) (test-indent-buffer t))
+ (write-file indented))
diff --git a/ci/test-indent/coq-test-indent.sh
b/ci/test-indent/coq-test-indent.sh
new file mode 100755
index 0000000..7204d00
--- /dev/null
+++ b/ci/test-indent/coq-test-indent.sh
@@ -0,0 +1,37 @@
+
+# This script should be launched from its own directory, so that file
+# coq-test-indent.el is accessible.
+
+GREEN='\033[1;32m'
+RED='\033[1;31m'
+MAGENTA='\033[1;35m'
+NC='\033[0m' # No Color
+
+TESTFILE=$1
+INDENTEDTESTFILE=indented_$1
+
+BOXED="nil"
+if [[ "$1" == *"boxed.v" ]];
+then
+ BOXED="t"
+fi
+
+echo "cp $TESTFILE $INDENTEDTESTFILE"
+cp $TESTFILE $INDENTEDTESTFILE
+
+emacs -q -batch --eval "(progn (load-file \"coq-test-indent.el\") (launch-test
\"$TESTFILE\" \"$INDENTEDTESTFILE\" $BOXED))"
+
+# echo "grep \"INDENT CHANGED\" $INDENTEDTESTFILE"
+# grep "INDENT CHANGED" $INDENTEDTESTFILE
+echo -n " diff -q $TESTFILE $INDENTEDTESTFILE..."
+diff -q $TESTFILE $INDENTEDTESTFILE > /dev/null
+if [[ $? == 1 ]] ;
+then echo " DIFFERENCES FOUND"
+ printf "${RED} TEST FAILURE ***${NC}\n"
+ echo " *** details can be seen with:"
+ echo " *** diff --side-by-side --suppress-common-lines $TESTFILE
$INDENTEDTESTFILE"
+ echo " *** or graphically: "
+ echo " *** meld $TESTFILE $INDENTEDTESTFILE"
+else echo "NO DIFFERENCE"
+ printf "${GREEN} TEST SUCCESS *** ${NC}\n"
+fi
diff --git a/ci/test-indent/indent-commands-boxed.v
b/ci/test-indent/indent-commands-boxed.v
new file mode 100644
index 0000000..f22bb50
--- /dev/null
+++ b/ci/test-indent/indent-commands-boxed.v
@@ -0,0 +1,268 @@
+
+Require Export Coq.Lists.List.
+
+Module Mod.
+
+ Module Foo.
+ Axiom X:Set.
+ Axiom Y:Set.
+ Axiom Z:Set.
+ End Foo.
+
+ Section Sec.
+ Axiom X:Set.
+ Axiom Y:Set.
+ Axiom Z:Set.
+ End Sec.
+
+ Definition a1 := 1.
+ Definition A2 := 1.
+ Definition arith1:=
+ 1.
+ Definition arith1
+ :=
+ 1.
+ Definition
+ arith1
+ :=
+ 1.
+
+ Let x := 1. Let y := 2.
+
+ Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope.
+
+
+ Inductive test : nat -> Prop :=
+ C1 : forall n, test n
+ | C2 : forall n, test n
+ | C3 : forall n, test n
+ | C4 : forall n, test n.
+
+ Inductive testbar' : nat -> Prop :=
+ | Cbar1 : forall n, test n
+ | Cbar2 : forall n, test n
+ | Cbar3 : forall n, test n
+ | Cbar4 : forall n, test n.
+
+ Inductive test2 : nat -> Prop
+ := | C21 : forall n, test2 n
+ | C22 : forall n, test2 n
+ | C23 : forall n, test2 n
+ | C24 : forall n, test2 n.
+
+ Inductive test' : nat -> Prop :=
+ C1' : forall n, test' n
+ | C2' : forall n, test' n
+ | C3' : forall n, test' n
+ | C4' : forall n, test' n
+ with
+ test2' : nat -> Prop :=
+ C21' : forall n, test2' n
+ | C22' : forall n, test2' n
+ | C23' : forall n, test2' n
+ | C24' : forall n, test2' n
+ with test3' : nat -> Prop :=
+ C21' : forall n, test2' n
+ | C22' : forall n, test2' n
+ | C23' : forall n, test2' n
+ | C24' : forall n, test2' n
+ with test4' : nat -> Prop :=
+ | C21' : forall n, test2' n
+ | C22' : forall n, test2' n
+ | C23' : forall n, test2' n
+ | C24' : forall n, test2' n.
+
+
+ Inductive test3
+ : nat -> Prop
+ := C31 : forall n, test3 n
+ | C32 : forall n, test3 n
+ | C33 : forall n, test3 n .
+
+ (* Goal parenthesizing. *)
+ Lemma L : True.
+ Proof.
+ idtac.
+ idtac... (* special case of command ender. *)
+ idtac.
+ Qed.
+
+ (* Goal starter *)
+ Definition Foo:True.
+ exact I.
+ Defined.
+
+ (* Bullets. *)
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac. idtac.
+ idtac.
+ {
+ idtac.
+ idtac.
+ }
+ idtac. {
+ idtac.
+ idtac. }
+ { idtac.
+ idtac.
+ }
+ {
+ idtac.
+ idtac.
+ }
+ { idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+
+ { idtac . {
+ idtac.
+ idtac.
+ }
+ }
+ idtac.
+ }
+ idtac. { idtac. {
+ idtac.
+ idtac.
+ }
+ }
+ idtac.
+
+ { idtac . {
+ idtac.
+ idtac.
+ }
+ }
+ {
+ idtac.
+ idtac.
+ idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ Qed.
+
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ { idtac.
+ idtac. }
+ {
+ idtac.
+ idtac.
+ }
+ { idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ { idtac. idtac. { idtac.
+ idtac. }
+ idtac.
+ }
+ { idtac. { idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ }
+ { idtac. { idtac.
+ {
+ idtac.
+ idtac.
+ }
+ idtac.
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ {
+ idtac.
+ - idtac.
+ idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ Qed.
+
+
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ -
+ idtac.
+ idtac.
+ - idtac.
+ idtac.
+ + idtac.
+ idtac.
+ + idtac.
+ idtac.
+ * idtac.
+ - idtac.
+ Qed.
+
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ -
+ idtac.
+ idtac.
+ idtac.
+ idtac.
+ - idtac.
+ { idtac.
+ - idtac.
+ idtac.
+ - idtac.
+ idtac.
+ }
+ - idtac. idtac. {
+ idtac.
+ - idtac.
+ idtac.
+ - idtac.
+ idtac.
+ }
+ idtac.
+ - idtac.
+ Qed.
+
+
+ (* goal selectors. *)
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ 2:idtac.
+ 3-6:idtac.
+
+ 2:{ idtac.
+ idtac. }
+ {
+ idtac.
+ idtac.
+ }
+ [foo]:{
+ idtac.
+ - idtac.
+ idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ Qed.
+
+
+
+End Mod.
diff --git a/ci/test-indent/indent-commands.v b/ci/test-indent/indent-commands.v
new file mode 100644
index 0000000..9d1c52c
--- /dev/null
+++ b/ci/test-indent/indent-commands.v
@@ -0,0 +1,265 @@
+
+Require Export Coq.Lists.List.
+
+Module Mod.
+
+ Module Foo.
+ Axiom X:Set.
+ Axiom Y:Set.
+ Axiom Z:Set.
+ End Foo.
+
+ Section Sec.
+ Axiom X:Set.
+ Axiom Y:Set.
+ Axiom Z:Set.
+ End Sec.
+
+ Definition a1 := 1.
+ Definition A2 := 1.
+ Definition arith1:=
+ 1.
+ Definition arith1
+ :=
+ 1.
+ Definition
+ arith1
+ :=
+ 1.
+
+ Let x := 1. Let y := 2.
+
+ Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope.
+
+
+ Inductive test : nat -> Prop :=
+ C1 : forall n, test n
+ | C2 : forall n, test n
+ | C3 : forall n, test n
+ | C4 : forall n, test n.
+
+ Inductive testbar' : nat -> Prop :=
+ | Cbar1 : forall n, test n
+ | Cbar2 : forall n, test n
+ | Cbar3 : forall n, test n
+ | Cbar4 : forall n, test n.
+
+ Inductive test2 : nat -> Prop
+ := | C21 : forall n, test2 n
+ | C22 : forall n, test2 n
+ | C23 : forall n, test2 n
+ | C24 : forall n, test2 n.
+
+ Inductive test' : nat -> Prop :=
+ C1' : forall n, test' n
+ | C2' : forall n, test' n
+ | C3' : forall n, test' n
+ | C4' : forall n, test' n
+ with
+ test2' : nat -> Prop :=
+ C21' : forall n, test2' n
+ | C22' : forall n, test2' n
+ | C23' : forall n, test2' n
+ | C24' : forall n, test2' n
+ with test3' : nat -> Prop :=
+ C21' : forall n, test2' n
+ | C22' : forall n, test2' n
+ | C23' : forall n, test2' n
+ | C24' : forall n, test2' n
+ with test4' : nat -> Prop :=
+ | C21' : forall n, test2' n
+ | C22' : forall n, test2' n
+ | C23' : forall n, test2' n
+ | C24' : forall n, test2' n.
+
+
+ Inductive test3
+ : nat -> Prop
+ := C31 : forall n, test3 n
+ | C32 : forall n, test3 n
+ | C33 : forall n, test3 n .
+
+ (* Goal parenthesizing. *)
+ Lemma L : True.
+ Proof.
+ idtac.
+ idtac... (* special case of command ender. *)
+ idtac.
+ Qed.
+
+ (* Goal starter *)
+ Definition Foo:True.
+ exact I.
+ Defined.
+
+ (* Bullets. *)
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac. idtac.
+ idtac.
+ {
+ idtac.
+ idtac.
+ }
+ idtac. {
+ idtac.
+ idtac. }
+ { idtac.
+ idtac.
+ }
+ {
+ idtac.
+ idtac.
+ }
+ { idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+
+ { idtac . {
+ idtac.
+ idtac.
+ }
+ }
+ idtac.
+ }
+ idtac. { idtac. {
+ idtac.
+ idtac.
+ }
+ }
+ idtac.
+
+ { idtac . {
+ idtac.
+ idtac.
+ }
+ }
+ {
+ idtac.
+ idtac.
+ idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ Qed.
+
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ { idtac.
+ idtac. }
+ {
+ idtac.
+ idtac.
+ }
+ { idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ { idtac. idtac. { idtac.
+ idtac. }
+ idtac.
+ }
+ { idtac. { idtac. {
+ idtac.
+ idtac.
+ }} }
+ { idtac. { idtac.
+ {
+ idtac.
+ idtac.
+ }
+ idtac.
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ {
+ idtac.
+ - idtac.
+ idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ Qed.
+
+
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ -
+ idtac.
+ idtac.
+ - idtac.
+ idtac.
+ + idtac.
+ idtac.
+ + idtac.
+ idtac.
+ * idtac.
+ - idtac.
+ Qed.
+
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ -
+ idtac.
+ idtac.
+ idtac.
+ idtac.
+ - idtac.
+ { idtac.
+ - idtac.
+ idtac.
+ - idtac.
+ idtac.
+ }
+ - idtac. idtac. {
+ idtac.
+ - idtac.
+ idtac.
+ - idtac.
+ idtac.
+ }
+ idtac.
+ - idtac.
+ Qed.
+
+
+ (* goal selectors. *)
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ 2:idtac.
+ 3-6:idtac.
+
+ 2:{ idtac.
+ idtac. }
+ {
+ idtac.
+ idtac.
+ }
+ [foo]:{
+ idtac.
+ - idtac.
+ idtac. {
+ idtac.
+ idtac.
+ }
+ idtac.
+ }
+ Qed.
+
+
+
+End Mod.
diff --git a/ci/test-indent/indent-inside-command-boxed.v
b/ci/test-indent/indent-inside-command-boxed.v
new file mode 100644
index 0000000..b5b0e93
--- /dev/null
+++ b/ci/test-indent/indent-inside-command-boxed.v
@@ -0,0 +1,104 @@
+
+Require Export
+ Coq.Lists.List.
+Require
+ Export
+ Arith.
+
+Module
+ Mod.
+
+ Module
+ Foo.
+ Axiom
+ X
+ :
+ Set.
+ Axiom Y
+ :
+ Set.
+ Axiom Z:
+ Set.
+ End
+ Foo.
+
+
+ Definition a1 :=
+ 1.
+ Definition A2
+ := 1.
+ Definition arith1
+ :=
+ 1.
+ Definition
+ arith1
+ :=
+ 1.
+
+ Let x := 1. Let y := 2.
+
+ Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope.
+
+
+ Inductive test
+ : nat
+ ->
+ Prop :=
+ C1 : forall n,
+ test n
+ | C2 : forall n,
+ test
+ n
+ | C3 :
+ forall
+ n, test n
+ | C4 : forall n, test n.
+
+
+ (* Goal parenthesizing. *)
+ Lemma L :
+ True.
+ Proof.
+ idtac.
+ idtac... (* special case of command ender. *)
+ idtac.
+ Qed.
+
+
+ Lemma L4 : forall x:nat,
+ Nat.iter x (A:=nat)
+ (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+ Lemma L3 : forall x:nat,
+ Nat.iter
+ x
+ (A:=nat)
+ (plus 2)
+ 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+ Lemma L1 : forall x:nat, Nat.iter x
+ (A:=nat)
+ (plus 2)
+ 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+ Lemma L2 : forall x:nat, Nat.iter
+ x
+ (A:=nat)
+ (plus 2)
+ 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+
+
+End Mod.
diff --git a/ci/test-indent/indent-inside-command.v
b/ci/test-indent/indent-inside-command.v
new file mode 100644
index 0000000..5ad50e6
--- /dev/null
+++ b/ci/test-indent/indent-inside-command.v
@@ -0,0 +1,93 @@
+
+Require Export
+ Coq.Lists.List.
+Require
+ Export
+ Arith.
+
+Module
+ Mod.
+
+ Module
+ Foo.
+ Axiom
+ X
+ :
+ Set.
+ Axiom Y
+ :
+ Set.
+ Axiom Z:
+ Set.
+ End
+ Foo.
+
+
+ Definition a1 :=
+ 1.
+ Definition A2
+ := 1.
+ Definition arith1
+ :=
+ 1.
+ Definition
+ arith1
+ :=
+ 1.
+
+ Let x := 1. Let y := 2.
+
+ Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope.
+
+
+ Inductive test
+ : nat
+ ->
+ Prop :=
+ C1 : forall n,
+ test n
+ | C2 : forall n,
+ test
+ n
+ | C3 :
+ forall
+ n, test n
+ | C4 : forall n, test n.
+
+ Lemma L4 : forall x:nat,
+ Nat.iter x (A:=nat)
+ (plus 2) 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+ Lemma L3 : forall x:nat,
+ Nat.iter
+ x
+ (A:=nat)
+ (plus 2)
+ 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+ Lemma L1 : forall x:nat, Nat.iter x
+ (A:=nat)
+ (plus 2)
+ 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+ Lemma L2 : forall x:nat, Nat.iter
+ x
+ (A:=nat)
+ (plus 2)
+ 0 >= x.
+ Proof.
+ idtac.
+ Qed.
+
+
+
+End Mod.
diff --git a/ci/test-indent/indent-tac-boxed.v
b/ci/test-indent/indent-tac-boxed.v
new file mode 100644
index 0000000..8c37d91
--- /dev/null
+++ b/ci/test-indent/indent-tac-boxed.v
@@ -0,0 +1,164 @@
+Module foo.
+ Lemma toto:nat.
+ Proof.
+ {{
+ exact 3.
+ }}
+ Qed.
+
+ Lemma foo: forall n: nat,
+ exists m:nat,
+ m = n + 1.
+ Proof.
+ intros n.
+ destruct n. {
+ exists 1.
+ reflexivity. }
+ exists (S (S n)).
+ simpl.
+ rewrite Nat.add_1_r.
+ reflexivity.
+ Qed.
+
+ Lemma L : forall x:nat,
+ Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof with auto with arith.
+ intros x.
+
+ induction x;simpl;intros...
+
+ induction x;
+ simpl ;
+ simpl ;
+ simpl ;
+ intros.
+ Qed.
+
+ Ltac foo:= intros x;
+ induction x;
+ simpl ;
+ intros.
+
+
+ Lemma L :
+ forall x:nat ,
+ Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof with auto with arith.
+ intros x;
+ induction x;
+ simpl ;
+ intros.
+ idtacjqslkjd;[
+ intros x ;
+ induction x ;
+ simpl ;
+ intros].
+ Qed.
+
+
+
+ Lemma L' : forall x:nat ,
+ Nat.iter x (A:=nat) (plus 2) 0 >= x
+ with L'' : forall x:nat ,
+ Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof with auto with arith.
+ - induction x;simpl;intros...
+ - induction x;simpl;intros...
+ Qed.
+
+End foo.
+
+Section SET.
+ Definition set (T : Type) := Ensemble T.
+
+ Require Import Program.
+
+
+ Definition eq_n : forall A n (v:Vector.t A n) n',
+ n=n' ->
+ Vector.t A n'.
+ Proof.
+ intros A n v n' H.
+ rewrite <- H.
+ assumption.
+ Defined.
+
+End SET.
+
+Module curlybracesatend.
+
+
+ Lemma foo2: forall n: nat,
+ exists m:nat,
+ m = n + 1.
+ Proof.
+ intros n.
+ destruct n. {
+ exists 1.
+ reflexivity. }
+
+ exists (S (S n)).
+ simpl.
+ rewrite Nat.add_1_r.
+ reflexivity.
+ Qed.
+
+ Lemma foo3: forall n: nat,
+ forall n: nat,
+ forall n: nat,
+ forall n: nat, forall n: nat,
+ exists m:nat,
+ m = n + 1 ->
+ m = n + 1 ->
+ m = n + 1
+ -> m = n + 1
+ -> m = n + 1 ->
+ m = n + 1.
+ Proof.
+ intros n. cut (n = n). {
+ destruct n. {
+ exists 1.
+ reflexivity. } {
+ exists (S (S n)).
+ simpl.
+ rewrite Nat.add_1_r.
+ reflexivity. }
+ }
+ idtac.
+ reflexivity.
+ Qed.
+
+ Lemma foooooooooooooooo3: forall n: nat,
+ forall n: nat, forall n: nat,
+ f x ->
+ g y ->
+ f x -> forall n: nat,
+ forall n: nat,
+ forall n: nat,
+ exists m:nat,
+ m = n + 1 ->
+ m = n + 1 ->
+ m = n + 1
+ -> m = n + 1
+ -> m = n + 1 ->
+ m = n + 1 ->
+ True.
+ Proof.
+ intros n. cut (n = n).
+ {
+ destruct n. {
+ exists 1.
+ reflexivity. } {
+ exists (S (S n)).
+ simpl.
+ rewrite Nat.add_1_r.
+ reflexivity.
+ }
+ }
+ idtac.
+ reflexivity.
+ Qed.
+
+
+End curlybracesatend.
+
diff --git a/coq/ex/indent.v b/ci/test-indent/indent-tac.v
similarity index 57%
copy from coq/ex/indent.v
copy to ci/test-indent/indent-tac.v
index 2a0d5e4..7e474d4 100644
--- a/coq/ex/indent.v
+++ b/ci/test-indent/indent-tac.v
@@ -1,123 +1,206 @@
-(* First check that ".." is not considered as a command end. *)
-Require Export Coq.Lists.List.
-Notation "[ ]" := nil : list_scope.
-Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope.
-Require Import Arith.
-Open Scope nat_scope.
-Definition arith1:=
- 1 + 3 *
- 4.
+Module foo.
+ Lemma toto:nat.
+ Proof.
+ {{
+ exact 3.
+ }}
+ Qed.
-Definition arith2 :=
- 1 * 3 +
- 4.
+ Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof with auto with arith.
+ intros x.
+
+ induction x;simpl;intros...
-Definition logic1 :=
- True \/ False /\
- False.
+ induction x;
+ simpl ;
+ simpl ;
+ simpl ;
+ intros.
-Definition logic2 :=
- True /\ False \/
- False.
+ Ltac foo:=
+ intros x;
+ induction x;
+ simpl ;
+ simpl ;
+ simpl ;
+ intros.
-Definition logic3 :=
- let x := True /\ False in True \/
- False .
-Definition logic4 :=
- (let x := True /\ False in True) \/
- False .
+
+ induction x
+ ;
+ simpl
+ ;
+ intros
+ ;
+ intros
+ ;
+ intros
+ .
+
+
+ idtac
+ ;
+ [
+ induction x
+ ;
+ simpl
+ ;
+ intros
+ ].
+
+ Ltac foo
+ :=
+ intros x
+ ;
+ induction x
+ ;
+ simpl
+ ;
+ intros
+ ;
+ intros
+ .
+
-Record a : Type := make_a {
- aa : nat
- }.
+ idtac
+ ;
+ [
+ induction x
+ ;
+ simpl ;
+ simpl
+ | intros
+ ].
+
+ Ltac foo :=
+ intros x
+ ;
+ induction x
+ ;
+ simpl
+ ;
+ intros
+ ;
+ intros
+ .
+
-Module foo.
- Inductive test : nat -> Prop :=
- C1 : forall n, test n
- | C2 : forall n, test n
- | C3 : forall n, test n
- | C4 : forall n, test n.
-
- Inductive testbar' : nat -> Prop :=
- | Cbar1 : forall n, test n
- | Cbar2 : forall n, test n
- | Cbar3 : forall n, test n
- | Cbar4 : forall n, test n.
-
- Inductive test2 : nat -> Prop
- := | C21 : forall n, test2 n
- | C22 : forall n, test2 n
- | C23 : forall n, test2 n
- | C24 : forall n, test2 n.
-
- Inductive test' : nat -> Prop :=
- C1' : forall n, test' n
- | C2' : forall n, test' n
- | C3' : forall n, test' n
- | C4' : forall n, test' n
- with
- test2' : nat -> Prop :=
- C21' : forall n, test2' n
- | C22' : forall n, test2' n
- | C23' : forall n, test2' n
- | C24' : forall n, test2' n
- with test3' : nat -> Prop :=
- C21' : forall n, test2' n
- | C22' : forall n, test2' n
- | C23' : forall n, test2' n
- | C24' : forall n, test2' n
- with test4' : nat -> Prop :=
- | C21' : forall n, test2' n
- | C22' : forall n, test2' n
- | C23' : forall n, test2' n
- | C24' : forall n, test2' n.
-
- Let x := 1. Let y := 2.
-
- Let y2 := (1, 2, 3,
- 4, 5).
-
- Inductive test3 (* fixindent *)
- : nat -> Prop
- := C31 : forall n, test3 n
- | C32 : forall n, test3 n.
+
+
+ induction x ;
+ simpl ;
+ intros.
+
+ induction x
+ ;
+ simpl ;
+ intros.
+
+ induction x ;
+ simpl
+ ;
+ simpl ;
+ intros.
+
+
+ intros x
+ ; induction x
+ ; simpl
+ ; intros.
+
+ idtac;(intros x
+ ; induction x
+ ; simpl
+ ; intros).
+
+
+ idtac;( induction x;
+ simpl ;
+ intros ).
+
+ idtac;[ intros x
+ ; induction x
+ ; simpl
+ ; intros].
+
+ idtac
+ ;
+ [
+ induction x;
+ simpl ;
+ intros
+ | simpl
+ ; intros ].
+
+
+ idtac;[ intros x
+ ; induction x
+ | simpl
+ ; intros].
+
+
+ idtac;[ intros x ;
+ induction x
+ | simpl ;
+ intros
+ ].
+
+
+ idtac foobar;[ induction x;
+ simpl ;
+ intros ].
+
+ Qed.
+
+ Ltac foo:=
+ intros x;
+ induction x;
+ simpl ;
+ intros.
-End foo.
-
-Lemma toto:nat.
-Proof.
- {{
- exact 3.
- }}
-Qed.
-
-Let xxx (* Precedence of "else" w.r.t "," and "->"! *)
- : if true then nat * nat else nat ->
- nat
- := (if true then 1 else 2,
- 3).
-
-Module Y.
+
+ Lemma L :
+ forall x:nat ,
+ Nat.iter x (A:=nat) (plus 2) 0 >= x.
+ Proof with auto with arith.
+ intros x;
+ induction x;
+ simpl ;
+ intros.
+ idtacjqslkjd;[
+ intros x ;
+ induction x ;
+ simpl ;
+ intros].
+ Qed.
Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
Proof with auto with arith.
- intros x.
- induction x;simpl;intros...
+ intros x;
+ [ induction x;
+ [
+ simpl;
+ intros...
+ ]
+ ]
Qed.
+
+
Lemma L2 : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x.
Proof with auto with arith.
idtac.
(* "as" tactical *)
induction x
as
- [ | x IHx].
+ [ | x IHx].
- cbn.
apply Nat.le_trans
with
- (n:=0) (* aligning the different closes of a "with". *)
- (m:=0)
- (p:=0).
+ (n:=0) (* aligning the different closes of a "with". *)
+ (m:=0)
+ (p:=0).
+ auto with arith.
+ auto with arith.
- simpl.
@@ -219,18 +302,23 @@ Module M1'.
intros.
Lemma l7: forall n:nat, n = n.
Proof.
- destruct n.
+ destruct n. intros.
{
auto.
}
{
- destruct n.
- {
- idtac;[
+ destruct n.
+ idtac a
+ ;
+ [
+ auto;
auto
+ |
+ auto;
+ auto.
].
- }
- auto.
+ }
+ auto.
}
Qed.
{destruct n.
@@ -254,8 +342,8 @@ Module M4'.
- auto.
- destruct n.
+ idtac;[
- auto
- ].
+ auto
+ ].
+ destruct n.
* auto.
* auto.
@@ -283,28 +371,30 @@ End M1''.
Record rec:Set := {
- fld1:nat;
- fld2:nat;
- fld3:bool
- }.
+ fld1:nat;
+ fld2:nat;
+ fld3:bool
+ }.
Class cla {X:Set}:Set := {
- cfld1:nat;
- cld2:nat;
- cld3:bool
- }.
+ cfld1:nat;
+ cld2:nat;
+ cld3:bool
+ }.
Module X.
- Lemma l
- :
+ Lemma l:
forall r:rec,
exists r':rec,
r'.(fld1) = r.(fld2)/\ r'.(fld2) = r.(fld1).
Proof.
- intros r.
- { exists
+ idtac.
+ idtac.
+ idtac.
+ intros r. {
+ exists
{|
fld1:=r.(fld2);
fld2:=r.(fld1);
@@ -314,9 +404,20 @@ Module X.
{auto. }
{auto. }
}
+ auto.
+ auto.
Qed.
-
+ (* Issue #574 *)
+ Goal let x := 1 in True.
+ Proof.
+ intro.
+ match goal with
+ | y := _ : unit |- _ => idtac "unit"
+ | y := _ : nat |- _ => idtac "nat"
+ end.
+ Qed.
+
Lemma l2 :
forall r:rec,
exists r':rec,
@@ -342,7 +443,7 @@ Module X.
match goal with
| ?g := _:rec |- ?a /\ ?b => split
- | _ => fail
+ | _ => fail
end.
Fail
@@ -359,6 +460,27 @@ Module X.
{ simpl. auto. }
{ simpl. auto. }}}
+
+ - split.
+ match
+ goal
+ with
+ X => foo
+ end.
+ - split.
+ match goal with
+ X |- _ => foo
+ | H: X := Y |- _ => foo
+ end.
+ - split.
+ match H with
+ ?a = ?b |- _ => foo
+ | ?a < ?b |- _ => foo
+ end.
+ - split.
+ let x := f y in
+ let foo := idtac x in
+ idtac foo.
Qed.
End X.
@@ -419,25 +541,25 @@ Section SET.
(Vector.t T n) -> Prop :=
match v1 with
Vector.nil _ =>
- fun v2 =>
- match v2 with
- Vector.nil _ => True
- | _ => False
- end
+ fun v2 =>
+ match v2 with
+ Vector.nil _ => True
+ | _ => False
+ end
| (Vector.cons _ x n' v1') =>
- fun v2 =>
- (* indentation of dependen "match" clause. *)
- match v2
- as
- X
- in
- Vector.t _ n''
- return
- (Vector.t T (pred n'') -> Prop) -> Prop
- with
- | Vector.nil _ => fun _ => False
- | (Vector.cons _ y n'' v2') => fun v2'' => (x y) /\ (v2'' v2')
- end (setVecProd T n' v1')
+ fun v2 =>
+ (* indentation of dependen "match" clause. *)
+ match v2
+ as
+ X
+ in
+ Vector.t _ n''
+ return
+ (Vector.t T (pred n'') -> Prop) -> Prop
+ with
+ | Vector.nil _ => fun _ => False
+ | (Vector.cons _ y n'' v2') => fun v2'' => (x y) /\ (v2'' v2')
+ end (setVecProd T n' v1')
end.
End SET.
@@ -459,8 +581,8 @@ Module curlybracesatend.
Qed.
Lemma foo2: forall n: nat,
- exists m:nat, (* This is strange compared to the same line in the
previous lemma *)
- m = n + 1.
+ exists m:nat,
+ m = n + 1.
Proof.
intros n.
destruct n. {
@@ -473,9 +595,19 @@ Module curlybracesatend.
reflexivity.
Qed.
- Lemma foo3: forall n: nat,
- exists m:nat, (* This is strange compared to the same line in the
previous lemma *)
- m = n + 1.
+ Lemma foo3:
+ forall n: nat,
+ forall n: nat,
+ forall n: nat,
+ forall n: nat,
+ forall n: nat,
+ exists m:nat,
+ m = n + 1 ->
+ m = n + 1 ->
+ m = n + 1
+ -> m = n + 1
+ -> m = n + 1 ->
+ m = n + 1.
Proof.
intros n. cut (n = n). {
destruct n. {
@@ -490,6 +622,37 @@ Module curlybracesatend.
reflexivity.
Qed.
+ Lemma foooooooooooooooo3: forall n: nat,
+ forall n: nat, forall n: nat,
+ f x ->
+ g y ->
+ f x -> forall n: nat,
+ forall n: nat,
+ forall n: nat,
+ exists m:nat,
+ m = n + 1 ->
+ m = n + 1 ->
+ m = n + 1
+ -> m = n + 1
+ -> m = n + 1 ->
+ m = n + 1 ->
+ True.
+ Proof.
+ intros n. cut (n = n).
+ {
+ destruct n. {
+ exists 1.
+ reflexivity. } {
+ exists (S (S n)).
+ simpl.
+ rewrite Nat.add_1_r.
+ reflexivity.
+ }
+ }
+ idtac.
+ reflexivity.
+ Qed.
+
End curlybracesatend.
diff --git a/ci/test-indent/indent_equations.v
b/ci/test-indent/indent_equations.v
new file mode 100644
index 0000000..3e200b5
--- /dev/null
+++ b/ci/test-indent/indent_equations.v
@@ -0,0 +1,79 @@
+(* Needs Equations plugin to work. *)
+
+From Coq Require Import Arith Omega Program.
+From Equations Require Import Equations.
+Require Import Bvector.
+
+
+Module Equations.
+ Equations neg (b : bool) : bool :=
+ neg true := false ;
+ neg false := true.
+
+ Lemma neg_inv : forall b, neg (neg b) = b.
+ Proof.
+ intros b.
+ funelim (neg b); now simp neg.
+ Defined.
+
+
+ Inductive list {A} : Type := nil : list | cons : A -> list -> list.
+
+ Arguments list : clear implicits.
+ Notation "x :: l" := (cons x l).
+
+ Equations tail {A} (l : list A) : list A :=
+ | nil := nil ;
+ | (cons a v) := v.
+
+ Equations tail' {A} (l : list A) : list A :=
+ | nil :=
+ nil ;
+ | (cons a v)
+ := v.
+
+ (* The cases inside { } are recognized as record fields, which from
+ an indentation perspective is OK *)
+ Equations filter {A} (l : list A) (p : A -> bool) : list A :=
+ filter nil p := nil;
+ filter (cons a l) p with p a => {
+ | true := a :: filter l p ;
+ | false := filter l p
+ }.
+
+ Equations filter' {A} (l : list A) (p : A -> bool) : list A :=
+ filter' (cons a l) p with p a =>
+ {
+ | true := a :: filter' l p ;
+ | false := filter' l p
+ };
+ filter' nil p := nil.
+
+ Equations filter' {A} (l : list A) (p : A -> bool) : list A :=
+ filter' (cons a l) p with p a =>
+ {
+ true := a :: filter' l p ;
+ false := filter' l p
+ };
+ filter' nil p := nil.
+
+ Equations filter'' {A} (l : list A) (p : A -> bool) : list A :=
+ filter'' (cons a l) p with p a =>
+ { | true := a :: filter'' l p ;
+ | false := filter'' l p };
+ filter'' nil p := nil.
+
+ Equations unzip {A B} (l : list (A * B)) : list A * list B :=
+ unzip nil := (nil, nil) ;
+ unzip (cons p l) with unzip l => {
+ unzip (cons (pair a b) l) (pair la lb) := (a :: la, b :: lb) }.
+
+
+ Equations equal (n m : nat) : { n = m } + { n <> m } :=
+ equal O O := left eq_refl ;
+ equal (S n) (S m) with equal n m :=
+ { equal (S n) (S ?(n)) (left eq_refl) := left eq_refl ;
+ equal (S n) (S m) (right p) := right _ } ;
+ equal x y := right _.
+
+End Equations.
diff --git a/ci/test-indent/indent_monadic.v b/ci/test-indent/indent_monadic.v
new file mode 100644
index 0000000..1cc6e8c
--- /dev/null
+++ b/ci/test-indent/indent_monadic.v
@@ -0,0 +1,44 @@
+(* Needs ext-lib library to compile. *)
+
+Require Import Coq.ZArith.ZArith_base Coq.Strings.Ascii Coq.Strings.String.
+Require Import ExtLib.Data.Monads.StateMonad ExtLib.Structures.Monads.
+Import StringSyntax.
+Open Scope string_scope.
+Section StateGame.
+
+ Check Ascii.Space.
+
+ Import MonadNotation.
+ Local Open Scope Z_scope.
+ Local Open Scope char_scope.
+ Local Open Scope monad_scope.
+
+ Definition GameValue : Type := Z.
+ Definition GameState : Type := (prod bool Z).
+
+ Variable m : Type -> Type.
+ Context {Monad_m: Monad m}.
+ Context {State_m: MonadState GameState m}.
+
+ Print Grammar constr.
+
+ Fixpoint playGame (s: string) m' {struct s}: m GameValue :=
+ match s with
+ | EmptyString =>
+ v <- (if true then m' else get) ;;
+ let '(on, score) := v in ret score
+ | String x xs =>
+ v <- get ;;
+ let '(on, score) := v in
+ match x, on with
+ | "a"%char, true => put (on, score + 1)
+ | "b"%char, true => put (on, score - 1)
+ | "c"%char, _ => put (negb on, score)
+ | _, _ => put (on, score)
+ end ;;
+ playGame xs m'
+ end.
+
+ Definition startState: GameState := (false, 0).
+
+End StateGame.
diff --git a/ci/test-indent/tests.sh b/ci/test-indent/tests.sh
new file mode 100755
index 0000000..9dcd5c0
--- /dev/null
+++ b/ci/test-indent/tests.sh
@@ -0,0 +1,8 @@
+
+
+
+
+for i in $(find . -name "*.v" -exec basename '{}' \; | grep -v "indented_") ;
do
+ echo -n "Testing $i..."
+ ./coq-test-indent.sh $i 2>&1 | tee .$i.log | grep "\*\*\*"
+done
diff --git a/coq/coq-indent.el b/coq/coq-indent.el
index 3a531e5..715c1e2 100644
--- a/coq/coq-indent.el
+++ b/coq/coq-indent.el
@@ -78,7 +78,7 @@ No context checking.")
(defconst coq-bullet-prefix-regexp-backward
(concat "\\(?:\\(?:" coq-simple-cmd-ender-prefix-regexp-backward
"\\)\\(?:\\.\\s-+\\)"
"\\(?:\\(?:" coq-goal-selector-regexp "\\)?"
- "{\\|}\\|-\\|+\\|\\*\\)*\\)"))
+ "{\\|}\\|-\\|+\\|\\*\\s-\\)*\\)"))
;; matches regular command end (. and ... followed by a space or "}" or buffer
end)
;; ". " and "... " are command endings, ".. " is not, same as in
diff --git a/coq/coq-smie.el b/coq/coq-smie.el
index 88e3375..b3357d0 100644
--- a/coq/coq-smie.el
+++ b/coq/coq-smie.el
@@ -162,7 +162,8 @@ attention to case differences."
(cmdstrt (save-excursion (coq-find-real-start)))
(enclosing (coq-is-inside-enclosing cmdstrt)))
(cond
- ((string-equal enclosing "{|") nil)
+ ((string-equal enclosing "{|") nil) ;; only records
+ ((and enclosing (string-match "{" enclosing)) nil) ;; more agressive:
record-like notations
(t (save-excursion
(goto-char cmdstrt)
(let ((case-fold-search nil))
@@ -486,13 +487,14 @@ The point should be at the beginning of the command name."
(t (save-excursion (coq-smie-backward-token))))) ;; recursive call
((or (string-match coq-bullet-regexp-nospace tok)
(member tok '("=>" ":=" "::=" "exists" "in" "as" "∀" "∃" "→" "∨" "∧"
";"
- "," ":" "eval")))
+ "," ":" "eval" "return")))
;; The important lexer for indentation's performance is the backward
;; lexer, so for the forward lexer we delegate to the backward one when
;; we can.
(save-excursion (coq-smie-backward-token)))
- ((member tok '("lazymatch" "lazy_match" "multimatch" "multi_match"))
"match")
+ ;; match needs to be catpured now to avoid being catpured by "Com start"
+ ((member tok '("match" "lazymatch" "lazy_match" "multimatch"
"multi_match")) "match")
;; detect "with signature", otherwies use coq-smie-backward-token
((equal tok "with")
@@ -547,6 +549,16 @@ The point should be at the beginning of the command name."
((coq-dot-friend-p tok) ".")
;; Try to rely on backward-token for non empty tokens: bugs (hangs)
;; ((not (zerop (length tok))) (save-excursion (coq-smie-backward-token)))
+
+ ;; Com start is a token for the first word of a command (provided it is a
word)
+ ((save-excursion
+ (and (smie-default-backward-token)
+ (coq-is-at-command-real-start)
+ (> (length tok) 0)
+ (or (string= "Lu" (get-char-code-property (aref tok 0)
'general-category))
+ (string= "Ll" (get-char-code-property (aref tok 0)
'general-category)))))
+ "Com start")
+
;; return it.
(tok)
)))
@@ -556,6 +568,11 @@ The point should be at the beginning of the command name."
;; This is very approximate and should be used with care
(let ((case-fold-search nil)) (looking-at coq-command-defn-regexp)))
+(defun coq-is-at-def-or-decl ()
+ ;; This is very approximate and should be used with care
+ (let ((case-fold-search nil))
+ (or (looking-at coq-command-defn-regexp) (looking-at
coq-command-decl-regexp))))
+
;; ":= with module" is really to declare some sub-information ":=
;; with" is for mutual definitions where both sides are of the same
@@ -588,13 +605,11 @@ The point should be at the beginning of the command name."
((equal corresp "where") ":= inductive") ;; inductive or fixpoint,
nevermind
((or (eq ?\{ (char-before))) ":= record")
((equal (point) cmdstrt)
- (if (or (looking-at "Equations") ;; note: "[[]" is the regexp for a
single "["
- (not (coq-is-at-def))
- )
- ":="
- ":= def")) ; := outside of any parenthesis
- (t ":=")
- ))) ; a parenthesis stopped the search
+ ;; we reached the command start: either we were in an Equation,
+ ;; or the ":=" was inpatter of an Ltac match (pattern the form
+ ;; "| H: T := t |- _"). Toherwise we are probably in a Definition.
+ (if (or (looking-at "Equations\\|match\\|let")) ":=" ":= def"))
+ (t ":="))))
(defun coq-smie-semicolon-deambiguate ()
@@ -631,6 +646,8 @@ The point should be at the beginning of the command name."
(cond
;; Distinguish between "," from quantification and other uses of
;; "," (tuples, tactic arguments)
+ ;; we cannot distinguish between tuples and tac args, because of:
+ ;; an term (f x , v) and a tactic expecting a tuple (tac x , v)
((equal tok ",")
(save-excursion
(let ((backtok (coq-smie-search-token-backward
@@ -702,7 +719,8 @@ The point should be at the beginning of the command name."
;(coq-find-real-start)
(coq-smie-module-deambiguate)))
- ((member tok '("lazy_?match" "multi_?match")) "match")
+ ;; match needs to be catpured now to avoid being catpured by "Com start"
+ ((member tok '("match" "lazy_match" "lazymatch" "multi_match"
"multimatch")) "match")
((equal tok "tryif") "if")
@@ -737,7 +755,7 @@ The point should be at the beginning of the command name."
;; (let ((nxttok (coq-smie-backward-token))) ;; recursive call
;; (coq-is-cmdend-token nxttok))))
;; (forward-char -1)
- ;; (if (looking-at "{") "{ subproof" "} subproof"))
+ ;; (if (looking-at "{") "{ subproof" "} subproof")))
((and (equal tok ":") (looking-back "\\<\\(constr\\|ltac2?\\|uconstr\\)"
(- (point) 7)))
@@ -817,6 +835,17 @@ The point should be at the beginning of the command name."
((member prev-interesting '("Morphism" "Relation")) "as morphism")
(t tok)))))
+ ((equal tok "return")
+ (save-excursion
+ (let ((prev-interesting
+ (coq-smie-search-token-backward
+ '("match" "lazymatch" "multimatch" "lazy_match" "multi_match"
"Morphism" "Relation" "." ". proofstart")
+ nil
+ '((("match" "lazy_match" "multi_match" "let") . "with") ("with"
. "signature")))))
+ (cond
+ ((member prev-interesting '("match" "lazymatch" "multimatch"
"lazy_match" "mult_match")) "return match")
+ (t tok)))))
+
((equal tok "by")
(let ((p (point)))
(if (and (equal (smie-default-backward-token) "proved")
@@ -883,11 +912,26 @@ The point should be at the beginning of the command name."
(let ((newtok (coq-smie-backward-token))) ; recursive call
(concat newtok "." tok)))
- ;; easier to return directly than calling coq-smie-backward-token
((member tok '("lazymatch" "lazy_match" "multimatch" "multi_match"))
"match")
-
((coq-dot-friend-p tok) ".")
+
+ ;; Default fallback for words at command start position: We use a
+ ;; generic "Com start" token, so that everything in the command
+ ;; is considered a child of this token. This makes indentation
+ ;; never look above the current command start (unless indenting
+ ;; the first line of the command. For now we only apply this to
+ ;; things starting with a letter, because the grammar makes use
+ ;; of non letters token and this would hide them. Other
+ ;; exception: Ltac things like "match" and "let' that need to be
+ ;; recognized as such by the grammar.
+ ((and (coq-is-at-command-real-start)
+ (> (length tok) 0)
+ (not (member tok '("match" "lazymatch" "let"))) ;; match are
already captured
+ (or (string= "Lu" (get-char-code-property (aref tok 0)
'general-category))
+ (string= "Ll" (get-char-code-property (aref tok 0)
'general-category))))
+ "Com start")
+
(tok))))
@@ -905,6 +949,9 @@ Lemma foo: forall n,
:type 'boolean
:group 'coq)
+(make-variable-buffer-local 'coq-indent-box-style)
+
+
(defun coq-indent-safep (indent)
(>= indent 0))
@@ -970,14 +1017,71 @@ Typical values are 2 or 4."
:group 'coq
:safe #'coq-indent-safep)
-;; - TODO: remove tokens "{ subproof" and "} subproof" but they are
-;; needed by the lexers at a lot of places.
-;; - FIXME: This does not know about Notations.
-;; - TODO Actually there are two grammars: one at script level, for
-;; indenting each command with respect to the previous commands, and
-;; a standard one inside commands. Separating the two grammars would
-;; greatly simplify this file. We should ask Stefan Monnier how to
-;; have two grammars with smie.
+
+
+;; smie grammar. General Remarks.
+
+;; 1. One oddity (a standard one IIUC) is that the "command end token"
+;; is considerd a separator. So any command is the child of the
+;; previous one. This may lead to strange things wrt to indentation if
+;; we don't take care. For instance the following script
+;:;
+;; Com1 .(1)
+;; Definition foo := bar .(2)
+;; ...
+;; could easily lead to the grammar tree
+;;
+;; __.(2)
+;; .(1) \
+;; / \ ...
+;; / \
+;; Com1 :=
+;; / \
+;; Def foo bar
+;;
+;; which means that "(1)" is the parent of ":=", which is the parent
+;; of "Def foo". This leads to hell. We need Def to be the parent. But
+;; there are hundreds of commands in coq. so we adopt the policy below.
+;;
+;; 2. the lexer tries to always treat the first word of a command as a
+;; dstinguished token "Com start". And a command is of the form ("Com
+;; start" exp) in smie grammar. This way the top-node of a command is
+;; always this token.
+;;
+;; This way the above script is parsed as:
+;;
+;; __.(2)
+;; .(1) \
+;; / \ ...
+;; / \
+;; Com1 Com start
+;; |
+;; :=
+;; / \
+;; foo bar
+;;
+;; which is much better. Indenting *inside* a command never looks
+;; above its own "Com start". This makes indentation rules much
+;; simpler, and hopefully speeds up things too since in practice it
+;; means indentation never inspect too far.
+;;
+;; 3. The only exception to "Com start" token at command start is
+;; structuring commands like "Proof" "Module", "{ subproof", bullets,
+;; goal selectors.
+;;
+;; 4. All non-word tokens (in particular bullets) are also not seen as
+;; "Com start". Thus user-defined commands (or tactics) starting with
+;; a non-word token will probably break indentation.
+;;
+;; 5. KNOWN BUGS: This does not know about Notations, but users can
+;; add new syntax for already defined tokens.
+;;
+;; 6. BUGS: probably dozens of.
+;;
+;; TODO: factorize infix operators into a series of "opxx" where "xx"
+;; is the coq grammar priority. users could then add there own infix
+;; operators in a consistent way.
+
(defconst coq-smie-grammar
(smie-prec2->grammar
(smie-bnf->prec2
@@ -994,7 +1098,6 @@ Typical values are 2 or 4."
("fun" exp "=> fun" exp) ("if" exp "then" exp "else" exp)
("quantif exists" exp ", quantif" exp)
("forall" exp ", quantif" exp)
-;;;
(exp "<- monadic" exp) (exp ";; monadic" exp)
("(" exp ")") ("{|" exps "|}") ("{" exps "}")
(exp "; tactic" exp) (exp "in tactic" exp) (exp "as" exp)
@@ -1008,11 +1111,14 @@ Typical values are 2 or 4."
(exp "+" exp) (exp "-" exp)
(exp "*" exp) (exp "&&" exp)
(exp "^" exp)
- (exp ": ltacconstr" exp)(exp ". selector" exp))
+ (exp ": ltacconstr" exp)(exp ". selector" exp)
+ ("Com start" exp)
+ )
+
;; Having "return" here rather than as a separate rule in `exp' causes
;; it to be indented at a different level than "with".
(matchexp (exp) (exp "as match" exp) (exp "in match" exp)
- (exp "return" exp) )
+ (exp "return match" exp) )
(exps (affectrec) (exps "; record" exps))
(affectrec (exp ":= record" exp))
(assigns (exp ":= let" exp) (exp "<- monadic" exp))
@@ -1065,29 +1171,33 @@ Typical values are 2 or 4."
(assoc "-- bullet") (assoc "++ bullet") (assoc "** bullet")
(assoc "--- bullet") (assoc "+++ bullet") (assoc "*** bullet")
(assoc "---- bullet") (assoc "++++ bullet") (assoc "**** bullet")
- (assoc ".")
+ (left ".")
(assoc "with inductive" "with fixpoint" "where"))
- '((assoc ":= equations") (assoc ":= def" ":= inductive")
- (assoc "|") (assoc "; equations") (assoc "=>") (assoc ":=")
- (assoc "xxx provedby")
- (assoc "as morphism") (assoc "with signature") (assoc "with match")
+ '((nonassoc "Com start") (assoc ":= equations")
+ (assoc ":= def" ":= inductive")
+ (left "|") (assoc "; equations") (assoc "=>") (assoc ":=")
+ (assoc "as morphism") (assoc "xxx provedby")
+ (assoc "with signature") (assoc "with match")
(assoc "in let" "in monadic")
- (assoc "in eval") (assoc "=> fun") (assoc ", quantif") (assoc "then")
+ (assoc "in eval") (left "=> fun") (left ", quantif") (assoc "then")
(assoc "|| tactic") ;; FIXME: detecting "+ tactic" and "|| tactic" seems
impossible
- (assoc "; tactic") (assoc "in tactic") (assoc "as" "by") (assoc "with")
- (assoc "|-") (assoc ":" ":<") (assoc ",")
+ (left "; tactic") (assoc "in tactic") (assoc "as" "by") (assoc "with")
+ (assoc "|-") (assoc ":" ":<") (left ",")
(assoc "else")
(assoc "->") (assoc "<->")
- (assoc "\\/") (assoc "&") (assoc "/\\")
- (assoc "==") (assoc "=") (assoc "<" ">" "<=" ">=" "<>")
+ (left "\\/") (left "&" "/\\")
+ ;; FTR: left (instead of assoc) for "<" makes the hoare triple notation
+ ;; <{ .. }>\n exp \n<{ ... }> indent the two assertions at the same
column.
+ (assoc "==") (assoc "=") (left "<" ">" "<=" ">=" "<>")
(assoc "=?") (assoc "<=?") (assoc "<?")
(assoc ";; monadic") (assoc "<- monadic")
(assoc "^")
(assoc "||") ;; FIXME: detecting "+ tactic" and "|| tactic" seems
impossible
- (assoc "+") (assoc "-") (assoc "*")(assoc "&&")
+ ;; this make indentation as expected.
+ (left "+" "-") (left "*") (left "&&")
(assoc ": ltacconstr") (assoc ". selector"))
- '((assoc ":" ":<") (assoc "<"))
- '((assoc ". modulestart" "." ". proofstart") (assoc "Module def")
+ '((assoc ":" ":<") (left "<"))
+ '((assoc "Module def")
(assoc "with module" "module nodecl") (assoc ":= module")
(assoc ":= with module") (assoc ":" ":<"))
'((assoc ":= def") (assoc "; record") (assoc ":= record"))))
@@ -1143,17 +1253,38 @@ Typical values are 2 or 4."
"Return non-nil if PARENT-POS is on same line as CHILD-POS."
(= (line-number-at-pos parent-pos) (line-number-at-pos child-pos)))
-(defcustom coq-indent-basic nil
+(defcustom coq-indent-basic 2
"Basic indentation step.
If nil, default to `proof-indent' if it exists or to `smie-indent-basic'."
:group 'coq-mode
:type '(choice (const :tag "Fallback on global settings" nil)
integer))
-
-;; Debugging smie parent token, needs the highlight library
-;;and something like this in .emacs:
-;; (require 'highlight)
+;; otherwise there are some glitches
+(setq smie-indent-basic coq-indent-basic)
+
+;;;;;;;;;; DEBUG CODE ;;;;;;
+;; smie-config-show-indent is sufficient most of the time.
+
+(defun coq-debug-smie--parent (point parent &optional num)
+ ;;refresh highlighting? Not a good idea since this is called several times.
+ ;;(hlt-unhighlight-region)
+ (let* ((beg (if (listp (car parent)) (caar parent) (car parent)))
+ (end (cadr parent))
+ (regi (list (list beg end)))
+ (tok (caddr parent))
+ (face (cond
+ ((equal num 1) 'hlt-regexp-level-1)
+ ((equal num 2) 'hlt-regexp-level-2)
+ (t 'hlt-regexp-level-1))))
+ ;; uncomment to see visually the region
+ ;;(and parent (hlt-highlight-regions regi face))
+ ;;(when end (hlt-highlight-regions (list (list end (+ end 1)))
'hlt-regexp-level-1))
+ ;; and the point considered
+ (hlt-highlight-regions (list (list point (+ point 1))) 'holiday)))
+
+;; Debugging smie rules calls, needs the highlight library and
+;; something like this in .emacs: (require 'highlight)
;; (custom-set-faces '(highlight ((((type x) (class color) (background light))
(:background "Wheat")))))
(defun coq-show-smie--parent (parent token parent-token &optional num msg)
(ignore-errors
@@ -1167,248 +1298,133 @@ If nil, default to `proof-indent' if it exists or to
`smie-indent-basic'."
((equal num 2) 'hlt-regexp-level-2)
(t 'hlt-regexp-level-1))))
(and parent (hlt-highlight-regions regi face)))))
+;;;;;;;;;; END DEBUG CODE ;;;;;;;;;;;;
+
+(defun coq-indent-categorize-token-after (tk)
+ "Factorize tokens behaving the same \"smie-rules\"-wise (kind:after)."
+ (cond
+ ((coq-is-bullet-token tk) "after bullet")
+ ((member tk '("with" ":" "by" "in tactic" "as" ",")) "tactic infix")
+ ((member tk '("<:" "<+" "with module")) "modulespec infix") ;; ":=
inductive" ":= module" and other ":= xxx"
+ ((string-prefix-p ":= " tk) "after :=")
+ ((member tk '(". proofstart" ". modulestart")) "dot script parent open")
+ ;; by default we pass the token name, but maybe it would be safer
+ ;; to simply fail, so that we detect missing tokens in this function?
+ (t tk)))
+
+(defun coq-indent-categorize-token-before (tk)
+ "Factorize tokens behaving the same \"smie-rules\"-wise (kind:after)."
+ (cond
+ ((member tk '(". proofstart" ". modulestart")) "dot script parent open")
+ ((member tk '(":" "by" "in tactic" "as" "with" ",")) "tactic infix")
+ ((string-prefix-p ":= " tk) "before :=")
+
+ ;; by default we pass the token name, but maybe it would be safer
+ ;; to simply fail, so that we detect missing tokens in this function?
+ (t tk)))
+
+
+;; ";" is a usual operator, with no indentation
+;; it would be like this;
+;; foo.
+;; foo ;
+;; bar ;
+;; bar.
+;; foo.
+;; which is confusing. So we indent the first ";" of a sequence
+;; if not already inside an ltacdef of parenthesized tactic:
+;; foo ;
+;; tac ; <--- indented
+;; tac ; <--- no indent
+;; [ tac2 ;
+;; tac1 ; <-- no indentation here
+;; now ( tac3 ; <- neither here
+;; tac5) ;
+;; ]
+(defun coq-smie-ltac-semicol-indent-first (parent-semicol)
+ (and coq-indent-semicolon-tactical (not parent-semicol)
+ (not (coq-smie-is-ltacdef))
+ (not (coq-smie-is-inside-parenthesized-tactic))))
+
+
+;; this should be called if we already know that parent is a quantif.
+(defun coq--prev-quantif-at-indent-p ()
+ (save-excursion
+ (coq-smie-search-token-backward '("forall" "quantif exists"))
+ (equal (current-column) (current-indentation))))
-
+;; Reminder: (smie-rule-separator kind) only works for *parenthesized*
enumerations.
+;; and ":= inductive" is not considered a parenthesis so "|" needs special hack
+;; below. "," for tuples and for tac args cannot be distinguished, so it
cannot be
+;; treated like this either.
(defun coq-smie-rules (kind token)
"Indentation rules for Coq. See `smie-rules-function'.
KIND is the situation and TOKEN is the thing w.r.t which the rule applies."
- (pcase kind
- (`:elem (pcase token
- (`basic (or coq-indent-basic
- (bound-and-true-p proof-indent)
- smie-indent-basic))))
- (`:close-all t)
- (`:list-intro
- (or (member token '("fun" "forall" "quantif exists" "with"))
- ;; We include "." in list-intro for the ". { .. } \n { .. }" so the
- ;; second {..} is aligned with the first rather than being indented as
- ;; if it were an argument to the first.
- ;; FIXME: this gives a strange indentation for ". { \n .. } \n { .. }"
-; (when (or (coq-is-bullet-token token)
-; (coq-is-dot-token token)
-; (member token '("{ subproof")))
-; (forward-char 1) ; skip de "."
-; (equal (coq-smie-forward-token) "{ subproof"))
- ))
- (`:after
- ;;(coq-show-smie--parent smie--parent smie--token (smie-indent--parent)
1 "AFTER")
- (cond
- ;; Override the default indent step added because of their presence
- ;; in smie-closer-alist.
- ((or (coq-is-bullet-token token)
- (member token '(":" ":=" ":= with" ":= def" ":= equations"
- "by" "in tactic" "<:" "<+" ":= record"
- "with module" "as" ":= inductive" ":= module" )))
- 2)
-
- ((equal token "with match") coq-match-indent)
-
- ;; Inductive foo ...
- ;; ...
- ;; with
- ;; bar <-- indent this by 2
- ;; TODO: have this optional?
- ((equal token "with inductive")
- (if (smie-rule-parent-p "with inductive")
- 0
- 2))
-
- ((equal token "with") 2) ; add 2 to the column of "with" in the
children
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;XXXXXXXXXXXXXXXXXXXXXXXx
- ((and (member token '("{" "{|"))
- (smie-rule-prev-p ":=" ":= def")
- (not coq-indent-box-style))
- (save-excursion
- (smie-backward-sexp t)
- (cons 'column (+ 2 (smie-indent-virtual)))))
-
-
- ;;; the ";" tactical ;;;
- ;; ";" is a usual operator, with no indentation
- ;; it would be like this;
- ;; foo.
- ;; foo ;
- ;; bar ;
- ;; bar.
- ;; foo.
- ;; which is confusing. So we indent the first ";" of a sequence
- ;; if not already inside an ltacdef of parenthesized tactic:
- ;; foo ;
- ;; tac ; <--- indented
- ;; tac ; <--- no indent
- ;; [ tac2 ;
- ;; tac1 ; <-- no indentation here
- ;; now ( tac3 ; <- neither here
- ;; tac5) ;
- ;; ]
- ((equal token "; tactic")
- (if (and (smie-rule-hanging-p)
- coq-indent-semicolon-tactical
- (not (coq-smie-is-ltacdef))
- (not (coq-smie-is-inside-parenthesized-tactic))
- (or (not (smie-rule-parent-p "; tactic"))
- ;; FIXME: Don't depend on SMIE's internals!
- (and (boundp 'smie--parent)
- smie--parent
- (coq-smie--same-line-as-parent
- (nth 1 smie--parent) (point)))))
- coq-indent-semicolon-tactical
- nil))
-
- ((member token '("in let" "in monadic")) (smie-rule-parent))
-
- ((equal token "} subproof")
- (smie-rule-parent))
-
- ;; proofstart is a special hack, since "." should be used as a
- ;; separator between commands, here it is recognized as an open
- ;; parenthesis, hence the current command (C) ending with "."
- ;; is not recognized as correctly terminated. The "parent"
- ;; computed by smie is therefore wrong and default indetation
- ;; is broken. We fix this by indenting from the real-start of
- ;; the command terminated by ". proofstart".
- ((equal token ". proofstart")
- (save-excursion (forward-char -1) (coq-find-real-start)
- `(column . ,(+ coq-indent-proofstart
(current-column)))))
- ((equal token ". modulestart")
- (save-excursion (forward-char -1) (coq-find-real-start)
- `(column . ,(+ coq-indent-modulestart
(current-column)))))))
-
- (`:before
- ;(coq-show-smie--parent smie--parent smie--token (smie-indent--parent) 2
"BEFORE")
- (cond
+ (let ((boxed coq-indent-box-style))
+ ;; smie-rule... short synonyms
+ (cl-flet ((parent-p (&rest x) (apply 'smie-rule-parent-p x))
+ (parent (&optional x) (smie-rule-parent x))(hang-p ()
(smie-rule-hanging-p)))
+ (pcase (cons kind token)
+ (`(,_ . (or "; record")) (smie-rule-separator kind)) ;; see also the
"before" rule
+ (`(:elem . basic) (or coq-indent-basic (bound-and-true-p proof-indent)
2))
+ (`(:elem . arg) nil)
+ (`(:close-all . ,_) t)
+ (`(:list-intro . ,_) (member token '("fun" "forall" "quantif exists"
+ "with" "Com start")))
+ (`(:after . ,_) ;; indent relative to token (parent of token at point).
+ (pcase (coq-indent-categorize-token-after token)
+ ("} subproof" 0) ;;shouldn't be captured by (:elem . args)?
+ ;; decrement indentation when hanging
+ ((and (or "tactic infix" "after :=") (guard (or (hang-p)
(smie-rule-bolp)))) 0)
+ ((and "->" (guard (hang-p))) 0) ((or ":=" "with inductive") 2)
+ ((or "." "; equations" "in let" "in monadic" ";; monadic") 0)
+ ((and "; tactic" (guard (hang-p)) (guard (not (parent-p "Com
start")))) 0)
+ ("; tactic" 2);; only applies "after" so when ";" is alone at its
line
+ ((guard (string-match "^[^][:alnum:](){}\[]" token)) 2); guessing
infix operator.
+ ;;((guard (and (message "DEFAULTING") nil)) nil)
+ ))
+ (`(:before . ,_) ; indent token at point itself
+ (let* ((cat (coq-indent-categorize-token-before token))
+ (real-start-col (save-excursion (coq-find-real-start)
(current-column))))
+ (pcase cat
+ ;; indenting the ". modulestart" itself, which is a prenthesizing
cmd
+ ("dot script parent open" `(column . ,real-start-col))
+ ;; special case for equations, so that "| xxx\n :=" is indented
nicely
+ ((and ":=" (guard (and (not (hang-p)) (parent-p "|")))) 4)
+ ("before :=" (parent 2)) ;; ":= xxx" always introduced by a parent
+ ("tactic infix" (parent 2))
+ ("|" (cond ((parent-p ":= inductive" ":= equations") -2)
+ (t 0)));((parent-p "|") 0)
+ ;; align quantifiers with the previous one
+ ((and(or "forall" "quantif exists")(guard (parent-p "forall"
"quantif exists")))
+ (parent))
+ ((and(or "fun")(guard (parent-p "fun"))) (parent))
+ ;; indent on level after a ";" but only at command level.
+ ((and "; tactic" (guard (parent-p "Com start"))) (parent))
+ ("; record" 0); is also a smie-rule-separator
+ ;; VIRTUAL INDENTATION for "unboxed" indentation: we are in the
"before"
+ ;; section, but we compute the indentation for a token NOT
appearing at
+ ;; beginning of line. This happens when not indenting the token
itself but
+ ;; rather querying its virtual indentation to compute indentation
of another
+ ;; (child) token. unbox ==> indent relative to parent.
+ ;; unboxed indent for "{" not at bol:
+ ((and (or "{ subproof" "[" "{") (guard (not (smie-rule-bolp))))
+ (cond
+ ((smie-rule-prev-p "} subproof" "]" "}") (parent 0))
+ (t (parent 2))))
+ ;; unboxed indent for quantifiers (if coq-indent-box-style non
nil)
+ ((and (or "forall" "quantif exists") (guard (not boxed))
+ (guard (not (smie-rule-bolp))) )
+ (parent coq-smie-after-bolp-indentation))
+ ;;((guard (and (message "DEFAULTING") nil)) nil)
+ )))))))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;XXXXXXXXXXXXXXXXXXXXXXXx;;;;;;;;;;;;;;
- ;; trying to indent "{" at the end of line for records, but the
- ;; parent is not what I think.
- ;; ((and (member token '("{" "{|"))
- ;; (not coq-indent-box-style))
- ;; (if (smie-rule-bolp) 2 0))
- ;(and (zerop (length tok)) (member (char-before) '(?\{ ?\})))
- ((and (zerop (length token))
- (looking-back "}" (1- (point))) ;; "|}" useless when looking
backward
- (not coq-indent-box-style))
- (smie-backward-sexp)
- (smie-backward-sexp t)
- (smie-indent-virtual)
- )
-
- ;; "with" is also in the :list-intro rules and in :after.
- ((equal token "with")
- ;; Hack: We know that "with" is linked to the first word of
- ;; the current atomic tactic. This tactic is the parent, not
- ;; the "." of the previous command.
- `(column . ,(+ 2 (coq-find-with-related-backward))))
-
- ((equal token "with module")
- (if (smie-rule-parent-p "with module")
- (smie-rule-parent)
- (smie-rule-parent 2)))
-
- ((member token '("in tactic" "as" "by"))
- (cond
- ((smie-rule-parent-p "- bullet" "+ bullet" "* bullet"
- "-- bullet" "++ bullet" "** bullet"
- "--- bullet" "+++ bullet" "*** bullet"
- "---- bullet" "++++ bullet" "**** bullet"
- "{ subproof" ". proofstart")
- (smie-rule-parent 4))
- ((smie-rule-parent-p "in tactic") (smie-rule-parent))
- (t (smie-rule-parent 2))))
-
- ((equal token "as")
- (if (smie-rule-parent-p "in tactic") (smie-rule-parent) 2))
-
- ((equal token "as morphism") (smie-rule-parent 2))
- ((member token '("xxx provedby" "with signature"))
- (if (smie-rule-parent-p "xxx provedby" "with signature")
- (smie-rule-parent)
- (smie-rule-parent 4)))
-
-
- ;; This applies to forall located on the same line than "Lemma"
- ;; & co. This says that "if it *were* be on the beginning of
- ;; line" (which it is not) it would be indented of 2 wrt
- ;; "Lemma". This never applies directly to indent the forall,
- ;; but it is used to guess indentation of the next line. This
- ;; allows fo the following indentation:
- ;; Lemma foo: forall x:nat,
- ;; x <= 0 -> x = 0.
- ;; which refer to:
- ;; Lemma foo:
- ;; forall x:nat, <--- if it where on its own line it would be on
column 2
- ;; x <= 0 -> x = 0. <--- therefore this is on column 4.
- ;; instead of:
- ;; Lemma foo: forall x:nat,
- ;; x <= 0 -> x = 0.
-
- ((and (member token '("forall" "quantif exists"))
- (not coq-indent-box-style)
- (not (smie-rule-bolp)))
- (smie-rule-parent coq-smie-after-bolp-indentation))
-
-
-
- ((and (member token '("forall" "quantif exists"))
- (smie-rule-parent-p "forall" "quantif exists"))
- (if (save-excursion
- (coq-smie-search-token-backward '("forall" "quantif exists"))
- (equal (current-column) (current-indentation)))
- (smie-rule-parent)
- (smie-rule-parent 2)))
-
-
- ;; This rule allows "End Proof" to align with corresponding ".
- ;; proofstart" PARENT instead of ". proofstart" itself
- ;; Typically:
- ;; "Proof" ". proofstart"
- ;; "Qed" <- parent is ". proofstart" above
- ;; Align with the real command start of the ". xxxstart"
- ((member token '(". proofstart" ". modulestart"))
- (save-excursion (coq-find-real-start)
- `(column . ,(current-column))))
-
- ((or (member token '(":= inductive" ":= def" ":= equations" ":="))
- (and (equal token ":") (smie-rule-parent-p ".")))
- (let ((pcol
- (save-excursion
- ;; Indent relative to the beginning of the current command
- ;; rather than relative to the previous command.
- (smie-backward-sexp token)
- ;; special case: if this ":=" corresponds to a "with
- ;; foo", then the previous smie-backward-sexp stopped
- ;; between "with" and "foo" (because "with inductive"
- ;; and co are considered as ".", maybe this is the
- ;; problem), but we want to indent from the column of
- ;; "with" instead
- (let ((col1 (current-column)))
- (if (equal (coq-smie-backward-token) "with inductive")
- (current-column)
- col1)
- ))))
- `(column . ,(if (smie-rule-hanging-p) pcol (+ 2 pcol)))))
-
- ((equal token "|")
- (cond
- ;; ":= equations" and "; record" are for Equations plugin
- ((smie-rule-parent-p "with match" ":= equations" "; record")
- (- (funcall smie-rules-function :after "with match") 2))
- ;; This is also for Equations plugijns, but happens at first
- ;; line if a pattern matching and it is ugly to have the "|"
- ;; at the saem column than "{"
- ((smie-rule-parent-p "{")
- (funcall smie-rules-function :after "with match"))
- ((smie-rule-prev-p ":= inductive")
- (- (funcall smie-rules-function :after ":= inductive") 2))
- (t (smie-rule-separator kind))))))
- ))
;; No need of this hack anymore?
;; ((and (equal token "Proof End")
-;; (smie-rule-parent-p "Module" "Section" "goalcmd"))
+;; (parent-p "Module" "Section" "goalcmd"))
;; ;; ¡¡Major gross hack!!
;; ;; This typically happens when a Lemma had no "Proof" keyword.
;; ;; We should ideally find some other way to handle it (e.g. matching
Qed
@@ -1418,7 +1434,7 @@ KIND is the situation and TOKEN is the thing w.r.t which
the rule applies."
;; ;; when parsing backward.
;; ;; FIXME: This is fundamentally very wrong, but it seems to work
;; ;; OK in practice.
-;; (smie-rule-parent 2))
+;; (parent 2))
diff --git a/coq/coq-syntax.el b/coq/coq-syntax.el
index afcbd31..b8b498a 100644
--- a/coq/coq-syntax.el
+++ b/coq/coq-syntax.el
@@ -1385,7 +1385,7 @@ different."
(defconst coq-command-prefix-regexp
"\\(Local\\s-\\|Global\\s-\\|#[[][^]]*[]]\\)")
;; FIXME: incomplete
-(defun coq-add-command-prefix (reg) (concat "\\(" coq-command-prefix-regexp
"\\)?" (mapconcat #'identity coq-keywords-defn "\\|")))
+(defun coq-add-command-prefix (reg) (concat "\\(" coq-command-prefix-regexp
"\\)?" (mapconcat #'identity reg "\\|")))
(defconst coq-command-decl-regexp (coq-add-command-prefix coq-keywords-decl))
(defconst coq-command-defn-regexp (coq-add-command-prefix coq-keywords-defn))
diff --git a/coq/ex/indent.v b/coq/ex/indent.v
index 2a0d5e4..17bf481 100644
--- a/coq/ex/indent.v
+++ b/coq/ex/indent.v
@@ -342,7 +342,7 @@ Module X.
match goal with
| ?g := _:rec |- ?a /\ ?b => split
- | _ => fail
+ | _ => fail
end.
Fail