diff options
Diffstat (limited to 'coq/coq.el')
-rw-r--r-- | coq/coq.el | 518 |
1 files changed, 480 insertions, 38 deletions
@@ -1,12 +1,23 @@ -;; coq.el --- Major mode for Coq proof assistant -*- coding: utf-8 -*- -;; Copyright (C) 1994-2009 LFCS Edinburgh. +;;; coq.el --- Major mode for Coq proof assistant -*- coding: utf-8 -*- + +;; This file is part of Proof General. + +;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh +;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. +;; Portions © Copyright 2001-2017 Pierre Courtieu +;; Portions © Copyright 2010, 2016 Erik Martin-Dorel +;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews +;; Portions © Copyright 2015-2017 Clément Pit-Claudel + ;; Authors: Healfdene Goguen, Pierre Courtieu -;; License: GPL (GNU GENERAL PUBLIC LICENSE) ;; Maintainer: Pierre Courtieu <Pierre.Courtieu@cnam.fr> -;; -;; $Id$ +;; License: GPL (GNU GENERAL PUBLIC LICENSE) +;;; Commentary: +;; + +;;; Code: (eval-when-compile (require 'cl) @@ -42,7 +53,6 @@ (require 'coq-seq-compile) ; sequential compilation of Requires (require 'coq-par-compile) ; parallel compilation of Requires - ;; for compilation in Emacs < 23.3 (NB: declare function only works at top level) (declare-function smie-bnf->prec2 "smie") (declare-function smie-rule-parent-p "smie") @@ -78,7 +88,7 @@ ;; :group 'coq) (defcustom coq-user-init-cmd nil - "user defined init commands for Coq. + "User defined init commands for Coq. These are appended at the end of `coq-shell-init-cmd'." :type '(repeat (cons (string :tag "command"))) :group 'coq) @@ -91,12 +101,12 @@ These are appended at the end of `coq-shell-init-cmd'." ;; Default coq is only Private_ and _subproof (defcustom coq-search-blacklist-string ; add this? \"_ind\" \"_rect\" \"_rec\" "\"Private_\" \"_subproof\"" - "String for blacklisting strings from requests to coq environment." + "String for blacklisting strings from requests to Coq environment." :type 'string :group 'coq) (defcustom coq-prefer-top-of-conclusion nil - "prefer start of the conclusion over its end when displaying goals + "Prefer start of the conclusion over its end when displaying goals that do not fit in the goals window." :type 'boolean :group 'coq) @@ -432,7 +442,8 @@ This is a subroutine of `proof-shell-filter'." (set-marker proof-shell-urgent-message-scanner (if end ;; couldn't find message start; move forward to avoid rescanning - (max initstart + (max (or lastend 1) ;; goto after last end urgent msg + ;; or near the end of current output if that jumps farther. (- (point) (1+ proof-shell-eager-annotation-start-length))) ;; incomplete message; leave marker at start of message @@ -884,7 +895,7 @@ Support dot.notation.of.modules." (if notation (concat "\"" notation "\"") "")))) (defcustom coq-remap-mouse-1 nil - "Wether coq mode should remap mouse button 1 to coq queries. + "Whether Coq mode should remap mouse button 1 to Coq queries. This overrides the default global binding of (control mouse-1) and (shift mouse-1) (buffers and faces menus). Hence it is nil by @@ -935,13 +946,14 @@ Otherwise propose identifier at point if any." nil 'proof-minibuffer-history guess))) -(defun coq-ask-do (ask do &optional dontguess postformatcmd) +(defun coq-ask-do (ask do &optional dontguess postformatcmd wait) "Ask for an ident and print the corresponding term." (let* ((cmd) (postform (if (eq postformatcmd nil) 'identity postformatcmd))) (proof-shell-ready-prover) (setq cmd (coq-guess-or-ask-for-string ask dontguess)) (proof-shell-invisible-command - (format (concat do " %s . ") (funcall postform cmd))))) + (format (concat do " %s . ") (funcall postform cmd)) + wait))) (defun coq-flag-is-on-p (testcmd) @@ -1043,15 +1055,6 @@ This is specific to `coq-mode'." (interactive) (coq-ask-do "SearchRewrite" "SearchRewrite" nil)) -;; TODO SearchAbout become Search in v8.5, change when V8.4 becomes old. -(defun coq-SearchAbout () - (interactive) - (coq-ask-do - ;; TODO: use [Add Search Blacklist "foo"] to exclude optionaly some patterns: - ;; "_ind" "_rec" "R_" "_equation" - "SearchAbout (ex: \"eq_\" eq -bool)" - "SearchAbout") - (message "use [Coq/Settings/Search Blacklist] to change blacklisting.")) @@ -1063,6 +1066,11 @@ With flag Printing All if some prefix arg is given (C-u)." (coq-ask-do-show-all "Print" "Print") (coq-ask-do "Print" "Print"))) +(defun coq-Print-Ltac () + "Ask for an ident and print the corresponding Ltac term." + (interactive) + (coq-ask-do "Print Ltac" "Print Ltac")) + (defun coq-Print-with-implicits () "Ask for an ident and print the corresponding term." (interactive) @@ -1359,26 +1367,411 @@ goal is redisplayed." (rd (read-number (format "Width (%S): " deflt) deflt))) (coq-adapt-printing-width t rd))) +;;;;; utils fo overlays +(defun coq-overlays-at (pt prop) + (let ((overlays (overlays-at pt)) + found) + (while overlays + (let ((overlay (car overlays))) + (if (overlay-get overlay prop) + (setq found (cons overlay found)))) + (setq overlays (cdr overlays))) + found)) + +;;;;;;;;;; Hypothesis tracking ;;;;;;;;;; +;;; Facilities to build overlays for hyp names and hyp+type + hypcross +;;; ((un)folding buttons). +(defvar coq-hypname-map (make-sparse-keymap) "Keymap for visible hypothesis") +(defvar coq-hypcross-map (make-sparse-keymap) "Keymap for visible hypothesis") + +(defvar coq-hypcross-hovering-help t + "Whether hyps fold cross pops up a help when hovered.") + +(defvar coq-hyps-positions nil + "The list of positions of hypothesis in the goals buffer. +Maintained by a hook in `proof-shell-handle-delayed-output-hook'.") + +;; Hyps name are clickable and have a special keymap. +(defun coq-make-hypname-overlay (beg end h buf) + (let ((ov (make-overlay beg end buf))) + (when ov + (overlay-put ov 'evaporate t) + (overlay-put ov 'is-hypname t) + (overlay-put ov 'hyp-name h) + (overlay-put ov 'keymap coq-hypname-map)) + ov)) + +;; Hyps types are clickable only when folded +(defun coq-make-hyp-overlay (beg end h buf) + (let ((ov (make-overlay beg end buf))) + (when ov + (overlay-put ov 'evaporate t) + (overlay-put ov 'is-hyp t) + (overlay-put ov 'hyp-name h)) + ov)) + +(defun coq-hypcross-unfolded-string() + (propertize + "-" + 'face 'coq-button-face + 'mouse-face 'coq-button-face-pressed)) + +(defun coq-hypcross-folded-string() + (propertize + "+" + 'face 'coq-button-face + 'mouse-face 'coq-button-face-pressed)) + +;; hypcross is displayerd with a "-" when unfolded and a "+" when unfolded. +;; It is highlighted when hovered, is clickable and have a special +;; keymap (f toggles folding, h toggles highlighting...). +;; PC: using button faces of make-button makes the button larger than a +;; characters, which messes columns. So we use simple background colors in +;; coq-hyp...faces +(defun coq-make-hypcross-overlay (beg end h buf) + (let ((ov (make-overlay beg end buf))) + (when ov + (overlay-put ov 'evaporate t) + (overlay-put ov 'is-hypcross t) + (overlay-put ov 'hyp-name h) + (overlay-put ov 'keymap coq-hypcross-map) + (overlay-put ov 'display (coq-hypcross-unfolded-string)) + ;(overlay-put ov 'face 'coq-button-face) + ;(overlay-put ov 'mouse-face 'coq-button-face-pressed) + ;(overlay-put ov 'width .6) + ;(overlay-put ov 'height -1) + (when (eq coq-hypcross-hovering-help t) + (overlay-put ov 'help-echo "mouse-3: unfold; mouse-2 copy name"))) + ov)) + +;; Once we have created the 3 overlays, each recieves a reference to the 2 +;; others. +(defun coq-hyp-overlay-build-cross-refs (hypnameov hypov crosshypov) + (overlay-put hypnameov 'hypcross-ov crosshypov) + (overlay-put hypov 'hypcross-ov crosshypov) + (overlay-put hypnameov 'hyp-ov hypov) + (overlay-put crosshypov 'hyp-ov hypov) + (overlay-put hypov 'hypname-ov hypnameov) + (overlay-put crosshypov 'hypname-ov hypnameov)) + +(defun coq-build-hyp-overlay (hyp-positions buf) + (let* ((names (car hyp-positions)) + (fstname (car names)) + (positions (cdr hyp-positions)) + (begcross (car positions)) + (beghypname (cadr positions)) + (endhypname (caddr positions)) + (beg (cadddr positions)) + (end (cadddr (cdr positions)))) + (let ((hypnameov (coq-make-hypname-overlay beghypname endhypname fstname buf)) + (hypov (coq-make-hyp-overlay beg end fstname buf)) + (crosshypov (coq-make-hypcross-overlay begcross (+ 1 begcross) fstname buf)) + res) + (coq-hyp-overlay-build-cross-refs hypnameov hypov crosshypov) + (mapc + (lambda (s) + (setq res + (cons + (cons (substring-no-properties s) + (cons hypov (cons hypnameov (cons crosshypov nil)) )) + res))) + names) + res))) + +(defun coq-build-hyps-overlays (hyp-positions buf) + (let ((res)) + (mapc (lambda (x) (let ((lassoc (coq-build-hyp-overlay x buf))) + (setq res (append lassoc res)))) + hyp-positions) + res)) + +; builds the list of names from one hyp position (which may contained several +; hyp names) +(defun coq-build-hyp-name (hyp-positions) + (let* ((names (car hyp-positions)) + res) + (mapc (lambda (s) (setq res (cons (substring-no-properties s) res))) names) + res)) + +;; Build the list of hyps names +(defun coq-build-hyps-names (hyp-positions) + (let ((res)) + (mapc (lambda (x) (let ((lassoc (coq-build-hyp-name x))) + (setq res (append lassoc res)))) + hyp-positions) + res)) + + +(defun coq-detect-hyps-in-goals () + "Detect all hypothesis displayed in goals buffer and create overlays. +Three overlays are created for each hyp: (hypov hypnameov hypcrossov), respectively +for the whole hyp, only its name and the overlay for fold/unfold cross. +Returnns the list of mappings hypname -> overlays. +" + (let* + ((fsthyp-pos (coq-find-first-hyp)) + (fsthyp-ov (when fsthyp-pos (with-current-buffer proof-goals-buffer + (overlays-at fsthyp-pos)))) + ; is there at least one hyp overlay there? + (fsthyp-hypov (when fsthyp-ov + (cl-some (lambda(x) (overlay-get x 'hyp-name)) + fsthyp-ov)))) + (if fsthyp-hypov coq-hyps-positions ;overlays are already there + (coq-build-hyps-overlays (coq-detect-hyps-positions-in-goals) proof-goals-buffer)))) + +(defun coq-find-hyp-overlay (h) + (cadr (assoc h coq-hyps-positions))) + +;;;;;;;;;;;;;; Highlighting hypothesis ;;;;;;;; +;; Feature: highlighting of hyptohesis that remains when the cript is played +;; (and goals buffer is updated). + +;; On by default. This only works with the SearchAbout function for now. +(defvar coq-highlight-hyps-cited-in-response t + "If non-nil, try to highlight in goals buffers hyps cited in response.") + +;; We maintain a list of hypothesis names that must be highlighted at each +;; regeneration of goals buffer. +(defvar coq-highlighted-hyps nil + "List of hypothesis names that must be highlighted. +These are rehighlighted at each regeneration of goals buffer +using a hook in `proof-shell-handle-delayed-output-hook'.") + +(defun coq-highlight-hyp-aux (h) + "Auxiliary function, use `coq-highlight-hyp' for sticky highlighting. +Unless you want the highlighting to disappear after the goals +buffer is updated." + (let ((hyp-overlay (coq-find-hyp-overlay h))) + (when hyp-overlay + (overlay-put hyp-overlay 'face '(:background "lavender"))))) + +(defun coq-unhighlight-hyp-aux (h) + "Auxiliary function, use `coq-unhighlight-hyp' for sticky highlighting. +Unless you want the highlighting to disappear after the goals +buffer is updated." + (let* ((hyp-overlay (coq-find-hyp-overlay h))) + (when hyp-overlay + (overlay-put hyp-overlay 'face nil)))) + +(defun coq-highlight-hyp (h) + "Highlight hypothesis named H (sticky). +use `coq-unhighlight-hyp' to unhilight." + (unless (member h coq-highlighted-hyps) + (setq coq-highlighted-hyps (cons h coq-highlighted-hyps))) + (coq-highlight-hyp-aux h)) + +(defun coq-unhighlight-hyp (h) + "Unhighlight hypothesis named H." + (when (member h coq-highlighted-hyps) + (setq coq-highlighted-hyps (delete h coq-highlighted-hyps)) + (coq-unhighlight-hyp-aux h))) + +(defun coq-highlight-hyps (lh) + (mapc 'coq-highlight-hyp lh)) + +(defun coq-unhighlight-hyps (lh) + (mapc 'coq-unhighlight-hyp-aux lh)) + +(defun coq-highlight-selected-hyps () + "Highlight all hyps stored in `coq-highlighted-hyps'. +This used in hook to rehilight hypothesis after goals buffer is +updated." + (interactive) + (coq-highlight-hyps coq-highlighted-hyps)) + +(defun coq-unhighlight-selected-hyps () + "Unhighlight all hyps stored in `coq-highlighted-hyps'. +This used before updating `coq-highlighted-hyps' with a new set +of hypothesis to highlight." + (interactive) + (coq-unhighlight-hyps coq-highlighted-hyps) + (setq coq-highlighted-hyps nil)) + +(defun coq-get-hyps-cited-in-response () + "Returns locations of hyps in goals buffer that are cited in response buffer. +See `coq-highlight-hyps-cited-in-response' and `SearchAbout'." + (let* ((hyps-cited-pos (coq-detect-hyps-positions proof-response-buffer)) + (hyps-cited (coq-build-hyps-names hyps-cited-pos))) + (remove-if-not + (lambda (e) + (cl-some;seq-find + (lambda (f) + (string-equal (car e) f)) + hyps-cited)) + coq-hyps-positions))) + +(defun coq-highlight-hyps-cited-in-response () + "Highlight hypothesis cited in response buffer. +Highlight always takes place in goals buffer." + (let ((inters (coq-get-hyps-cited-in-response))) + (coq-unhighlight-selected-hyps) + (setq coq-highlighted-hyps (mapcar 'car inters)) + (coq-highlight-selected-hyps))) + +(defun coq-toggle-highlight-hyp (h) + "Toggle the highlighting status of hypothesis H. +See `coq-highlight-hyp'." + (interactive "sHypothesis name to highlight:") + (if (member h coq-highlighted-hyps) + (coq-unhighlight-hyp h) + (coq-highlight-hyp h))) + +(defun coq-toggle-highlight-hyp-at (pt) + "Toggle hiding the hypothesis at point." + (interactive) + (let* ((ov + (or (car (coq-overlays-at pt 'hyp-name)) + ;; we may be between hypname and hyp, so skip backward to + ;; something meaningful + (save-excursion + (goto-char pt) + (search-backward-regexp "[^ :=]\\|\n") + (car (coq-overlays-at (point) 'hyp-name))))) + (hypname (and ov + (overlay-get ov 'hyp-name)))) + (when hypname + (if (member hypname coq-highlighted-hyps) + (coq-unhighlight-hyp hypname) + (coq-highlight-hyp hypname))))) + +(defun coq-toggle-highlight-hyp-at-point () + (interactive) + (coq-toggle-highlight-hyp-at (point))) + -(defvar coq-highlight-id-last-regexp nil) +(defun coq-insert-at-point-hyp-at-mouse (event) + (interactive "e") + (let ((hyp-name (save-excursion + (with-current-buffer proof-goals-buffer + (save-excursion + (overlay-get (car (overlays-at (posn-point (event-start event)))) + 'hyp-name)))))) + (insert hyp-name))) + +;;;;;;;;;;; Hiding Hypothesis ;;;;;;;;;;; +(defvar coq-hidden-hyp-map (make-sparse-keymap) "Keymap for hidden hypothesis") -(defun coq-highlight-id-in-goals (re) - (with-current-buffer proof-goals-buffer - (highlight-regexp re 'lazy-highlight))) +(defvar coq-hidden-hyps nil + "List of hypothesis that should be hidden in goals buffer. +These are re-hidden at each regeneration of goals buffer +using a hook in `proof-shell-handle-delayed-output-hook'.") -(defun coq-unhighlight-id-in-goals (re) - (with-current-buffer proof-goals-buffer - (unhighlight-regexp re))) -(defun coq-highlight-id-at-pt-in-goals () +(defun coq-toggle-fold-hyp-at (pt) + "Toggle hiding the hypothesis at point." (interactive) - (let* ((id (coq-id-or-notation-at-point)) - (re (regexp-quote (or id "")))) - (when coq-highlight-id-last-regexp - (coq-unhighlight-id-in-goals coq-highlight-id-last-regexp)) - (coq-highlight-id-in-goals re) - (setq coq-highlight-id-last-regexp re))) + (let* ((ov (car (coq-overlays-at pt 'hyp-name))) + (hypname (and ov (overlay-get ov 'hyp-name)))) + (when hypname + (if (member hypname coq-hidden-hyps) + (coq-unfold-hyp hypname) + (coq-fold-hyp hypname))))) + +(defun coq-toggle-fold-hyp-at-point () + (interactive) + (coq-toggle-fold-hyp-at (point))) +(defun coq-toggle-fold-hyp-at-mouse (event) + "Toggle hiding the hypothesis at mouse click. +Used on hyptohesis overlays in goals buffer mainly." + (interactive "e") + (save-excursion + (with-current-buffer proof-goals-buffer + (save-excursion (coq-toggle-fold-hyp-at (posn-point (event-start event))))))) + +(defun coq-configure-hyp-overlay-hidden (hyp-overlay h) + (when hyp-overlay + (let* ((lgthhyp (- (overlay-end hyp-overlay) (overlay-start hyp-overlay))) + (prefx (make-string (min 8 lgthhyp) ?.)) + (hypcross-ov (overlay-get hyp-overlay 'hypcross-ov))) + (overlay-put + hyp-overlay 'display + prefx ;(propertize prefx 'keymap coq-hidden-hyp-map) + ) + (overlay-put hyp-overlay 'evaporate t) + (overlay-put hyp-overlay 'mouse-face 'proof-command-mouse-highlight-face) + (overlay-put hyp-overlay 'help-echo "mouse-3: unfold; mouse-2 copy name") + (overlay-put hyp-overlay 'hyp-name h) + (overlay-put hyp-overlay 'keymap coq-hidden-hyp-map) + (overlay-put hypcross-ov 'display (coq-hypcross-folded-string))))) + +(defun coq-configure-hyp-overlay-visible (hyp-overlay h) + (when hyp-overlay + (overlay-put hyp-overlay 'display nil) + (overlay-put hyp-overlay 'evaporate t) + (overlay-put hyp-overlay 'mouse-face nil) + (overlay-put hyp-overlay 'help-echo nil) + (overlay-put hyp-overlay 'keymap nil) + (overlay-put (overlay-get hyp-overlay 'hypcross-ov) 'display (coq-hypcross-unfolded-string)))) + +(defun coq-fold-hyp-aux (h) + "Fold hypothesis H's type from the context temporarily. +Displays \".......\" instead. This function relies on variable +coq-hyps-positions. The hiding is cancelled as soon as the goals +buffer is changed, consider using `coq-fold-hyp' if you want the +hiding to be maintain when scripting/undoing." + (let ((hyp-overlay (coq-find-hyp-overlay h))) + (when hyp-overlay (coq-configure-hyp-overlay-hidden hyp-overlay h)))) + +(defun coq-fold-hyp (h) + "Fold hypothesis H's type from the context durably. +(displays \".......\" instead). This function relies on variable +coq-hyps-positions. The hiding maintained as the goals buffer is +changed, thanks to a hook on +`proof-shell-handle-delayed-output-hook', consider using +`coq-fold-hyp' if you want the hiding to be maintain when +scripting/undoing." + (interactive) + (unless (member h coq-hidden-hyps) + (setq coq-hidden-hyps (cons h coq-hidden-hyps)) + (coq-fold-hyp-aux h))) + +(defun coq-unfold-hyp-aux (h) +"Unfold hypothesis H temporarily. +See `coq-fold-hyp-aux'." + (let ((hyp-overlay (coq-find-hyp-overlay h))) + (coq-configure-hyp-overlay-visible hyp-overlay h))) + +(defun coq-unfold-hyp (h) +"Unfold hypothesis H durably. +See `coq-fold-hyp'." + (interactive) + (when (member h coq-hidden-hyps) + (setq coq-hidden-hyps (delete h coq-hidden-hyps)) + (coq-unfold-hyp-aux h))) + +(defun coq-unfold-hyp-list (lh) + "Fold the type of hypothesis in LH temporarily. +See `coq-unfold-hyp-aux'." + (mapc 'coq-unfold-hyp-aux lh)) + +(defun coq-fold-hyp-list (lh) + "Fold the type of hypothesis in LH temporarily. +See `coq-fold-hyp-aux'." + (mapc 'coq-fold-hyp-aux lh)) + +(defun coq-fold-hyps () + "Fold the type of hypothesis in LH durably. +See `coq-fold-hyp'." + (interactive) + (coq-fold-hyp-list coq-hidden-hyps)) + + +(defun coq-unfold-hyps () + "Unfold the type of hypothesis in LH durably. +See `coq-unfold-hyp'." + (interactive) + (coq-unfold-hyp-list coq-hidden-hyps) + (setq coq-hidden-hyps nil)) + +(defun coq-toggle-fold-hyp (h) + "Toggle the hiding status of hypothesis H (asked interactively). +See `coq-fold-hyp'." + (interactive "sHypothesis to fold: ") + (if (member h coq-hidden-hyps) + (coq-unfold-hyp h) + (coq-fold-hyp h))) +;;;;;;; (proof-definvisible coq-PrintHint "Print Hint. ") @@ -1840,7 +2233,7 @@ Near here means PT is either inside or just aside of a comment." (defpacustom search-blacklist coq-search-blacklist-string - "Strings to blacklist in requests to coq environment." + "Strings to blacklist in requests to Coq environment." :type 'string :get 'coq-get-search-blacklist :setting coq-set-search-blacklist) @@ -2394,6 +2787,21 @@ Completion is on a quasi-exhaustive list of Coq tacticals." (proof-shell-invisible-command q)))) +;; TODO SearchAbout become Search in v8.5, change when V8.4 becomes old. +(defun coq-SearchAbout () + (interactive) + (coq-ask-do + ;; TODO: use [Add Search Blacklist "foo"] to exclude optionaly some patterns: + ;; "_ind" "_rec" "R_" "_equation" + "SearchAbout (ex: \"eq_\" eq -bool)" + "SearchAbout" + nil nil t) + (when coq-highlight-hyps-cited-in-response + (coq-highlight-hyps-cited-in-response) + (message "M-x coq-unhighlight-selected-hyps to remove highlighting, [Coq/Settings/Search Blacklist] to change blacklisting.")) + (unless coq-highlight-hyps-cited-in-response + (message "[Coq/Settings/Search Blacklist] to change blacklisting."))) + ;; Insertion commands (define-key coq-keymap [(control ?i)] 'coq-insert-intros) (define-key coq-keymap [(control ?m)] 'coq-insert-match) @@ -2443,6 +2851,11 @@ Completion is on a quasi-exhaustive list of Coq tacticals." (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?w)] 'coq-ask-adapt-printing-width-and-show) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?l)] 'coq-LocateConstant) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?n)] 'coq-LocateNotation) +;; specific to goals buffer: (un)foldinng and (un)highlighting shortcuts +(define-key coq-goals-mode-map [?f] 'coq-toggle-fold-hyp-at-point) +(define-key coq-goals-mode-map [?F] 'coq-unfold-hyps) +(define-key coq-goals-mode-map [?h] 'coq-toggle-highlight-hyp-at-point) +(define-key coq-goals-mode-map [?H] 'coq-unhighlight-selected-hyps) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?c)] 'coq-Check) @@ -2481,6 +2894,27 @@ Completion is on a quasi-exhaustive list of Coq tacticals." (define-key proof-goals-mode-map [(control shift down-mouse-1)] 'coq-id-under-mouse-query) (define-key proof-goals-mode-map [(control shift mouse-1)] '(lambda () (interactive)))) + + +;; Default binding on hypothesis names: clicking on the name of an hyp with +;; button 3 folds it. Click on it with button 2 copies the names at current +;; point. +(when coq-hypname-map + (define-key coq-hypname-map [(mouse-3)] 'coq-toggle-fold-hyp-at-mouse) + (define-key coq-hypname-map [(mouse-2)] 'coq-insert-at-point-hyp-at-mouse)) + +;; Default binding: clicking on the cross to folds/unfold hyp. +;; Click on it with button 2 copies the names at current point. +(when coq-hypname-map + (define-key coq-hypcross-map [(mouse-1)] 'coq-toggle-fold-hyp-at-mouse) + (define-key coq-hypcross-map [return] 'coq-toggle-fold-hyp-at-point) + (define-key coq-hypcross-map [(mouse-2)] 'coq-insert-at-point-hyp-at-mouse)) +;; Ddefault binding: clicking on a hidden hyp with button 3 unfolds it, with +;; button 2 it copies hyp name at current point. +(when coq-hidden-hyp-map + (define-key coq-hidden-hyp-map [(mouse-3)] 'coq-toggle-fold-hyp-at-mouse) + (define-key coq-hidden-hyp-map [(mouse-2)] 'coq-insert-at-point-hyp-at-mouse)) + ;;;;;;;;;;;;;;;;;;;;;;;; ;; error handling ;;;;;;;;;;;;;;;;;;;;;;;; @@ -2626,7 +3060,7 @@ number of hypothesis displayed, without hiding the goal" (with-selected-window goal-win ;; find snd goal or buffer end, if not found this goes to the ;; end of buffer - (search-forward-regexp "subgoal 2\\|\\'") + (search-forward-regexp "subgoal 2\\|\\*\\*\\* Unfocused goals:\\|\\'") (beginning-of-line) ;; find something backward else than a space: bottom of concl (ignore-errors (search-backward-regexp "\\S-")) @@ -2683,6 +3117,14 @@ number of hypothesis displayed, without hiding the goal" proof-shell-last-output) (proof-clean-buffer proof-goals-buffer)))) +(add-hook 'proof-shell-handle-delayed-output-hook + (lambda () + (setq coq-hyps-positions (coq-detect-hyps-in-goals)) + (coq-highlight-selected-hyps) + (coq-fold-hyps) + )) + + (defun is-not-split-vertic (selected-window) (<= (- (frame-height) (window-height)) 2)) |