[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: PATCH: ewoc.el to permit node representation abutment
From: |
Thien-Thi Nguyen |
Subject: |
Re: PATCH: ewoc.el to permit node representation abutment |
Date: |
08 May 2006 04:48:05 -0400 |
User-agent: |
Gnus/5.09 (Gnus v5.9.0) Emacs/21.4 |
i've revised the patch (please see below) to handle empty representations.
this was tested by modifying `cvs-fileinfo-pp' to output empty string for a
certain hardcoded filename in my local repo, making the empty string
conditional on a variable and toggling the variable followed by either
`ewoc-refresh' or `ewoc-invalidate' calls. (this description omits several
steps for preparing the testing framework, but you get the idea.)
* emacs-lisp/ewoc.el (ewoc--create-node): Don't insert
trailing newline. Also, create marker with insertion type t.
(ewoc--refresh-node): Delete all text from current node's
start marker to the next one's. Also, make the marker
"stay put" before calling the pretty-printer, and return it.
(ewoc--init-stay-put-list, ewoc--reset-marker-types): New funcs.
(ewoc-create): Use marker insertion type t.
(ewoc-map): Collect "stay put" markers; reset them when done.
(ewoc-invalidate): Rewrite.
(ewoc-refresh): Don't insert newline.
Collect "stay put" markers; reset them when done.
(ewoc-set-hf): Reset header and footer markers when done.
* pcvs-info.el (cvs-fileinfo-pp): Insert trailing newline.
note that ewoc.el is 1.19 from cvs.
thi
_________________________________________________________
diff -c -F '^(' ewoc.el ewoc.el.NEW
*** ewoc.el Mon May 8 10:00:48 2006
--- ewoc.el.NEW Mon May 8 10:11:45 2006
*************** (defun ewoc--create-node (data pretty-pr
*** 249,261 ****
(when (markerp pos) (setq pos (marker-position pos)))
(goto-char pos)
(let ((inhibit-read-only t))
- ;; Insert the trailing newline using insert-before-markers
- ;; so that the start position for the next element is updated.
- (insert-before-markers ?\n)
- ;; Move back, and call the pretty-printer.
- (backward-char 1)
(funcall pretty-printer data)
! (ewoc--node-create (copy-marker pos) data))))
(defun ewoc--delete-node-internal (ewoc node)
--- 249,256 ----
(when (markerp pos) (setq pos (marker-position pos)))
(goto-char pos)
(let ((inhibit-read-only t))
(funcall pretty-printer data)
! (ewoc--node-create (copy-marker pos t) data))))
(defun ewoc--delete-node-internal (ewoc node)
*************** (defun ewoc--delete-node-internal (ewoc
*** 276,293 ****
;; Delete the node, and return the wrapper.
(ewoc--node-delete node)))
(defun ewoc--refresh-node (pp node)
! "Redisplay the element represented by NODE using the pretty-printer PP."
(let ((inhibit-read-only t))
(save-excursion
;; First, remove the string from the buffer:
(delete-region (ewoc--node-start-marker node)
! (1- (marker-position
! (ewoc--node-start-marker (ewoc--node-right node)))))
;; Calculate and insert the string.
! (goto-char (ewoc--node-start-marker node))
! (funcall pp (ewoc--node-data node)))))
;;;
===========================================================================
;;; Public members of the Ewoc package
--- 271,317 ----
;; Delete the node, and return the wrapper.
(ewoc--node-delete node)))
+ ;; Refresh protocol
+ ;;
+ ;; Refresh requires essentially two passes. The first collects info on which
+ ;; nodes have been visited. The header is always visited, the footer never.
+ ;; For each node visited in order of increasing position: (1a) set marker
+ ;; insertion type to nil; (1b) do the pretty-printing (if necessary). Then,
+ ;; when all pretty-printing is done: (2) reset all insertion types to t.
+ ;;
+ ;; This approach ensures that a series of prior nodes (including the header)
+ ;; can insert nothing (empty string) and maintain their start markers (aka
+ ;; "stay put") should a later node insert something (non-empty string) at the
+ ;; same position. Note: "series" for prior and "a" for later because when
+ ;; something is inserted, that changes the position. This property explains
+ ;; the "if necessary" in the previous paragraph; for partial refresh (i.e.,
+ ;; `ewoc-invalidate') we must visit those nodes prior to the ones requested
+ ;; iff they have the same position even though we do not pretty-print them.
(defun ewoc--refresh-node (pp node)
! "Redisplay the element represented by NODE using the pretty-printer PP.
! Set NODE's start marker's insertion type to nil and return it."
(let ((inhibit-read-only t))
(save-excursion
;; First, remove the string from the buffer:
(delete-region (ewoc--node-start-marker node)
! (ewoc--node-start-marker (ewoc--node-right node)))
;; Calculate and insert the string.
! (let ((m (ewoc--node-start-marker node)))
! (goto-char m)
! (set-marker-insertion-type m nil)
! (funcall pp (ewoc--node-data node))
! m))))
!
! (defun ewoc--init-stay-put-list (ewoc)
! (let ((m (ewoc--node-start-marker (ewoc--header ewoc))))
! (set-marker-insertion-type m nil)
! (list m)))
!
! (defsubst ewoc--reset-marker-types (list)
! (dolist (m list)
! (set-marker-insertion-type m t)))
!
;;;
===========================================================================
;;; Public members of the Ewoc package
*************** (defun ewoc-create (pretty-printer &opti
*** 301,308 ****
PRETTY-PRINTER should be a function that takes one argument, an
element, and inserts a string representing it in the buffer (at
point). The string PRETTY-PRINTER inserts may be empty or span
! several lines. A trailing newline will always be inserted
! automatically. The PRETTY-PRINTER should use `insert', and not
`insert-before-markers'.
Optional second argument HEADER is a string that will always be
--- 325,331 ----
PRETTY-PRINTER should be a function that takes one argument, an
element, and inserts a string representing it in the buffer (at
point). The string PRETTY-PRINTER inserts may be empty or span
! several lines. The PRETTY-PRINTER should use `insert', and not
`insert-before-markers'.
Optional second argument HEADER is a string that will always be
*************** (defun ewoc-create (pretty-printer &opti
*** 317,323 ****
;; Set default values
(unless header (setq header ""))
(unless footer (setq footer ""))
! (setf (ewoc--node-start-marker dll) (copy-marker pos))
(let ((foot (ewoc--create-node footer 'insert pos))
(head (ewoc--create-node header 'insert pos)))
(ewoc--node-enter-first dll head)
--- 340,346 ----
;; Set default values
(unless header (setq header ""))
(unless footer (setq footer ""))
! (setf (ewoc--node-start-marker dll) (copy-marker pos t))
(let ((foot (ewoc--create-node footer 'insert pos))
(head (ewoc--create-node header 'insert pos)))
(ewoc--node-enter-first dll head)
*************** (defun ewoc-map (map-function ewoc &rest
*** 400,411 ****
If more than two arguments are given, the remaining
arguments will be passed to MAP-FUNCTION."
(ewoc--set-buffer-bind-dll-let* ewoc
! ((footer (ewoc--footer ewoc))
! (node (ewoc--node-nth dll 1)))
(while (not (eq node footer))
(if (apply map-function (ewoc--node-data node) args)
! (ewoc--refresh-node (ewoc--pretty-printer ewoc) node))
! (setq node (ewoc--node-next dll node)))))
(defun ewoc-filter (ewoc predicate &rest args)
"Remove all elements in EWOC for which PREDICATE returns nil.
--- 423,437 ----
If more than two arguments are given, the remaining
arguments will be passed to MAP-FUNCTION."
(ewoc--set-buffer-bind-dll-let* ewoc
! ((pp (ewoc--pretty-printer ewoc))
! (footer (ewoc--footer ewoc))
! (node (ewoc--node-nth dll 1))
! (stay-put (ewoc--init-stay-put-list ewoc)))
(while (not (eq node footer))
(if (apply map-function (ewoc--node-data node) args)
! (push (ewoc--refresh-node pp node) stay-put))
! (setq node (ewoc--node-next dll node)))
! (ewoc--reset-marker-types stay-put)))
(defun ewoc-filter (ewoc predicate &rest args)
"Remove all elements in EWOC for which PREDICATE returns nil.
*************** (defun ewoc-locate (ewoc &optional pos g
*** 497,505 ****
(defun ewoc-invalidate (ewoc &rest nodes)
"Call EWOC's pretty-printer for each element in NODES.
Delete current text first, thus effecting a \"refresh\"."
! (ewoc--set-buffer-bind-dll ewoc
! (dolist (node nodes)
! (ewoc--refresh-node (ewoc--pretty-printer ewoc) node))))
(defun ewoc-goto-prev (ewoc arg)
"Move point to the ARGth previous element in EWOC.
--- 523,562 ----
(defun ewoc-invalidate (ewoc &rest nodes)
"Call EWOC's pretty-printer for each element in NODES.
Delete current text first, thus effecting a \"refresh\"."
! (ewoc--set-buffer-bind-dll-let* ewoc
! ((pp (ewoc--pretty-printer ewoc))
! (header (ewoc--header ewoc))
! (stay-put (ewoc--init-stay-put-list ewoc)))
! (setq nodes
! (sort nodes
! (lambda (a b)
! (let ((am (ewoc--node-start-marker a))
! (bm (ewoc--node-start-marker b)))
! (cond ((> am bm) nil)
! ((< am bm) t)
! (t ;; i.e., (= am bm)
! ;; Maintain DLL ordering: A is "less than" B
! ;; if is found closer to the header than B.
! (let (donep lessp)
! (while (not (or donep
! (eq header
! (setq b (ewoc--node-left
! b)))))
! (when (eq a b)
! (setq lessp t donep t)))
! lessp)))))))
! (let ((stop (ewoc--header ewoc))
! node-m mid mid-m)
! (dolist (node nodes)
! (setq node-m (ewoc--node-start-marker node)
! mid node)
! (while (and (not (eq stop (setq mid (ewoc--node-left mid))))
! (= node-m (setq mid-m (ewoc--node-start-marker mid))))
! (set-marker-insertion-type mid-m nil)
! (push mid-m stay-put))
! (push (ewoc--refresh-node pp node) stay-put)
! (setq stop node)))
! (ewoc--reset-marker-types stay-put)))
(defun ewoc-goto-prev (ewoc arg)
"Move point to the ARGth previous element in EWOC.
*************** (defun ewoc-refresh (ewoc)
*** 551,563 ****
(delete-region (ewoc--node-start-marker (ewoc--node-nth dll 1))
(ewoc--node-start-marker footer))
(goto-char (ewoc--node-start-marker footer))
! (let ((node (ewoc--node-nth dll 1)))
(while (not (eq node footer))
! (set-marker (ewoc--node-start-marker node) (point))
! (funcall (ewoc--pretty-printer ewoc)
! (ewoc--node-data node))
! (insert "\n")
! (setq node (ewoc--node-next dll node)))))
(set-marker (ewoc--node-start-marker footer) (point))))
(defun ewoc-collect (ewoc predicate &rest args)
--- 608,625 ----
(delete-region (ewoc--node-start-marker (ewoc--node-nth dll 1))
(ewoc--node-start-marker footer))
(goto-char (ewoc--node-start-marker footer))
! (let* ((pp (ewoc--pretty-printer ewoc))
! (node (ewoc--node-nth dll 1))
! (stay-put (ewoc--init-stay-put-list ewoc))
! m)
(while (not (eq node footer))
! (setq m (ewoc--node-start-marker node))
! (set-marker m (point))
! (set-marker-insertion-type m nil)
! (push m stay-put)
! (funcall pp (ewoc--node-data node))
! (setq node (ewoc--node-next dll node)))
! (ewoc--reset-marker-types stay-put)))
(set-marker (ewoc--node-start-marker footer) (point))))
(defun ewoc-collect (ewoc predicate &rest args)
*************** (defun ewoc-set-hf (ewoc header footer)
*** 597,604 ****
"Set the HEADER and FOOTER of EWOC."
(setf (ewoc--node-data (ewoc--header ewoc)) header)
(setf (ewoc--node-data (ewoc--footer ewoc)) footer)
! (ewoc--refresh-node 'insert (ewoc--header ewoc))
! (ewoc--refresh-node 'insert (ewoc--footer ewoc)))
(provide 'ewoc)
--- 659,668 ----
"Set the HEADER and FOOTER of EWOC."
(setf (ewoc--node-data (ewoc--header ewoc)) header)
(setf (ewoc--node-data (ewoc--footer ewoc)) footer)
! (let ((stay-put (list
! (ewoc--refresh-node 'insert (ewoc--header ewoc))
! (ewoc--refresh-node 'insert (ewoc--footer ewoc)))))
! (ewoc--reset-marker-types stay-put)))
(provide 'ewoc)