emacs-devel
[Top][All Lists]
Advanced

[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)






reply via email to

[Prev in Thread] Current Thread [Next in Thread]