aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--coq/coq-abbrev.el7
-rw-r--r--coq/coq.el62
-rw-r--r--lib/local-vars-list.el226
3 files changed, 292 insertions, 3 deletions
diff --git a/coq/coq-abbrev.el b/coq/coq-abbrev.el
index ae21a1fb..19b2ac44 100644
--- a/coq/coq-abbrev.el
+++ b/coq/coq-abbrev.el
@@ -5,6 +5,10 @@
(interactive)
(describe-variable 'holes-doc))
+(defun coq-local-vars-list-show-doc ()
+ (interactive)
+ (describe-variable 'coq-local-vars-doc))
+
;#s and @{..} are replaced by holes by holes-abbrev-complete
(if (boundp 'holes-abbrev-complete)
()
@@ -390,7 +394,8 @@
;; With all these submenus you have to wonder if these things belong
;; on the main menu. Are they the most often used?
["Compile" coq-Compile t]
- ["Set coq prog name for this file persistently" coq-ask-insert-coq-prog-name t]
+ ["Set coq prog name *for this file persistently*" coq-ask-insert-coq-prog-name t]
+ ["help on setting prog name persistently for a file" coq-local-vars-list-show-doc t]
))
;; da: Moved this from the main menu to the Help submenu.
diff --git a/coq/coq.el b/coq/coq.el
index 3e4f9660..bb4c10fb 100644
--- a/coq/coq.el
+++ b/coq/coq.el
@@ -15,6 +15,7 @@
(require 'proof)
(require 'holes-load) ; in lib directory
+(require 'local-vars-list) ; in lib directory
;; coq-syntaxe is required below
;; ----- coq-shell configuration options
@@ -181,6 +182,63 @@ To disable coqc being called (and use only make), set this to nil."
+(defconst coq-local-vars-doc nil
+ "A very convenient way to customize file-specific variables is to use the
+File Variables ((xemacs)File Variables). This feature of Emacs allows to
+specify the values to use for certain Emacs variables when a file is
+loaded. Those values are written as a list at the end of the file.
+
+We provide the following feature to help you:
+
+\\[coq-ask-insert-coq-prog-name] that builds standard local variable list for a
+coq file by asking you some questions. it is accessible in the menu:
+
+\"coq\"/\"set coq prog name for this file persistently\".
+
+You should be able to use this feature without reading the rest of this
+documentation, which explains how it is used for coq. For more precision, refer
+to the emacs info manual at ((xemacs)File Variables).
+
+In projects involving multiple directories, it is often useful to set the
+variables `proof-prog-name', `proof-prog-args' and `compile-command' for each
+file. Here is an example for Coq users: for the file .../dir/bar/foo.v, if you
+want Coq to be started with the path .../dir/theories/ added in the libraries
+path (\"-I\" option), you can put at the end of foo.v:
+
+(*
+*** Local Variables: ***
+*** coq-prog-name: \"coqtop\" ***
+*** coq-prog-args: (\"-emacs\" \"-I\" \"../theories\") ***
+*** End: ***
+*)
+
+That way the good command is called when the scripting starts in foo.v. Notice
+that the command argument \"-I\" \"../theories\" is specific to the file foo.v,
+and thus if you set it via the configuration tool, you will need to do it each
+time you load this file. On the contrary with this method, Emacs will do this
+operation automatically when loading this file. Please notice that all the
+strings above should never contain spaces see documentation of variables
+`proof-prog-name' and `proof-prog-args'.
+
+Extending the previous example, if the makefile for foo.v is located in
+directory .../dir/, you can add the right compile command. And if you want a
+non standard coq executable to be used, here is what you should put in
+variables:
+
+(*
+ Local Variables:
+ coq-prog-name: \"../../coqsrc/bin/coqtop\"
+ coq-prog-args: \"-emacs\" \"-I\" \"../theories\"
+ compile-command: \"make -C .. -k bar/foo.vo\"
+ End:
+*)
+
+And then the right call to make will be done if you use the \\[compile]
+command. Notice that the lines are commented in order to be ignored by the
+proof assistant. It is possible to use this mechanism for any other buffer
+local variable (info:(xemacs)File Variables).
+" )
+
(defun coq-insert-coq-prog-name (progname progargs)
@@ -1412,8 +1470,8 @@ mouse activation."
(provide 'coq)
;; Local Variables: ***
-;; fill-column: 85 ***
-;; indent-tabs-mode:nil ***
+;; fill-column: 79 ***
+;; indent-tabs-mode: nil ***
;; End: ***
;;; coq.el ends here
diff --git a/lib/local-vars-list.el b/lib/local-vars-list.el
new file mode 100644
index 00000000..7038ebf9
--- /dev/null
+++ b/lib/local-vars-list.el
@@ -0,0 +1,226 @@
+;;; local-vars.el --- local variables list utilities
+;; Copyright (C) 2006 Pierre Courtieu
+;; Authors: Pierre Courtieu
+;; Maintainer: Pierre Courtieu <Pierre.Courtieu@cnam.fr>
+
+;; This software is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public
+;; License version 2, as published by the Free Software Foundation.
+;;
+;; This software is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;; See the GNU General Public License version 2 for more details
+;; (enclosed in the file GPL).
+;;
+;; See documentation in variable holes-short-doc.
+;;
+
+;;; Commentary:
+;; See documentation in variable holes-doc.
+
+;;; History:
+;;
+
+;;; Help:
+
+(defconst local-vars-list-doc nil
+ "Quoting emacs info:
+
+A file can contain a \"local variables list\", which specifies the values to use for
+certain Emacs variables when that file is edited. See info node \"(xemacs)File
+Variables\".
+
+local-vars-list provides two useful functions:
+
+\\[local-vars-list-get] that reads a local variable value at the end of the file.
+
+\\[local-vars-list-set] that writes a local variable value at the end of the file.")
+
+(defun local-vars-list-help (describe-variable 'local-vars-list-doc))
+
+;;TOTO: use the code in xemacs-sources/lisp/files.el
+;; in particular the function hack-local-variables-last-page
+
+(defun local-vars-list-insert-empty-zone ()
+ "Insert an empty local variables zone at the end of the buffer.
+Indents the zone according to mode after insertion."
+ (save-excursion
+ (goto-char (point-max))
+ (let ((pt (point)))
+ (cond
+ ((not comment-start)
+ (insert
+ "
+*** Local Variables: ***
+*** End: ***
+"
+ ))
+
+ ((string-equal comment-end "")
+ (insert
+ (format
+ "
+%s** Local Variables: ***
+%s** End: ***
+"
+ comment-start comment-start)))
+
+ (t
+ (insert
+ (format
+ "
+%s
+*** Local Variables: ***
+*** End: ***
+%s"
+ comment-start comment-end))
+ ))
+ (indent-region pt (point) nil)
+ (message "%s" "Local variables zone added at the end of the buffer."))))
+
+
+(defun local-vars-list-find ()
+ "Find the local variable definition paragraph.
+Return a list containing the prefix and the suffix of its first line,
+or throw 'notfound if not found. Sets the point at the beginning of
+the second line of the paragraph."
+ (goto-char (point-max))
+ (catch 'notfound
+ (if (not (re-search-backward "Local Variables:" nil t)) (throw 'notfound nil))
+ (let ((bol (save-excursion (beginning-of-line) (point)))
+ (eol (save-excursion (end-of-line) (point)))
+ (lpattern)
+ (rpattern))
+ (setq lpattern (buffer-substring bol (point)))
+ (re-search-forward "Local Variables:" eol t)
+ (setq rpattern (buffer-substring (point) eol))
+ (forward-line 1)
+ (beginning-of-line)
+ (cons lpattern (cons rpattern nil)))))
+
+(defun local-vars-list-goto-var (symb lpat rpat)
+ "Search a line defining local variable symb at current line and below.
+If successful set point to the beginning of the *value* and return t.
+Otherwise set point to the beginning of the last line of the local
+variables list (the one containing \"End:\"), and return nil.
+
+lpat and rpat are the suffix and prefix of the local variable list.
+
+Note: this function must be called when at the beginning of a local
+variable definition (or at the \"End:\" line)."
+ (let* ((symbname (symbol-name symb))
+ (found nil) (endreached nil)
+ (eol))
+ (while (and (not found) (not endreached))
+ (setq eol (save-excursion (end-of-line) (point)))
+ (search-forward lpat eol)
+ (re-search-forward "\\([^ :]+\\):" eol)
+ (let ((varname (match-string 1)))
+ (message "varname = %s" varname)
+ (cond
+ ((string-equal varname "End") (setq endreached t) (beginning-of-line))
+ ((string-equal varname symbname) (setq found t))
+ (t (forward-line 1) (beginning-of-line))
+ ))
+ (message "found %s" found)
+ (message "endreached %s" endreached)
+ )
+ (if found t nil)))
+
+
+; precond: really be on a var def line
+(defun local-vars-list-get-current (lpat rpat)
+ "Return the value written in the local variable list at current line.
+
+lpat and rpat are the suffix and prefix of the local variable list.
+
+Note: this function must be called when at the beginning of a local
+variable definition (or at the \"End:\" line)."
+ (let ((bol (save-excursion (beginning-of-line) (point)))
+ (eol (save-excursion (end-of-line) (point)))
+ (varname ""))
+ (catch 'notfound
+ (if (not (search-forward lpat eol t)) (throw 'notfound nil))
+ (if (not (re-search-forward "\\([^ :]+\\):" eol t)) (throw 'notfound nil))
+ (setq varname (match-string 1))
+ (let ((boexp (point)))
+ (if (not (search-forward rpat eol t)) (throw 'notfound nil))
+ (search-backward rpat bol) ; should always succeed
+ (read (buffer-substring boexp (point))))))) ; TODO: catch errors here?
+
+
+
+(defun local-vars-list-set-current (val lpat rpat)
+ "Write the value val in the local variable list at current line.
+
+lpat and rpat are the suffix and prefix of the local variable list.
+
+Note: this function must be called when at the beginning of a local
+variable definition (or at the \"End:\" line)."
+ (let ((bol (save-excursion (beginning-of-line) (point)))
+ (eol (save-excursion (end-of-line) (point)))
+ (varname ""))
+ (search-forward lpat eol)
+ (re-search-forward "\\([^ :]+\\):" eol)
+ (setq varname (match-string 1))
+ (let ((boexp (point)))
+ (search-forward rpat eol)
+ (search-backward rpat bol)
+ (kill-region boexp (point))
+ (insert (format " %S " val))
+ )
+ )
+ )
+
+
+(defun local-vars-list-get (symb)
+ "Return the value written in the local variable list for variable symb.
+Raises an error if symb is not in the list."
+ (save-excursion
+ (let*
+ ((lrpat (local-vars-list-find))
+ (dummy (if lrpat t (error "local variables zone not found. ")))
+ (lpat (car lrpat))
+ (rpat (car (cdr lrpat)))
+ )
+ (beginning-of-line)
+ (if (local-vars-list-goto-var symb lpat rpat)
+ t
+ (error "variable %s not found" symb))
+ (beginning-of-line)
+ (local-vars-list-get-current lpat rpat))))
+
+(defun local-vars-list-set (symb val)
+ "Write the value val in the local variable list for variable symb.
+If the variable is already specified in the list, replace the value. If no local
+variable list is found, create one at the end of the buffer first."
+ (save-excursion
+ (let ((lrpat (local-vars-list-find)))
+ (if (not lrpat)
+ (progn
+ (local-vars-list-insert-empty-zone)
+ (setq lrpat (local-vars-list-find))))
+ (beginning-of-line)
+ (let ((lpat (car lrpat))
+ (rpat (car (cdr lrpat))))
+ (if (local-vars-list-goto-var symb lpat rpat)
+ (progn (beginning-of-line)
+ (local-vars-list-set-current val lpat rpat))
+ (insert (format "%s%s: %S%s\n" lpat (symbol-name symb) val rpat))
+ (forward-line -1)
+ (indent-according-to-mode))))))
+
+
+(provide 'local-vars-list)
+
+
+
+;;; Local Variables: ***
+;;; fill-column: 85 ***
+;;; indent-tabs-mode: nil ***
+;;; End: ***
+
+
+