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