diff options
author | David Aspinall <da@inf.ed.ac.uk> | 2002-07-16 14:47:01 +0000 |
---|---|---|
committer | David Aspinall <da@inf.ed.ac.uk> | 2002-07-16 14:47:01 +0000 |
commit | 745efc79b2786730bbef4e9693127dc6574da244 (patch) | |
tree | 000709f511807614910e0ccf44266d2e24584f2d /generic/pg-goals.el | |
parent | 6310e9f4a781b4bb12946204f033c5e298e2f831 (diff) |
Refactoring
Diffstat (limited to 'generic/pg-goals.el')
-rw-r--r-- | generic/pg-goals.el | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/generic/pg-goals.el b/generic/pg-goals.el new file mode 100644 index 00000000..66b932f1 --- /dev/null +++ b/generic/pg-goals.el @@ -0,0 +1,350 @@ +;; pg-goals.el Proof General goals buffer mode. +;; +;; Copyright (C) 1994-2002 LFCS Edinburgh. +;; Authors: David Aspinall, Yves Bertot, Healfdene Goguen, +;; Thomas Kleymann and Dilip Sequeira +;; License: GPL (GNU GENERAL PUBLIC LICENSE) +;; +;; $Id$ +;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Goals buffer mode +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(eval-and-compile ; to define proof-goals-mode-map +(define-derived-mode proof-goals-mode proof-universal-keys-only-mode + proof-general-name + "Mode for goals display. +May enable proof-by-pointing or similar features. +\\{proof-goals-mode-map}" + ;; defined-derived-mode proof-goals-mode initialises proof-goals-mode-map + (setq proof-buffer-type 'goals) + (easy-menu-add proof-goals-mode-menu proof-goals-mode-map) + (easy-menu-add proof-assistant-menu proof-goals-mode-map) + (proof-toolbar-setup) + (erase-buffer))) + +;; +;; Keys for goals buffer +;; +(define-key proof-goals-mode-map [q] 'bury-buffer) +(cond +(proof-running-on-XEmacs +(define-key proof-goals-mode-map [(button2)] 'pbp-button-action) +(define-key proof-goals-mode-map [(control button2)] 'proof-undo-and-delete-last-successful-command) +;; button 2 is a nuisance on 2 button mice, so we'll do 1 as well. +;; Actually we better hadn't, people like to use it for cut and paste. +;; (define-key proof-goals-mode-map [(button1)] 'pbp-button-action) +;; (define-key proof-goals-mode-map [(control button1)] 'proof-undo-and-delete-last-successful-command) +(define-key proof-goals-mode-map [(button3)] 'pbp-yank-subterm)) +(t +(define-key proof-goals-mode-map [mouse-2] 'pbp-button-action) +(define-key proof-goals-mode-map [C-mouse-2] 'proof-undo-and-delete-last-successful-command) +;; (define-key proof-goals-mode-map [mouse-1] 'pbp-button-action) +;; (define-key proof-goals-mode-map [C-mouse-1] 'proof-undo-and-delete-last-successful-command) +(define-key proof-goals-mode-map [mouse-3] 'pbp-yank-subterm))) + + +;; +;; Menu for goals buffer (identical to response mode menu currently) +;; +(easy-menu-define proof-goals-mode-menu + proof-goals-mode-map + "Menu for Proof General goals buffer." + (cons proof-general-name + (append + proof-toolbar-scripting-menu + proof-shared-menu + proof-config-menu + proof-bug-report-menu))) + +(defun proof-goals-config-done () + "Initialise the goals buffer after the child has been configured." + (proof-font-lock-configure-defaults nil) + (proof-x-symbol-configure)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Subterm markup and Proof-by-Pointing functionality +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Fairly specific to the mechanism implemented in LEGO +;; To make sense of this code, you should read the +;; relevant LFCS tech report by tms, yb, and djs + +(defun pbp-yank-subterm (event) + "Copy the subterm indicated by the mouse-click EVENT. +This function should be bound to a mouse button in the Proof General +goals buffer. + +The EVENT is used to find the smallest subterm around a point. The +subterm is copied to the kill-ring, and immediately yanked (copied) +into the current buffer at the current cursor position. + +In case the current buffer is the goals buffer itself, the yank +is not performed. Then the subterm can be retrieved later by an +explicit yank." + (interactive "e") + (let (span) + (save-window-excursion + (save-excursion + (mouse-set-point event) + ;; Get either the proof body or whole goalsave + (setq span (or + (span-at (point) 'proof) + (span-at (point) 'goalsave))) + (if span (copy-region-as-kill + (span-start span) + (span-end span))))) + (if (and span (not (eq proof-buffer-type 'goals))) + (yank)))) + +(defun pbp-button-action (event) + "Construct a proof-by-pointing command based on the mouse-click EVENT. +This function should be bound to a mouse button in the Proof General +goals buffer. + +The EVENT is used to find the smallest subterm around a point. A +position code for the subterm is sent to the proof assistant, to ask +it to construct an appropriate proof command. The command which is +constructed will be inserted at the end of the locked region in the +proof script buffer, and immediately sent back to the proof assistant. +If it succeeds, the locked region will be extended to cover the +proof-by-pointing command, just as for any proof command the +user types by hand." + (interactive "e") + (mouse-set-point event) + (pbp-construct-command)) + +;; Using the spans in a mouse behavior is quite simple: from the +;; mouse position, find the relevant span, then get its annotation +;; and produce a piece of text that will be inserted in the right +;; buffer. + +(defun proof-expand-path (string) + (let ((a 0) (l (length string)) ls) + (while (< a l) + (setq ls (cons (int-to-string + (char-to-int (aref string a))) + (cons " " ls))) + (incf a)) + (apply 'concat (nreverse ls)))) + +(defun pbp-construct-command () + (let* ((span (span-at (point) 'goalsave)) + (top-span (span-at (point) 'proof-top-element)) + top-info) + (if (null top-span) () + (setq top-info (span-property top-span 'proof-top-element)) + (pop-to-buffer proof-script-buffer) + (cond + (span + (proof-shell-invisible-command + (format (if (eq 'hyp (car top-info)) pbp-hyp-command + pbp-goal-command) + (concat (cdr top-info) (proof-expand-path + (span-property span 'goalsave)))))) + ((eq (car top-info) 'hyp) + (proof-shell-invisible-command + (format pbp-hyp-command (cdr top-info)))) + (t + (proof-insert-pbp-command + (format pbp-change-goal (cdr top-info)))))))) + +;; +;; Goals buffer processing +;; +;; FIXME: rename next fn proof-display-in-goals or similar +(defun proof-shell-analyse-structure (string) + "Analyse the term structure of STRING and display it in proof-goals-buffer. +This function converts proof-by-pointing markup into mouse-highlighted +extents." + (save-excursion + ;; Response buffer may be out of date. It may contain (error) + ;; messages relating to earlier proof states + + ;; FIXME da: this isn't always the case. In Isabelle + ;; we get <WARNING MESSAGE> <CURRENT GOALS> output, + ;; or <WARNING MESSAGE> <ORDINARY MESSAGE>. Both times + ;; <WARNING MESSAGE> would be relevant. + ;; We should only clear the output that was displayed from + ;; the *previous* prompt. + + ;; Erase the response buffer if need be, maybe also removing the + ;; window. Indicate that it should be erased before the next + ;; output. + (proof-shell-maybe-erase-response t t) + + ;; Erase the goals buffer and add in the new string + (set-buffer proof-goals-buffer) + (erase-buffer) + (insert string) + + ;; Do term-structure markup if its enabled + (unless (not proof-shell-goal-char) + (proof-shell-analyse-structure1 (point-min) (point-max))) + + ;; Now get fonts and characters right + ;; FIXME: this may be broken by markup or aided by it! + (proof-fontify-region (point-min) (point-max)) + + ;; Record a cleaned up version of output string + (setq proof-shell-last-output + (buffer-substring (point-min) (point-max))) + + (set-buffer-modified-p nil) ; nicety + + ;; Keep point at the start of the buffer. Might be nicer to + ;; keep point at "current" subgoal a la Isamode, but never mind + ;; just now. + (proof-display-and-keep-buffer proof-goals-buffer (point-min)))) + + +(defun proof-shell-analyse-structure1 (start end) + "Really analyse the structure here." + (let* + ((cur start) + (len (- end start)) + (ann (make-string len ?x)) ; (more than) enough space for longest ann'n + (ap 0) + c stack topl span) + + (while (< cur end) + (setq c (char-after cur)) + (cond + ;; Seen goal char: this is the start of a top extent + ;; (assumption or goal) + ((= c proof-shell-goal-char) + (setq topl (cons cur topl)) + (setq ap 0)) + + ;; Seen subterm start char: it's followed by at least + ;; one subterm pointer byte + ((= c proof-shell-start-char) + (incf cur) + (if proof-analyse-using-stack + (setq ap (- ap (- (char-after cur) 128))) + (setq ap (- (char-after cur) 128))) + (incf cur) + ;; Now search for a matching end-annotation char, recording the + ;; annotation found. + (while (not (= (setq c (char-after cur)) proof-shell-end-char)) + (aset ann ap (- c 128)) + (incf ap) + (incf cur)) + ;; Push the buffer pos and annotation + (setq stack (cons cur + (cons (substring ann 0 ap) stack)))) + + ;; Seen a field char, which terminates an annotated position + ;; in the concrete syntax. We make a highlighting span now. + ((and (consp stack) (= c proof-shell-field-char)) + ;; (consp stack) added to make the code more robust. + ;; [ Condition violated with lego/example.l and GNU Emacs 20.3 ] + (setq span (make-span (car stack) cur)) + (set-span-property span 'mouse-face 'highlight) + (set-span-property span 'goalsave (cadr stack));; FIXME: 'goalsave? + (if proof-analyse-using-stack + ;; Pop annotation off stack + (progn + (setq ap 0) + (while (< ap (length (cadr stack))) + (aset ann ap (aref (cadr stack) ap)) + (incf ap)))) + ;; Finish popping annotations + (setq stack (cdr (cdr stack))))) + ;; On to next char + (incf cur)) + + ;; List of subterm regions (goals) found + (setq topl (reverse (cons end topl))) + + ;; If we want Coq pbp: (setq coq-current-goal 1) + (if proof-goal-hyp-fn + (while (setq ip (car topl) + topl (cdr topl)) + (pbp-make-top-span ip (car topl)))) + + ;; Finally: strip the specials. This should + ;; leave the spans in exactly the right place. + (proof-shell-strip-special-annotations-buf start end))) + + +(defun pbp-make-top-span (start end) + "Make a top span (goal area) for mouse active output." + (let (span name) + (goto-char start) + ;; We need to skip an annotation here for proof-goal-hyp-fn + ;; to work again now we don't strip buffers. Is it + ;; safe to assume that we're called exactly at proof-goal-char? + ;; [maybe except for last case?] + (forward-char) + (setq name (funcall proof-goal-hyp-fn)) + (beginning-of-line) + (setq start (point)) + (goto-char end) + (beginning-of-line) + (backward-char) + (setq span (make-span start (point))) + (set-span-property span 'mouse-face 'highlight) + (set-span-property span 'proof-top-element name))) + + +(defun proof-shell-strip-special-annotations (string) + "Strip special annotations from a string, returning cleaned up string. +*Special* annotations are characters with codes higher than +'proof-shell-first-special-char'. +If proof-shell-first-special-char is unset, return STRING unchanged." + (if proof-shell-first-special-char + (let* ((ip 0) (op 0) (l (length string)) (out (make-string l ?x ))) + (while (< ip l) + (if (>= (aref string ip) proof-shell-first-special-char) + (if (char-equal (aref string ip) proof-shell-start-char) + (progn (incf ip) + (while + ;; FIXME: this relies on annotations + ;; being characters between + ;; \200 and \360 (first special char). + ;; Why do we not just look for the + ;; field char?? + (< (aref string ip) + proof-shell-first-special-char) + (incf ip)))) + (aset out op (aref string ip)) + (incf op)) + (incf ip)) + (substring out 0 op)) + string)) + +(defun proof-shell-strip-special-annotations-buf (start end) + "Strip specials and return new END value." + (let (c) + (goto-char start) + (while (< (point) end) + ;; FIXME: small OBO here: if char at end is special + ;; it won't be removed. + (if (>= (setq c (char-after (point))) + proof-shell-first-special-char) + (progn + (delete-char 1) + (decf end) + (if (char-equal c proof-shell-start-char) + (progn + ;; FIXME: could simply replace this by replace + ;; match, matching on field-char?? + (while (and (< (point) end) + (< (char-after (point)) + proof-shell-first-special-char)) + (delete-char 1) + (decf end))))) + (forward-char))) + end)) + + +(provide 'pg-goals) +;; pg-goals.el ends here. |