aboutsummaryrefslogtreecommitdiff
path: root/isa/thy-mode.el
diff options
context:
space:
mode:
authorDavid Aspinall2006-12-05 12:49:56 +0000
committerDavid Aspinall2006-12-05 12:49:56 +0000
commit7077e2e8fed4a52af4894954c8446781cb5d40d6 (patch)
tree023224bae2e0e278d99e94bba2f0d3fe98984495 /isa/thy-mode.el
parent1ea338cca92204c9a98a373adb80ab60c3a10107 (diff)
Deleted file
Diffstat (limited to 'isa/thy-mode.el')
-rw-r--r--isa/thy-mode.el1045
1 files changed, 0 insertions, 1045 deletions
diff --git a/isa/thy-mode.el b/isa/thy-mode.el
deleted file mode 100644
index 2eef0988..00000000
--- a/isa/thy-mode.el
+++ /dev/null
@@ -1,1045 +0,0 @@
-;; thy-mode.el - Mode for Isabelle theory files.
-;;
-;; Copyright (C) 1998 LFCS Edinburgh.
-;; Author: David Aspinall <David.Aspinall@ed.ac.uk>
-;; License: GPL (GNU GENERAL PUBLIC LICENSE)
-;;
-;; Taken from Isamode, version: 3.6 1998/09/02 11:40:45
-;;
-;; $Id$
-;;
-;; NAMESPACE management: all functions and variables declared
-;; in this file begin with thy-
-
-(require 'proof-site)
-(require 'proof-syntax)
-(require 'isa)
-
-;; In case thy mode was invoked directly or by -*- thy -*- at
-;; the start of the file, ensure that isa mode is used from now
-;; on for .thy files.
-;; FIXME: be less messy with auto-mode-alist here (remove dups)
-(setq auto-mode-alist
- (cons '("\\.thy$" . isa-mode) auto-mode-alist))
-
-;;; ========== Theory File Mode User Options ==========
-
-(defcustom thy-heading-indent 0
- "Indentation for section headings."
- :type 'integer
- :group 'thy)
-
-(defcustom thy-indent-level 2
- "*Indentation level for Isabelle theory files. An integer."
- :type 'integer
- :group 'thy)
-
-(defcustom thy-indent-strings t
- "If non-nil, indent inside strings.
-You may wish to disable indenting inside strings if your logic uses
-any of the usual bracket characters in unusual ways."
- :type 'boolean
- :group 'thy)
-
-(defcustom thy-use-sml-mode nil
- "*If non-nil, invoke sml-mode inside \"ML\" section of theory files.
-This option is left-over from Isamode. Really, it would be more
-useful if the script editing mode of Proof General itself could be based
-on sml-mode, but at the moment there is no way to do this."
- :type 'boolean
- :group 'thy)
-
-
-;;; ====== Theory and ML file templates =========================
-
-(defcustom thy-sections
- ;; NB: preceding white space in templates deleted by indentation alg.
- ;; top must come first.
- '(("top" . thy-insert-header)
- ("classes" . thy-insert-class)
- ("default" . thy-insert-default-sort) ; is "default" obsolete?
- ("defaultsort" . thy-insert-default-sort)
- ("types" . thy-insert-type)
- ("typedecl")
- ("arities" . thy-insert-arity)
- ;; =================================
- ;; These only make sense for HOL.
- ;; Ideally we should parameterise these parts on the theory.
- ("datatype") ("typedef")
- ("inductive") ("coninductive")
- ("intrs") ("monos")
- ("primrec") ("recdef")
- ("rep_datatype") ("distinct") ("induct")
- ;; ==============================
- ("consts" . thy-insert-const)
- ("translations" . "\"\"\t==\t\"\"")
- ("axclass")
- ("syntax")
- ("instance")
- ("rules" . thy-insert-rule)
- ("defs" . thy-insert-rule)
- ("axioms" . thy-insert-rule)
- ("use")
- ("theory")
- ("files")
- ("constdefs")
- ("oracle")
- ("local")
- ("locale")
- ("nonterminals")
- ("setup")
- ("global")
- ("end")
- ("ML"))
- "Names of theory file sections and their templates.
-Each item in the list is a pair of a section name and a template.
-A template is either a string to insert or a function. Useful functions are:
- thy-insert-header, thy-insert-class, thy-insert-default-sort,
- thy-insert-const, thy-insert-rule.
-The nil template does nothing.
-You can add extra sections to theory files by extending this variable."
- :type '(repeat
- (cons string
- (choice function
- string
- (const :tag "no template" nil))))
- :group 'thy)
-
-(defcustom thy-id-header
- "(*
- File: %f
- Theory Name: %t
- Logic Image: %l
-*)\n\n"
- "*Identification header for .thy and .ML files.
-Format characters: %f replaced by filename, %t by theory name,
-and %l by the logic image name this file should be read in."
- :group 'thy
- :type 'string)
-
-(defcustom thy-template
-"%t = %p +\n
-classes\n
-default\n
-types\n
-arities\n
-consts\n
-translations\n
-rules\n
-end\n
-ML\n"
-"Template for theory files.
-Contains a default selection of sections in a traditional order.
-You can use the following format characters:
-
-`%t' --- replaced by theory name.
-
-`%p' --- replaced by names of parents, separated by `+' characters."
- :group 'thy
- :type 'string)
-
-
-
-;;; ========== Code ==========
-
-(defvar thy-mode-map nil)
-
-(defvar thy-mode-syntax-table nil) ; Shared below.
-
-(if thy-mode-syntax-table
- nil
- ;; This is like sml-mode, except:
- ;; . is a word constituent (not punctuation). (bad for comments?)
- ;; " is a paired delimiter
- (setq thy-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\( "()1 " thy-mode-syntax-table)
- (modify-syntax-entry ?\) ")(4 " thy-mode-syntax-table)
- (modify-syntax-entry ?\\ "\\ " thy-mode-syntax-table)
- (modify-syntax-entry ?* ". 23" thy-mode-syntax-table)
- (modify-syntax-entry ?_ "w " thy-mode-syntax-table)
- (modify-syntax-entry ?\' "w " thy-mode-syntax-table)
-; it's annoying to match with quotes from previous strings,
-; so this has been removed.
-; (modify-syntax-entry ?\" "$ " thy-mode-syntax-table)
- (modify-syntax-entry ?. "w " thy-mode-syntax-table))
-
-(or thy-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [(control up)] 'thy-goto-prev-section)
- (define-key map [(control down)] 'thy-goto-next-section)
- (define-key map "\C-c\C-n" 'thy-goto-next-section)
- (define-key map "\C-c\C-p" 'thy-goto-prev-section)
- (define-key map "\C-c\C-m" 'thy-minor-sml-mode)
- (define-key map "\C-c\C-t" 'thy-insert-template)
- ;; Disabled for Proof General
- ;;(define-key map "\C-c\C-u" 'thy-use-file)
- ;;(define-key map "\C-c\C-l" 'thy-raise-windows)
- (define-key map "\C-c\C-o" 'thy-find-other-file)
- (define-key map "\C-M" 'newline-and-indent)
- (define-key map "\C-k" 'thy-kill-line)
- (setq thy-mode-map map)))
-
-(defun thy-add-menus (&optional file)
- "Add Proof General and Isabelle menu to current menu bar."
- (require 'proof-script) ; Later: proof-menu, autoloaded
- (easy-menu-define thy-mode-pg-menu
- thy-mode-map
- "PG Menu for Isabelle Proof General"
- (cons proof-general-name
- (append
- (list
- ;; A couple from the toolbar that make sense here
- ;; (also in proof-universal-keys)
- ["Issue command" proof-minibuffer-cmd t]
- ["Interrupt prover" proof-interrupt-process t])
- (list proof-buffer-menu)
- (list proof-help-menu))))
- (easy-menu-define thy-mode-isa-menu
- thy-mode-map
- "Menu for Isabelle Proof General, theory file mode."
- (cons "Theory"
- (list
- ["Next Section" thy-goto-next-section t]
- ["Prev Section" thy-goto-prev-section t]
- ["Insert Template" thy-insert-template t]
- ["Process Theory" isa-process-thy-file
- :active (proof-locked-region-empty-p)]
- ["Retract Theory" isa-retract-thy-file
- :active (proof-locked-region-full-p)]
- ["Next Error" proof-next-error t]
- ["Switch to Script" thy-find-other-file t])))
- (easy-menu-add thy-mode-pg-menu thy-mode-map)
- (easy-menu-add thy-mode-isa-menu thy-mode-map)
-
- (if file
- (progn (easy-menu-remove thy-mode-deps-menu)
- (proof-thy-menu-define-deps file)
- (easy-menu-add thy-mode-deps-menu thy-mode-map))))
-
-
-(defun thy-mode (&optional nomessage)
- "Major mode for editing Isabelle theory files.
-\\<thy-mode-map>
-\\[thy-goto-next-section]\t Skips to the next section.
-\\[thy-goto-prev-section]\t Skips to the previous section.
-
-\\[indent-for-tab-command]\t Indents the current line.
-
-\\[thy-insert-template]\t Inserts a template for the file or current section.
-
-If thy-use-sml-mode is non-nil, \\<thy-mode-map>\\[thy-minor-sml-mode] \
-invokes sml-mode as a minor mode
-in the ML section. This is done automatically by \
-\\[indent-for-tab-command].
-
-The style of indentation for theory files is controlled by these variables:
- thy-heading-indent
- thy-indent-level
- thy-indent-strings
-- see individual variable documentation for details.
-
-Here is the full list of theory mode key bindings:
-\\{thy-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (setq major-mode 'thy-mode)
- (setq mode-name "Theory")
- (use-local-map thy-mode-map)
- (thy-add-menus)
-
- (set-syntax-table thy-mode-syntax-table)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'thy-indent-line)
- (make-local-variable 'comment-start) ; Following lines as in sml-mode
- (setq comment-start "(* ") ; .
- (make-local-variable 'comment-end) ; .
- (setq comment-end " *)") ; .
- (setq comment-start-skip "(\\*+[ \t]?") ; .
- (setq font-lock-keywords
- thy-mode-font-lock-keywords)
-
- ;; Toolbar: needs alteration for non-scripting mode!
- ;; (if (featurep 'proof-toolbar)
- ;; (proof-toolbar-setup))
- ;;
-
-
- (run-hooks 'thy-mode-hook)
- (force-mode-line-update)
- (if (null nomessage)
- (message
- (substitute-command-keys
- "Isabelle theory-file mode. Use \\[thy-insert-template] to insert templates; \\[describe-mode] for help.")))
- )
-
-(defun thy-mode-quiet ()
- (interactive)
- (thy-mode t))
-
-
-
-
-;;; "use" and "use_thy" with theory files ========================
-
-;;; FIXME: Isabelle has been improved, so the following code could
-;;; be cleaned up. Also set variable to allow automatic starting
-;;; of process by reading logic image.
-
-;;; NB: this is a mess at the moment because of the theory file
-;;; naming conventions. Really we need to parse the theory/ML
-;;; file - yuk!!
-;;; The next version of Isabelle will be more consistent.
-
-;(defun thy-use-file (&optional force-use_thy)
-; "Send the file of the current buffer to an Isabelle buffer with use_thy or use."
-; (interactive "P")
-; (let ((fname (buffer-file-name)))
-; (if fname
-; (isa-query-save (current-buffer))
-; (setq fname
-; (or (buffer-file-name)
-; (read-file-name "Use file: " nil nil t))))
-; (let*
-; ((has-thy-extn (string-match "\\.thy$" fname)) ; o/w assume ML.
-; (tname (if has-thy-extn
-; (substring fname 0 -4); cos use_thy is daft!
-; fname))
-; (use (if (or has-thy-extn force-use_thy)
-; "use_thy"
-; "use"))
-; (use-thy-string (concat use " \"" tname "\";"))
-; (logic (isa-guess-root)))
-; (thy-send-string logic use-thy-string))))
-
-;(defun thy-use-region (beg end)
-; "Send the region to an Isabelle buffer, with use"
-; (interactive "r")
-; (write-region beg end thy-use-tempname nil 'nomessage)
-; (let* ((use-thy-string (concat "use \"" thy-use-tempname "\";"))
-; (logic (isa-guess-root)))
-; (thy-send-string logic use-thy-string)))
-
-;(defun thy-copy-region (beg end &optional isa-buffer)
-; "Copy the region to an Isabelle buffer."
-; (interactive "r")
-; (let ((text (buffer-substring beg end))
-; (logic (isa-guess-root)))
-; (save-excursion
-; (thy-send-string logic text))))
-
-;(defun thy-use-line (&optional isabuffer)
-; "Send the current interactive ML line to an Isabelle buffer.
-;Advance to the next line."
-; (interactive)
-; (isa-apply-to-interactive-line 'thy-copy-region))
-
-;(defun thy-send-string (logic text &optional hide)
-; "Send TEXT to a buffer running LOGIC.
-;If LOGIC is nil, pick the first Isabelle buffer."
-; (require 'isa-mode)
-; (setq logic nil) ;;; #### HACK! This all needs changing for single-session.
-; (let ((cur-frm (selected-frame))) ; Preserve selected frame.
-; (if logic ; switch to Isabelle buffer, without
-; (isabelle-session logic) ; raising the frame.
-; ; (NB: this fails if was renamed).
-; (set-buffer
-; (or (car-safe (isa-find-buffers-in-mode 'isa-mode))
-; (error "Can't find an Isabelle buffer"))))
-; (if hide
-; (isa-send-string
-; (get-buffer-process (current-buffer))
-; text)
-; (isa-insert-ret text)) ; send use command
-; (select-frame cur-frm)))
-
-(defun thy-proofgeneral-send-string (logic text &optional hide)
- ;; FIXME -- new function!
- )
-
-;(defun thy-raise-windows ()
-; "Raise windows/frames associated with Isabelle session."
-; (interactive)
-; (isa-select-buffer isa-session-buffer t)
-; (let ((raise t))
-; (mapcar 'isa-display-if-active
-; isa-associated-buffers)))
-
-
-;(defun thy-guess-logic-in-use ()
-; (if (featurep 'isa-mode)
-; (let* ((buf (car-safe (isa-find-buffers-in-mode 'isa-mode)))
-; (log (and buf
-; (save-excursion
-; (set-buffer buf)
-; isa-logic-name))))
-; log)
-; nil))
-
-
-;(defvar thy-use-tempname ".region.ML"
-; "*Name of temporary file to hold region dring thy-use-region.")
-
-
-;(defconst thy-logic-image-regexp
-; "[lL][oO][gG][iI][cC] [iI][mM][aA][gG][eE]:[ \t]*\"?\\([^ \t\n\"]+\\)\"?[ \t]*$"
-; "Regexp for locating name of logic image file in a .thy or .ML file.")
-
-;(defvar isa-logic-parents
-; ;; I can't be bothered to write all of them in here,
-; ;; and anyway they're ambiguous. Use "Logic image:"
-; ;; instead. (Or find a way of getting emacs to track
-; ;; theory structure...)
-; '(("List" . "HOL") ("Prod" . "HOL") ("Nat" . "HOL")
-; ("Ord" . "HOL") ("Set" ."HOL") ("Sexp" . "HOL")
-; ("Univ" . "HOL") ("WF" . "HOL") ("Sum" . "HOL")
-; ("IFOL" . "FOL"))
-; "*An alist of parents of theories that live in logic files.")
-
-;(defun isa-guess-root ()
-; "Guess the root logic of the .thy or .ML file in current buffer.
-;Choice based on first name found by:
-; (i) special text: \"Logic Image: <name>\" toward start of file
-; (ii) guess work based on parent in THY = <parent> if a .thy file."
-; (save-excursion
-; (goto-char (point-min))
-; (cond
-; ((re-search-forward thy-logic-image-regexp 500 t)
-; (buffer-substring (match-beginning 1) (match-end 1)))
-; ((and (string-match "\\.thy$" (or (buffer-file-name) ""))
-; (re-search-forward
-; "\\w+[ \t\n]*=[ \t\n]*\\(\\w+\\)[ \t\n]*\\+") 500 t)
-; ;; Something looks like a parent theory:
-; ;; MyThy = HOL + ...
-; (let ((child
-; (buffer-substring (match-beginning 1) (match-end 1))))
-; (or (cdr-safe (assoc child isa-logic-parents))
-; child))))))
-
-;(defun isa-query-save (buffer)
-; (and (buffer-modified-p buffer)
-; (y-or-n-p (concat "Save file "
-; (buffer-file-name buffer)
-; "? "))
-; (save-excursion (set-buffer buffer) (save-buffer))))
-
-
-
-
-;;; Interfacing with sml-mode ========================
-
-;; extending sml-mode. This only works if you visit the theory file
-;; (or start Isabelle mode) first.
-;; This is probably fairly close to The Right Thing...
-
-(defun isa-sml-hook ()
- "Hook to customize sml-mode for use with Isabelle."
- ;(isa-menus) ; Add Isabelle main menu
- ;; NB: these keydefs will affect other sml-mode buffers too!
- (define-key sml-mode-map "\C-c\C-o" 'thy-find-other-file)
- ; Disabled for proof general
- ;(define-key sml-mode-map "\C-c\C-u" 'thy-use-file)
- ;(define-key sml-mode-map "\C-c\C-r" 'thy-use-region)
- ;(define-key sml-mode-map "\C-c\C-l" 'thy-use-line)
- ;; listener minor mode removed: \C-c\C-c freed up
- (define-key sml-mode-map "\C-c\C-t" 'thy-insert-id-header))
-
-(add-hook 'sml-mode-hook 'isa-sml-hook)
-
-(defun isa-sml-mode ()
- "Invoke sml-mode after installing Isabelle hook."
- (interactive)
- (and (fboundp 'sml-mode) (sml-mode)))
-
-(defcustom isa-ml-file-extension ".ML"
- "*File name extension to use for ML files."
- :type 'string
- :group 'isabelle)
-
-(defun thy-find-other-file (&optional samewindow)
- "Find associated .ML or .thy file.
-Finds and switch to the associated ML file (when editing a theory file)
-or theory file (when editing an ML file).
-If SAMEWINDOW is non-nil (interactively, with an optional argument)
-the other file replaces the one in the current window."
- (interactive "p")
- (and
- (buffer-file-name)
- (let* ((fname (buffer-file-name))
- (thyfile (string-match "\\.thy$" fname))
- (mlfile (string-match
- (concat (regexp-quote isa-ml-file-extension) "$") fname))
- (basename (file-name-sans-extension fname))
- (findfn (if samewindow 'find-file else 'find-file-other-window)))
- (cond (thyfile
- (funcall findfn (concat basename isa-ml-file-extension)))
- (mlfile
- (funcall findfn (concat basename ".thy")))))))
-
-
-;;; "minor" sml-mode inside theory files ==========
-
-(defvar thy-minor-sml-mode-map nil)
-
-(defun thy-install-sml-mode ()
- (progn
- (require 'sml-mode)
- (setq thy-minor-sml-mode-map (copy-keymap sml-mode-map))
- ;; Bind TAB to what it should be in sml-mode.
- (define-key thy-minor-sml-mode-map "\t" 'indent-for-tab-command)
- (define-key thy-minor-sml-mode-map "\C-c\C-m" 'thy-mode-quiet)
- (define-key thy-minor-sml-mode-map "\C-c\C-t" 'thy-insert-template)))
-
-(defun thy-minor-sml-mode ()
- "Invoke sml-mode as if a minor mode inside a theory file.
-This has no effect if thy-use-sml-mode is nil."
- (interactive)
- (if thy-use-sml-mode
- (progn
- (if (not (boundp 'sml-mode))
- (thy-install-sml-mode))
- (kill-all-local-variables)
- (sml-mode) ; Switch to sml-mode
- (setq major-mode 'thy-mode)
- (setq mode-name "Theory Sml") ; looks like it's a minor-mode.
- (use-local-map thy-minor-sml-mode-map) ; special map has \C-c\C-c binding.
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'thy-do-sml-indent)
- (force-mode-line-update)
- (message "Use C-c C-c to exit SML mode."))))
-
-(defun thy-do-sml-indent ()
- "Run sml-indent-line in an Isabelle theory file, provided inside ML section.
-If not, will turn off simulated minor mode and run thy-indent-line."
- (interactive)
- (if (string= (thy-current-section) "ML") ; NB: Assumes that TAB key was
- (sml-indent-line) ; bound to sml-indent-line.
- (thy-mode t) ; (at least, it is now!).
- (thy-indent-line)))
-
-
-(defun thy-insert-name (name)
- "Insert NAME -- as a string if there are non-alphabetic characters in NAME."
- (if (string-match "[a-zA-Z]+" name)
- (insert name)
- (insert "\"" name "\"")))
-
-(defun thy-insert-class (name supers)
- (interactive
- (list
- (isa-read-id "Class name: ")
- (isa-read-idlist "Super classes %s: ")))
- (insert name)
- (if supers (insert "\t< " (isa-splice-separator ", " supers)))
- (indent-according-to-mode)
- (forward-line 1))
-
-(defun thy-insert-default-sort (sort)
- (interactive
- (list
- (isa-read-id "Default sort: ")))
- (insert sort)
- (indent-according-to-mode)
- (thy-goto-next-section))
-
-(defun thy-insert-type (name no-of-args)
- (interactive
- (list
- (isa-read-id "Type name: ")
- (isa-read-num "Number of arguments: ")))
- ;; make type variables for arguments. Daft things for >26!
- (cond
- ((zerop no-of-args))
- ((= 1 no-of-args)
- (insert "'a "))
- (t
- (insert "(")
- (let ((i 0))
- (while (< i no-of-args)
- (if (> i 0) (insert ","))
- (insert "'" (+ ?a i))
- (setq i (1+ i))))
- (insert ") ")))
- (thy-insert-name name)
- (indent-according-to-mode)
- ;; forward line, although use may wish to add infix.
- (forward-line 1))
-
-(defun thy-insert-arity (name param-sorts result-class)
- (interactive
- (list
- (isa-read-id "Type name: ")
- (isa-read-idlist "Parameter sorts %s: ")
- (isa-read-id "Result class: ")))
- (insert name " :: ")
- (if param-sorts
- (insert "(" (isa-splice-separator ", " param-sorts) ") "))
- (insert result-class)
- (indent-according-to-mode)
- (forward-line 1))
-
-(defun thy-insert-const (name type)
- ;; only does a single constant, no lists.
- (interactive
- (let* ((thename (isa-read-id "Constant name: "))
- (thetype (isa-read-string (format "Type of `%s' : " thename))))
- (list thename thetype)))
- (thy-insert-name name)
- (insert " ::\t \"" type "\"\t\t")
- (indent-according-to-mode)
- ;; no forward line in case user adds mixfix
- )
-
-(defun thy-insert-rule (name)
- (interactive
- (list
- (isa-read-id "Axiom name: ")))
- (end-of-line 1)
- (insert name "\t\"\"")
- (backward-char)
- (indent-according-to-mode))
-
-(defun thy-insert-template ()
- "Insert a syntax template according to the current section"
- (interactive)
- (thy-check-mode)
- (let* ((sect (thy-current-section))
- (tmpl (cdr-safe (assoc sect thy-sections))))
- ;; Ensure point is at start of an empty line.
- (beginning-of-line)
- (skip-chars-forward "\t ")
- (if (looking-at sect)
- (progn
- (forward-line 1)
- (skip-chars-forward "\t ")))
- (if (looking-at "$")
- nil
- (beginning-of-line)
- (newline)
- (forward-line -1))
- (cond ((stringp tmpl)
- (insert tmpl)
- (indent-according-to-mode))
- ((null tmpl)) ; nil is a symbol!
- ((symbolp tmpl)
- (call-interactively tmpl)))))
-
-;;; === Functions for reading from the minibuffer.
-;;;
-
-; These could be improved, e.g. to enforce syntax for identifiers.
-; Unfortunately, Xemacs, and now Emacs too, lack a
-; read-no-blanks-input function!
-
-(defun isa-read-idlist (prompt &optional init)
- "Read a list of identifiers from the minibuffer."
- (let ((items init) item)
- (while (not (string= ""
- (setq item (read-string
- (format prompt (or items ""))))))
- (setq items (nconc items (list item))))
- items))
-
-(defun isa-read-id (prompt &optional init)
- "Read an identifier from the minibuffer."
- ;; don't allow empty input
- (let ((result ""))
- (while (string= result "")
- (setq result (read-string prompt init)))
- result))
-
-(defun isa-read-string (prompt &optional init)
- "Read a non-empty string from the minibuffer"
- ;; don't allow empty input
- (let ((result ""))
- (while (string= result "")
- (setq result (read-string prompt init)))
- result))
-
-(defun isa-read-num (prompt)
- "Read a number from the minibuffer."
- (read-number prompt t))
-
-;(defun thy-read-thy-name ()
-; (let* ((default (car
-; (isa-file-name-cons-extension
-; (file-name-nondirectory
-; (abbreviate-file-name (buffer-file-name)))))))
-; default))
-
-(defun thy-read-thy-name ()
- (let* ((default (car
- (isa-file-name-cons-extension
- (file-name-nondirectory
- (abbreviate-file-name (buffer-file-name))))))
- (name (read-string
- (format "Name of theory [default %s]: " default))))
- (if (string= name "") default name)))
-
-(defun thy-read-logic-image ()
- (let* ((defimage "Pure")
- ;; (or (thy-guess-logic-in-use)
- ;; "Pure"))
-
- (logic (read-string
- (format "Name of logic image to use [default %s]: "
- defimage))))
- (if (string= logic "") defimage logic)))
-
-(defun thy-insert-header (name logic parents)
- "Insert a theory file header, for LOGIC, theory NAME with PARENTS"
- (interactive
- (list
- (thy-read-thy-name)
- (thy-read-logic-image)
- (isa-read-idlist "Parent theory %s: ")))
- (let* ((parentplus (isa-splice-separator
- " + "
- (or parents (list (or logic "Pure")))))
- (formalist (list
- (cons "%t" name)
- (cons "%p" parentplus))))
- (thy-insert-id-header name logic)
- (insert (isa-format formalist thy-template)))
- (goto-char (point-min))
- (thy-goto-next-section))
-
-(defun thy-insert-id-header (name logic)
- "Insert an identification header, for theory NAME logic image LOGIC."
- (interactive
- (list
- (thy-read-thy-name)
- (thy-read-logic-image)))
- (let* ((formalist (list
- (cons "%f" (buffer-file-name))
- (cons "%t" name)
- (cons "%l" logic))))
- (insert (isa-format formalist thy-id-header))))
-
-(defun thy-check-mode ()
- (if (not (eq major-mode 'thy-mode))
- (error "Not in Theory mode.")))
-
-
-(defconst thy-headings-regexp
- (concat
- "^\\s-*\\("
- (substring (apply 'concat (mapcar
- '(lambda (pair)
- (concat "\\|" (car pair)))
- (cdr thy-sections))) 2)
- "\\)[ \t]*")
- "Regular expression matching headings in theory files.")
-
-(defvar thy-mode-font-lock-keywords
- (list
- (list (proof-ids-to-regexp
- (append '("infixl" "infixr" "binder")
- (mapcar 'car (cdr thy-sections))))
- 0 'font-lock-keyword-face)
- ;; FIXME: needs more work. Get symbols in quotes, etc, etc.
- (list "\\s-*\\(\\w+\\)\\s-*\\(::?\\)"
- 2 'font-lock-preprocessor-face)
- (list "\\s-*\\(\\w+\\)\\s-*::?"
- 1 'font-lock-variable-name-face)
- (list "\".*\"\\s-*\\(::?\\)"
- 1 'font-lock-preprocessor-face)
- (list "\"\\(.*\\)\"\\s-*\\(::?\\)"
- 1 'font-lock-variable-name-face))
-; (list "^\\s-*\\(\\w*\\)\\s-*\\(::\\)"
-; 1 'font-lock-function-name-face
-; 2 'font-lock-preprocessor-face))
- "Font lock keywords for thy-mode.")
-
-;;; movement between sections ===================================
-
-(defun thy-goto-next-section (&optional count noerror)
- "Goto the next (or COUNT'th next) section of a theory file.
-Negative value for count means previous sections.
-If NOERROR is non-nil, failed search will not be signalled."
- (interactive "p")
- (condition-case nil
- ;; string matching would probably be good enough
- (cond ((and count (< count 0))
- (let ((oldp (point)))
- (beginning-of-line)
- (thy-goto-top-of-section)
- ;; not quite right here - should go to top
- ;; of file, like top of section does.
- (if (equal (point) oldp)
- (progn
- (re-search-backward thy-headings-regexp
- nil nil (1+ (- count)))
- (forward-line 1))))
- t)
- (t
- (re-search-forward thy-headings-regexp nil nil count)
- (forward-line 1)
- t))
- ;; could just move to top or bottom if this happens, instead
- ;; of giving this error.
- (search-failed (if noerror nil
- (error "No more headings")))))
-
-(defun thy-goto-prev-section (&optional count noerror)
- "Goto the previous section (or COUNT'th previous) of a theory file.
-Negative value for count means following sections.
-If NOERROR is non-nil, failed search will not be signalled."
- (interactive)
- (thy-goto-next-section (if count (- count) -1) noerror))
-
-(defun thy-goto-top-of-section ()
- "Goto the top of the current section"
- (interactive)
- (if (re-search-backward thy-headings-regexp nil t)
- (forward-line 1)
- (goto-char (point-min))))
-
-(defun thy-current-section ()
- "Return the current section of the theory file, as a string.
-\"top\" indicates no section."
- (save-excursion
- (let* ((gotsect (re-search-backward thy-headings-regexp nil t))
- (start (if gotsect
- (progn
- (skip-chars-forward " \t")
- (point)))))
- (if (not start)
- "top"
- (skip-chars-forward "a-zA-z")
- (buffer-substring start (point))))))
-
-
-
-;;; kill line ==================================================
-
-(defun thy-kill-line (&optional arg)
- "As kill-line, except in a string will kill continuation backslashes also.
-Coalesces multiple lined strings by leaving single spaces."
- (interactive "P")
- (let ((str (thy-string-start))
- (kill-start (point))
- following-slash)
- (if (not str)
- ;; Usual kill line if not inside a string.
- (kill-line arg)
- (if arg
- (forward-line (prefix-numeric-value arg))
- (if (eobp)
- (signal 'end-of-buffer nil)))
- (setq kill-start (point))
- (if (thy-string-start str) ; if still inside a string
- (cond
- ((looking-at "[ \t]*$") ; at end of line bar whitespace
- (skip-chars-backward
- " \t"
- (save-excursion (beginning-of-line) (1+ (point))))
- (backward-char)
- (if (looking-at "\\\\") ; preceding backslash
- (progn
- (skip-chars-backward " \t")
- (setq following-slash t)
- (setq kill-start (min (point) kill-start)))
- (goto-char kill-start))
- (forward-line 1))
- ((looking-at "[ \t]*\\\\[ \t]*$") ; before final backslash
- (setq following-slash t)
- (forward-line 1))
- ((looking-at "\\\\[ \t]*\\\\[ \t]*$") ; an empty line!
- (forward-line 1))
- ((looking-at ".*\\(\\\\\\)[ \t]*$") ; want to leave backslash
- (goto-char (match-beginning 1)))
- ((and kill-whole-line (bolp))
- (forward-line 1))
- (t
- (end-of-line))))
- (if (and following-slash
- (looking-at "[ \t]*\\\\")) ; delete following slash if
- (goto-char (1+ (match-end 0)))) ; there's one
- (kill-region kill-start (point)) ; do kill
- (if following-slash
- ;; did do just-one-space, but it's not nice to delete backwards
- ;; too
- (delete-region (point)
- (save-excursion
- (skip-chars-forward " \t")
- (point)))))))
-
-
-;;; INDENTATION ==================================================
-
-;;; Could do with thy-correct-string function,
-;;; which does roughly the same as indent-region.
-;;; Then we could have an electric " that did this!
-
-;;; Could perhaps have used fill-prefix to deal with backslash
-;;; indenting, rather than lengthy code below?
-
-(defun thy-indent-line ()
- "Indent the current line in an Isabelle theory file.
-If in the ML section, this switches into a simulated minor sml-mode."
- (let ((sect (thy-current-section)))
- (cond
- ((and thy-use-sml-mode (string= sect "ML"))
- (progn ; In "ML" section,
- (thy-minor-sml-mode) ; switch to sml mode.
- (sml-indent-line)))
-
- (t (let ((indent (thy-calculate-indentation sect)))
- (save-excursion
- (beginning-of-line)
- (let ((beg (point)))
- (skip-chars-forward "\t ")
- (delete-region beg (point)))
- (indent-to indent))
- (if (< (current-column)
- (current-indentation))
- (skip-chars-forward "\t ")))))))
-
-;; Better Emacs major modes achieve a kind of "transparency" to
-;; the user, where special indentation,etc. happens under your feet, but
-;; in a useful way that you soon get accustomed to. Worse modes
-;; cause frustration and repetitive re-editing of automatic indentation.
-;; I hope I've achieved something in the first category...
-
-(defun thy-calculate-indentation (sect)
- "Calculate the indentation for the current line.
-SECT should be the string name of the current section."
- (save-excursion
- (beginning-of-line)
- (or (thy-long-comment-string-indentation)
- (if (looking-at "\\s-*$")
- ;; Empty lines use indentation for section.
- (thy-indentation-for sect)
- (if (looking-at thy-headings-regexp)
- thy-heading-indent
- (progn
- (skip-chars-forward "\t ")
- (cond
- ;; A comment?
- ((looking-at "(\\*")
- (thy-indentation-for sect))
- ;; Anything else, use indentation for section
- (t (thy-indentation-for sect)))))))))
-
-(defun thy-long-comment-string-indentation ()
- "Calculate the indentation if inside multi-line comment or string.
-Also indent string contents."
- (let* ((comstr (thy-comment-or-string-start))
- (bolpos (save-excursion
- (beginning-of-line)
- (point)))
- (multi (and comstr
- (< comstr bolpos))))
- (if (not multi)
- nil
- (save-excursion
- (beginning-of-line)
- (cond
-
- ;; Inside a comment?
- ((char-equal (char-after comstr) ?\( )
- (forward-line -1)
- (if (looking-at "[\t ]*(\\*")
- (+ 3 (current-indentation))
- (current-indentation)))
-
- ;; Otherwise, a string.
- ;; Enforce correct backslashing on continuing
- ;; line and return cons of backslash indentation
- ;; and string contents indentation for continued
- ;; line.
- (t
- (let ((quote-col (save-excursion (goto-char comstr)
- (current-column))))
- (if thy-indent-strings
- (thy-string-indentation comstr)
- ;; just to right of matching "
- (+ quote-col 1)))))))))
-
-(defun thy-string-indentation (start)
- ;; Guess indentation for text inside a string
- (let* ((startcol (save-excursion (goto-char start) (current-column)))
- (pps-state (parse-partial-sexp (1+ start) (point)))
- (par-depth (car pps-state)))
- (cond (;; If not in nested expression, startcol+1
- (zerop par-depth)
- (1+ startcol))
- (;; If in a nested expression, use position of opening bracket
- (natnump par-depth)
- (save-excursion
- (goto-char (nth 1 pps-state))
- (+ (current-column)
- (cond ((looking-at "\\[|") 3)
- (t 1)))))
- (;; Give error for too many closing parens
- t
- (error "Mismatched parentheses")))))
-
-(defun thy-indentation-for (sect)
- "Return the indentation for section SECT"
- (if (string-equal sect "top")
- thy-heading-indent
- thy-indent-level))
-
-(defun thy-string-start (&optional min)
- "Return position of start of string if inside one, nil otherwise."
- (let ((comstr (thy-comment-or-string-start)))
- (if (and comstr
- (save-excursion
- (goto-char comstr)
- (looking-at "\"")))
- comstr)))
-
-;;; Is this parsing still too slow? (better way? e.g., try setting
-;;; variable "char" and examining it, rather than finding current
-;;; state first - fewer branches in non-interesting cases, perhaps.
-;;; NB: it won't understand escape sequences in strings, such as \"
-
-(defun thy-comment-or-string-start (&optional min)
- "Find if point is in a comment or string, starting parse from MIN.
-Returns the position of the comment or string start or nil.
-If MIN is nil, starts from top of current section.
-
-Doesn't understand nested comments."
- (or min
- (setq min
- (save-excursion
- (thy-goto-top-of-section) (point))))
- (if (<= (point) min)
- nil
- (let ((pos (point))
- (incomdepth 0)
- incom instring) ; char
- (goto-char min)
- (while (< (point) pos)
- ;; When inside a string, only look for its end
- (if instring
- (if (eq (char-after (point)) ?\") ; looking-at "\""
- (setq instring nil))
- ;; If inside a comment, look for a comment end
- (if (> 0 incomdepth)
- (if (and ; looking-at "\\*)"
- (eq (char-after (point)) ?\*)
- (eq (char-after (1+ (point))) ?\)))
- (setq incomdepth (1- incomdepth)))
- ;; If inside neither comment nor string, look for
- ;; a string start.
- (if (eq (char-after (point)) ?\") ; looking-at "\""
- (setq instring (point))))
- ;; Look for a comment start (unless inside a string)
- (if (and
- (eq (char-after (point)) ?\()
- (eq (char-after (1+ (point))) ?\*))
- (progn
- (if (= 0 incomdepth) ; record start of main comment
- (setq incom (point))) ; only
- (setq incomdepth (1+ incomdepth)))))
- (forward-char))
- (if (> 0 incomdepth) incom instring))))
-
-
-
-
-(provide 'thy-mode)
-
-;;; end of thy-mode.el