Changeset 4079 for trunk/lisp/emacs-lisp/ewoc.el
- Timestamp:
- 05/13/06 11:31:18 (3 years ago)
- Files:
-
- trunk/lisp/emacs-lisp/ewoc.el (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/lisp/emacs-lisp/ewoc.el
r4037 r4079 145 145 \(fn NODE CHILD)") 146 146 147 (defun ewoc--dll-create ()148 "Create an empty doubly linked list."149 (let ((dummy-node (ewoc--node-create 'DL-LIST 'DL-LIST)))150 (setf (ewoc--node-right dummy-node) dummy-node)151 (setf (ewoc--node-left dummy-node) dummy-node)152 dummy-node))153 154 (defun ewoc--node-enter-before (node elemnode)155 "Insert ELEMNODE before NODE in a DLL."156 (assert (and (null (ewoc--node-left elemnode)) (null (ewoc--node-right elemnode))))157 (setf (ewoc--node-left elemnode) (ewoc--node-left node))158 (setf (ewoc--node-right elemnode) node)159 (setf (ewoc--node-right (ewoc--node-left node)) elemnode)160 (setf (ewoc--node-left node) elemnode))161 162 (defun ewoc--node-enter-first (dll node)163 "Add a free floating NODE first in DLL."164 (ewoc--node-enter-before (ewoc--node-right dll) node))165 166 (defun ewoc--node-enter-last (dll node)167 "Add a free floating NODE last in DLL."168 (ewoc--node-enter-before dll node))169 170 147 (defun ewoc--node-next (dll node) 171 148 "Return the node after NODE, or nil if NODE is the last node." … … 175 152 "Return the node before NODE, or nil if NODE is the first node." 176 153 (unless (eq (ewoc--node-left node) dll) (ewoc--node-left node))) 177 178 (defun ewoc--node-delete (node)179 "Unbind NODE from its doubly linked list and return it."180 ;; This is a no-op when applied to the dummy node. This will return181 ;; nil if applied to the dummy node since it always contains nil.182 (setf (ewoc--node-right (ewoc--node-left node)) (ewoc--node-right node))183 (setf (ewoc--node-left (ewoc--node-right node)) (ewoc--node-left node))184 (setf (ewoc--node-left node) nil)185 (setf (ewoc--node-right node) nil)186 node)187 154 188 155 (defun ewoc--node-nth (dll n) … … 222 189 buffer will *not* have been changed. 223 190 Return value of last form in FORMS." 224 (let ((old-buffer (make-symbol "old-buffer")) 225 (hnd (make-symbol "ewoc"))) 226 `(let* ((,old-buffer (current-buffer)) 227 (,hnd ,ewoc) 191 (let ((hnd (make-symbol "ewoc"))) 192 `(let* ((,hnd ,ewoc) 228 193 (dll (ewoc--dll ,hnd)) 229 194 ,@varlist) 230 (set-buffer (ewoc--buffer ,hnd)) 231 (unwind-protect 232 (progn ,@forms) 233 (set-buffer ,old-buffer))))) 195 (with-current-buffer (ewoc--buffer ,hnd) 196 ,@forms)))) 234 197 235 198 (defmacro ewoc--set-buffer-bind-dll (ewoc &rest forms) … … 243 206 node)) 244 207 245 246 (defun ewoc--create-node (data pretty-printer pos) 247 "Call PRETTY-PRINTER with point set at POS in current buffer. 248 Remember the start position. Create a wrapper containing that 249 start position and the element DATA." 208 (defun ewoc--insert-new-node (node data pretty-printer) 209 "Insert before NODE a new node for DATA, displayed by PRETTY-PRINTER. 210 Call PRETTY-PRINTER with point at NODE's start, thus pushing back 211 NODE and leaving the new node's start there. Return the new node." 250 212 (save-excursion 251 ;; Remember the position as a number so that it doesn't move252 ;; when we insert the string.253 (when (markerp pos) (setq pos (marker-position pos)))254 (goto-char pos)255 (let ((inhibit-read-only t))213 (let* ((inhibit-read-only t) 214 (m (copy-marker (ewoc--node-start-marker node))) 215 (pos (marker-position m)) 216 (elemnode (ewoc--node-create m data))) 217 (goto-char pos) 256 218 ;; Insert the trailing newline using insert-before-markers 257 219 ;; so that the start position for the next element is updated. … … 260 222 (backward-char 1) 261 223 (funcall pretty-printer data) 262 (ewoc--node-create (copy-marker pos) data)))) 263 264 265 (defun ewoc--delete-node-internal (ewoc node) 266 "Delete a data string from EWOC. 267 Can not be used on the footer. Return the wrapper that is deleted. 268 The start-marker in the wrapper is set to nil, so that it doesn't 269 consume any more resources." 270 (let ((dll (ewoc--dll ewoc)) 271 (inhibit-read-only t)) 272 ;; If we are about to delete the node pointed at by last-node, 273 ;; set last-node to nil. 274 (if (eq (ewoc--last-node ewoc) node) 275 (setf (ewoc--last-node ewoc) nil)) 276 277 (delete-region (ewoc--node-start-marker node) 278 (ewoc--node-start-marker (ewoc--node-next dll node))) 279 (set-marker (ewoc--node-start-marker node) nil) 280 ;; Delete the node, and return the wrapper. 281 (ewoc--node-delete node))) 282 224 (setf (marker-position m) pos 225 (ewoc--node-left elemnode) (ewoc--node-left node) 226 (ewoc--node-right elemnode) node 227 (ewoc--node-right (ewoc--node-left node)) elemnode 228 (ewoc--node-left node) elemnode) 229 elemnode))) 283 230 284 231 (defun ewoc--refresh-node (pp node) 285 232 "Redisplay the element represented by NODE using the pretty-printer PP." 286 233 (let ((inhibit-read-only t)) 287 (save-excursion 288 ;; First, remove the string from the buffer: 289 (delete-region (ewoc--node-start-marker node) 290 (1- (marker-position 291 (ewoc--node-start-marker (ewoc--node-right node))))) 292 ;; Calculate and insert the string. 293 (goto-char (ewoc--node-start-marker node)) 294 (funcall pp (ewoc--node-data node))))) 234 ;; First, remove the string from the buffer: 235 (delete-region (ewoc--node-start-marker node) 236 (1- (marker-position 237 (ewoc--node-start-marker (ewoc--node-right node))))) 238 ;; Calculate and insert the string. 239 (goto-char (ewoc--node-start-marker node)) 240 (funcall pp (ewoc--node-data node)))) 295 241 296 242 ;;; =========================================================================== … … 314 260 newline. Optional third argument FOOTER is similar, and will 315 261 be inserted at the bottom of the ewoc." 316 (let ((new-ewoc 317 (ewoc--create (current-buffer) 318 pretty-printer nil nil (ewoc--dll-create))) 319 (pos (point))) 262 (let* ((dummy-node (ewoc--node-create 'DL-LIST 'DL-LIST)) 263 (dll (progn (setf (ewoc--node-right dummy-node) dummy-node) 264 (setf (ewoc--node-left dummy-node) dummy-node) 265 dummy-node)) 266 (new-ewoc 267 (ewoc--create (current-buffer) 268 pretty-printer nil nil dll)) 269 (pos (point)) 270 head foot) 320 271 (ewoc--set-buffer-bind-dll new-ewoc 321 272 ;; Set default values 322 273 (unless header (setq header "")) 323 274 (unless footer (setq footer "")) 324 (setf (ewoc--node-start-marker dll) (copy-marker pos)) 325 (let ((foot (ewoc--create-node footer (lambda (x) (insert footer)) pos)) 326 (head (ewoc--create-node header (lambda (x) (insert header)) pos))) 327 (ewoc--node-enter-first dll head) 328 (ewoc--node-enter-last dll foot) 329 (setf (ewoc--header new-ewoc) head) 330 (setf (ewoc--footer new-ewoc) foot))) 275 (setf (ewoc--node-start-marker dll) (copy-marker pos) 276 foot (ewoc--insert-new-node dll footer 'insert) 277 head (ewoc--insert-new-node foot header 'insert) 278 (ewoc--footer new-ewoc) foot 279 (ewoc--header new-ewoc) head)) 331 280 ;; Return the ewoc 332 281 new-ewoc)) … … 357 306 Return the new node." 358 307 (ewoc--set-buffer-bind-dll ewoc 359 (ewoc--node-enter-before 360 node 361 (ewoc--create-node 362 data 363 (ewoc--pretty-printer ewoc) 364 (ewoc--node-start-marker node))))) 308 (ewoc--insert-new-node node data (ewoc--pretty-printer ewoc)))) 365 309 366 310 (defun ewoc-next (ewoc node) … … 407 351 ((footer (ewoc--footer ewoc)) 408 352 (node (ewoc--node-nth dll 1))) 409 (while (not (eq node footer)) 410 (if (apply map-function (ewoc--node-data node) args) 411 (ewoc--refresh-node (ewoc--pretty-printer ewoc) node)) 412 (setq node (ewoc--node-next dll node))))) 353 (save-excursion 354 (while (not (eq node footer)) 355 (if (apply map-function (ewoc--node-data node) args) 356 (ewoc--refresh-node (ewoc--pretty-printer ewoc) node)) 357 (setq node (ewoc--node-next dll node)))))) 413 358 414 359 (defun ewoc-filter (ewoc predicate &rest args) … … 422 367 ((node (ewoc--node-nth dll 1)) 423 368 (footer (ewoc--footer ewoc)) 424 (next nil)) 369 (next nil) 370 (L nil) (R nil) 371 (inhibit-read-only t)) 425 372 (while (not (eq node footer)) 426 373 (setq next (ewoc--node-next dll node)) 427 374 (unless (apply predicate (ewoc--node-data node) args) 428 (ewoc--delete-node-internal ewoc node)) 375 ;; If we are about to delete the node pointed at by last-node, 376 ;; set last-node to nil. 377 (if (eq (ewoc--last-node ewoc) node) 378 (setf (ewoc--last-node ewoc) nil)) 379 (delete-region (ewoc--node-start-marker node) 380 (ewoc--node-start-marker (ewoc--node-next dll node))) 381 (set-marker (ewoc--node-start-marker node) nil) 382 (setf L (ewoc--node-left node) 383 R (ewoc--node-right node) 384 ;; Link neighbors to each other. 385 (ewoc--node-right L) R 386 (ewoc--node-left R) L 387 ;; Forget neighbors. 388 (ewoc--node-left node) nil 389 (ewoc--node-right node) nil)) 429 390 (setq node next)))) 430 391 … … 503 464 Delete current text first, thus effecting a \"refresh\"." 504 465 (ewoc--set-buffer-bind-dll ewoc 505 (dolist (node nodes) 506 (ewoc--refresh-node (ewoc--pretty-printer ewoc) node)))) 466 (save-excursion 467 (dolist (node nodes) 468 (ewoc--refresh-node (ewoc--pretty-printer ewoc) node))))) 507 469 508 470 (defun ewoc-goto-prev (ewoc arg) … … 556 518 (ewoc--node-start-marker footer)) 557 519 (goto-char (ewoc--node-start-marker footer)) 558 (let ((node (ewoc--node-nth dll 1))) 520 (let ((pp (ewoc--pretty-printer ewoc)) 521 (node (ewoc--node-nth dll 1))) 559 522 (while (not (eq node footer)) 560 523 (set-marker (ewoc--node-start-marker node) (point)) 561 (funcall (ewoc--pretty-printer ewoc) 562 (ewoc--node-data node)) 524 (funcall pp (ewoc--node-data node)) 563 525 (insert "\n") 564 526 (setq node (ewoc--node-next dll node))))) … … 602 564 (setf (ewoc--node-data (ewoc--header ewoc)) header) 603 565 (setf (ewoc--node-data (ewoc--footer ewoc)) footer) 604 (ewoc--refresh-node (lambda (x) (insert header)) (ewoc--header ewoc)) 605 (ewoc--refresh-node (lambda (x) (insert footer)) (ewoc--footer ewoc))) 566 (save-excursion 567 (ewoc--refresh-node 'insert (ewoc--header ewoc)) 568 (ewoc--refresh-node 'insert (ewoc--footer ewoc)))) 606 569 607 570
