aboutsummaryrefslogtreecommitdiff
path: root/isa
diff options
context:
space:
mode:
Diffstat (limited to 'isa')
-rw-r--r--isa/BUGS50
-rw-r--r--isa/Example-Xsym.ML15
-rw-r--r--isa/Example.ML13
-rw-r--r--isa/Example.thy10
-rw-r--r--isa/Example2.ML15
-rw-r--r--isa/README33
-rw-r--r--isa/depends.ML100
-rw-r--r--isa/interface236
-rw-r--r--isa/interface-setup.el48
-rw-r--r--isa/isa-syntax.el304
-rw-r--r--isa/isa.el765
-rw-r--r--isa/isabelle-system.el382
-rw-r--r--isa/thy-mode.el1047
-rw-r--r--isa/todo84
-rw-r--r--isa/x-symbol-isabelle.el410
15 files changed, 3512 insertions, 0 deletions
diff --git a/isa/BUGS b/isa/BUGS
new file mode 100644
index 00000000..068e7fa9
--- /dev/null
+++ b/isa/BUGS
@@ -0,0 +1,50 @@
+-*- mode:outline -*-
+
+* Isabelle Proof General Bugs
+
+See also ../BUGS for generic bugs.
+
+
+** set proof_timing is problematic
+
+It will make the goals display disappear during proof. This is
+because Proof General only displays goals output that appears *after*
+Isabelle messages, but Isabelle prints the timing message after the
+goals are displayed.
+
+** General difficulty with proof scripts containing ML structures, etc.
+
+Proof General does not understand full ML syntax(!), so it will be
+confused by structures which contain semi-colons after declarations,
+for example. Also, it cannot undo function declarations. See the
+section on ML files in the manual for more details.
+
+** Blocking when processing multiple files, beginning from a .ML file.
+
+Proof General will block the Emacs process when it is waiting for a
+theory file (and it's ancestors) to be read as scripting is turned on.
+To avoid this, assert the theory file rather than the ML file.
+
+** Subsection Interaction with theory database
+
+Isabelle Proof General uses some support from Isabelle to remove and
+reload theories from the theory database. To maintain consistency,
+Isabelle is rather conservative. So re-asserting a retracted file will
+often re-load it, even if it has not changed. (This is because the
+file may have implicit dependencies on things in the global ML
+environment not made apparent by the theory structure).
+This may lead to seemingly unnecessary repetition of time-consuming
+proofs, so be careful not to retract more than you need!
+
+As of Isabelle 99-1 and Proof General 3.2, there should be much
+less unncessary re-loading of theories; be careful to use Isabelle's
+mechanisms of declaring dependencies in theory file headers.
+
+** Clash with SML mode
+
+Since Isabelle proof scripts are not differentiated from `.ML' files,
+Proof General may compete with `sml-mode' (if you use it) for
+controlling these buffers. To ensure Proof General wins, load it last.
+
+Workaround: use another extension for real ML files, e.g. `.sml',
+and disable `.ML' from entering `sml-mode'.
diff --git a/isa/Example-Xsym.ML b/isa/Example-Xsym.ML
new file mode 100644
index 00000000..d566a850
--- /dev/null
+++ b/isa/Example-Xsym.ML
@@ -0,0 +1,15 @@
+(*
+ Example proof script for Isabelle Proof General.
+
+ $Id$
+
+ Just a version of Example.ML using XSymbol
+*)
+
+Goal "A \\<and> B \\<longrightarrow> B \\<and> A";
+by (rtac impI 1);
+by (etac conjE 1);
+by (rtac conjI 1);
+by (assume_tac 1);
+by (assume_tac 1);
+qed "and_comms";
diff --git a/isa/Example.ML b/isa/Example.ML
new file mode 100644
index 00000000..720e3a47
--- /dev/null
+++ b/isa/Example.ML
@@ -0,0 +1,13 @@
+(*
+ Example proof script for Isabelle Proof General.
+
+ $Id$
+*)
+
+Goal "A & B --> B & A";
+ by (rtac impI 1);
+ by (etac conjE 1);
+ by (rtac conjI 1);
+ by (assume_tac 1);
+ by (assume_tac 1);
+qed "and_comms";
diff --git a/isa/Example.thy b/isa/Example.thy
new file mode 100644
index 00000000..252a5a4c
--- /dev/null
+++ b/isa/Example.thy
@@ -0,0 +1,10 @@
+(*
+ Example theory file for Isabelle
+
+ David Aspinall <da@dcs.ed.ac.uk>
+
+ $Id$
+
+*)
+
+Example = Main
diff --git a/isa/Example2.ML b/isa/Example2.ML
new file mode 100644
index 00000000..ab2fef03
--- /dev/null
+++ b/isa/Example2.ML
@@ -0,0 +1,15 @@
+(*
+ Example proof script for Isabelle Proof General.
+
+ $Id$
+
+ Same as Example.ML, except using X-Symbol input tokens.
+*)
+
+Goal "A \\<and> B \\<longrightarrow> B \\<and> A";
+ by (rtac impI 1);
+ by (etac conjE 1);
+ by (rtac conjI 1);
+ by (assume_tac 1);
+ by (assume_tac 1);
+qed "and_comms";
diff --git a/isa/README b/isa/README
new file mode 100644
index 00000000..8207071a
--- /dev/null
+++ b/isa/README
@@ -0,0 +1,33 @@
+Isabelle Proof General
+
+Written by David Aspinall, later with assistance from
+Markus Wenzel and David von Oheimb.
+
+Status: supported
+Maintainer: David Aspinall
+Isabelle versions: Isabelle99-1, Isabelle99-2, Isabelle2002
+Isabelle homepage: http://www.cl.cam.ac.uk/Research/HVG/Isabelle/
+
+========================================
+
+Isabelle Proof General has full support for multiple file scripting,
+with dependencies between theories communicated between Isabelle and
+Proof General. It has a mode for editing theory files taken from
+Isamode.
+
+There is proper support for X Symbol, using the Isabelle print mode
+for X Symbol tokens. Many Isabelle theories have X Symbol syntax
+already defined and it's easy to add to your own theories.
+
+There is no support for proof by pointing yet, and no tags program.
+
+The script `interface' and file 'interface-setup.el' are used to start
+Isabelle Proof General via the 'Isabelle' shell command. These files
+were provided by Markus Wenzel.
+
+Check the value of isabelle-prog-name.
+
+========================================
+
+$Id$
+
diff --git a/isa/depends.ML b/isa/depends.ML
new file mode 100644
index 00000000..65e2b91f
--- /dev/null
+++ b/isa/depends.ML
@@ -0,0 +1,100 @@
+(* depends.ML
+
+ Experimental code for communicating theorem dependencies from Isabelle
+ to Proof General.
+
+ This code is taken from thm_deps.ML in Isabelle 99-2. It's incompatible
+ with other Isabelle versions.
+
+ It is duplicated almost verbatim because what we need is
+ hardwired to a call on the browser tool.
+*)
+
+
+fun depends_enable () = Thm.keep_derivs := ThmDeriv;
+fun depends_disable () = Thm.keep_derivs := MinDeriv;
+
+
+
+fun is_internal (name, tags) = name = "" orelse Drule.has_internal tags;
+
+fun is_thm_axm (Theorem x) = not (is_internal x)
+ | is_thm_axm (Axiom x) = not (is_internal x)
+ | is_thm_axm _ = false;
+
+fun get_name (Theorem (s, _)) = s
+ | get_name (Axiom (s, _)) = s
+ | get_name _ = "";
+
+fun make_deps_graph ((gra, parents), Join (ta, ders)) =
+ let
+ val name = get_name ta;
+ in
+ if is_thm_axm ta then
+ if is_none (Symtab.lookup (gra, name)) then
+ let
+ val (gra', parents') = foldl make_deps_graph ((gra, []), ders);
+ val prefx = #1 (Library.split_last (NameSpace.unpack name));
+ val session =
+ (case prefx of
+ (x :: _) =>
+ (case ThyInfo.lookup_theory x of
+ Some thy =>
+ let val name = #name (Present.get_info thy)
+ in if name = "" then [] else [name] end
+ | None => [])
+ | _ => ["global"]);
+ in
+ (Symtab.update ((name,
+ {name = Sign.base_name name, ID = name,
+ dir = space_implode "/" (session @ prefx),
+ unfold = false, path = "", parents = parents'}), gra'), name ins parents)
+ end
+ else (gra, name ins parents)
+ else
+ foldl make_deps_graph ((gra, parents), ders)
+ end;
+
+fun thm_deps thms =
+ let
+ val _ = writeln "Generating graph ...";
+ val gra = map snd (Symtab.dest (fst (foldl make_deps_graph ((Symtab.empty, []),
+ map (#2 o #der o Thm.rep_thm) thms))));
+ val path = File.tmp_path (Path.unpack "theorems.graph");
+ val _ = Present.write_graph gra path;
+ val _ = system ("$ISATOOL browser -d " ^ Path.pack (Path.expand path) ^ " &");
+ in () end;
+
+fun new_thm_deps thms =
+ let
+ val header = "Proof General, the theorem dependencies are: \"";
+ val gra = map snd (Symtab.dest (fst (foldl make_deps_graph ((Symtab.empty, []),
+ map (#2 o #der o Thm.rep_thm) thms))));
+ val deps = sort_strings (foldl (op union) ([],(map #parents gra)))
+ val msg = header ^ (space_implode " " deps) ^ "\""
+ in priority msg end;
+
+val old_qed = qed;
+fun qed name =
+ let val _ = old_qed name
+ val proved_thm = thm name
+ in new_thm_deps [proved_thm] end;
+
+val old_qed_goal = qed_goal;
+fun qed_goal name thy goal tacsf =
+ let val _ = old_qed_goal name thy goal tacsf
+ val proved_thm = thm name
+ in new_thm_deps [proved_thm] end;
+
+val old_qed_goalw = qed_goalw;
+fun qed_goalw name thy rews goal tacsf =
+ let val _ = old_qed_goalw name thy rews goal tacsf
+ val proved_thm = thm name
+ in new_thm_deps [proved_thm] end;
+
+(* FIXME: this one only in HOL?? *)
+val old_qed_spec_mp = qed_spec_mp;
+fun qed_spec_mp name =
+ let val _ = old_qed_spec_mp name
+ val proved_thm = thm name
+ in new_thm_deps [proved_thm] end;
diff --git a/isa/interface b/isa/interface
new file mode 100644
index 00000000..46c78a58
--- /dev/null
+++ b/isa/interface
@@ -0,0 +1,236 @@
+#!/usr/bin/env bash
+#
+# $Id$
+#
+# Proof General interface wrapper for Isabelle.
+
+
+## self references
+
+THIS=$(cd "$(dirname "$0")"; pwd)
+SUPER=$(cd "$THIS/.."; pwd)
+KIND=$(basename "$(dirname "$0")")
+
+if [ "$KIND" = isar ]; then
+ ISAR=true
+else
+ ISAR=false
+fi
+
+
+## diagnostics
+
+usage()
+{
+ echo
+ echo "Usage: Isabelle [OPTIONS] [FILES ...]"
+ echo
+ echo " Options are:"
+ echo " -I BOOL use Isabelle/Isar instead of classic Isabelle (default $ISAR)"
+ echo " -P BOOL actually start Proof General (default true), otherwise"
+ echo " run plain tty session"
+ echo " -X BOOL configure the X-Symbol package on startup (default true)"
+ echo " -g GEOMETRY specify Emacs geometry"
+ echo " -k NAME use specific isar-keywords for named logic"
+ echo " -l NAME logic image name (default \$ISABELLE_LOGIC=$ISABELLE_LOGIC)"
+ echo " -m MODE add print mode for output"
+ echo " -p NAME Emacs program name (default xemacs)"
+ echo " -u BOOL use personal .emacs file (default true)"
+ echo " -w BOOL use window system (default true)"
+ echo " -x BOOL enable the X-Symbol package on startup (default false)"
+ echo
+ echo "Starts Proof General for Isabelle with theory and proof FILES"
+ echo "(default Scratch.thy)."
+ echo
+ echo " PROOFGENERAL_OPTIONS=$PROOFGENERAL_OPTIONS"
+ echo
+ exit 1
+}
+
+fail()
+{
+ echo "$1" >&2
+ exit 2
+}
+
+
+## process command line
+
+# options
+
+ISABELLE_OPTIONS=""
+START_PG="true"
+GEOMETRY=""
+KEYWORDS=""
+LOGIC="$ISABELLE_LOGIC"
+PROGNAME="xemacs"
+INITFILE="true"
+WINDOWSYSTEM="true"
+XSYMBOL=""
+XSYMBOLSETUP=true
+
+getoptions()
+{
+ OPTIND=1
+ while getopts "I:P:X:g:k:l:m:p:u:w:x:" OPT
+ do
+ case "$OPT" in
+ I)
+ ISAR="$OPTARG"
+ ;;
+ P)
+ START_PG="$OPTARG"
+ ;;
+ X)
+ XSYMBOLSETUP="$OPTARG"
+ ;;
+ g)
+ GEOMETRY="$OPTARG"
+ ;;
+ k)
+ KEYWORDS="$OPTARG"
+ ;;
+ l)
+ LOGIC="$OPTARG"
+ ;;
+ m)
+ if [ -z "$ISABELLE_OPTIONS" ]; then
+ ISABELLE_OPTIONS="-m $OPTARG"
+ else
+ ISABELLE_OPTIONS="$ISABELLE_OPTIONS -m $OPTARG"
+ fi
+ ;;
+ p)
+ PROGNAME="$OPTARG"
+ ;;
+ u)
+ INITFILE="$OPTARG"
+ ;;
+ w)
+ WINDOWSYSTEM="$OPTARG"
+ ;;
+ x)
+ XSYMBOL="$OPTARG"
+ ;;
+ \?)
+ usage
+ ;;
+ esac
+ done
+}
+
+getoptions $PROOFGENERAL_OPTIONS
+
+getoptions "$@"
+shift $(($OPTIND - 1))
+
+if [ "$ISAR" = true ]; then
+ KIND=isar
+ DEFAULT_FILES="Scratch.thy"
+else
+ KIND=isa
+ DEFAULT_FILES="Scratch.thy Scratch.ML"
+fi
+
+
+# args
+
+if [ "$#" -eq 0 ]; then
+ FILES="$DEFAULT_FILES"
+else
+ FILES=""
+ while [ "$#" -gt 0 ]; do
+ FILES="$FILES '$1'"
+ shift
+ done
+fi
+
+
+## smart X11 font installation
+
+function checkfonts ()
+{
+ XLSFONTS=$(xlsfonts -fn "-xsymb-xsymb0-*" 2>&1) || return 1
+
+ case "$XLSFONTS" in
+ xlsfonts:*)
+ return 1
+ ;;
+ esac
+
+ return 0
+}
+
+function installfonts ()
+{
+ checkfonts "$XSYMBOL_PATTERN" || eval $XSYMBOL_INSTALLFONTS
+}
+
+
+## main
+
+if [ "$START_PG" = false ]; then
+
+ [ "$ISAR" = true ] && ISABELLE_OPTIONS="$ISABELLE_OPTIONS -I"
+ exec "$ISABELLE" $ISABELLE_OPTIONS "$LOGIC"
+
+else
+
+ ARGS=""
+
+ [ -n "$GEOMETRY" ] && ARGS="$ARGS -geometry '$GEOMETRY'"
+
+ [ "$INITFILE" = false ] && ARGS="$ARGS -q"
+
+ if [ "$WINDOWSYSTEM" = true -a -n "$DISPLAY" ]; then
+ ARGS="$ARGS -T Isabelle"
+ [ -n "$XSYMBOL_INSTALLFONTS" -a "$XSYMBOLSETUP" = true ] && installfonts
+ else
+ ARGS="$ARGS -nw"
+ XSYMBOL=false
+ fi
+
+ [ ! "$XSYMBOLSETUP" = true ] && XSYMBOL_HOME=""
+
+
+ ARGS="$ARGS -l '$SUPER/isa/interface-setup.el'"
+
+ if [ -n "$KEYWORDS" ]; then
+ if [ -f "$ISABELLE_HOME_USER/etc/isar-keywords-$KEYWORDS.el" ]; then
+ ARGS="$ARGS -l '$ISABELLE_HOME_USER/etc/isar-keywords-$KEYWORDS.el'"
+ elif [ -f "$ISABELLE_HOME/etc/isar-keywords-$KEYWORDS.el" ]; then
+ ARGS="$ARGS -l '$ISABELLE_HOME/etc/isar-keywords-$KEYWORDS.el'"
+ else
+ fail "No isar-keywords file for '$KEYWORDS'"
+ fi
+ elif [ -f "$ISABELLE_HOME_USER/etc/isar-keywords.el" ]; then
+ ARGS="$ARGS -l '$ISABELLE_HOME_USER/etc/isar-keywords.el'"
+ elif [ -f "$ISABELLE_HOME/etc/isar-keywords.el" ]; then
+ ARGS="$ARGS -l '$ISABELLE_HOME/etc/isar-keywords.el'"
+ fi
+
+ for FILE in "$ISABELLE_HOME/etc/proofgeneral-settings.el" \
+ "$ISABELLE_HOME_USER/etc/proofgeneral-settings.el"
+ do
+ [ -f "$FILE" ] && ARGS="$ARGS -l '$FILE'"
+ done
+
+ case "$LOGIC" in
+ /*)
+ ;;
+ */*)
+ LOGIC="$PWD/$LOGIC"
+ ;;
+ esac
+
+ PROOFGENERAL_HOME="$SUPER"
+ PROOFGENERAL_ASSISTANTS="$KIND"
+ PROOFGENERAL_LOGIC="$LOGIC"
+ PROOFGENERAL_XSYMBOL="$XSYMBOL"
+
+ export PROOFGENERAL_HOME PROOFGENERAL_ASSISTANTS PROOFGENERAL_LOGIC PROOFGENERAL_XSYMBOL
+ export ISABELLE_OPTIONS
+
+ eval exec "$PROGNAME" "$ARGS" "$FILES"
+
+fi
diff --git a/isa/interface-setup.el b/isa/interface-setup.el
new file mode 100644
index 00000000..2ed504cb
--- /dev/null
+++ b/isa/interface-setup.el
@@ -0,0 +1,48 @@
+;; interface-setup.el Interface wrapper for Isabelle Proof General
+;;
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; Author: Markus Wenzel <wenzelm@in.tum.de>
+;;
+;; $Id$
+;;
+
+;;;
+;;; X-Symbol
+;;;
+
+(if (string-match "XEmacs" emacs-version) ;current X-Symbol works with XEmacs only!
+ (let ((xsymbol-home (getenv "XSYMBOL_HOME"))
+ (xsymbol (getenv "PROOFGENERAL_XSYMBOL"))
+ (enable-var
+ (if (equal (getenv "PROOFGENERAL_ASSISTANTS") "isa")
+ 'isa-x-symbol-enable 'isar-x-symbol-enable)))
+ ;; setup the x-symbol package, if not already present
+ (if (and xsymbol-home
+ (not (equal xsymbol-home ""))
+ (not (fboundp 'x-symbol-initialize))
+ (not (get 'x-symbol 'x-symbol-initialized)))
+ (progn
+ (load (expand-file-name "lisp/x-symbol/auto-autoloads" xsymbol-home))
+ (push (expand-file-name "lisp/x-symbol" xsymbol-home) load-path)
+ (if (boundp 'data-directory-list)
+ (push (expand-file-name "etc/" xsymbol-home) data-directory-list))
+ (if (boundp 'Info-directory-list)
+ (push (expand-file-name "info/" xsymbol-home) Info-directory-list))
+ (if (not (boundp 'x-symbol-image-converter)) ;avoid confusing warning message
+ (customize-set-variable 'x-symbol-image-converter nil))
+ (x-symbol-initialize)))
+ ;; tell Proof General about -x option
+ (if (and xsymbol (not (equal xsymbol "")))
+ (customize-set-variable enable-var (equal xsymbol "true")))))
+
+
+;;
+;; Proof General
+;;
+
+(if (not (featurep 'proof-site))
+ (load (concat (getenv "PROOFGENERAL_HOME") "/generic/proof-site.el")))
diff --git a/isa/isa-syntax.el b/isa/isa-syntax.el
new file mode 100644
index 00000000..d8697cb8
--- /dev/null
+++ b/isa/isa-syntax.el
@@ -0,0 +1,304 @@
+;; isa-syntax.el Syntax expressions for Isabelle
+;; Copyright (C) 1994-1998 LFCS Edinburgh.
+;;
+;; Author: David Aspinall <da@dcs.ed.ac.uk>
+;; Maintainer: Proof General maintainer <proofgen@dcs.ed.ac.uk>
+;;
+;; $Id$
+;;
+;;
+(require 'proof-syntax)
+
+;; character syntax
+
+(defun isa-init-syntax-table ()
+ "Set appropriate values for syntax table in current buffer."
+ (modify-syntax-entry ?\$ ".")
+ (modify-syntax-entry ?\/ ".")
+ (modify-syntax-entry ?\\ ".")
+ (modify-syntax-entry ?+ ".")
+ (modify-syntax-entry ?- ".")
+ (modify-syntax-entry ?= ".")
+ (modify-syntax-entry ?% ".")
+ (modify-syntax-entry ?< ".")
+ (modify-syntax-entry ?> ".")
+ (modify-syntax-entry ?\& ".")
+ (modify-syntax-entry ?. "w")
+ (modify-syntax-entry ?_ "w")
+ (modify-syntax-entry ?\' "w")
+ (modify-syntax-entry ?\| ".")
+ (modify-syntax-entry ?\* ". 23")
+ (modify-syntax-entry ?\( "()1")
+ (modify-syntax-entry ?\) ")(4"))
+
+(defun isa-init-output-syntax-table ()
+ "Set appropriate values for syntax table for Isabelle output."
+ (isa-init-syntax-table)
+ ;; ignore strings so font-locking works
+ ;; inside them
+ (modify-syntax-entry ?\" " ")
+ (modify-syntax-entry ?\* ".")
+ (modify-syntax-entry ?\( "()")
+ (modify-syntax-entry ?\) ")(")
+ (modify-syntax-entry ?\{ "(}")
+ (modify-syntax-entry ?\} "){"))
+
+;;
+;; Syntax for font-lock and other features
+;;
+
+;; Note: this command-keyword recognition of the proof script isn't
+;; good enough for Isabelle, since we can have arbitrary ML code
+;; around.
+;; Alternatives:
+;; 1) propose a restricted language consisting of the interactive
+;; commands. Or try Markus Wenzel's Isar proof language!
+;; 2) add hooks from Isabelle to say "I've just seen a goal command"
+;; or "I've just seen a tactic". This would allow more accurate
+;; counting of undos. We could even approximate this without hooks,
+;; by examining the proof state output carefully.
+;;
+
+;; FIXME da: here are some examples of input failures I've
+;; found in real proofs:
+;;
+;; val lemma = result() RS spec RS mp;
+;;
+;; Not recognized as a qed command, and therefore assumed
+;; to be an undoable tactic command.
+;;
+
+(defgroup isa-syntax nil
+ "Customization of Isabelle syntax for proof mode"
+ :group 'isa-settings)
+
+(defcustom isa-keywords-decl
+ '("val" "fun" "datatype" "signature" "structure")
+ "Isabelle keywords for declarations. Includes ML keywords to fontify ML files."
+ :group 'isa-syntax
+ :type '(repeat string))
+
+(defcustom isa-keywords-defn
+ '("bind_thm" "bind_thms")
+ "Isabelle keywords for definitions"
+ :group 'isa-syntax
+ :type '(repeat string))
+
+;; isa-keywords-goal is used to manage undo actions
+(defcustom isa-keywords-goal
+ '("Goal" "Goalw" "goal" "goalw" "goalw_cterm" "atomic_goal" "atomic_goalw")
+ "Isabelle commands to begin an interactive proof"
+ :group 'isa-syntax
+ :type '(repeat string))
+
+(defcustom isa-keywords-save
+ '("qed" "qed_spec_mp" "no_qed")
+ ;; Related commands, but having different types, so PG
+ ;; won't bother support them:
+ ;; "uresult" "bind_thm" "store_thm"
+ "Isabelle commands to extract the proved theorem"
+ :group 'isa-syntax
+ :type '(repeat string))
+
+(defcustom isa-keywords-commands
+ '("by" "byev"
+ "ba" "br" "be" "bd" "brs" "bes" "bds"
+ "chop" "choplev" "back" "undo" "ProofGeneral.repeat_undo"
+ "fa" "fr" "fe" "fd" "frs" "fes" "fds"
+ "bw" "bws" "ren"
+ ;; batch proofs
+ "prove_goal" "qed_goal" "prove_goalw" "qed_goalw" "prove_goalw_cterm")
+ "Isabelle command keywords"
+ :group 'isa-syntax
+ :type '(repeat string))
+
+;; NB: this means that any adjustments above by customize will
+;; only have effect in next session.
+(defconst isa-keywords
+ (append isa-keywords-goal isa-keywords-save isa-keywords-decl
+ isa-keywords-defn isa-keywords-commands)
+ "All keywords in a Isabelle script")
+
+(defconst isa-keywords-proof-commands
+ (append isa-keywords-goal isa-keywords-save isa-keywords-commands)
+ "Actual Isabelle proof script commands")
+
+;; The most common Isabelle/Pure tacticals
+(defconst isa-tacticals
+ '("ALLGOALS" "DETERM" "EVERY" "EVERY'" "FIRST" "FIRST'" "FIRSTGOAL"
+ "ORELSE" "ORELSE'" "REPEAT" "REPEAT" "REPEAT1" "REPEAT_FIRST"
+ "REPEAT_SOME" "SELECT_GOAL" "SOMEGOAL" "THEN" "THEN'" "TRY" "TRYALL"))
+
+
+;; ----- regular expressions
+
+(defconst isa-id "\\([A-Za-z][A-Za-z0-9'_]*\\)")
+(defconst isa-idx (concat isa-id "\\(\\.[0-9]+\\)?"))
+
+(defconst isa-ids (proof-ids isa-id "[ \t]*")
+ "Matches a sequence of identifiers separated by whitespace.")
+
+(defconst isa-string "\"\\(\\([^\\\"]\\|\\\\\"\\)*\\)\"")
+
+(defcustom isa-save-command-regexp
+ (proof-regexp-alt
+ (proof-anchor-regexp (proof-ids-to-regexp isa-keywords-save))
+ ;; match val ... = result blah
+ (proof-anchor-regexp
+ (concat
+ (proof-ids-to-regexp '("val")) ".+=\\s-*"
+ "\\(" (proof-ids-to-regexp isa-keywords-save) "\\)")))
+ "Regular expression used to match a qed/result."
+ :type 'regexp
+ :group 'isabelle-config)
+
+
+;; CHECKED
+(defconst isa-save-with-hole-regexp
+ (concat "\\(" (proof-ids-to-regexp isa-keywords-save)
+ "\\)\\s-+\"\\(" isa-id "\\)\"\\s-*;"))
+
+(defcustom isa-goal-command-regexp
+ (proof-regexp-alt
+ (proof-anchor-regexp (proof-ids-to-regexp isa-keywords-goal))
+ ;; match val ... = goal blah
+ (proof-anchor-regexp
+ (concat
+ (proof-ids-to-regexp '("val")) ".+=\\s-*"
+ "\\(" (proof-ids-to-regexp isa-keywords-goal) "\\)")))
+ "Regular expression used to match a goal."
+ :type 'regexp
+ :group 'isabelle-config)
+
+(defconst isa-string-regexp
+ (concat "\\s-*\"\\(" isa-id "\\)\"\\s-*")
+ "Regexp matching ML strings, with contents bracketed.")
+
+(defconst isa-goal-with-hole-regexp
+ (concat "\\("
+ ;; Don't bother with "val xxx = prove_goal blah".
+ (proof-ids-to-regexp '("qed_goal"))
+ "\\)" isa-string-regexp)
+ "Regexp matching goal commands in Isabelle which name a theorem")
+
+
+(defconst isa-proof-command-regexp
+ (proof-ids-to-regexp isa-keywords-proof-commands)
+ "Regexp to match proof commands, with no extra output (apart from proof state)")
+
+
+;; ----- Isabelle inner syntax hilite
+
+(defface isabelle-class-name-face
+ '((((type x) (class color) (background light))
+ (:foreground "red"))
+ (((type x) (class color) (background dark))
+ (:foreground "red3"))
+ (t
+ (bold t)))
+ "*Face for Isabelle term / type hiliting"
+ :group 'proof-faces)
+
+(defface isabelle-tfree-name-face
+ '((((type x) (class color) (background light))
+ (:foreground "purple"))
+ (((type x) (class color) (background dark))
+ (:foreground "purple3"))
+ (t
+ (bold t)))
+ "*Face for Isabelle term / type hiliting"
+ :group 'proof-faces)
+
+(defface isabelle-tvar-name-face
+ '((((type x) (class color) (background light))
+ (:foreground "purple"))
+ (((type x) (class color) (background dark))
+ (:foreground "purple3"))
+ (t
+ (bold t)))
+ "*Face for Isabelle term / type hiliting"
+ :group 'proof-faces)
+
+(defface isabelle-free-name-face
+ '((((type x) (class color) (background light))
+ (:foreground "blue"))
+ (((type x) (class color) (background dark))
+ (:foreground "blue3"))
+ (t
+ (bold t)))
+ "*Face for Isabelle term / type hiliting"
+ :group 'proof-faces)
+
+(defface isabelle-bound-name-face
+ '((((type x) (class color) (background light))
+ (:foreground "green4"))
+ (((type x) (class color) (background dark))
+ (:foreground "green"))
+ (t
+ (bold t)))
+ "*Face for Isabelle term / type hiliting"
+ :group 'proof-faces)
+
+(defface isabelle-var-name-face
+ '((((type x) (class color) (background light))
+ (:foreground "darkblue"))
+ (((type x) (class color) (background dark))
+ (:foreground "blue3"))
+ (t
+ (bold t)))
+ "*Face for Isabelle term / type hiliting"
+ :group 'proof-faces)
+
+(defconst isabelle-class-name-face 'isabelle-class-name-face)
+(defconst isabelle-tfree-name-face 'isabelle-tfree-name-face)
+(defconst isabelle-tvar-name-face 'isabelle-tvar-name-face)
+(defconst isabelle-free-name-face 'isabelle-free-name-face)
+(defconst isabelle-bound-name-face 'isabelle-bound-name-face)
+(defconst isabelle-var-name-face 'isabelle-var-name-face)
+
+
+(defvar isa-font-lock-keywords-1
+ (list
+ (cons (proof-ids-to-regexp isa-keywords) 'font-lock-keyword-face)
+ (cons (proof-ids-to-regexp isa-tacticals) 'proof-tacticals-name-face)
+ (list isa-goal-with-hole-regexp 2 'font-lock-function-name-face)
+ (list isa-save-with-hole-regexp 2 'font-lock-function-name-face)))
+
+(defvar isa-output-font-lock-keywords-1
+ (list
+ (cons (concat "\351" isa-id "\350") 'isabelle-class-name-face)
+ (cons (concat "\352'" isa-id "\350") 'isabelle-tfree-name-face)
+ (cons (concat "\353\\?'" isa-idx "\350") 'isabelle-tvar-name-face)
+ (cons (concat "\354" isa-id "\350") 'isabelle-free-name-face)
+ (cons (concat "\355" isa-id "\350") 'isabelle-bound-name-face)
+ (cons (concat "\356\\?" isa-idx "\350") 'isabelle-var-name-face)
+ (cons (concat "\357\\?" isa-idx "\350") 'proof-declaration-name-face)
+ )
+ "*Font-lock table for Isabelle terms.")
+
+(defvar isa-goals-font-lock-keywords
+ (append
+ (list
+ "^Level [0-9].*"
+ "^No subgoals!$"
+ "^Variables:$"
+ "^Constants:$"
+ "\\s-*[0-9][0-9]?\\. ")
+ isa-output-font-lock-keywords-1)
+ "*Font-lock table for Isabelle goals output.")
+
+
+;; ----- indentation
+
+(defconst isa-indent-any-regexp
+ (proof-regexp-alt (proof-ids-to-regexp isa-keywords) "\\s(" "\\s)"))
+(defconst isa-indent-inner-regexp
+ (proof-regexp-alt "\\s(" "\\s)"))
+(defconst isa-indent-enclose-regexp
+ (proof-ids-to-regexp isa-keywords-save))
+(defconst isa-indent-open-regexp
+ (proof-regexp-alt (proof-ids-to-regexp isa-keywords-goal) "\\s("))
+(defconst isa-indent-close-regexp
+ (proof-regexp-alt (proof-ids-to-regexp isa-keywords-save) "\\s)"))
+
+(provide 'isa-syntax)
diff --git a/isa/isa.el b/isa/isa.el
new file mode 100644
index 00000000..245c17d0
--- /dev/null
+++ b/isa/isa.el
@@ -0,0 +1,765 @@
+;; isa-mode.el Emacs support for Isabelle proof assistant
+;; Copyright (C) 1993-2000 LFCS Edinburgh, David Aspinall.
+;;
+;; Author: David Aspinall <da@dcs.ed.ac.uk>
+;; Contact: isa@proofgeneral.org
+;;
+;; $Id$
+;;
+;; -----------------------------------------------------------------
+;;
+;; This file and the rest of Isabelle Proof General contain code taken
+;; from David Aspinall's Isamode system, a personal project undertaken
+;; 1993-1999 as a contribution to the Isabelle community.
+;;
+;; -----------------------------------------------------------------
+
+
+;; Add Isabelle image onto splash screen
+;;
+;; (don't use customize-set-variable since it will be saved with options!)
+(setq proof-splash-extensions
+ '(list
+ nil
+ (proof-splash-display-image "isabelle_transparent" t)))
+
+;; In case Isa mode was invoked directly or by -*- isa -*- at
+;; the start of the file, ensure that Isa mode is used from now
+;; on for .thy and .ML files.
+;; FIXME: be less messy with auto-mode-alist here (remove dups)
+(setq auto-mode-alist
+ (cons '("\\.ML$\\|\\.thy$" . isa-mode) auto-mode-alist))
+
+(require 'proof)
+(require 'isa-syntax)
+(require 'isabelle-system)
+
+;;;
+;;; ======== User settings for Isabelle ========
+;;;
+
+;;; proof-site provides us with the cusomization groups
+;;;
+;;; 'isabelle - User options for Isabelle Proof General
+;;; 'isabelle-config - Configuration of Isabelle Proof General
+;;; (constants, but may be nice to tweak)
+
+
+;;;
+;;; ======== Configuration of generic modes ========
+;;;
+
+(defcustom isa-outline-regexp
+ (proof-ids-to-regexp '("goal" "Goal" "prove_goal"))
+ "Outline regexp for Isabelle ML files"
+ :type 'regexp
+ :group 'isabelle-config)
+
+;;; End of a command needs parsing to find, so this is approximate.
+(defcustom isa-outline-heading-end-regexp ";[ \t\n]*"
+ "Outline heading end regexp for Isabelle ML files."
+ :type 'regexp
+ :group 'isabelle-config)
+
+(defvar isa-shell-outline-regexp "\370[ \t]*\\([0-9]+\\)\\.")
+(defvar isa-shell-outline-heading-end-regexp "$")
+
+
+
+
+(defun isa-mode-config-set-variables ()
+ "Configure generic proof scripting/thy mode variables for Isabelle.
+Settings here are the ones which are needed for both shell mode
+and script mode."
+ (setq
+ proof-assistant-home-page isabelle-web-page
+ proof-mode-for-script 'isa-proofscript-mode
+ ;; proof script syntax
+ proof-terminal-char ?\; ; ends a proof
+ proof-comment-start "(*" ; comment in a proof
+ proof-comment-end "*)" ;
+ ;; Next few used for func-menu and recognizing goal..save regions in
+ ;; script buffer.
+ proof-save-command-regexp isa-save-command-regexp
+ proof-goal-command-regexp isa-goal-command-regexp
+ proof-goal-with-hole-regexp isa-goal-with-hole-regexp
+ proof-save-with-hole-regexp isa-save-with-hole-regexp
+ ;; Unfortunately the default value of proof-script-next-entity-regexps
+ ;; is no good, because goals with holes in Isabelle are batch
+ ;; commands, and not terminated by saves. So we omit the forward
+ ;; search from the default value.
+ proof-script-next-entity-regexps
+ (list (proof-regexp-alt
+ isa-goal-with-hole-regexp
+ isa-save-with-hole-regexp)
+ (list isa-goal-with-hole-regexp 2)
+ (list isa-save-with-hole-regexp 2
+ 'backward isa-goal-command-regexp))
+
+ proof-indent-enclose-offset (- proof-indent)
+ proof-indent-open-offset 0
+ proof-indent-close-offset 0
+ proof-indent-any-regexp isa-indent-any-regexp
+ proof-indent-inner-regexp isa-indent-inner-regexp
+ proof-indent-enclose-regexp isa-indent-enclose-regexp
+ proof-indent-open-regexp isa-indent-open-regexp
+ proof-indent-close-regexp isa-indent-close-regexp
+
+ ;; proof engine commands
+ proof-showproof-command "pr();"
+ proof-goal-command "Goal \"%s\";"
+ proof-save-command "qed \"%s\";"
+ proof-context-command "ProofGeneral.show_context();"
+ proof-info-command "ProofGeneral.help();"
+ proof-kill-goal-command "ProofGeneral.kill_goal();"
+ proof-find-theorems-command "ProofGeneral.thms_containing (space_explode \",\" \"%s\");"
+ proof-shell-start-silent-cmd "Goals.disable_pr();"
+ proof-shell-stop-silent-cmd "Goals.enable_pr();"
+ ;; command hooks
+ proof-goal-command-p 'isa-goal-command-p
+ proof-count-undos-fn 'isa-count-undos
+ proof-find-and-forget-fn 'isa-find-and-forget
+ proof-state-preserving-p 'isa-state-preserving-p
+
+ ;; close goal..save regions eagerly
+ proof-completed-proof-behaviour 'closeany
+
+ proof-shell-compute-new-files-list 'isa-shell-compute-new-files-list
+ proof-shell-inform-file-processed-cmd
+ "ProofGeneral.inform_file_processed \"%s\";"
+ proof-shell-inform-file-retracted-cmd
+ "ProofGeneral.inform_file_retracted \"%s\";"
+
+ ;; Parsing error messages. Bit tricky to allow for
+ ;; multitude of possible error formats Isabelle spits out.
+ ;; Ideally we shouldn't bother parsing errors that appear
+ ;; in the temporary ML files generated while reading
+ ;; theories, but unfortunately the user sometimes needs to
+ ;; examine them to understand a strange problem...
+ proof-shell-next-error-regexp
+ "\\(error on \\|Error: in '[^']+', \\)line \\([0-9]+\\)\\|The error(s) above occurred"
+ proof-shell-next-error-filename-regexp
+ "\\(Loading theory \"\\|Error: in '\\)\\([^\"']+\\)[\"']"
+ proof-shell-next-error-extract-filename
+ "%s.thy"))
+
+
+
+(defun isa-shell-mode-config-set-variables ()
+ "Configure generic proof shell mode variables for Isabelle."
+ (setq
+ proof-shell-first-special-char ?\350
+
+ proof-shell-wakeup-char ?\372
+ proof-shell-annotated-prompt-regexp "\\(val it = () : unit\n\\)?> \372"
+
+ ;; This pattern is just for comint
+ proof-shell-prompt-pattern "^2?[ML-=#>]>? \372?"
+
+ ;; for issuing command, not used to track cwd in any way.
+ proof-shell-cd-cmd "ThyLoad.add_path \"%s\";"
+
+ ;; Escapes for filenames inside ML strings.
+ ;; We also make a hack for Isabelle, by switching from backslashes
+ ;; to forward slashes if it looks like we're running on Windows.
+ proof-shell-filename-escapes
+ (if (fboundp 'win32-long-file-name) ; rough test for XEmacs on win32
+ ;; Patterns to unixfy names. Avoids a deliberate bomb in Isabelle which
+ ;; barfs at paths with these characters in them.
+ '(("\\\\" . "/") ("\"" . "\\\"") ("^[a-zA-Z]:" . ""))
+ ;; Normal case: quotation for backslash, quote mark.
+ '(("\\\\" . "\\\\") ("\"" . "\\\"")))
+
+ proof-shell-interrupt-regexp "Interrupt"
+ proof-shell-error-regexp "^\364\\*\\*\\*\\|^.*Error:\\|^uncaught exception \\|^Exception-\\( \\|$\\)"
+
+ ;; matches names of assumptions
+ proof-shell-assumption-regexp isa-id
+ ;; matches subgoal name
+ ;; FIXME: not used yet. In future will be used for
+ ;; proof-by-pointing like features.
+ ;; proof-shell-goal-regexp "\370[ \t]*\\([0-9]+\\)\\."
+
+ proof-shell-start-goals-regexp "\366"
+ proof-shell-end-goals-regexp "\367"
+ proof-shell-goal-char ?\370
+
+ proof-shell-proof-completed-regexp "^No subgoals!"
+
+ ;; initial command configures Isabelle by hacking print functions,
+ ;; restoring settings saved by Proof General, etc.
+
+ ;; FIXME: temporary hack for almost enabling/disabling printing.
+ ;; Also for setting default values.
+ proof-shell-pre-sync-init-cmd "ProofGeneral.init false;"
+ proof-shell-init-cmd (proof-assistant-settings-cmd)
+
+ proof-shell-restart-cmd "ProofGeneral.isa_restart();"
+ proof-shell-quit-cmd "quit();"
+
+ ;; NB: the settings below will only recognize tracing output in
+ ;; Isabelle 2001.
+ proof-shell-eager-annotation-start "\360\\|\362"
+ proof-shell-eager-annotation-start-length 1
+ proof-shell-eager-annotation-end "\361\\|\363"
+ ;; see isa-pre-shell-start for proof-shell-trace-output-regexp
+
+ ;; Some messages delimited by eager annotations
+ proof-shell-clear-response-regexp "Proof General, please clear the response buffer."
+ proof-shell-clear-goals-regexp "Proof General, please clear the goals buffer."
+ proof-shell-set-elisp-variable-regexp "Proof General, please set the variable \\([^ ]+\\) to: #\\([^#]+\\)#\\."
+ proof-shell-theorem-dependency-list-regexp "Proof General, the theorem dependencies are: \"\\([^\"]*\\)\""
+
+ ;; Dirty hack to allow font-locking for output based on hidden
+ ;; annotations, see isa-output-font-lock-keywords-1
+ proof-shell-leave-annotations-in-output t
+
+ ;; === ANNOTATIONS === ones here are broken
+ proof-shell-result-start "\372 Pbp result \373"
+ proof-shell-result-end "\372 End Pbp result \373"
+ proof-analyse-using-stack t
+ proof-shell-start-char ?\372
+ proof-shell-end-char ?\373
+ proof-shell-field-char ?\374
+
+ ;; === MULTIPLE FILE HANDLING ===
+ proof-shell-process-file
+ (cons
+ ;; Theory loader output and verbose update() output.
+ "Proof General, this file is loaded: \"\\(.*\\)\""
+ (lambda (str)
+ (match-string 1 str)))
+ ;; This is the output returned by a special command to
+ ;; query Isabelle for outdated files.
+ ;; proof-shell-clear-included-files-regexp
+ ;; "Proof General, please clear your record of loaded files."
+ proof-shell-retract-files-regexp
+ "Proof General, you can unlock the file \"\\(.*\\)\""
+ proof-shell-compute-new-files-list 'isa-shell-compute-new-files-list
+ )
+ (add-hook 'proof-activate-scripting-hook 'isa-shell-update-thy 'append)
+ )
+
+
+;;;
+;;; Theory loader operations
+;;;
+
+;; Experiments for background non-blocking loading of theory: this is
+;; quite difficult, actually: we need to set a callback from
+;; proof-done-invisible to take the final step in switching on
+;; scripting. We may be able to pass the hook argument into the
+;; action list using the "span" argument which means nothing for
+;; invisible command usually.
+
+; attempt to trap C-g. Needs more work so revert to previous
+;(defun isa-update-thy-only (file try wait)
+; "Tell Isabelle to update current buffer's theory, and all ancestors."
+; ;; Trap interrupts from C-g during the update
+; (condition-case err
+; (proof-shell-invisible-command
+; (format "ProofGeneral.%supdate_thy_only \"%s\";"
+; (if try "try_" "") (file-name-sans-extension file))
+; wait)
+; (t (message "Isabelle Proof General: error or interrupt during update theory...")
+; (if proof-shell-busy
+; (proof-interrupt-process))
+; (sit-for 1)
+; (proof-deactivate-scripting)
+; (if (cdr err) ;; quit is just (quit).
+; (error (cdr err))))))
+
+(defun isa-update-thy-only (file try wait)
+ "Tell Isabelle to update current buffer's theory, and all ancestors."
+ ;; First make sure we're in the right directory to take care of
+ ;; relative "files" paths inside theory file.
+ (proof-cd-sync)
+ (proof-shell-invisible-command
+ (proof-format-filename
+ ;; %r parameter means relative (don't expand) path
+ (format "ProofGeneral.%supdate_thy_only \"%%r\";" (if try "try_" ""))
+ (file-name-nondirectory (file-name-sans-extension file)))
+ wait))
+
+(defun isa-shell-update-thy ()
+ "Possibly issue update_thy_only command to Isabelle.
+If the current buffer has an empty locked region, the interface is
+about to send commands from it to Isabelle. This function sends
+a command to read any theory file corresponding to the current ML file.
+This is a hook function for proof-activate-scripting-hook."
+ (if (proof-locked-region-empty-p)
+ ;; If we switch to this buffer and it *does* have a locked
+ ;; region, we could check that no updates are needed and
+ ;; unlock the whole buffer in case they were. But that's
+ ;; a bit messy. Instead we assume that things must be
+ ;; up to date, after all, the user wasn't allowed to edit
+ ;; anything that this file depends on, was she?
+ (progn
+ ;; Wait after sending, so that queue is cleared for further
+ ;; commands without giving "proof process busy" error.
+ (isa-update-thy-only buffer-file-name t
+ ;; whether to block or not
+ (if (and (boundp 'activated-interactively)
+ activated-interactively)
+ t ; was nil, but falsely leaves Scripting on!
+ t))
+ ;; Leave the messages from the update around.
+ (setq proof-shell-erase-response-flag nil))))
+
+(defun isa-remove-file (name files cmp-base)
+ (if (not files) nil
+ (let*
+ ((file (car files))
+ (rest (cdr files))
+ (same (if cmp-base (string= name (file-name-nondirectory file))
+ (string= name file))))
+ (if same (isa-remove-file name rest cmp-base)
+ (cons file (isa-remove-file name rest cmp-base))))))
+
+(defun isa-shell-compute-new-files-list (str)
+ "Compute the new list of files read by the proof assistant.
+This is called when Proof General spots output matching
+proof-shell-retract-files-regexp."
+ (let*
+ ((name (match-string 1 str))
+ (base-name (file-name-nondirectory name)))
+ (if (string= name base-name)
+ (isa-remove-file name proof-included-files-list t)
+ (isa-remove-file (file-truename name) proof-included-files-list nil))))
+
+
+;;
+;; Define the derived modes
+;;
+(eval-and-compile
+(define-derived-mode isa-shell-mode proof-shell-mode
+ "Isabelle shell" nil
+ (isa-shell-mode-config)))
+
+(eval-and-compile
+(define-derived-mode isa-response-mode proof-response-mode
+ "Isabelle response" nil
+ (isa-response-mode-config)))
+
+(eval-and-compile ; to define vars for byte comp.
+(define-derived-mode isa-goals-mode proof-goals-mode
+ "Isabelle goals" nil
+ (isa-goals-mode-config)))
+
+(eval-and-compile ; to define vars for byte comp.
+(define-derived-mode isa-proofscript-mode proof-mode
+ "Isabelle script" nil
+ (isa-mode-config)))
+
+
+;;
+;; Automatically selecting theory mode or Proof General script mode.
+;;
+
+(defun isa-mode ()
+ "Mode for Isabelle buffers: either isa-proofscript-mode or thy-mode.
+Files with extension .thy will be in thy-mode, otherwise we choose
+isa-proofscript-mode."
+ (interactive)
+ (cond
+ (;; Theory files only if they have the right extension
+ (and (buffer-file-name)
+ (proof-string-match "\\.thy$" (buffer-file-name)))
+
+ ;; Enter theory mode, but first configure settings for proof
+ ;; script if they haven't been done already. This is a hack,
+ ;; needed because Proof General assumes that the script mode must
+ ;; have been configured before shell mode can be triggered, which
+ ;; isn't true for Isabelle.
+ ;; (proof-config-done-related and proof-shell-mode refer to
+ ;; the troublesome settings in question)
+ ;; 3.3 fix: add require proof-script since context menus are
+ ;; now added for response/goals buffer, which requires proof mode.
+ (unless proof-terminal-char
+ (require 'proof-script)
+ (proof-menu-define-specific)
+ (isa-mode-config-set-variables))
+
+ (thy-mode)
+
+ ;; related mode configuration including locking buffer,
+ ;; fontification, etc.
+ (proof-config-done-related)
+
+ ;; Hack for splash screen
+ (if (and (boundp 'proof-mode-hook)
+ (memq 'proof-splash-timeout-waiter proof-mode-hook))
+ (proof-splash-timeout-waiter)
+ ;; Otherwise, user may need welcoming.
+ (proof-splash-message)))
+ (t
+ (isa-proofscript-mode))))
+
+(eval-after-load
+ "thy-mode"
+ ;; Extend theory mode keymap
+ '(let ((map thy-mode-map))
+(define-key map "\C-c\C-b" 'isa-process-thy-file)
+(define-key map "\C-c\C-r" 'isa-retract-thy-file)
+(proof-define-keys map proof-universal-keys)))
+
+;; FIXME: could test that the buffer isn't already locked.
+(defun isa-process-thy-file (file)
+ "Process the theory file FILE. If interactive, use buffer-file-name."
+ (interactive (list buffer-file-name))
+ (save-some-buffers)
+ (isa-update-thy-only file nil nil))
+
+(defcustom isa-retract-thy-file-command "ThyInfo.remove_thy \"%r\";"
+ "Sent to Isabelle to forget theory file and descendants.
+Resulting output from Isabelle will be parsed by Proof General."
+ :type 'string
+ :group 'isabelle-config)
+
+(defun isa-retract-thy-file (file)
+ "Retract the theory file FILE. If interactive, use buffer-file-name.
+To prevent inconsistencies, scripting is deactivated before doing this.
+So if scripting is active in an ML file which is not completely processed,
+you will be asked to retract the file or process the remainder of it."
+ (interactive (list buffer-file-name))
+ (proof-deactivate-scripting)
+ (proof-shell-invisible-command
+ (proof-format-filename isa-retract-thy-file-command
+ (file-name-nondirectory
+ (file-name-sans-extension file)))))
+
+
+;; Next bits taken from isa-load.el
+;; isa-load.el,v 3.8 1998/09/01
+
+(defgroup thy nil
+ "Customization of Isamode's theory editing mode"
+ ;; :link '(info-link "(Isamode)Theory Files")
+ :load 'thy-mode
+ :group 'isabelle)
+
+(autoload 'thy-mode "thy-mode"
+ "Major mode for Isabelle theory files" t nil)
+
+(autoload 'thy-find-other-file "thy-mode"
+ "Find associated .ML or .thy file." t nil)
+
+(defun isa-splice-separator (sep strings)
+ (let (stringsep)
+ (while strings
+ (setq stringsep (concat stringsep (car strings)))
+ (setq strings (cdr strings))
+ (if strings (setq stringsep
+ (concat stringsep sep))))
+ stringsep))
+
+(defun isa-file-name-cons-extension (name)
+ "Return cons cell of NAME without final extension and extension"
+ (if (string-match "\\.[^\\.]+$" name)
+ (cons (substring name 0 (match-beginning 0))
+ (substring name (match-beginning 0)))
+ (cons name "")))
+
+(defun isa-format (alist string)
+ "Format a string by matching regexps in ALIST against STRING"
+ (while alist
+ (while (string-match (car (car alist)) string)
+ (setq string
+ (concat (substring string 0 (match-beginning 0))
+ (cdr (car alist))
+ (substring string (match-end 0)))))
+ (setq alist (cdr alist)))
+ string)
+
+;; Key to switch to theory mode
+(define-key isa-proofscript-mode-map
+ [(control c) (control o)] 'thy-find-other-file)
+
+
+
+
+;;
+;; Code that's Isabelle specific
+;;
+
+(defcustom isa-not-undoable-commands-regexp
+ (proof-ids-to-regexp '("undo"))
+ "Regular expression matching commands which are *not* undoable."
+ :type 'regexp
+ :group 'isabelle-config)
+
+;; This next function is the important one for undo operations.
+(defun isa-count-undos (span)
+ "Count number of undos in a span, return the command needed to undo that far."
+ (let
+ ((case-fold-search nil)
+ (ct 0) str i)
+ (if (and span (prev-span span 'type)
+ (not (eq (span-property (prev-span span 'type) 'type) 'comment))
+ (isa-goal-command-p
+ (span-property (prev-span span 'type) 'cmd)))
+ (concat "choplev 0" proof-terminal-string)
+ (while span
+ (setq str (span-property span 'cmd))
+ (cond ((eq (span-property span 'type) 'vanilla)
+ (or (proof-string-match isa-not-undoable-commands-regexp str)
+ (setq ct (+ 1 ct))))
+ ((eq (span-property span 'type) 'pbp)
+ ;; this case probably redundant for Isabelle, unless we
+ ;; think of some nice ways of matching non-undoable cmds.
+ (cond ((not (proof-string-match
+ isa-not-undoable-commands-regexp str))
+ (setq i 0)
+ (while (< i (length str))
+ (if (= (aref str i) proof-terminal-char)
+ (setq ct (+ 1 ct)))
+ (setq i (+ 1 i))))
+ (t nil))))
+ (setq span (next-span span 'type)))
+ (concat "ProofGeneral.repeat_undo "
+ (int-to-string ct) proof-terminal-string))))
+
+(defun isa-goal-command-p (str)
+ "Decide whether argument is a goal or not"
+ (proof-string-match isa-goal-command-regexp str)) ; this regexp defined in isa-syntax.el
+
+;; Isabelle has no concept of a Linear context, so forgetting back
+;; to the declaration of a particular something makes no real
+;; sense. Perhaps in the future there will be functions to remove
+;; theorems from theories, but even then all we could do is
+;; forget particular theorems one by one. So we ought to search
+;; backwards in isa-find-and-forget, rather than forwards as
+;; the code from the type theory provers does.
+
+;; MMW: this version even does nothing at all
+(defun isa-find-and-forget (span)
+ proof-no-command)
+
+(defun isa-state-preserving-p (cmd)
+ "Non-nil if command preserves the proofstate."
+ (not (proof-string-match isa-not-undoable-commands-regexp cmd)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Isa shell startup and exit hooks ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun isa-pre-shell-start ()
+ (setq proof-prog-name (isabelle-command-line))
+ (setq proof-mode-for-shell 'isa-shell-mode)
+ (setq proof-mode-for-goals 'isa-goals-mode)
+ (setq proof-mode-for-response 'isa-response-mode)
+ (setq proof-shell-trace-output-regexp "\375"))
+
+(defun isa-mode-config ()
+ (isa-mode-config-set-variables)
+ (isa-init-syntax-table)
+ (setq font-lock-keywords isa-font-lock-keywords-1)
+ (proof-config-done)
+ ;; outline
+ ;; FIXME: do we need to call make-local-variable here?
+ (make-local-variable 'outline-regexp)
+ (setq outline-regexp isa-outline-regexp)
+ (make-local-variable 'outline-heading-end-regexp)
+ (setq outline-heading-end-regexp isa-outline-heading-end-regexp)
+ ;; tags
+ ; (and (boundp 'tag-table-alist)
+ ; (setq tag-table-alist
+ ; (append '(("\\.ML$" . isa-ML-file-tags-table)
+ ; ("\\.thy$" . thy-file-tags-table))
+ ; tag-table-alist)))
+ (setq blink-matching-paren-dont-ignore-comments t))
+
+
+;; These hooks are added on load because proof shells can
+;; be started from .thy (not in scripting mode) or .ML files.
+(add-hook 'proof-pre-shell-start-hook 'isa-pre-shell-start nil t)
+(add-hook 'proof-shell-insert-hook 'isa-preprocessing)
+
+(defun isa-shell-mode-config ()
+ "Configure Proof General proof shell for Isabelle."
+ (isa-init-output-syntax-table)
+ (setq font-lock-keywords isa-output-font-lock-keywords-1)
+ (isa-shell-mode-config-set-variables)
+ (proof-shell-config-done))
+
+(defun isa-response-mode-config ()
+ (setq font-lock-keywords isa-output-font-lock-keywords-1)
+ (isa-init-output-syntax-table)
+ (proof-response-config-done))
+
+(defun isa-goals-mode-config ()
+ ;; FIXME: next two broken, of course, as is PBP everywhere except LEGO.
+ (setq pbp-change-goal "Show %s.")
+ (setq pbp-error-regexp proof-shell-error-regexp)
+ (isa-init-output-syntax-table)
+ (setq font-lock-keywords isa-goals-font-lock-keywords)
+ (proof-goals-config-done))
+
+(defun isa-preprocessing () ;dynamic scoping of `string'
+ "Handle ^VERBATIM marker -- acts on variable STRING by dynamic scoping"
+ (if (proof-string-match isabelle-verbatim-regexp string)
+ (setq string (match-string 1 string))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; x-symbol support for Isabelle PG, provided by David von Oheimb.
+;;
+;; The following settings configure the generic PG package.
+;; The token language "Isabelle Symbols" is in file x-symbol-isa.el
+;;
+
+(setq proof-xsym-extra-modes '(thy-mode)
+ proof-xsym-activate-command
+ "print_mode := ([\"xsymbols\",\"symbols\"] @ ! print_mode);"
+ proof-xsym-deactivate-command
+ "print_mode := (! print_mode \\\\ [\"xsymbols\",\"symbols\"]);")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Completion table for Isabelle identifiers
+;;
+;; Ideally this could be set automatically from the running process,
+;; and maybe a default value could be dumped by Isabelle when it is
+;; built.
+
+(defpgdefault completion-table
+ '("quit"
+ "cd" "use" "use_thy" "time_use" "time_use_thy"
+ "Pretty.setdepth" "Pretty.setmargin" "print_depth"
+ "show_hyps" "show_types" "show_sorts"
+ "print_exn"
+ "goal" "goalw" "goalw_cterm" "premises"
+ "by" "byev"
+ "result" "uresult"
+ "chop" "choplev" "back" "undo"
+ "pr" "prlev" "goals_limit"
+ "proof_timing"
+ "prove_goal" "prove_goalw" "prove_goalw_cterm"
+ "push_proof" "pop_proof" "rotate_proof"
+ "save_proof" "restore_proof"
+ "read" "prin" "printyp"
+ "topthm" "getgoal" "gethyps"
+ "filter_goal" "compat_goal"
+
+ ;; short cuts - should these be included?
+ "ba" "br" "be" "bd" "brs" "bes" "bds"
+ "fs" "fr" "fe" "fd" "frs" "fes" "fds"
+ "bw" "bws" "ren"
+
+ "resolve_tac" "eresolve_tac" "dresolve_tac" "forward_tac"
+ "assume_tac" "eq_assume_tac"
+ "match_tac" "ematch_tac" "dmatch_tac"
+ "res_inst_tac" "eres_inst_tac" "dres_inst_tac" "forw_inst_tac"
+ "rewrite_goals_tac" "rewrite_tac" "fold_goals_tac"
+ "fold_goals_tac" "fold_tac"
+ "cut_facts_tac" "subgoal_tac"
+
+ ;; short cuts - should these be included?
+ "rtac" "etac" "dtac" "atac" "ares_tac" "rewtac"
+
+ ;; In general, I think rules should appear in rule tables, not here.
+ "asm_rl" "cut_rl"
+
+ "flexflex_tac" "rename_tac" "rename_last_tac"
+ "Logic.set_rename_prefix" "Logic.auto_rename"
+
+ "compose_tac"
+
+ "biresolve_tac" "bimatch_tac" "subgoals_of_brl" "lessb"
+ "head_string" "insert_thm" "delete_thm" "compat_resolve_tac"
+
+ "could_unify" "filter_thms" "filt_resolve_tac"
+
+ ;; probably shouldn't be included:
+ "tapply" "Tactic" "PRIMITIVE" "STATE" "SUBGOAL"
+
+ "pause_tac" "print_tac"
+
+ "THEN" "ORELSE" "APPEND" "INTLEAVE"
+ "EVERY" "FIRST" "TRY" "REPEAT_DETERM" "REPEAT" "REPEAT1"
+ "trace_REPEAT"
+ "all_tac" "no_tac"
+ "FILTER" "CHANGED" "DEPTH_FIRST" "DEPTH_SOLVE"
+ "DEPTH_SOLVE_1" "trace_DEPTH_FIRST"
+ "BREADTH_FIRST" "BEST_FIRST" "THEN_BEST_FIRST"
+ "trace_BEST_FIRST"
+ "COND" "IF_UNSOLVED" "DETERM"
+
+ "SELECT_GOAL" "METAHYPS"
+
+ "ALLGOALS" "TRYALL" "SOMEGOAL" "FIRSTGOAL"
+ "REPEAT_SOME" "REPEAT_FIRST" "trace_goalno_tac"
+
+ ;; include primed versions of tacticals?
+
+ "EVERY1" "FIRST1"
+
+ "prth" "prths" "prthq"
+ "RSN" "RLN" "RL"
+
+ ;; simplifier
+
+ "addsimps" "addeqcongs" "delsimps"
+ "setsolver" "setloop" "setmksimps" "setsubgoaler"
+ "empty_ss" "merge_ss" "prems_of_ss" "rep_ss"
+ "simp_tac" "asm_full_simp_tac" "asm_simp_tac"
+
+ ;; classical prover
+
+ "empty_cs"
+ "addDs" "addEs" "addIs" "addSDs" "addSEs" "addSIs"
+ "print_cs"
+ "rep_claset" "best_tac" "chain_tac" "contr_tac" "eq_mp_tac"
+ "fast_tac" "joinrules" "mp_tac" "safe_tac" "safe_step_tac"
+ "slow_best_tac" "slow_tac" "step_tac" "swapify"
+ "swap_res_tac" "inst_step_tac"
+
+ ;; that's it for now!
+ ))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Theorem dependencies (experimental)
+;;
+
+(defpacustom theorem-dependencies nil
+ "Whether to track theorem dependencies within Proof General."
+ :type 'boolean
+ ;; when this is built-in (or with a ":=%b" setting).
+ ;; :setting ("depends_enable()" . "depends_disable()")
+ :eval (isa-theorem-dependencies-switch))
+
+(defvar isa-dependsml-file-loaded nil)
+
+(add-hook 'proof-shell-kill-function-hooks
+ (lambda () (setq isa-dependsml-file-loaded nil)))
+
+(defun isa-load-dependsml-file ()
+ ;; NB: maybe doesn't work if enabled before Isabelle starts.
+ (if (proof-shell-available-p)
+ (progn
+ (proof-shell-invisible-command
+ (proof-format-filename
+ "use \"%r\";"
+ (concat (file-name-directory
+ (locate-library "isa"))
+ "depends.ML")))
+ (setq isa-dependsml-file-loaded t))))
+
+(defun isa-theorem-dependencies-switch ()
+ "Switch on/off theorem dependency tracking. (Experimental feature)."
+ (if (and isa-theorem-dependencies (not isa-dependsml-file-loaded))
+ (isa-load-dependsml-file))
+ (proof-shell-invisible-command (if isa-theorem-dependencies
+ "depends_enable()"
+ "depends_disable()")))
+
+
+
+
+
+(provide 'isa)
diff --git a/isa/isabelle-system.el b/isa/isabelle-system.el
new file mode 100644
index 00000000..01d98767
--- /dev/null
+++ b/isa/isabelle-system.el
@@ -0,0 +1,382 @@
+;; isabelle-system.el Interface with Isabelle system
+;;
+;; Copyright (C) 2000 LFCS Edinburgh, David Aspinall.
+;;
+;; Author: David Aspinall <da@dcs.ed.ac.uk>
+;; Maintainer: Proof General maintainer <proofgen@dcs.ed.ac.uk>
+;;
+;; $Id$
+;;
+;; Most of this code is taken from the final version of Isamode.
+;; --------------------------------------------------------------
+;;
+
+(require 'proof)
+
+(defconst isa-running-isar (eq proof-assistant-symbol 'isar))
+
+;; If we're using Isabelle/Isar then the isabelle custom
+;; group won't have been defined yet.
+(if isa-running-isar
+(defgroup isabelle nil
+ "Customization of user options for Isabelle and Isabelle/Isar Proof General"
+ :group 'proof-general))
+
+(defcustom isabelle-web-page
+ "http://www.cl.cam.ac.uk/Research/HVG/Isabelle/"
+ ;; "http://isabelle.in.tum.de"
+ ;; "http://www.dcs.ed.ac.uk/home/isabelle"
+ "URL of web page for Isabelle."
+ :type 'string
+ :group 'isabelle)
+
+
+;;; ================ Extract Isabelle settings ================
+
+(defcustom isa-isatool-command
+ (or (getenv "ISATOOL")
+ (proof-locate-executable "isatool")
+ (let ((possibilities
+ '("/usr/bin/isatool"
+ "/usr/share/Isabelle/bin/isatool"
+ "/usr/local/bin/isatool"
+ "/usr/local/Isabelle/bin/isatool"
+ "/opt/bin/isatool"
+ "/opt/Isabelle/bin/isatool")))
+ (while (and possibilities
+ (not (file-executable-p
+ (car possibilities))))
+ (setq possibilities (cdr possibilities)))
+ (car-safe possibilities))
+ "path_to_isatool_is_unknown")
+ "Command to invoke Isabelle tool 'isatool'.
+XEmacs should be able to find `isatool' if it is on the PATH when
+started. Then several standard locations are attempted.
+Otherwise you should set this, using a full path name here for reliable
+working."
+ :type 'file
+ :group 'isabelle)
+
+(defun isa-set-isatool-command ()
+ "Make sure isa-isatool-command points to a valid executable.
+If it does not, prompt the user for the proper setting.
+If it appears we're running on win32 or FSF Emacs, we allow this to
+remain unverified.
+Returns non-nil if isa-isatool-command is surely an executable
+with full path."
+ (interactive)
+ (while (unless proof-running-on-win32
+ (not (file-executable-p isa-isatool-command)))
+ (beep)
+ (setq isa-isatool-command
+ (read-file-name
+ "Please type in the full path to the `isatool' program: "
+ nil nil t)))
+ (if (and proof-running-on-win32
+ (not (file-executable-p isa-isatool-command)))
+ (warning "Proof General: isatool command not found; ignored because Win32 system detected."))
+ (file-executable-p isa-isatool-command))
+
+(defun isa-shell-command-to-string (command)
+ "Like shell-command-to-string except the last character is stripped."
+ ;; FIXME: sometimes the command may fail. This will usually cause PG
+ ;; to break. Bit of an effort to trap errors here, we would need
+ ;; to provide some advice to shell-command-to-string to retain result
+ ;; of call to call-process, and raise and error in case it failed.
+ (substring (shell-command-to-string command) 0 -1))
+
+(defun isa-getenv (envvar &optional default)
+ "Extract an environment variable setting using the `isatool' program.
+If the isatool command is not available, try using elisp's getenv
+to extract the value from Emacs' environment.
+If there is no setting for the variable, DEFAULT will be returned"
+ (isa-set-isatool-command)
+ (if (file-executable-p isa-isatool-command)
+ (let ((setting (isa-shell-command-to-string
+ (concat isa-isatool-command
+ " getenv -b " envvar))))
+ (if (string-equal setting "")
+ default
+ setting))
+ (or (getenv envvar) default)))
+
+;;;
+;;; ======= Interaction with System using Isabelle tools =======
+;;;
+
+(defcustom isabelle-program-name
+ (if (fboundp 'proof-running-on-win32)
+ "C:\\sml\\bin\\.run\\run.x86-win32.exe @SMLload=C:\\Isabelle\\"
+ (proof-locate-executable "isabelle" t))
+ "*Default name of program to run Isabelle.
+
+The default value except when running under Windows is \"isabelle\",
+which will get expanded using PATH if possible.
+
+The default value when running under Windows is:
+
+ C:\\sml\\bin\\.run\\run.x86-win32.exe @SMLload=C:\\Isabelle\\
+
+This expects SML/NJ in C:\\sml and Isabelle images in C:\Isabelle.
+The logic image name is tagged onto the end.
+
+NB: The Isabelle settings mechanism or the environment variable
+ISABELLE will always override this setting."
+ :type 'file
+ :group 'isabelle)
+
+(defvar isabelle-prog-name isabelle-program-name
+ "Set from `isabelle-program-name', has name of logic appended sometimes.")
+
+(defun isabelle-command-line ()
+ "Make proper command line for running Isabelle"
+ (let*
+ ;; The ISABELLE and PROOFGENERAL_LOGIC values (as set when run
+ ;; under the interface wrapper script) indicate that we should
+ ;; determine the proper command line from the current Isabelle
+ ;; settings environment.
+ ((isabelle (or
+ (getenv "ISABELLE") ; overrides default, may be updated
+ isabelle-program-name ; calculated earlier
+ "isabelle")) ; to be really sure
+ (isabelle-opts (getenv "ISABELLE_OPTIONS"))
+ (opts (concat
+ (if isa-running-isar " -PI" "")
+ (if (and isabelle-opts (not (equal isabelle-opts "")))
+ (concat " " isabelle-opts) "")))
+ (logic (or isabelle-chosen-logic
+ (getenv "PROOFGENERAL_LOGIC")))
+ (logicarg (if (and logic (not (equal logic "")))
+ (concat " " logic) "")))
+ (concat isabelle opts logicarg)))
+
+(defun isabelle-choose-logic (logic)
+ "Adjust isabelle-prog-name and proof-prog-name for running LOGIC."
+ ;; a little bit obnoxious maybe (but what naive user would expect)
+ ;; (customize-save-variable 'isabelle-chosen-logic logic)
+ (customize-set-variable 'isabelle-chosen-logic logic)
+ (setq isabelle-prog-name (isabelle-command-line))
+ (setq proof-prog-name isabelle-prog-name))
+
+(defun isa-tool-list-logics ()
+ "Generate a list of available object logics."
+ (if (isa-set-isatool-command)
+ (split-string (isa-shell-command-to-string
+ (concat isa-isatool-command " findlogics")) "[ \t]")))
+
+(defun isa-view-doc (docname)
+ "View Isabelle document DOCNAME, using Isabelle tools."
+ (if (isa-set-isatool-command)
+ (apply 'start-process
+ "isa-view-doc" nil
+ (list isa-isatool-command "doc" docname))))
+
+(defun isa-tool-list-docs ()
+ "Generate a list of documentation files available, with descriptions.
+This function returns a list of lists of the form
+ ((DOCNAME DESCRIPTION) ....)
+of Isabelle document names and descriptions. When DOCNAME is
+passed to isa-tool-doc-command, DOCNAME will be viewed."
+ (if (isa-set-isatool-command)
+ (let ((docs (isa-shell-command-to-string
+ (concat isa-isatool-command " doc"))))
+ (unless (string-equal docs "")
+ (mapcar
+ (function (lambda (docdes)
+ (list
+ (substring docdes
+ (proof-string-match "\\(\\S-+\\)[ \t]+" docdes)
+ (match-end 1))
+ (substring docdes (match-end 0)))))
+ (split-string docs "\n"))))))
+
+(defun isa-quit (save)
+ "Quit / save the Isabelle session.
+Called with one argument: t to save database, nil otherwise."
+ (if (not save)
+ (isa-insert-ret "quit();"))
+ (comint-send-eof))
+
+(defconst isabelle-verbatim-regexp "\\`\^VERBATIM: \\(\\(.\\|\n\\)*\\)\\'"
+ "Regexp matching internal marker for verbatim command output")
+
+(defun isabelle-verbatim (str)
+ "Mark internal command for verbatim output"
+ (concat "\^VERBATIM: " str))
+
+;;; Set proof-shell-pre-interrupt-hook for PolyML 3.
+(if (and
+ (not proof-shell-pre-interrupt-hook)
+ ;; (Older versions of Isabelle reported PolyML for PolyML 3).
+ (proof-string-match "\\`polyml" (isa-getenv "ML_SYSTEM"))
+ (not (proof-string-match "\\`polyml-4" (isa-getenv "ML_SYSTEM"))))
+ (add-hook
+ 'proof-shell-pre-interrupt-hook
+ (lambda () (proof-shell-insert (isabelle-verbatim "f") nil))))
+
+;;; ========== Utility functions ==========
+
+(defcustom isabelle-logics-available (isa-tool-list-logics)
+ "*List of logics available to use with Isabelle.
+If the `isatool' program is available, this is automatically
+generated with the lisp form `(isa-tool-list-logics)'."
+ :type (list 'string)
+ :group 'isabelle)
+
+;; FIXME: document this one
+(defcustom isabelle-chosen-logic nil
+ "*Choice of logic to use with Isabelle.
+If non-nil, will be added into isabelle-prog-name as default value.
+
+NB: you have saved a new logic image, it may not appear in the choices
+until Proof General is restarted."
+ :type (append
+ (list 'choice)
+ (mapcar (lambda (str) (list 'const str)) isabelle-logics-available)
+ (list '(string :tag "Choose another")
+ '(const :tag "Unset (use default)" nil)))
+ :group 'isabelle)
+
+(defconst isabelle-docs-menu
+ (let ((vc '(lambda (docdes)
+ (vector (car (cdr docdes))
+ (list 'isa-view-doc (car docdes)) t))))
+ (list (cons "Isabelle documentation" (mapcar vc (isa-tool-list-docs)))))
+ "Isabelle documentation menu. Constructed when PG is loaded.")
+
+
+;; It's a hassle to bother trying to reconstruct this
+;; dynamically like it was in Isamode, so we don't bother.
+
+(defconst isabelle-logics-menu
+ (cons "Logics"
+ (cons
+ ["Default"
+ (isabelle-choose-logic nil)
+ :active (not (proof-shell-live-buffer))
+ :style radio
+ :selected (not isabelle-chosen-logic)]
+ (mapcar (lambda (l)
+ (vector l (list 'isabelle-choose-logic l)
+ :active '(not (proof-shell-live-buffer))
+ :style 'radio
+ :selected (list 'equal 'isabelle-chosen-logic l)))
+ (isa-tool-list-logics))))
+ "Isabelle logics menu. Constructed when PG is loaded.")
+
+
+
+;;; ========== Mirroring Proof General options in Isabelle process ========
+
+;; NB: use of defpacustom here gives separate customizable
+;; options for Isabelle and Isabelle/Isar.
+
+(defpacustom show-types nil
+ "Whether to show types in Isabelle."
+ :type 'boolean
+ :setting "show_types:=%b;")
+
+(defpacustom show-sorts nil
+ "Whether to show sorts in Isabelle."
+ :type 'boolean
+ :setting "show_sorts:=%b;")
+
+(defpacustom show-consts nil
+ "Whether to show types of consts in Isabelle goals."
+ :type 'boolean
+ :setting "show_consts:=%b;")
+
+(defpacustom long-names nil
+ "Whether to show fully qualified names in Isabelle."
+ :type 'boolean
+ :setting "long_names:=%b;")
+
+(defpacustom eta-contract t
+ "Whether to print terms eta-contracted in Isabelle."
+ :type 'boolean
+ :setting "Syntax.eta_contract:=%b;")
+
+(defpacustom trace-simplifier nil
+ "Whether to trace the Simplifier in Isabelle."
+ :type 'boolean
+ :setting "trace_simp:=%b;")
+
+(defpacustom trace-rules nil
+ "Whether to trace the standard rules in Isabelle."
+ :type 'boolean
+ :setting "trace_rules:=%b;")
+
+(defpacustom quick-and-dirty t
+ "Whether to take a few short cuts occasionally."
+ :type 'boolean
+ :setting "quick_and_dirty:=%b;")
+
+(defpacustom full-proofs nil
+ "Whether to record full proof objects internally."
+ :type 'boolean
+ :setting "Library.error_fn := (fn _ => ()); Library.try (fn () => Context.use_mltext \"ProofGeneral.full_proofs %b;\" false None) ();")
+;FIXME should become "ProofGeneral.full_proofs %b;" next time
+
+(defpacustom global-timing nil
+ "Whether to enable timing in Isabelle."
+ :type 'boolean
+ :setting "Library.timing:=%b;")
+
+(defpacustom goals-limit 10
+ "Setting for maximum number of goals printed in Isabelle."
+ :type 'integer
+ :setting "goals_limit:=%i;")
+
+(defpacustom prems-limit 10
+ "Setting for maximum number of premises printed in Isabelle/Isar."
+ :type 'integer
+ :setting "ProofContext.prems_limit:=%i;")
+
+(defpacustom print-depth 10
+ "Setting for the ML print depth in Isabelle."
+ :type 'integer
+ :setting "print_depth %i;")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Generic Isabelle menu for Isabelle and Isabelle/Isar
+;;
+
+(defpgdefault menu-entries
+ (append
+ (if isa-running-isar
+ nil
+ (list ["Switch to theory" thy-find-other-file t]))
+ (list isabelle-logics-menu)))
+
+(defpgdefault help-menu-entries isabelle-docs-menu)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; X-Symbol language configuration, and adding to completion table
+;;
+
+(defpgdefault x-symbol-language 'isabelle)
+
+(setq proof-xsym-font-lock-keywords
+ ;; fontification for tokens themselves (FIXME: broken)
+ '(("\\\\<[A-Za-z][A-Za-z0-9_']*>" (0 font-lock-type-face))))
+
+(eval-after-load "x-symbol-isabelle"
+ ;; Add x-symbol tokens to isa-completion-table and rebuild
+ ;; internal completion table if completion is already active
+'(progn
+ (defpgdefault completion-table
+ (append (proof-ass completion-table)
+ (mapcar (lambda (xsym) (nth 2 xsym))
+ x-symbol-isabelle-table)))
+ (if (featurep 'completion)
+ (proof-add-completions))))
+
+
+
+
+(provide 'isabelle-system)
+;; End of isabelle-system.el
diff --git a/isa/thy-mode.el b/isa/thy-mode.el
new file mode 100644
index 00000000..07e0ca54
--- /dev/null
+++ b/isa/thy-mode.el
@@ -0,0 +1,1047 @@
+;; thy-mode.el - Mode for Isabelle theory files.
+;;
+;; Author: David Aspinall <da@dcs.ed.ac.uk>
+;; Maintainer: Isabelle maintainer <isabelle@dcs.ed.ac.uk>
+;;
+;; 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 isa-thy-
+
+(require 'proof-site)
+(require 'proof-syntax)
+(require 'isa)
+
+;;; ========== 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])
+ proof-shared-menu
+ ;; begin UGLY COMPATIBILTY HACK
+ ;; older/non-existent customize doesn't have
+ ;; this function.
+ (if (fboundp 'customize-menu-create)
+ (list (customize-menu-create 'proof-general)
+ (customize-menu-create
+ 'proof-general-internals
+ "Internals"))
+ nil)
+ ;; end UGLY COMPATIBILTY HACK
+ )))
+ (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
diff --git a/isa/todo b/isa/todo
new file mode 100644
index 00000000..8e68bc23
--- /dev/null
+++ b/isa/todo
@@ -0,0 +1,84 @@
+-*- mode:outline -*-
+
+* Things to do for Isabelle
+
+See also ../todo for generic things to do, priority codes.
+
+** D Isabelle: I think show_sorts -> show_types, how can we reflect this ?
+
+** D Fix mode naming for Isabelle
+ (might like isa-proofscript-mode -> isa-mode;
+ but this conflicts with entry mechanism for thy/isa mode).
+
+** D Might be nice to unify menus a little more, e.g. add Isabelle for .thy
+
+ But several of the ops there are not relevant for theory files.
+ Well, favourites at least. What we have at the moment is verging
+ GUI-atrocity: one shouldn't have menus of the same name with
+ different entries, but should rather use greyed out.
+
+** C Improvements to Isabelle that would be nice for Proof General:
+
+ -- ability to remove theorem from theorem database, issued
+ when undoing qed
+
+
+** C Investigate fix for looping rewriting in Isabelle. Continual
+ and frequent messages from the prover lock out the user.
+ Is there any easy way of fixing this?
+
+** C X-Symbol support for theory files: bugs at the moment, because
+ of duplicate calls to proof-x-symbol-mode and mess with
+ font-lock initialization. Problem with current version:
+ visit a.thy, b.thy then turn on xsym. Broken in b.thy.
+ Seems okay visiting new buffers after that.
+ Must also check interaction with xsym-isa-latex stuff
+ may be broken by removal of mode hook settings.
+ [DvO reports okay].
+ (May need to split extra modes into two parts?)
+
+** B auto-adjust Pretty.setmargin when window is resized. Use
+ generic code once it's implemented.
+
+** D Implement completion for Isabelle using tables generated by
+ the running process. Ideally context sensitive.
+ Would be a nice addition. (1 week)
+
+** D Add useful specific commands for Isabelle. Many could
+ be added. Would be better to merge in Isamode's menus.
+ (however, probably 2 week's work to bring together Isamode
+ and proof.el, making some of Isamode generic)
+
+** D Switching to other file with C-c C-o could be more savy
+ with file names and extensions (use some standard function?)
+
+** X weird bug: interrupting Isabelle process (under sml-nj) sometimes
+ doesn't return, why? (see first half of interrupt error only:
+
+ *** Interrupt.
+ *** At command "time_use".
+
+ uncaught exception ERROR
+ raised at: library.ML:1100.35-1100.40
+ But not "uncaught exception" part.
+ What is worse: prompt disappears! But process still seems to be
+ there underneath. Not sure where this bug comes from.
+
+ Moreover, killing process then hangs Emacs with message
+ "cleaning up", and get error
+ (1) (error/warning) Error in process sentinel: (no-catch exited t)
+
+ To see if this is some SML/NJ or Isabelle weirdness, test in
+ xterm: use "ROOT.ML", interrrupt, use "ROOT.ML" again.
+ sig 11! (flaky hardware?)
+ /usr/lib/Isabelle_22-Sep-1999/../../share/smlnj/bin/sml: Fatal error -- unexpected fault, signal = 11, code = 0x2ad09c43
+ Not reliably repeatable, but:
+ ProofGeneral.isa_restart();
+ /usr/lib/Isabelle_22-Sep-1999/../../share/smlnj/bin/sml: Fatal error -- unexpected fault, signal = 11, code = 0x2af9e01b
+
+** X Write perl scripts to generate TAGS file for ML and thy files.
+ (60h, any volunteers?) (hard);
+
+** X Manage multiple proofs, perhaps by automatically inserting
+ push_proof() and pop_proof() commands into the proof script.
+ But would lead to unholy mess for script management! (hard!)
diff --git a/isa/x-symbol-isabelle.el b/isa/x-symbol-isabelle.el
new file mode 100644
index 00000000..f9938491
--- /dev/null
+++ b/isa/x-symbol-isabelle.el
@@ -0,0 +1,410 @@
+;; ID: $Id$
+;; Author: David von Oheimb
+;; Copyright 1998 Technische Universitaet Muenchen
+;; token language "Isabelle Symbols" for package x-symbol
+;;
+;; NB: Part of Proof General distribution.
+;;
+
+(defvar x-symbol-isabelle-required-fonts nil)
+
+;; FIXME da: these next two are also set in proof-x-symbol.el, but
+;; it's handy to use this file away from PG. In future could
+;; fix things so just (require 'proof-x-symbol) would be enough
+;; here.
+(defvar x-symbol-isabelle-name "Isabelle Symbol")
+(defvar x-symbol-isabelle-modeline-name "isa")
+
+(defvar x-symbol-isabelle-header-groups-alist nil)
+;'(("Operator" bigop operator)
+; ("Relation" relation)
+; ("Arrow, Punctuation" arrow triangle shape
+; white line dots punctuation quote parenthesis)
+; ("Symbol" symbol currency mathletter setsymbol)
+; ("Greek Letter" greek greek1)
+; ("Acute, Grave" acute grave))
+; "*If non-nil, used in isasym specific grid/menu."
+
+(defvar x-symbol-isabelle-class-alist
+ '((VALID "Isabelle Symbol" (x-symbol-info-face))
+ (INVALID "no Isabelle Symbol" (red x-symbol-info-face))))
+(defvar x-symbol-isabelle-class-face-alist nil)
+(defvar x-symbol-isabelle-electric-ignore "[:'][A-Za-z]\\|<=\\|\\[\\[\\|\\]\\]\\|~=")
+
+
+;; Bold, super- and subscripts
+
+(defun x-symbol-isabelle-make-ctrl-regexp (s)
+ (concat "\\(\\\\?\\\\<\\^" s ">\\)\\(\\\\?\\\\<[A-Za-z][A-Za-z0-9_']*>\\|[^\\]\\)"))
+
+(defconst x-symbol-isabelle-font-lock-bold-regexp
+ (x-symbol-isabelle-make-ctrl-regexp "bold")
+ "Regexp matching bold marker in Isabelle.")
+
+(defconst x-symbol-isabelle-font-lock-scripts-regexp
+ (x-symbol-isabelle-make-ctrl-regexp "su[bp]")
+ "Regexp matching super- and subscript markers in Isabelle.")
+
+(defun x-symbol-isabelle-match-bold (limit)
+ ;; checkdoc-params: (limit)
+ "Match and skip over bold face.
+Return nil if `x-symbol-mode' is nil.
+Uses `x-symbol-isabelle-font-lock-bold-regexp'."
+ (and (proof-ass x-symbol-enable)
+ (or (proof-looking-at x-symbol-isabelle-font-lock-bold-regexp)
+ (proof-re-search-forward x-symbol-isabelle-font-lock-bold-regexp limit t))))
+
+(defun x-symbol-isabelle-match-scripts (limit)
+ ;; checkdoc-params: (limit)
+ "Match and skip over super- and subscripts.
+Return nil if `x-symbol-mode' is nil.
+Uses `x-symbol-isabelle-font-lock-scripts-regexp'."
+ (and (proof-ass x-symbol-enable)
+ (or (proof-looking-at x-symbol-isabelle-font-lock-scripts-regexp)
+ (proof-re-search-forward x-symbol-isabelle-font-lock-scripts-regexp limit t))))
+
+(defvar x-symbol-isabelle-font-lock-keywords
+ '((x-symbol-isabelle-match-bold
+ (1 x-symbol-invisible-face t)
+ (2 'underline prepend))
+ (x-symbol-isabelle-match-scripts
+ (1 x-symbol-invisible-face t)
+ (2 (if (or (eq (char-after (+ 5 (match-beginning 1))) ?b)
+ (eq (char-after (+ 6 (match-beginning 1))) ?b))
+ 'x-symbol-sub-face 'x-symbol-sup-face) prepend)))
+ "Isabelle font-lock keywords for bold, super- and subscripts.")
+
+
+(defvar x-symbol-isabelle-master-directory 'ignore)
+(defvar x-symbol-isabelle-image-searchpath '("./"))
+(defvar x-symbol-isabelle-image-cached-dirs '("images/" "pictures/"))
+(defvar x-symbol-isabelle-image-file-truename-alist nil)
+(defvar x-symbol-isabelle-image-keywords nil)
+
+(defvar x-symbol-isabelle-case-insensitive nil)
+;(defvar x-symbol-isabelle-token-shape '(?\\ "\\\\\\<[A-Za-z][A-Za-z0-9_']*>\\a'" . "[A-Za-z]"))
+(defvar x-symbol-isabelle-token-shape nil)
+
+(defvar x-symbol-isabelle-exec-specs '(nil ("\\`\\\\<[A-Za-z][A-Za-z0-9_']*>\\'" .
+ "\\\\<[A-Za-z][A-Za-z0-9_']*>")))
+
+(defvar x-symbol-isabelle-input-token-ignore nil)
+(defun x-symbol-isabelle-default-token-list (tokens) tokens)
+
+
+(defvar x-symbol-isabelle-token-list 'x-symbol-isabelle-default-token-list)
+
+(defvar x-symbol-isabelle-symbol-table ; symbols (isabelle font)
+ '((visiblespace "\\<spacespace>")
+ (Gamma "\\<Gamma>")
+ (Delta "\\<Delta>")
+ (Theta "\\<Theta>")
+ (Lambda "\\<Lambda>")
+ (Pi "\\<Pi>")
+ (Sigma "\\<Sigma>")
+ (Phi "\\<Phi>")
+ (Psi "\\<Psi>")
+ (Omega "\\<Omega>")
+ (alpha "\\<alpha>")
+ (beta "\\<beta>")
+ (gamma "\\<gamma>")
+ (delta "\\<delta>")
+ (epsilon1 "\\<epsilon>")
+ (zeta "\\<zeta>")
+ (eta "\\<eta>")
+ (theta "\\<theta>")
+ (kappa1 "\\<kappa>")
+ (lambda "\\<lambda>")
+ (mu "\\<mu>")
+ (nu "\\<nu>")
+ (xi "\\<xi>")
+ (pi "\\<pi>")
+ (rho1 "\\<rho>")
+ (sigma "\\<sigma>")
+ (tau "\\<tau>")
+ (phi1 "\\<phi>")
+ (chi "\\<chi>")
+ (psi "\\<psi>")
+ (omega "\\<omega>")
+ (notsign "\\<not>")
+ (logicaland "\\<and>")
+ (logicalor "\\<or>")
+ (universal1 "\\<forall>")
+ (existential1 "\\<exists>")
+ (biglogicaland "\\<And>")
+ (ceilingleft "\\<lceil>")
+ (ceilingright "\\<rceil>")
+ (floorleft "\\<lfloor>")
+ (floorright "\\<rfloor>")
+ (bardash "\\<turnstile>")
+ (bardashdbl "\\<Turnstile>")
+ (semanticsleft "\\<lbrakk>")
+ (semanticsright "\\<rbrakk>")
+ (periodcentered "\\<cdot>")
+ (element "\\<in>")
+ (reflexsubset "\\<subseteq>")
+ (intersection "\\<inter>")
+ (union "\\<union>")
+ (bigintersection "\\<Inter>")
+ (bigunion "\\<Union>")
+ (sqintersection "\\<sqinter>")
+ (squnion "\\<squnion>")
+ (bigsqintersection "\\<Sqinter>")
+ (bigsqunion "\\<Squnion>")
+ (perpendicular "\\<bottom>")
+ (dotequal "\\<doteq>")
+ (wrong "\\<wrong>")
+ (equivalence "\\<equiv>")
+ (notequal "\\<noteq>")
+ (propersqsubset "\\<sqsubset>")
+ (reflexsqsubset "\\<sqsubseteq>")
+ (properprec "\\<prec>")
+ (reflexprec "\\<preceq>")
+ (propersucc "\\<succ>")
+ (approxequal "\\<approx>")
+ (similar "\\<sim>")
+ (simequal "\\<simeq>")
+ (lessequal "\\<le>")
+ (coloncolon "\\<Colon>")
+ (arrowleft "\\<leftarrow>")
+ (endash "\\<midarrow>")
+ (arrowright "\\<rightarrow>")
+ (arrowdblleft "\\<Leftarrow>")
+; (nil "\\<Midarrow>")
+ (arrowdblright "\\<Rightarrow>")
+ (frown "\\<frown>")
+ (mapsto "\\<mapsto>")
+ (leadsto "\\<leadsto>")
+ (arrowup "\\<up>")
+ (arrowdown "\\<down>")
+ (notelement "\\<notin>")
+ (multiply "\\<times>")
+ (circleplus "\\<oplus>")
+ (circleminus "\\<ominus>")
+ (circlemultiply "\\<otimes>")
+ (circleslash "\\<oslash>")
+ (propersubset "\\<subset>")
+ (infinity "\\<infinity>")
+ (box "\\<box>")
+ (lozenge1 "\\<diamond>")
+ (circ "\\<circ>")
+ (bullet "\\<bullet>")
+ (bardbl "\\<parallel>")
+ (radical "\\<surd>")
+ (copyright "\\<copyright>")))
+
+(defvar x-symbol-isabelle-xsymbol-table ; xsymbols
+ '((Xi "\\<Xi>")
+ (Upsilon1 "\\<Upsilon>")
+ (iota "\\<iota>")
+ (upsilon "\\<upsilon>")
+ (plusminus "\\<plusminus>")
+ (division "\\<div>")
+ (longarrowright "\\<longrightarrow>")
+ (longarrowleft "\\<longleftarrow>")
+ (longarrowboth "\\<longleftrightarrow>")
+ (longarrowdblright "\\<Longrightarrow>")
+ (longarrowdblleft "\\<Longleftarrow>")
+ (longarrowdblboth "\\<Longleftrightarrow>")
+ (brokenbar "\\<bar>")
+ (hyphen "\\<hyphen>")
+ (macron "\\<inverse>")
+ (exclamdown "\\<exclamdown>")
+ (questiondown "\\<questiondown>")
+ (guillemotleft "\\<guillemotleft>")
+ (guillemotright "\\<guillemotright>")
+ (degree "\\<degree>")
+ (onesuperior "\\<onesuperior>")
+ (onequarter "\\<onequarter>")
+ (twosuperior "\\<twosuperior>")
+ (onehalf "\\<onehalf>")
+ (threesuperior "\\<threesuperior>")
+ (threequarters "\\<threequarters>")
+ (paragraph "\\<paragraph>")
+ (registered "\\<registered>")
+ (ordfeminine "\\<ordfeminine>")
+ (masculine "\\<ordmasculine>")
+ (section "\\<section>")
+ (sterling "\\<pounds>")
+ (yen "\\<yen>")
+ (cent "\\<cent>")
+ (currency "\\<currency>")
+ (braceleft2 "\\<lbrace>")
+ (braceright2 "\\<rbrace>")
+ (top "\\<top>")
+ (congruent "\\<cong>")
+ (club "\\<clubsuit>")
+ (diamond "\\<diamondsuit>")
+ (heart "\\<heartsuit>")
+ (spade "\\<spadesuit>")
+ (arrowboth "\\<leftrightarrow>")
+ (greaterequal "\\<ge>")
+ (proportional "\\<propto>")
+ (partialdiff "\\<partial>")
+ (ellipsis "\\<dots>")
+ (aleph "\\<aleph>")
+ (Ifraktur "\\<Im>")
+ (Rfraktur "\\<Re>")
+ (weierstrass "\\<wp>")
+ (emptyset "\\<emptyset>")
+ (angle "\\<angle>")
+ (gradient "\\<nabla>")
+ (product "\\<Prod>")
+ (arrowdblboth "\\<Leftrightarrow>")
+ (arrowdblup "\\<Up>")
+ (arrowdbldown "\\<Down>")
+ (angleleft "\\<langle>")
+ (angleright "\\<rangle>")
+ (summation "\\<Sum>")
+ (integral "\\<integral>")
+ (circleintegral "\\<ointegral>")
+ (dagger "\\<dagger>")
+ (sharp "\\<sharp>")
+ (star "\\<star>")
+ (smltriangleright "\\<triangleright>")
+ (triangleleft "\\<lhd>")
+ (triangle "\\<triangle>")
+ (triangleright "\\<rhd>")
+ (trianglelefteq "\\<unlhd>")
+ (trianglerighteq "\\<unrhd>")
+ (smltriangleleft "\\<triangleleft>")
+ (natural "\\<natural>")
+ (flat "\\<flat>")
+ (amalg "\\<amalg>")
+ (Mho "\\<mho>")
+ (arrowupdown "\\<updown>")
+ (longmapsto "\\<longmapsto>")
+ (arrowdblupdown "\\<Updown>")
+ (hookleftarrow "\\<hookleftarrow>")
+ (hookrightarrow "\\<hookrightarrow>")
+ (rightleftharpoons "\\<rightleftharpoons>")
+ (leftharpoondown "\\<leftharpoondown>")
+ (rightharpoondown "\\<rightharpoondown>")
+ (leftharpoonup "\\<leftharpoonup>")
+ (rightharpoonup "\\<rightharpoonup>")
+ (asym "\\<asymp>")
+ (minusplus "\\<minusplus>")
+ (bowtie "\\<bowtie>")
+ (centraldots "\\<cdots>")
+ (circledot "\\<odot>")
+ (propersuperset "\\<supset>")
+ (reflexsuperset "\\<supseteq>")
+ (propersqsuperset "\\<sqsupset>")
+ (reflexsqsuperset "\\<sqsupseteq>")
+ (lessless "\\<lless>")
+ (greatergreater "\\<ggreater>")
+ (unionplus "\\<uplus>")
+ (smile "\\<smile>")
+ (reflexsucc "\\<succeq>")
+ (dashbar "\\<stileturn>")
+ (biglogicalor "\\<Or>")
+ (bigunionplus "\\<Uplus>")
+ (daggerdbl "\\<ddagger>")
+ (bigbowtie "\\<Join>")
+ (booleans "\\<bool>")
+ (complexnums "\\<complex>")
+ (natnums "\\<nat>")
+ (rationalnums "\\<rat>")
+ (realnums "\\<real>")
+ (integers "\\<int>")
+ (lesssim "\\<lesssim>")
+ (greatersim "\\<greatersim>")
+ (lessapprox "\\<lessapprox>")
+ (greaterapprox "\\<greaterapprox>")
+ (definedas "\\<triangleq>")
+ (cataleft "\\<lparr>")
+ (cataright "\\<rparr>")
+ (bigcircledot "\\<Odot>")
+ (bigcirclemultiply "\\<Otimes>")
+ (bigcircleplus "\\<Oplus>")
+ (coproduct "\\<Coprod>")
+ (cedilla "\\<cedilla>")
+ (diaeresis "\\<dieresis>")
+ (acute "\\<acute>")
+ (hungarumlaut "\\<hungarumlaut>")
+ (lozenge "\\<lozenge>")
+ (smllozenge "\\<struct>")
+ (dotlessi "\\<index>")
+ (euro "\\<euro>")
+ (zero1 "\\<zero>")
+ (one1 "\\<one>")
+ (two1 "\\<two>")
+ (three1 "\\<three>")
+ (four1 "\\<four>")
+ (five1 "\\<five>")
+ (six1 "\\<six>")
+ (seven1 "\\<seven>")
+ (eight1 "\\<eight>")
+ (nine1 "\\<nine>")
+ ))
+
+(defun x-symbol-isabelle-prepare-table (table)
+ (let*
+ ((is-isar (eq proof-assistant-symbol 'isar))
+ (prfx1 (if is-isar "" "\\"))
+ (prfx2 (if is-isar "\\" "")))
+ (mapcar (lambda (entry)
+ (list (car entry) '() (concat prfx1 (cadr entry)) (concat prfx2 (cadr entry))))
+ table)))
+
+(defvar x-symbol-isabelle-table
+ (x-symbol-isabelle-prepare-table
+ (append
+ (if (boundp 'x-symbol-isabelle-user-table) x-symbol-isabelle-user-table nil)
+ x-symbol-isabelle-symbol-table
+ x-symbol-isabelle-xsymbol-table)))
+
+(defvar x-symbol-user-table
+ (append
+ (if (boundp 'x-symbol-user-table) x-symbol-user-table nil)
+ '((bardash 180 (arrow) (direction east . perpendicular) nil (t "|-"))
+ (bardashdbl 182 (arrow) (direction east) nil (t "|=")))))
+
+
+;;;===========================================================================
+;;; Internal
+;;;===========================================================================
+
+(defvar x-symbol-isabelle-menu-alist nil
+ "Internal. Alist used for Isasym specific menu.")
+(defvar x-symbol-isabelle-grid-alist nil
+ "Internal. Alist used for Isasym specific grid.")
+
+(defvar x-symbol-isabelle-decode-atree nil
+ "Internal. Atree used by `x-symbol-token-input'.")
+(defvar x-symbol-isabelle-decode-alist nil
+ "Internal. Alist used for decoding of Isasym macros.")
+(defvar x-symbol-isabelle-encode-alist nil
+ "Internal. Alist used for encoding to Isasym macros.")
+
+(defvar x-symbol-isabelle-nomule-decode-exec nil
+ "Internal. File name of Isasym decode executable.")
+(defvar x-symbol-isabelle-nomule-encode-exec nil
+ "Internal. File name of Isasym encode executable.")
+
+
+
+;;;===========================================================================
+;;; useful key bindings
+;;;===========================================================================
+
+
+;; FIXME: these break some standard bindings, and should only be set
+;; for proof shell, script (or minibuffer) modes.
+
+;(global-set-key [(meta l)] 'x-symbol-INSERT-lambda)
+
+;(global-set-key [(meta n)] 'x-symbol-INSERT-notsign)
+;(global-set-key [(meta a)] 'x-symbol-INSERT-logicaland)
+;(global-set-key [(meta o)] 'x-symbol-INSERT-logicalor)
+;(global-set-key [(meta f)] 'x-symbol-INSERT-universal1)
+;(global-set-key [(meta t)] 'x-symbol-INSERT-existential1)
+
+;(global-set-key [(meta A)] 'x-symbol-INSERT-biglogicaland)
+;(global-set-key [(meta e)] 'x-symbol-INSERT-equivalence)
+;(global-set-key [(meta u)] 'x-symbol-INSERT-notequal)
+;(global-set-key [(meta m)] 'x-symbol-INSERT-arrowdblright)
+
+;(global-set-key [(meta i)] 'x-symbol-INSERT-longarrowright)
+
+(provide 'x-symbol-isabelle)