aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--coq/coq-indent.el261
-rw-r--r--coq/coq-syntax.el32
-rw-r--r--coq/coq.el46
-rw-r--r--coq/ex/indent.v163
4 files changed, 390 insertions, 112 deletions
diff --git a/coq/coq-indent.el b/coq/coq-indent.el
index ff94a669..1f7f353e 100644
--- a/coq/coq-indent.el
+++ b/coq/coq-indent.el
@@ -22,7 +22,7 @@
(defconst coq-indent-inner-regexp
(proof-regexp-alt
- "[[]()]" "|" "šÕ"
+ "[[]()]" "[^{]|[^}]" "šÕ"
;; forall with must not be enclosed by \\< and
;;\\> . "~" forall but interacts with 'not'
(proof-ids-to-regexp
@@ -37,11 +37,11 @@
(defconst coq-indent-open-regexp
(proof-regexp-alt ;(proof-regexp-alt-list coq-keywords-goal) goal-command-p instead
(proof-ids-to-regexp '("Cases" "match" "BeginSubproof"))
- "\\s("))
+ "\\s(" "{|"))
(defconst coq-indent-close-regexp
- (proof-regexp-alt "\\s)"
- (proof-ids-to-regexp '("EndSubproof" "end"))
+ (proof-regexp-alt "\\s)" "|}" "}"
+ (proof-ids-to-regexp '("end" "EndSubProof"))
(proof-ids-to-regexp coq-keywords-save)))
@@ -81,7 +81,7 @@ detect if they start something or not."
(and (proof-string-match coq-goal-command-regexp str)
(not
- (and (proof-string-match "\\`\\(Local\\|Definition\\|Lemma\\|Module\\)\\>" str)
+ (and (proof-string-match "\\`\\(Definition\\|Instance\\|Lemma\\|Module\\)\\>" str)
(not (= letwith affect))))
(not (proof-string-match "\\`Declare\\s-+Module\\(\\w\\|\\s-\\|<\\)*:" str))
(not
@@ -92,8 +92,11 @@ detect if they start something or not."
;; ". " and "... " are command endings, ".. " is not, same as in
;; proof-script-command-end-regexp in coq.el
(defconst coq-end-command-regexp
- "\\(?:[^.]\\|\\.\\.\\)\\(\\.\\)\\(?:\\s-\\|\\'\\)")
-; "\\(?:[^.]\\|\\(?:\\.\\.\\)\\)\\(\\.\\)\\(?:\\s-\\|\\'\\)")
+ "\\(?2:[^.]\\|\\.\\.\\)?\\(?1:\\.\\)\\(?3:\\s-\\|\\'\\)\\|\\(?1:{\\)\\(?3:[^|]\\)\\|\\(?2:[^|]\\)\\(?1:}\\)"
+ "Regexp matching end of a command. There are 3 substrings:
+* number 1 is the real coq ending string,
+* number 2 is the left context matched that is not part of the ending string
+* number 3 is the right context matched that is not part of the ending string")
(defun coq-search-comment-delimiter-forward ()
@@ -177,7 +180,6 @@ Use this one for coq instead of the generic one."
(defconst coq-end-command-or-comment-start-regexp
(concat coq-comment-start-regexp "\\|" coq-end-command-regexp))
-
(defun coq-find-not-in-comment-backward (reg &optional lim submatch)
"Moves to the first not commented occurrence of REG found looking up.
The point is
@@ -190,7 +192,7 @@ found, go as far as possible and return nil."
(while (and (not found) continue)
(setq continue (re-search-backward regexp lim 'dummy))
(when continue
- (if (looking-at coq-comment-end-regexp)
+ (if (coq-looking-at-comment)
(progn (coq-skip-until-one-comment-backward))
(progn (when submatch (goto-char (match-beginning submatch)))
(setq found t))
@@ -217,43 +219,107 @@ and return nil."
(goto-char (match-beginning 0))
(if (looking-at coq-comment-start-regexp)
(progn (forward-char 2) (coq-skip-until-one-comment-forward))
- (progn (when submatch (goto-char (match-beginning submatch)))
+ (progn (when (and submatch (match-beginning submatch)) (goto-char (match-beginning submatch)))
(setq found t))
)))
(when found (point))))
-(defun coq-find-command-end-backward ()
+
+(defun coq-is-on-ending-context ()
+ (cond
+ ((looking-at "}") -1)
+ ((save-excursion
+ (ignore-errors
+ (forward-char -1) ; always nil, don't use "and"
+ (looking-at "{\\|\\."))) 1)
+ (t 0)))
+
+; slight modification of proof-script-generic-parse-cmdend (one of the
+; candidate for proof-script-parse-function), to allow "{" and "}" to be
+; command terminator when the command is empty. TO PLUG: swith the comment
+; below and rename coq-script-parse-function2 into coq-script-parse-function
+(defun coq-script-parse-cmdend-forward (&optional limit)
+ "Move to the first end of command found looking forward from point.
+Point is put exactly after the the ending token (but before matching
+substring if present). If no end command is found, go as far as possible
+and return nil. End of command appearing in comments are ignored."
+ (if (looking-at proof-script-comment-start-regexp)
+ ;; Handle comments
+ (if (proof-script-generic-parse-find-comment-end) 'comment)
+ ;; Handle non-comments: assumed to be commands
+ (if (< (coq-is-on-ending-context) 0) (ignore-errors (forward-char (coq-is-on-ending-context))))
+ (let (foundend)
+ ;; Find end of command
+ (while (and (setq foundend
+ (progn
+ (and
+ (re-search-forward proof-script-command-end-regexp limit t)
+ (match-end 1))))
+ (or (if (or (string-equal (match-string 1) "}")
+ (string-equal (match-string 1) "{"))
+ (save-excursion
+ ;; "{[^|]\\|[^|]}" matched, use length of match-string instead?
+ (goto-char (match-beginning 1))
+ (not (coq-empty-command-p)))
+ nil)
+ (proof-buffer-syntactic-context)))
+ ;; inside a string or comment before the command end
+ )
+ (if (and foundend
+ (goto-char foundend) ; move to command end
+ (not (proof-buffer-syntactic-context)))
+ ;; Found command end outside string/comment
+ 'cmd
+ ;; Didn't find command end
+ nil))))
+
+
+; slight modification of proof-script-generic-parse-cmdend (one of the
+; candidate for proof-script-parse-function), to allow "{" and "}" to be
+; command terminator when the command is empty. TO PLUG: swith the comment
+; below and rename coq-script-parse-function2 into coq-script-parse-function
+(defun coq-script-parse-cmdend-backward (&optional limit)
"Move to the first end of command (not commented) found looking up.
-Point is put exactly before the last \".\" of the ending token.
-If no end command is found, go as far as possible and return
-nil."
- (ignore-errors (forward-char 1)); because regexp looks one char after last "."
- (coq-find-not-in-comment-backward coq-end-command-regexp nil 1))
-
-
-(defun coq-find-command-end-forward ()
- "Move to the first end of command found looking down.
-The point is put exactly before the last \".\" of the ending
-token. If no end command is found, go as far as possible and
-return nil."
- (ignore-errors (backward-char 1)); because regexp looks one char before "."
- (coq-find-not-in-comment-forward coq-end-command-regexp nil 1))
-
-
-(defun coq-find-command-end (direction)
- "Move to the first end of command found looking at DIRECTION.
-The point is put exactly before the last \".\" of the ending
-token. If no end command is found, go as far as possible and
-return nil."
- (if (< direction 0) (coq-find-command-end-backward)
- (coq-find-command-end-forward)))
+Point is put exactly before the last ending token (before the last
+\".\" if \"...\"). If no end command is found, go as far as possible
+and return nil."
+ (if (looking-at proof-script-comment-start-regexp)
+ ;; Handle comments
+ (if (proof-script-generic-parse-find-comment-end) 'comment) ; start?
+ ;; Handle non-comments: assumed to be commands
+ ;; first shift if we are in the middle of a ending pattern
+ (if (> (coq-is-on-ending-context) 0) (ignore-errors(forward-char (coq-is-on-ending-context))))
+ (let (foundend)
+ ;; Find end of command
+ (while (and (setq foundend
+ (progn
+ (and
+ (re-search-backward proof-script-command-end-regexp limit t)
+ (match-beginning 1))))
+ (or (if (or (string-equal (match-string 1) "}")
+ (string-equal (match-string 1) "{"))
+ (save-excursion
+ (goto-char (match-beginning 1))
+ (not (coq-empty-command-p)))
+ nil)
+ (proof-buffer-syntactic-context)))
+ ;; inside a string or comment before the command end
+ )
+ (if (and foundend
+ (goto-char foundend) ; move to command end
+ (not (proof-buffer-syntactic-context)))
+ ;; Found command end outside string/comment
+ 'cmd
+ ;; Didn't find command end
+ nil))))
+
(defun coq-find-current-start ()
"Move to the start of command at point.
The point is put exactly after the end of previous command, or at the (point-min if
there is no previous command)."
- (coq-find-command-end-backward)
- (if (proof-looking-at "\\.\\s-") (forward-char 1))
+ (coq-script-parse-cmdend-backward)
+ (if (proof-looking-at "\\.\\s-\\|{\\|}") (forward-char 1)) ; else = no match found
(point))
@@ -273,35 +339,29 @@ Can jump line if NOJUMPLINES = nil."
(save-excursion
(let* ((st (coq-find-real-start)) ; va chercher trop loin? OUI
(linejumped (not (same-line initpos (point))))
- (nd (or (coq-find-command-end-forward) (- (point-max) 1)))) ; idem?
+ (xxx (goto-char (- (point) 1)))
+ (nd (or (if (coq-script-parse-cmdend-forward) (point) nil) (- (point-max) 1)))) ; idem?
(if (and st (or (not nojumplines) (not linejumped)))
(buffer-substring st (+ nd 1))
nil)))))
-;
-;(defun coq-command-at-point ()
-; "Return the string of the command at point."
-; (save-excursion
-; (let ((st (coq-find-real-start)) ; va chercher trop loin?
-; (nd (or (coq-find-command-end-forward) (- (point-max) 1)))) ; idem?
-; (if st (buffer-substring st (+ nd 1))))))
-;
-
-
(defun coq-commands-at-line (&optional nojumplines)
"Return the string of each command at current line."
(save-excursion
- (back-to-indentation)
+ ;; we must capture a "." or a "{" at start of the line. So we go at the end of
+ ;; previous line to have a left context to match
(let ((initpoint (point))
+ (forward-char (coq-is-on-ending-context))
(command-found (coq-command-at-point nojumplines))
res
)
+ (if command-found (coq-find-real-start))
(while (and command-found
;; need this second test even with nojumplines:
(same-line (point) initpoint))
(setq res (cons command-found res))
- (if (and (coq-find-command-end-forward)
+ (if (and (coq-script-parse-cmdend-forward)
(ignore-errors (forward-char 1) t);to fit in the "and"
(coq-find-real-start))
(setq command-found (coq-command-at-point nojumplines))
@@ -362,26 +422,29 @@ not inside the {} of a record)."
(setq topnotreached (= (forward-line -1) 0))
(end-of-line)
(if (proof-looking-at-syntactic-context)
- (coq-find-comment-start) ; (re-search-backward coq-comment-start-regexp nil 'dummy)
+ (re-search-backward coq-comment-start-regexp nil 'dummy)
))
(back-to-indentation)
(if (not topnotreached) 0 ;; returns nil if top of buffer was reached
;; if we are at end of a command (dot) find this command
; if there is a "." alone on the line
(let ((pos (point)))
- (ignore-errors (forward-char -1))
- (if (coq-indent-find-reg oldpt coq-end-command-regexp)
- (progn (forward-char -2)
+ ;(ignore-errors (forward-char -1))
+ (if (coq-script-parse-cmdend-forward oldpt)
+ (progn (forward-char -1)
+ ;; one more if "." found, no more if "{" or "}"
+ (when (proof-looking-at "\\.") (forward-char -1))
(coq-find-real-start)
(back-to-indentation)
1)
(goto-char pos)
(if (save-excursion
- (and (not (= (point) (point-min)))
+ (and
+ (not (= (point) (point-min)))
(or (forward-char -1) t)
(coq-find-real-start)
- (proof-looking-at-safe "Record")
- (coq-indent-find-reg oldpt "{")))
+ (proof-looking-at-safe "Record\\|Class\\|Instance"); {struct} should not match this
+ (coq-indent-find-reg oldpt "{[^|]")))
4
2)))))))
@@ -530,41 +593,79 @@ Returns point if found."
(defun coq-goal-count (l) (coq-add-iter l 'coq-indent-goal-command-p))
(defun coq-save-count (l)
- (coq-add-iter l '(lambda (x) (or (coq-save-command-p nil x)
- (eq (proof-string-match "\\<EndSubproof\\>" x) 0)))))
+ (coq-add-iter l '(lambda (x)
+ (or (coq-save-command-p nil x)
+ (eq (proof-string-match "\\<\\(?:EndSubproof\\)\\>\\|}" x) 0)))))
(defun coq-proof-count (l)
(coq-add-iter l '(lambda (x)
- (eq (proof-string-match "\\<\\(?:Proof\\|BeginSubproof\\)\\>" x) 0))))
+ (eq (proof-string-match "\\<\\(?:Proof\\|BeginSubproof\\)\\>\\|{" x) 0))))
;; returns the difference between goal (and assimilate Proof and BeginSubproof) and
;; save commands in a commands list. This is to
(defun coq-goal-save-diff-maybe-proof (l)
(let ((proofs (coq-proof-count l))
+ (saves (coq-save-count l))
(goals (coq-goal-count l)))
- (if (= goals 0) (- (if (<= proofs 0) 0 1) (coq-save-count l))
- (- goals (coq-save-count l)))))
+; (if (= goals 0) (- (if (<= proofs 0) 0 1) (coq-save-count l))
+; (- goals (coq-save-count l)))
+ (- (+ proofs goals) saves)
+ ))
(defun coq-indent-command-offset (kind prevcol prevpoint)
- "Returns the indentation offset of the current line. This function indents a *command* line (the first line of a command). Use `coq-indent-expr-offset' to indent a line belonging to an expression."
- (let ((diff-goal-save-current (coq-goal-save-diff-maybe-proof (coq-commands-at-line t)))
+ "Returns the indentation offset of the current line.
+This function indents a *command* line (the first line of a command).
+Use `coq-indent-expr-offset' to indent a line belonging to an expression."
+ (let ((diff-goal-save-current
+ (coq-goal-save-diff-maybe-proof (coq-commands-at-line t)))
(diff-goal-save-prev
- (save-excursion (goto-char prevpoint)
- (coq-goal-save-diff-maybe-proof (coq-commands-at-line t)))))
+ (save-excursion
+ (goto-char prevpoint)
+ (coq-goal-save-diff-maybe-proof (coq-commands-at-line t))))
+ (prev-closing-beginning ; t if the closing is at start of the (prev) line
+ (save-excursion
+ (goto-char prevpoint)
+ (back-to-indentation)
+ ;(forward-char -1)
+ (looking-at coq-indent-close-regexp)))
+ (current-closing-beginning ; t if the closing is at start of the (current) line
+ (save-excursion
+ (back-to-indentation)
+ (looking-at coq-indent-close-regexp))))
+ ;(message "currentkind,prevcol,prevpoint = %d , %d ,%d " kind prevcol prevpoint)
(cond
((proof-looking-at-safe "\\<Proof\\>") 0);; no indentation at "Proof ..."
- ;; we are at an end command -> one ident left unless previous line is a goal
- ;; (if goal and save are consecutive, then no indentation at all)
- ((and (< diff-goal-save-current 0) (<= diff-goal-save-prev 0)) (- proof-indent))
-
- ;; previous command is a goal command -> one indent right unless the current one
- ;; is an end (consecutive goal and save).
- ((and (>= diff-goal-save-current 0) (> diff-goal-save-prev 0)) proof-indent)
-
- ;; otherwise -> same indent as previous command
- (t 0))))
+ (t (* proof-indent
+ (let ((res
+ (let ((a diff-goal-save-prev) (b diff-goal-save-current)
+ (a2 prev-closing-beginning) (b2 current-closing-beginning))
+ ;(message "a,b,a2,b2 = %d,%d,%S,%S" a b a2 b2)
+ (cond
+ ((and (>= a 0) (>= b 0)) a)
+ ((and (>= a 0) (< b 0) b2) (+ a -1)) ; a + b
+ ((and (>= a 0) (< b 0) (not b2)) a)
+ ((and (< a 0) (< b 0) a2 b2) a) ; a +1 -1
+ ((and (< a 0) (< b 0) a2 (not b2)) (+ a 1))
+ ((and (< a 0) (< b 0) (not a2) b2) (+ a -1))
+ ((and (< a 0) (< b 0) (not a2) (not b2)) a)
+ ((and (< a 0) (>= b 0) a2) (+ a 1))
+ ((and (< a 0) (>= b 0) (not a2)) a)
+ (t (error "Muh?"))))))
+ ;(message "RES = %S" res)
+ ;(message "********************")
+ res))
+ )
+ ;; ;; we are at an end command -> one ident left unless previous line is a goal
+ ;; ;; (if goal and save are consecutive, then no indentation at all)
+ ;; ((and (< diff-goal-save-current 0) (<= diff-goal-save-prev 0)) (- proof-indent))
+ ;; ;; previous command is a goal command -> one indent right unless the current one
+ ;; ;; is an end (consecutive goal and save).
+ ;; ((and (>= diff-goal-save-current 0) (> diff-goal-save-prev 0)) proof-indent)
+ ;; ;; otherwise -> same indent as previous command
+ ;; (t 0)
+ )))
@@ -583,6 +684,7 @@ Returns point if found."
This function indents a *expression* line (a line inside of a command). Use
`coq-indent-command-offset' to indent a line belonging to a command. The fourth
argument must be t if inside the {}s of a record, nil otherwise."
+ ;(message "COQ-INDENT-EXPR-OFFSET")
(let ((pt (point)) real-start)
(save-excursion
(setq real-start (coq-find-real-start)))
@@ -660,8 +762,10 @@ argument must be t if inside the {}s of a record, nil otherwise."
;; just for side effect: jumps to end of previous line
((and (goto-char prevpoint)
(or (and (end-of-line) nil)
- (and (forward-char -1) t)) nil))
+ (and (coq-find-not-in-comment-backward "[^[:space:]]") t)) nil))
+ ;; TODO fix with new use of { for tactics enclosing
+ ;; should be ok if record is ok.
((and (proof-looking-at-safe ";") ;prev line has ";" at the end
record) ; and we are inside {}s of a record
(save-excursion
@@ -683,6 +787,7 @@ argument must be t if inside the {}s of a record, nil otherwise."
;; There is a indent keyword (fun, forall etc)
;; and we are not in {}s of a record just after a ";"
((coq-find-at-same-level-zero prevpoint coq-indent-kw)
+ ;(message "COQ-INDENT-KW")
(+ prevcol proof-indent))
((and (goto-char prevpoint) nil)) ;; just for side effect: go back to previous line
@@ -720,7 +825,7 @@ argument must be t if inside the {}s of a record, nil otherwise."
;;we were at the first line of a comment and the current line is the
;;previous one
(t (goto-char oldpt)
- (coq-find-command-end-backward)
+ (coq-script-parse-cmdend-backward)
(coq-find-real-start)
(current-column))))))))
@@ -731,7 +836,7 @@ argument must be t if inside the {}s of a record, nil otherwise."
(setq kind (coq-back-to-indentation-prevline) ;go to previous *command* (assert)
prevcol (current-column)
prevpoint (point)))
- ;; (message "coq-indent-offset... kind = %s ; prevcol = %s; prevpoint = %s" kind prevcol prevpoint)
+ ;(message "coq-indent-offset... kind = %s ; prevcol = %s; prevpoint = %s" kind prevcol prevpoint)
(cond
((= kind 0) 0 ; top of the buffer reached
)
diff --git a/coq/coq-syntax.el b/coq/coq-syntax.el
index f4daaa0f..eb04e901 100644
--- a/coq/coq-syntax.el
+++ b/coq/coq-syntax.el
@@ -431,7 +431,7 @@ See also `coq-prog-env' to adjust the environment."
("Inductive (3 args)" "indv3" "Inductive # : # :=\n| # : #\n| # : #\n| # : #." t )
("Inductive (4 args)" "indv4" "Inductive # : # :=\n| # : #\n| # : #\n| # : #\n| # : #." t )
("Inductive (5 args)" "indv5" "Inductive # : # :=\n| # : #\n| # : #\n| # : #\n| # : #\n| # : #." t )
- ("Instance" nil "Instance #:#.\nProof.\n#End." t "Instance")
+ ("Instance" nil "Instance #:#.\nProof.\n#Defined." t "Instance")
("Program Instance" "pinstance" "Program Instance [ # ] => # where \n# := #;\n# := #." t "Program\\s-+Instance")
("Let" "Let" "Let # : # := #." t "Let")
("Ltac" "ltac" "Ltac # := #" t "Ltac")
@@ -451,18 +451,25 @@ See also `coq-prog-env' to adjust the environment."
)
;; modules and section are indented like goal starters
+;;; PC TODO: this category is used only for indentation, because
+;;; scripting uses information from coq to decide if a goal is
+;;; started. Since it is impossible for some commands to know
+;;; syntactically if they start something (ex: Instance), the
+;;; right thing to do would be to indent only on "Proof." and forget
+;;; about this category for indentation.
+
(defvar coq-goal-starters-db
'(
- ("Add Morphism" "addmor" "Add Morphism @{f} : @{id}" t "Add\\s-+Morphism")
- ("Add Parametric Morphism" nil "Add Parametric Morphism : " t "Add\\s-+Parametric\\s-+Morphism")
- ("Add Parametric Relation" nil "Add Parametric Relation : " t "Add\\s-+Parametric\\s-+Relation")
+ ("Add Morphism" "addmor" "Add Morphism @{f} : @{id}" t "Add\\s-+Morphism")
+ ("Add Parametric Morphism" nil "Add Parametric Morphism : " t "Add\\s-+Parametric\\s-+Morphism")
("Chapter" "chp" "Chapter # : #." t "Chapter")
("Corollary" "cor" "Corollary # : #.\nProof.\n#\nQed." t "Corollary")
("Declare Module :" "dmi" "Declare Module # : #.\n#\nEnd #." t)
("Declare Module <:" "dmi2" "Declare Module # <: #.\n#\nEnd #." t)
- ("Definition goal" "defg" "Definition #:#.\n#\nSave." t);; careful
+ ("Definition goal" "defg" "Definition #:#.\n#\nDefined." t);; careful
("Fact" "fct" "Fact # : #." t "Fact")
("Goal" nil "Goal #." t "Goal")
+ ("Instance goal" "instg" "Instance #:#.\n#\nDefined." t);; careful
("Lemma" "l" "Lemma # : #.\nProof.\n#\nQed." t "Lemma")
("Program Lemma" "pl" "Program Lemma # : #.\nProof.\n#\nQed." t "Program\\s-+Lemma")
("Module! (interactive)" nil "Module # : #.\n#\nEnd #." nil nil coq-insert-section-or-module)
@@ -482,6 +489,7 @@ See also `coq-prog-env' to adjust the environment."
;; command that are not declarations, definition or goal starters
(defvar coq-other-commands-db
'(
+ ("Add Parametric Relation" nil "Add Parametric Relation : " t "Add\\s-+Parametric\\s-+Relation")
("BeginSubproof" "bs" "BeginSubproof.\n#\nEndSubproof." t "BeginSubproof")
("EndSubproof" "es" "EndSubproof.#" t "EndSubproof")
;; ("Abort" nil "Abort." t "Abort" nil nil);don't appear in menu
@@ -749,15 +757,13 @@ Used by `coq-goal-command-p'"
(coq-module-opening-p str))
)))
+;; TODO: rely on coq response nistead for span grouping
(defvar coq-keywords-save-strict
- '("Defined"
- "Save"
- "Qed"
-; "EndSubproof" ;; care: this must happen before "End"
- "End"
- "Admitted"
- "Abort"
- ))
+ '("Defined" "Save" "Qed" "End" "Admitted" "Abort" )
+ "This regexp must match *exactly* commands that close a goal/Module.
+It is used:
+ 1) for grouping spans into one when scripting
+ 2) for indentation.")
(defvar coq-keywords-save
(append coq-keywords-save-strict '("Proof"))
diff --git a/coq/coq.el b/coq/coq.el
index 12db171d..1558a82a 100644
--- a/coq/coq.el
+++ b/coq/coq.el
@@ -103,7 +103,7 @@ Set to t if you want this feature."
(require 'coq-syntax)
;; FIXME: Even if we don't use coq-indent for indentation, we still need it for
-;; coq-find-command-end-backward and coq-find-real-start.
+;; coq-script-parse-cmdend-forward/backward and coq-find-real-start.
(require 'coq-indent)
(defcustom coq-prog-env nil
@@ -288,6 +288,44 @@ SMIE is a navigation and indentation framework available in Emacs ≥ 23.3."
;; Auxiliary code for Coq modes
;;
+
+
+;;;;;;;;;;; Trying to accept { and } as terminator for empty commands. Actually
+;;;;;;;;;;; I am experimenting two new commands "{" and "}" (without no
+;;;;;;;;;;; trailing ".") which behave like BeginSubProof and EndSubproof. The
+;;;;;;;;;;; absence of a trailing "." makes it difficult to distinguish between
+;;;;;;;;;;; "{" of normal coq code (implicits, records) and this the new
+;;;;;;;;;;; commands. We therefore define a coq-script-parse-function to this
+;;;;;;;;;;; purpose.
+
+; coq-end-command-regexp is ni coq-indent.el
+(setq coq-script-command-end-regexp coq-end-command-regexp)
+; "\\(?:[^.]\\|\\(?:\\.\\.\\)\\)\\.\\(\\s-\\|\\'\\)")
+
+
+
+(defun coq-empty-command-p ()
+ "Test if between point and previous command is empty.
+Comments are ignored, of course."
+ (let ((end (point))
+ (start (coq-find-not-in-comment-backward "[^[:space:]]")))
+ ;; we must find a "." to be sure, because {O} {P} is allowed in definitions
+ ;; with implicits --> this function is recursive
+ (if (looking-at "{\\|}") (coq-empty-command-p)
+ (looking-at "\\."))))
+
+
+; slight modification of proof-script-generic-parse-cmdend (one of the
+; candidate for proof-script-parse-function), to allow "{" and "}" to be
+; command terminator when the command is empty. TO PLUG: swith the comment
+; below and rename coq-script-parse-function2 into coq-script-parse-function
+(defun coq-script-parse-function ()
+ "For `proof-script-parse-function' if `proof-script-command-end-regexp' set."
+ (coq-script-parse-cmdend-forward))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;; End of "{" and "} experiments ;;;;;;;;;;;;
+
+
(defun coq-set-undo-limit (undos)
(proof-shell-invisible-command (format "Set Undo %s . " undos)))
@@ -743,8 +781,8 @@ This is specific to `coq-mode'."
;; Coq error messages are thrown off by TAB chars.
(set (make-local-variable 'indent-tabs-mode) nil)
(setq proof-terminal-string ".")
- (setq proof-script-command-end-regexp
- "\\(?:[^.]\\|\\(?:\\.\\.\\)\\)\\.\\(\\s-\\|\\'\\)")
+ (setq proof-script-command-end-regexp coq-script-command-end-regexp)
+ (setq proof-script-parse-function 'coq-script-parse-function)
(setq proof-script-comment-start "(*")
(setq proof-script-comment-end "*)")
(setq proof-unnamed-theorem-name "Unnamed_thm") ; Coq's default name
@@ -1831,7 +1869,7 @@ Based on idea mentioned in Coq reference manual."
((str (string-match "<info type=\"infoH\">\\([^<]*\\)</info>"
proof-shell-last-response-output))
(substr (match-string 1 proof-shell-last-response-output)))
- (coq-find-command-end-backward)
+ (coq-script-parse-cmdend-backward)
(let ((inhibit-read-only t))
(insert (concat " as " substr)))))
diff --git a/coq/ex/indent.v b/coq/ex/indent.v
index b06ae922..ce8e1edb 100644
--- a/coq/ex/indent.v
+++ b/coq/ex/indent.v
@@ -9,22 +9,151 @@ Function div2 (n : nat) {struct n}: nat :=
end.
-Module toto.
- Lemma l1: forall n:nat, n = n.
- toto.
- Qed.
- Lemma l2: forall n:nat, n = n.
- toto. Qed.
- Lemma l3: forall n:nat, n <= n. intro. Qed.
- Lemma l4: forall n:nat, n <= n. Proof. intro. Qed.
- Lemma l5 : forall n:nat, n <= n.
- Proof. intro.
- Qed.
- Lemma l6: forall n:nat, n = n.
- toto.
- Lemma l7: forall n:nat, n = n.
- toto.
+Module M1.
+ Module M2.
+ Lemma l1: forall n:nat, n = n.
+ auto.
Qed.
- Qed.
-End toto.
+ Lemma l2: forall n:nat, n = n.
+ auto. Qed.
+ Lemma l3: forall n:nat, n <= n. auto. Qed.
+ (* Lemma l4: forall n:nat, n <= n. Proof. intro. Qed. *)
+ Lemma l5 : forall n:nat, n <= n.
+ Proof. auto.
+ Qed.
+ Lemma l6: forall n:nat, n = n.
+ intros.
+ Lemma l7: forall n:nat, n = n.
+ destruct n.
+ BeginSubproof.
+ auto.
+ EndSubproof.
+ BeginSubproof.
+ destruct n.
+ BeginSubproof.
+ auto.
+ EndSubproof.
+ auto.
+ EndSubproof.
+ Qed.
+ BeginSubproof.
+ destruct n.
+ BeginSubproof.
+ auto. EndSubproof.
+ BeginSubproof. auto.
+ EndSubproof.
+ EndSubproof.
+ Qed.
+ End M2.
+End M1.
+
+
+Module M1'.
+ Module M2'.
+ Lemma l6: forall n:nat, n = n.
+ intros.
+ Lemma l7: forall n:nat, n = n.
+ destruct n.
+ {
+ auto.
+ }
+ {
+ destruct n.
+ {
+ idtac;[
+ auto
+ ].
+ }
+ auto.
+ }
+ Qed.
+ {destruct n.
+ {
+ auto. }
+ {auto.}
+ }
+ Qed.
+ End M2'.
+End M1'.
+
+Record rec:Set := {
+ fld1:nat;
+ fld2:nat;
+ fld3:bool
+}.
+
+Class cla {X:Set}:Set := {
+ cfld1:nat;
+ cld2:nat;
+ cld3:bool
+}.
+
+
+
+
+Lemma l :
+ forall r:rec,
+ exists r':rec,
+ r'.(fld1) = r.(fld2) /\ r'.(fld2) = r.(fld1).
+Proof.
+ intros r.
+ {exists
+ {|
+ fld1:=r.(fld2);
+ fld2:=r.(fld1);
+ fld3:=false
+ |}.
+ split.
+ {auto. }
+ {auto. }
+ }
+Qed.
+
+
+Lemma l2 :
+ forall r:rec,
+ exists r':rec,
+ r'.(fld1) = r.(fld2) /\ r'.(fld2) = r.(fld1).
+Proof.
+ intros r.
+ {
+ idtac;
+ exists
+ {|
+ fld1:=r.(fld2);
+ fld2:=r.(fld1);
+ fld3:=false
+ |}.
+ (* ltac *)
+ match goal with
+ | _:rec |- ?a /\ ?b => split
+ | _ => fail
+ end.
+ {auto. }
+ {auto. }
+ }
+Qed.
+
+Require Import Morphisms.
+Generalizable All Variables.
+Open Local Scope signature_scope.
+Require Import RelationClasses.
+
+Module foo.
+Instance: (@RewriteRelation nat) impl.
+(* No goal created *)
+Definition XX := 0.
+
+
+Instance StrictOrder_Asymmetric `(StrictOrder A R) : Asymmetric R.
+(* One goal created. Then the user MUST put "Proof." to help indentation *)
+Proof.
+firstorder.
+Qed.
+ Program Fixpoint f (x:nat) {struct n} : nat :=
+ match x with
+ | 0 => 0
+ | S y => S (f y)
+ end.
+End Foo.