diff options
-rw-r--r-- | generic/pg-user.el | 34 | ||||
-rw-r--r-- | generic/proof-menu.el | 10 | ||||
-rw-r--r-- | generic/proof-script.el | 193 |
3 files changed, 118 insertions, 119 deletions
diff --git a/generic/pg-user.el b/generic/pg-user.el index 198f7fe9..f3dbd755 100644 --- a/generic/pg-user.el +++ b/generic/pg-user.el @@ -806,18 +806,18 @@ If NUM is negative, move upwards. Return new span." (defun pg-span-context-menu (event) (interactive "e") - (let ((span (pg-span-for-event event)) - cspan) - ;; Find controlling span - (while (setq cspan (span-property span 'controlspan)) - (setq span cspan)) - (let* - ((idiom (and span (span-property span 'idiom))) - (id (and span (span-property span 'id)))) - (popup-menu (pg-create-in-span-context-menu - span - (if idiom (symbol-name idiom)) - (if id (symbol-name id))))))) + (let* ((span (pg-span-for-event event)) + cspan) + (when span + ;; Find controlling span + (while (setq cspan (span-property span 'controlspan)) + (setq span cspan)) + (let* + ((idiom (and span (span-property span 'idiom))) + (id (and span (span-property span 'id)))) + (popup-menu (pg-create-in-span-context-menu + span idiom + (if id (symbol-name id)))))))) (defun pg-toggle-visibility () "Toggle visibility of region under point." @@ -826,8 +826,7 @@ If NUM is negative, move upwards. Return new span." (idiom (and span (span-property span 'idiom))) (id (and span (span-property span 'id)))) (and idiom id - (pg-toggle-element-visibility (symbol-name idiom) (symbol-name id))))) - + (pg-toggle-element-visibility idiom (symbol-name id))))) (defun pg-create-in-span-context-menu (span idiom name) "Create the dynamic context-sensitive menu for a span." @@ -839,12 +838,11 @@ If NUM is negative, move upwards. Return new span." (append (list (pg-span-name span)) (list (vector - "Show/hide" - (if idiom (list `pg-toggle-element-visibility idiom name) - idiom) + "Show/hide" + (if idiom (list 'pg-toggle-element-visibility (quote idiom) name)) (not (not idiom)))) (list (vector - "Copy" (list 'pg-copy-span-contents span) t)) + "Copy" (list 'pg-copy-span-contents span) t)) (list (vector "Undo" (list 'pg-span-undo span) t)) diff --git a/generic/proof-menu.el b/generic/proof-menu.el index d323e0a9..9efe56aa 100644 --- a/generic/proof-menu.el +++ b/generic/proof-menu.el @@ -233,11 +233,13 @@ without adjusting window layout." (defvar proof-show-hide-menu '(("Show All" - ["Proofs" (pg-show-all-portions "proof") t] - ["Comments" (pg-show-all-portions "comment") t]) + ["Proofs" (pg-show-all-portions 'proof) t] + ["Commands" (pg-show-all-portions 'command) t] + ["Comments" (pg-show-all-portions 'comment) t]) ("Hide All" - ["Proofs" (pg-show-all-portions "proof" 'hide) t] - ["Comments" (pg-show-all-portions "comment" 'hide) t])) + ["Proofs" (pg-show-all-portions 'proof 'hide) t] + ["Commands" (pg-show-all-portions 'command 'hide) t] + ["Comments" (pg-show-all-portions 'comment 'hide) t])) "Show/hide submenu.") (defvar proof-buffer-menu diff --git a/generic/proof-script.el b/generic/proof-script.el index b2c71bce..bdd8947b 100644 --- a/generic/proof-script.el +++ b/generic/proof-script.el @@ -72,6 +72,7 @@ This uses the size of the hash table for IDIOM." (concat (symbol-name idiom) "-" (int-to-string number))) (defun proof-next-element-id (idiom) + "Return a string suitable for naming the next element of type IDIOM." (proof-element-id idiom (proof-next-element-count idiom))) @@ -470,42 +471,41 @@ Intended as a hook function for `proof-shell-handle-error-or-interrupt-hook'." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; Names of proofs (and other elements) in a script +;; Names of proofs (and other parts) in a script. ;; -;; Each kind of part ("idiom") in a proof script has its own name space. -;; Visibility within a script is then handled with buffer-invisibility-spec -;; controlling appearance of each idiom. +;; Elements are represented as spans (overlays). +;; +;; Each kind of part ("idiom") in a proof script has its own name +;; space. Idioms are named with symbols. ;; (defvar pg-idioms '(proof) "Vector of script element kinds PG is aware of for this prover.") -(defvar pg-visibility-specs nil - "Cache of visibility spec symbols used by PG. -This is used for cleaning `buffer-invisibility-spec' in -`pg-clear-script-portions': it doesn't need to be exactly accurate.") - -(make-variable-buffer-local 'pg-visibility-specs) - -(defconst pg-default-invisibility-spec - '((t . nil) (hide . nil))) - (defun pg-clear-script-portions () - "Clear record of script portion names and types from internal list. -Also clear all visibility specifications." + "Clear record of script portion names and types from internal list." (dolist (idtbl pg-script-portions) - (clrhash (cdr idtbl))) - (mapc 'remove-from-invisibility-spec pg-visibility-specs)) - -(defun pg-remove-script-element (ns id) - "Remove the identifier ID from the script portion NS." - (let* ((elts (cdr-safe (assq ns pg-script-portions)))) - (if elts (remhash id elts)))) - -(defsubst pg-visname (namespace id) - "Return a unique symbol made from strings NAMESPACE and unique ID." - (intern (concat namespace ":" id))) - + (maphash (lambda (k span) (span-delete span)) (cdr idtbl)) + (clrhash (cdr idtbl)))) + +(defun pg-remove-element (idiom id) + "Remove the identifier ID from the script portion IDIOM." + (let* ((elts (cdr-safe (assq idiom pg-script-portions))) + (span (and elts (gethash idiom elts)))) + (when span + (span-detach span) ;; delete overlay, without pre-del fn + (remhash id elts)))) + +(defun pg-get-element (idiomsym id) + "Return proof script element of type IDIOM identifier ID. +IDIOM is a symbol, ID is a string." + (assert (symbolp idiomsym)) + (assert (stringp id)) + (let ((idsym (intern id)) + (elts (cdr-safe (assq idiomsym pg-script-portions)))) + (if elts + (gethash idsym elts)))) + (defun pg-add-element (idiomsym id span &optional name) "Add element of type IDIOMSYM with identifier ID, referred to by SPAN. This records the element in `pg-script-portions' and sets span @@ -514,89 +514,86 @@ IDIOMSYM is a symbol, whereas ID and optional NAME are strings. Identifiers must be unique for a given idiom; the optional NAME will be recorded as a textual name used instead of ID for users; NAME does not need to be unique." + (assert (symbolp idiomsym)) + (assert (stringp id)) + (if name (assert (stringp name))) (let* ((idsym (intern id)) (name (or name id)) (idiom (symbol-name idiomsym)) - (visname (pg-visname idiom id)) - (delfn `(lambda () (pg-remove-element (quote ,idiomsym) (quote ,idsym)))) - (elts (cdr-safe (assq idiomsym pg-script-portions)))) + (delfn `(lambda () (pg-remove-element + (quote ,idiomsym) (quote ,idsym)))) + (elts (cdr-safe (assq idiomsym pg-script-portions)))) (unless elts (setq pg-script-portions (cons (cons idiomsym (setq elts (make-hash-table))) pg-script-portions))) - (if (gethash id elts) + (if (gethash idsym elts) (proof-debug "Element named " name - " (type " idiom ") already in buffer.") - (puthash idsym t elts)) + " (type " idiom ") was already in buffer.")) + (puthash idsym span elts) ;; Idiom and ID are stored in the span as symbols; name as a string. (span-set-property span 'idiom idiomsym) (span-set-property span 'id idsym) (span-set-property span 'name name) (span-set-property span 'span-delete-action delfn) - (span-set-property span 'invisible visname) - ;; Bad behaviour if span gets copied: unique ID shouldn't be duplicated. - (span-set-property span 'duplicable nil) ;; NB: not supported in Emacs + + ;; Ideally: would keep invisible property to be the idiom type + ;; (span-set-property span 'invisible idiom) + ;; BUT: problems overlapping invisible regions with + ;; Unicode Tokens (crucial for hiding control sequences). + ;; Nice behaviour in with isearch: open invisible regions temporarily. (span-set-property span 'isearch-open-invisible 'pg-open-invisible-span) (span-set-property span 'isearch-open-invisible-temporary 'pg-open-invisible-span))) +(defun pg-set-element-span-invisible (span invisible) + "Function to adjust visibility of span to INVISIBLE." + (span-set-property span 'invisible invisible)) + (defun pg-open-invisible-span (span &optional invisible) "Function for `isearch-open-invisible' property." - (let ((idiom (span-property span 'idiom)) - (id (span-property span 'id))) - (and idiom id - (if invisible - (pg-make-element-invisible - (symbol-name idiom) id) - (pg-make-element-visible - (symbol-name idiom) (symbol-name id)))))) - -(defun pg-remove-element (ns idsym) - (pg-remove-script-element ns idsym) - ;; We could leave the visibility note, but that may - ;; be counterintuitive, so lets remove it. - (pg-make-element-visible (symbol-name ns) (symbol-name idsym))) - -(defun pg-make-element-invisible (idiom id) - "Make element ID of type IDIOM invisible, with ellipsis." - (let ((visspec (cons (pg-visname idiom id) t))) - (add-to-invisibility-spec visspec) - (add-to-list 'pg-visibility-specs visspec))) - -(defun pg-make-element-visible (idiom id) - "Make element ID of type IDIOM visible." - (let ((visspec (cons (pg-visname idiom id) t))) - (remove-from-invisibility-spec visspec) - (setq pg-visibility-specs (delete visspec pg-visibility-specs)))) - -(defun pg-toggle-element-visibility (idiom id) - "Toggle visibility of script element of type IDIOM, named ID." - (interactive) - (if (assq (pg-visname idiom id) buffer-invisibility-spec) - (pg-make-element-visible idiom id) - (pg-make-element-invisible idiom id)) - ;; GNU Emacs sometimes requires redisplay for change - ;; in `buffer-invisibility-spec', perhaps a bug? - (redraw-frame (selected-frame))) + ;; alias + (pg-set-element-span-invisible span invisible)) + +(defun pg-make-element-invisible (idiomsym id) + "Make element ID of type IDIOMSYM invisible, with ellipsis." + (let ((span (pg-get-element idiomsym id))) + (if span (pg-set-element-span-invisible span t)))) + +(defun pg-make-element-visible (idiomsym id) + "Make element ID of type IDIOMSYM visible." + (let ((span (pg-get-element idiomsym id))) + (if span (pg-set-element-span-invisible span nil)))) + +(defun pg-toggle-element-span-visibility (span) + "Toggle visibility of SPAN." + (span-set-property + span 'invisible + (not (span-property span 'invisible)))) + +(defun pg-toggle-element-visibility (idiomsym id) + "Toggle visibility of script element of type IDIOMSYM, named ID. +IDIOMSYM is a symbol and ID is a strings." + (let ((span (pg-get-element idiomsym id))) + (if span (pg-toggle-element-span-visibility span)))) (defun pg-show-all-portions (idiom &optional hide) "Show or conceal portions of kind IDIOM; if HIDE is non-nil, conceal." (interactive (list - (completing-read - (concat "Make " (if current-prefix-arg "in" "") "visible all regions of: ") - (apply 'vector pg-idioms) nil t) + (intern + (completing-read + (concat "Make " (if current-prefix-arg "in" "") "visible all regions of: ") + (apply 'vector pg-idioms) nil t)) current-prefix-arg)) - (let ((elts (cdr-safe (assq (intern idiom) pg-script-portions))) - (alterfn (if hide - (lambda (key val) - (pg-make-element-invisible idiom - (symbol-name key))) - (lambda (key val) - (pg-make-element-visible idiom - (symbol-name key)))))) + (let ((elts (cdr-safe (assq idiom pg-script-portions))) + (alterfn (if hide + (lambda (k span) + (pg-set-element-span-invisible span t)) + (lambda (k span) + (pg-set-element-span-invisible span nil))))) (proof-with-script-buffer ; may be called from menu (maphash alterfn elts)))) @@ -614,8 +611,8 @@ NAME does not need to be unique." (defun pg-add-proof-element (name span controlspan) "Add a span proof element to SPAN with name NAME and parent CONTROLSPAN." (let ((proofid (proof-next-element-id 'proof))) - (pg-add-element 'proof proofid span name) - ;; Set id in controlspan + (pg-add-element 'proof proofid span name) + ;; Set id in controlspan [NB: intern here means symbol-name elsewhere] (span-set-property controlspan 'id (intern proofid)) ;; Make a navigable link between the two spans. (span-set-property span 'controlspan controlspan) @@ -624,7 +621,7 @@ NAME does not need to be unique." (pg-set-span-helphighlights span proof-boring-face) (span-set-property span 'priority 10) ; lower than default (if proof-disappearing-proofs - (pg-make-element-invisible "proof" proofid)))) + (pg-make-element-invisible 'proof proofid)))) (defun pg-span-name (span) "Return a user-level name for SPAN." @@ -1560,17 +1557,22 @@ Subroutine of `proof-done-advancing-save'." newend newend nam))))) (defun proof-done-advancing-other (span) - ;; We might add hidable regions also for commands: the problem - ;; is that they have no natural surrounding region, so makes - ;; it difficult to define a region for revealing again. - ;; [ best solution would be to support clicking on ellipsis] - (if (funcall proof-goal-command-p span) - (incf proof-nesting-depth)) + (let ((bodyspan span) ;; might take subscript after first word/line + (id (proof-next-element-id 'command))) + ;; Hidable regions for commands: the problem is that they have no + ;; natural surrounding region, so makes it difficult to define a + ;; region for revealing again. + (cond + ((funcall proof-goal-command-p span) + (pg-add-element 'statement id bodyspan) + (incf proof-nesting-depth)) + (t + (pg-add-element 'command id bodyspan))) (if proof-shell-proof-completed (incf proof-shell-proof-completed)) - (pg-set-span-helphighlights span)) + (pg-set-span-helphighlights span))) @@ -2197,9 +2199,6 @@ command." ;; that they can be adjusted by prover specific code if need be. (proof-script-set-buffer-hooks) - ;; We use a list to manage invisibility of buffer parts - (setq buffer-invisibility-spec nil) - ;; Set after change functions (proof-script-set-after-change-functions) |