; isar.el --- Major mode for Isabelle/Isar proof assistant ;; Copyright (C) 1994-2004 LFCS Edinburgh. ;; ;; License: GPL (GNU GENERAL PUBLIC LICENSE) ;; ;; Maintainers: David Aspinall, Makarius, Stefan Berghofer ;; ;; Authors: David Aspinall ;; Markus Wenzel ;; ;; Contributors: David von Oheimb, Sebastian Skalberg ;; ;; ;; $Id$ ;; ;;; Code: (require 'proof) (eval-when-compile (require 'span) (require 'proof-syntax) (require 'pg-goals) (require 'pg-vars) (proof-ready-for-assistant 'isar)) ; compile for isar (require 'isabelle-system) ; system code (require 'isar-find-theorems) ; "Find Theorems" search form ;; ;; Load syntax ;; (defcustom isar-keywords-name nil "Specifies a theory-specific keywords setting to use with Isar. See -k option for Isabelle interface script." :type 'string :group 'isabelle-isar) (or (featurep 'isar-keywords) ;; Pickup isar-keywords file from somewhere appropriate, ;; giving user chance to set name of file, or based on ;; name of logic. (isabelle-load-isar-keywords (or isar-keywords-name isabelle-chosen-logic))) (require 'isar-syntax) ;; Completion table for Isabelle/Isar identifiers (defpgdefault completion-table isar-keywords-major) (defcustom isar-web-page "http://isabelle.in.tum.de/Isar/" "URL of web page for Isabelle/Isar." :type 'string :group 'isabelle-isar) ;; Adjust toolbar entries (must be done before proof-toolbar is loaded). (eval-after-load "pg-custom" '(setq isar-toolbar-entries (assq-delete-all 'qed (assq-delete-all 'goal isar-toolbar-entries)))) (defun isar-strip-terminators () "Remove explicit Isabelle/Isar command terminators `;' from the buffer." (interactive) (save-excursion (goto-char (point-min)) (while (proof-search-forward ";" (point-max) t) (if (not (proof-buffer-syntactic-context)) (progn (delete-backward-char 1) (or (proof-looking-at ";\\|\\s-\\|$") (insert " "))))))) (defun isar-markup-ml (string) "Return marked up version of ML command STRING for Isar." (format "ML_command {* %s *};" string)) (defun isar-mode-config-set-variables () "Configure generic proof scripting mode variables for Isabelle/Isar." (setq proof-assistant-home-page isar-web-page proof-guess-command-line 'isabelle-set-prog-name proof-prog-name-guess t ;; proof script syntax proof-terminal-char ?\; ; forcibly ends a command proof-electric-terminator-noterminator t ; don't insert it proof-script-command-start-regexp (proof-regexp-alt ;; FIXME: this gets { and } wrong: they must _not_ appear as {* *} ;; because that's lexically a kind of comment. isar-any-command-regexp (regexp-quote ";")) proof-script-integral-proofs t ;; FIXME: use old parser for now to avoid { } problem proof-script-use-old-parser t proof-script-comment-start isar-comment-start proof-script-comment-end isar-comment-end proof-script-comment-start-regexp isar-comment-start-regexp proof-script-comment-end-regexp isar-comment-end-regexp proof-string-start-regexp isar-string-start-regexp proof-string-end-regexp isar-string-end-regexp ;; For func-menu and finding goal..save regions proof-save-command-regexp isar-save-command-regexp proof-goal-command-regexp isar-goal-command-regexp proof-goal-with-hole-regexp isar-named-entity-regexp proof-goal-with-hole-result 2 proof-save-with-hole-regexp nil proof-script-next-entity-regexps isar-next-entity-regexps proof-script-imenu-generic-expression isar-generic-expression imenu-syntax-alist isar-script-syntax-table-alist proof-indent-enclose-offset (- proof-indent) proof-indent-open-offset 0 proof-indent-close-offset 0 proof-indent-any-regexp isar-indent-any-regexp ; proof-indent-inner-regexp isar-indent-inner-regexp proof-indent-enclose-regexp isar-indent-enclose-regexp proof-indent-open-regexp isar-indent-open-regexp proof-indent-close-regexp isar-indent-close-regexp ;; proof engine commands proof-showproof-command "pr" proof-goal-command "lemma \"%s\"" proof-save-command "qed" proof-context-command "print_context" proof-info-command "welcome" proof-query-identifier-command '((nil "thm %s;") (string "term \"%s\";") (comment "term \"%s\";")) proof-kill-goal-command "ProofGeneral.kill_proof" proof-shell-start-silent-cmd "disable_pr" proof-shell-stop-silent-cmd "enable_pr" proof-shell-trace-output-regexp "\^AV" ;; command hooks proof-goal-command-p 'isar-goal-command-p proof-really-save-command-p 'isar-global-save-command-p proof-count-undos-fn 'isar-count-undos proof-find-and-forget-fn 'isar-find-and-forget proof-state-preserving-p 'isar-state-preserving-p proof-shell-compute-new-files-list 'isar-shell-compute-new-files-list ;; span menu proof-script-span-context-menu-extensions 'isabelle-create-span-menu) ;; proof assistant settings (setq proof-use-pgip-askprefs t) (isar-configure-from-settings)) (defun isar-shell-mode-config-set-variables () "Configure generic proof shell mode variables for Isabelle/Isar." (setq proof-shell-wakeup-char nil proof-shell-annotated-prompt-regexp "^\\w*[>#] \^AS" ;; just for comint. proof-shell-prompt-pattern "^\\w*[>#] " ;; for issuing command, not used to track cwd in any way. proof-shell-cd-cmd (isar-markup-ml "ThyLoad.add_path \"%s\"") ;; Escapes for filenames inside ML strings. ;; We also make a hack for a bug in 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-filename) ; rough test for XEmacs on win32 ;; Patterns to unixfy names. ;; Jacques Fleuriot's patch in ML does this too: ("^[a-zA-Z]:" . "") ;; But I'll risk leaving drive names in, not sure how to replace them. '(("\\\\" . "/") ("\"" . "\\\"")) ;; Normal case: quotation for backslash, quote mark. '(("\\\\" . "\\\\") ("\"" . "\\\""))) proof-shell-interrupt-regexp "\^AM\\*\\*\\* Interrupt" proof-shell-error-regexp "\^AM\\*\\*\\*" proof-shell-proof-completed-regexp nil ; n.a. proof-shell-abort-goal-regexp nil ; n.a. pg-next-error-regexp "\\((line \\([0-9]+\\) of \"[^\"]+\")\\)" pg-next-error-filename-regexp "\\((line [0-9]+ of \"\\([^\"]+\\)\")\\)" ;; matches names of assumptions proof-shell-assumption-regexp isar-id proof-shell-start-goals-regexp "\^AO\n" proof-shell-end-goals-regexp "\^AP" proof-shell-init-cmd nil proof-shell-restart-cmd "ProofGeneral.restart" proof-shell-eager-annotation-start-length 2 proof-shell-eager-annotation-start "\^AI\\|\^AK" proof-shell-eager-annotation-end "\^AJ\\|\^AL" proof-shell-strip-output-markup 'isar-strip-output-markup ;; Isabelle is learning to talk PGIP... proof-shell-match-pgip-cmd " lev 0) (setq lev (- lev 1)) (setq ans 'no))) ;; global goal: done ((proof-string-match isar-goal-command-regexp cmd) (setq ans 'yes)))) (eq ans 'yes)))) (defvar isar-current-goal 1 "Last goal that Emacs looked at.") (defun isar-state-preserving-p (cmd) "Non-nil if command CMD preserves the proofstate." (proof-string-match isar-undo-skip-regexp cmd)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Commands specific to isar ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (proof-defshortcut isar-bold "\\<^bold>%p" [(control b)]) (proof-defshortcut isar-local "\\<^loc>%p" [(control c)]) (proof-defshortcut isar-super "\\<^sup>%p" [(control u)]) (proof-defshortcut isar-sub "\\<^sub>%p" [(control l)]) (proof-defshortcut isar-longsuper "\\<^bsup>%p\\<^esup>" [?u]) (proof-defshortcut isar-longsub "\\<^bsub>%p\\<^esub>" [?l]) (proof-defshortcut isar-idsub "\\<^isub>%p" [(control i)]) (proof-defshortcut isar-raw "\\<^raw:%p>" [(control r)]) (proof-defshortcut isar-antiquote "@{text \"%p\"}" [(control a)]) (proof-defshortcut isar-ml "ML {* %p *}" [(control x)]) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Isar shell startup and exit hooks ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar isar-shell-current-line-width nil "Current line width of the Isabelle process's pretty printing module. Its value will be updated whenever the corresponding screen gets selected.") (defun isar-shell-adjust-line-width () "Use Isabelle's pretty printing facilities to adjust output line width. Checks the width in the `proof-goals-buffer'" (let ((ans "")) (and (buffer-live-p proof-goals-buffer) (proof-shell-live-buffer) (save-excursion (set-buffer proof-goals-buffer) (let ((current-width ;; Actually, one might want the width of the ;; proof-response-buffer instead. Never mind. (max 20 (window-width (get-buffer-window proof-goals-buffer t))))) (if (equal current-width isar-shell-current-line-width) () (setq isar-shell-current-line-width current-width) (set-buffer proof-shell-buffer) (setq ans (format "pretty_setmargin %d;" (- current-width 4))))))) ans)) ;; ;; Shell mode command adjusting ;; (defconst isar-nonwrap-regexp ;; FIXME: approx: should only match at start or after terminator (regexp-opt (append (list "ProofGeneral.process_pgip") isar-undo-commands))) (defun isar-string-wrapping (string) (concat "\"" (proof-replace-regexp-in-string "[\000-\037\"\\\\]" (lambda (str) (format "\\\\%03d" (string-to-char str))) string) "\"")) (defun isar-positions-of (buffer span) (let (line column) (if span (save-excursion (set-buffer (span-buffer span)) (goto-char (span-start span)) (skip-chars-forward " \t\n") ;; NB: position is relative to display (narrowing, etc) (setq line (line-number-at-pos (point))) (setq column (current-column)))) (concat "(" (proof-splice-separator ", " (list (if (and buffer (buffer-file-name buffer)) (format "\"file\"=%s" (isar-string-wrapping (buffer-file-name buffer)))) (if line (format "\"line\"=\"%d\"" line)) (if column (format "\"column\"=\"%d\"" column)))) ") "))) (defun isar-command-wrapping (string scriptspan) (if (not (proof-string-match isar-nonwrap-regexp string)) (concat "Isabelle.command " (isar-positions-of proof-script-buffer scriptspan) (isar-string-wrapping string)) (proof-replace-regexp-in-string "\n" "\\\\<^newline>" string))) (defun isar-preprocessing () "Insert sync markers and other hacks. Uses variables `string' and `scriptspan' passed by dynamic scoping." (save-match-data (if (proof-string-match isabelle-verbatim-regexp string) (setq string (match-string 1 string)) (unless (proof-string-match ";[ \t]*\\'" string) (setq string (concat string ";"))) (setq string (concat "\\<^sync>; " (isar-shell-adjust-line-width) (isar-command-wrapping string scriptspan) " \\<^sync>;"))))) ;; ;; Configuring proof output buffer ;; (defun isar-mode-config () (isar-mode-config-set-variables) (isar-init-syntax-table) (setq proof-script-font-lock-keywords isar-font-lock-keywords-1) (set (make-local-variable 'comment-quote-nested) nil) ;; can cope with nested comments (set (make-local-variable 'outline-regexp) isar-outline-regexp) (set (make-local-variable 'outline-heading-end-regexp) isar-outline-heading-end-regexp) (set (make-local-variable 'blink-matching-paren-dont-ignore-comments) t) (add-hook 'proof-shell-insert-hook 'isar-preprocessing) (proof-config-done)) (defun isar-shell-mode-config () "Configure Proof General proof shell for Isabelle/Isar." (isar-init-output-syntax-table) (isar-shell-mode-config-set-variables) (proof-shell-config-done)) (defun isar-response-mode-config () (isar-init-output-syntax-table) (setq proof-response-font-lock-keywords (append proof-response-font-lock-keywords isar-output-font-lock-keywords-1)) (setq font-lock-multiline t) (make-local-variable 'jit-lock-chunk-size) (setq jit-lock-chunk-size 2000) (proof-response-config-done)) (defun isar-goals-mode-config () (setq pg-goals-change-goal "prefer %s") (setq pg-goals-error-regexp proof-shell-error-regexp) (isar-init-output-syntax-table) (setq proof-goals-font-lock-keywords (append proof-goals-font-lock-keywords isar-goals-font-lock-keywords)) (setq font-lock-multiline t) (make-local-variable 'jit-lock-chunk-size) (setq jit-lock-chunk-size 2000) (proof-goals-config-done)) (provide 'isar) ;;; isar.el ends here