branch: elpa/proof-general
commit 05ad8c2ae97c432abe59dce98b01efd55d9bb041
Author: Pierre Courtieu <pierre.court...@cnam.fr>
Commit: Pierre Courtieu <pierre.court...@cnam.fr>
Plug back and robistify proof-prog-name-ask.
More precisely we try to find coqdep and coqc according to the
user-given prog-name if any. This should make auto compilation more
reliable.
---
coq/coq-system.el | 116 +++++++++++++++++++++++++++++++-------------------
doc/ProofGeneral.texi | 2 +-
2 files changed, 74 insertions(+), 44 deletions(-)
diff --git a/coq/coq-system.el b/coq/coq-system.el
index 8ded6f4d7c..7e7bba02b1 100644
--- a/coq/coq-system.el
+++ b/coq/coq-system.el
@@ -53,8 +53,21 @@ On Windows you might need something like:
(setq coq-prog-env '(\"HOME=C:\\Program Files\\Coq\\\"))"
:group 'coq)
-(defun coq-detect-coqdep () (coq-detect-prog-gen "coqdep" "rocq"))
-(defun coq-detect-coqc () (coq-detect-prog-gen "coqc" "rocq"))
+(defun coq-detect-rocq-cli ()
+ "Return non nil if the detected coq/rocq executable obeys the rocq CLI."
+ (let* ((coq-command (or proof-prog-name (coq-autodetect-progname)))
+ (coq-args (list "c"))
+ (process-args (list coq-command nil t nil "c")))
+ (condition-case nil
+ (with-temp-buffer (equal (apply 'process-file process-args) 0))
+ (error nil))))
+
+(defun coq-detect-coqdep ()
+ (if (coq-detect-rocq-cli) (coq-detect-prog-gen "rocq")
+ (coq-detect-prog-gen "coqdep")))
+(defun coq-detect-coqc ()
+ (if (coq-detect-rocq-cli) (coq-detect-prog-gen "rocq")
+ (coq-detect-prog-gen "coqc")))
;; We return the executable coqtop or rocq. But not the rocq option
;; (dep, c, top)) triggering the particular tool.
@@ -127,8 +140,8 @@ fails. Return also nil on other kinds of errors (e.g.,
`coq-prog-name'
not found).
This function supports calling coqtop via tramp.
This function must not rely on coq-autodetect-version, it would be a cycle."
- (let* ((coq-command (or coq-prog-name (coq-autodetect-progname)))
- (coq-args (if (string-match "rocq" coq-command) (list "top" option)
(list option)))
+ (let* ((coq-command (or proof-prog-name coq-prog-name
(coq-autodetect-progname)))
+ (coq-args (if (coq-detect-rocq-cli) (list "top" option) (list
option)))
(process-args (append (list coq-command nil t nil) coq-args))
retv)
(condition-case nil
@@ -155,7 +168,6 @@ Interactively (with INTERACTIVE-P), show that number."
(let ((coq-output (coq-callcoq "-help")))
(setq coq-autodetected-help (or coq-output ""))))
-
(defun coq--version< (v1 v2)
"Compare Coq versions V1 and V2."
;; -snapshot is only supported by Emacs 24.5, not 24.3
@@ -183,18 +195,6 @@ Returns nil if the version can't be detected."
(signal 'coq-unclassifiable-version coq-version-to-use))
(t (signal (car err) (cdr err))))))))
-(defun coq--post-v9 ()
- "Return t if the auto-detected version of Coq (or rocs) is >= 9.
-Return nil if the version cannot be detected."
- (let ((coq-version-to-use (or (coq-version t) "8.20")))
- (condition-case err
- (not (coq--version< coq-version-to-use "9"))
- (error
- (cond
- ((equal (substring (cadr err) 0 15) "Invalid version")
- (signal 'coq-unclassifiable-version coq-version-to-use))
- (t (signal (car err) (cdr err))))))))
-
(defun coq--post-v86 ()
"Return t if the auto-detected version of Coq is >= 8.6.
Return nil if the version cannot be detected."
@@ -511,7 +511,7 @@ LOADPATH, CURRENT-DIRECTORY, PRE-V85: see
`coq-include-options'."
(defun coq-coqdep-prog-args (loadpath &optional current-directory pre-v85)
"Build a list of option for coqdep."
(append
- (if (coq--post-v9) (list "dep") nil)
+ (if (coq-detect-rocq-cli) (list "dep") nil)
(coq-include-prog-args loadpath current-directory pre-v85)))
(defun coq-coqc-prog-args (loadpath &optional current-directory pre-v85)
@@ -519,7 +519,7 @@ LOADPATH, CURRENT-DIRECTORY, PRE-V85: see
`coq-include-options'."
LOADPATH, CURRENT-DIRECTORY, PRE-V85: see `coq-include-options'."
;; coqtop always adds the current directory to the LoadPath, so don't
;; include it in the -Q options.
- (append (if (coq--post-v9) (list "c") nil)
+ (append (if (coq-detect-rocq-cli) (list "c") nil)
(coq-common-prog-args loadpath current-directory pre-v85)))
;; coq-coqtop-prog-args is the user-set list of arguments to pass to
@@ -532,7 +532,7 @@ LOADPATH, CURRENT-DIRECTORY, PRE-V85: see
`coq-include-options'."
"Build a list of options for coqc.
LOADPATH, CURRENT-DIRECTORY, PRE-V85: see `coq-coqc-prog-args'."
(append
- (if (coq--post-v9) (list "top") nil)
+ (if (coq-detect-rocq-cli) (list "top") nil)
(list "-emacs")
(coq-topfile-prog-arg)
(coq-common-prog-args loadpath current-directory pre-v85)))
@@ -558,23 +558,29 @@ path (including the -R lib options) (see
`coq-load-path')."
;; FIXME: should we add "Make" as a valid project name? Maybe only if
;; _xxProject is not present? And/Or if its content seems ok?
-(defun coq-default-project-find-file (dir)
+;; \\` and \\' avoid matching "_CoqProject~" and such
+(defcustom coq-project-file-regexp "\\`\\(_coqproject\\|_rocqproject\\)\\'"
+ "The regexp matching file names which PG detects as coq/rocq project files.
+
+It is used by `coq--default-project-find-file' in a case insensistive way."
+ :type 'string
+ :safe 'stringp
+ :group 'coq)
+
+
+(defun coq--default-project-find-file (dir)
"Default function for `coq-project-filename'.
If DIR contains an acceptable coq/rocq project file, return it. Return
-nil otherwise. See `coq-project-filename'.
-"
- (let* ((case-fold-search t)
- (files (directory-files dir)))
- ;; \\` and \\' avoid matching "_CoqProject~" and such
- (cl-find-if
- (lambda (s) (string-match "\\`\\(_coqproject\\|_rocqproject\\)\\'" s nil
t))
- files)))
-
-(defcustom coq-project-filename #'coq-default-project-file-p
+nil otherwise. See `coq-project-filename'."
+ (when (file-directory-p dir)
+ (let* ((case-fold-search t) (files (directory-files dir)))
+ (cl-find-if (lambda (s) (string-match coq-project-file-regexp s nil))
files))))
+
+(defcustom coq-project-filename 'coq--default-project-find-file
"Variable containing the function detecting a project file.
-See it default value `coq-default-project-find-file' for an example.
+See its default value `coq--default-project-find-file' for an example.
The function takes one argument, the name of a directory, and returns
the name of a coq/rocq project file it contains if there is one. Return
@@ -608,9 +614,13 @@ files also work and override project file settings.
"Return '(buf alreadyopen) where buf is the buffer visiting coq project file.
alreadyopen is t if buffer already existed."
(when buffer-file-name
- (let* ((projectfiledir (locate-dominating-file buffer-file-name
#'coq-default-project-find-file)))
+ (let* ((projectfiledir
+ (locate-dominating-file
+ buffer-file-name
+ (lambda (f) (funcall coq-project-filename f)))))
(when projectfiledir
- (let* ((projectfile (expand-file-name (coq-default-project-find-file
projectfiledir) projectfiledir))
+ (let* ((projectfilel (funcall coq-project-filename projectfiledir))
+ (projectfile (expand-file-name projectfilel projectfiledir))
;; we store this intermediate result to know if we have to kill
;; the coq project buffer at the end
(projectbufferalreadyopen (find-buffer-visiting projectfile))
@@ -767,18 +777,38 @@ Does nothing if `coq-use-project-file' is nil."
#'coq-load-project-file
nil t)))
-; detecting coqtop args should happen at the last moment before
-; calling the process. In particular it should ahppen after that
-; proof-prog-name-ask is performed, this hook is at the right place.
+;; Detecting coqtop or rocq args should happen at the last moment
+;; before calling the process. In particular it should happen after
+;; that proof-prog-name-ask is performed. This hook is exactly called
+;; after querying proof-prog-name (if proof-prog-name-ask is t). This
+;; way the options can be elaborated correctly (coqtop and rocq have
+;; different options). We first detect executables (taking
+;; proof-prog-name-ask into account), then elaborate the
+;; proof-prog-args. Note: we don't support proof-prog-name-guess
(add-hook 'proof-shell-before-process-hook
(lambda ()
- ;; It seems coq-prog-name and proof-prog-name are not correctly
linked
- ;; so let us make sure they are the same before computing options
- ;; coq < 9 needs "coqtop",
- (setq proof-prog-name (coq-autodetect-progname))
- (setq coq-compiler (coq-detect-coqc))
- (setq coq-dependency-analyzer (coq-detect-coqdep))
+ ;; detect executables unless explicitely set by hand. In
+ ;; this case we try to find coqdep and coqc in the same
+ ;; directory
+ (if (and proof-prog-name-ask proof-prog-name)
+ ;; let us find other executables in the exact same
+ ;; place. TODO: go back to default exec-path if not found?
+ (let ((exec-path (list (file-name-directory proof-prog-name))))
+ (setq coq-compiler (executable-find (coq-detect-coqc)))
+ (setq coq-dependency-analyzer (executable-find
(coq-detect-coqdep))))
+ ;; default: detect everything from the current exec-path
+ (setq proof-prog-name (coq-autodetect-progname))
+ (setq coq-compiler (coq-detect-coqc))
+ (setq coq-dependency-analyzer (coq-detect-coqdep)))
+ (when coq-debug
+ (message "coq-proof-prog-name: %S" proof-prog-name)
+ (message "coq-dependency-analyzer: %S" coq-dependency-analyzer)
+ (message "coq-compiler: %S" coq-compiler))
+ ;; in principe coq-prog-name is only used to set up
+ ;; proof-prog-name, but it may sometimes be used by itself
+ ;; so let us sync them
(setq coq-prog-name proof-prog-name)
+ ;; now elaborate args
(setq coq-prog-args (coq-prog-args))))
;; smie's parenthesis blinking is too slow, let us have the default one back
diff --git a/doc/ProofGeneral.texi b/doc/ProofGeneral.texi
index 855f684f66..d7e2cc910e 100644
--- a/doc/ProofGeneral.texi
+++ b/doc/ProofGeneral.texi
@@ -4523,7 +4523,7 @@ Documentation of the user option
@code{coq-project-filename}:
@defvar coq-project-filename
Variable containing the function detecting a project file.
-See it default value @samp{@code{coq-default-project-find-file}} for an
example.
+See its default value @samp{@code{coq--default-project-find-file}} for an
example.
The function takes one argument, the name of a directory, and returns
the name of a coq/rocq project file it contains if there is one. Return