Mercurial > emacs
comparison lisp/emacs-lisp/ewoc.el @ 71052:529644115612
(ewoc--current-dll): Remove. Basically undo the change of 2006-05-26:
use extra arguments instead of dynamic scoping.
(ewoc-locate): Remove unused var `footer'.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Mon, 29 May 2006 04:39:46 +0000 |
parents | bf1f0ff1e25e |
children | 1d4b1a32fd66 a8190f7e546e |
comparison
equal
deleted
inserted
replaced
71051:bf1f0ff1e25e | 71052:529644115612 |
---|---|
99 | 99 |
100 ;;; Code: | 100 ;;; Code: |
101 | 101 |
102 (eval-when-compile (require 'cl)) | 102 (eval-when-compile (require 'cl)) |
103 | 103 |
104 ;; The doubly linked list is implemented as a circular list | 104 ;; The doubly linked list is implemented as a circular list with a dummy |
105 ;; with a dummy node first and last. The dummy node is used as | 105 ;; node first and last. The dummy node is used as "the dll". |
106 ;; "the dll" (or rather the dynamically bound `ewoc--current-dll'). | |
107 | |
108 (defvar ewoc--current-dll) | |
109 | |
110 (defstruct (ewoc--node | 106 (defstruct (ewoc--node |
111 (:type vector) ;ewoc--node-nth needs this | 107 (:type vector) ;ewoc--node-nth needs this |
112 (:constructor nil) | 108 (:constructor nil) |
113 (:constructor ewoc--node-create (start-marker data))) | 109 (:constructor ewoc--node-create (start-marker data))) |
114 left right data start-marker) | 110 left right data start-marker) |
115 | 111 |
116 (defun ewoc--node-next (node) | 112 (defun ewoc--node-next (dll node) |
117 "Return the node after NODE, or nil if NODE is the last node." | 113 "Return the node after NODE, or nil if NODE is the last node." |
118 (let ((R (ewoc--node-right node))) | 114 (let ((R (ewoc--node-right node))) |
119 (unless (eq ewoc--current-dll R) R))) | 115 (unless (eq dll R) R))) |
120 | 116 |
121 (defun ewoc--node-prev (node) | 117 (defun ewoc--node-prev (dll node) |
122 "Return the node before NODE, or nil if NODE is the first node." | 118 "Return the node before NODE, or nil if NODE is the first node." |
123 (let ((L (ewoc--node-left node))) | 119 (let ((L (ewoc--node-left node))) |
124 (unless (eq ewoc--current-dll L) L))) | 120 (unless (eq dll L) L))) |
125 | 121 |
126 (defun ewoc--node-nth (n) | 122 (defun ewoc--node-nth (dll n) |
127 "Return the Nth node from the doubly linked list `ewoc--current-dll'. | 123 "Return the Nth node from the doubly linked list `dll'. |
128 N counts from zero. If N is negative, return the -(N+1)th last element. | 124 N counts from zero. If N is negative, return the -(N+1)th last element. |
129 If N is out of range, return nil. | 125 If N is out of range, return nil. |
130 Thus, (ewoc--node-nth 0) returns the first node, | 126 Thus, (ewoc--node-nth dll 0) returns the first node, |
131 and (ewoc--node-nth -1) returns the last node." | 127 and (ewoc--node-nth dll -1) returns the last node." |
132 ;; Presuming a node is ":type vector", starting with `left' and `right': | 128 ;; Presuming a node is ":type vector", starting with `left' and `right': |
133 ;; Branch 0 ("follow left pointer") is used when n is negative. | 129 ;; Branch 0 ("follow left pointer") is used when n is negative. |
134 ;; Branch 1 ("follow right pointer") is used otherwise. | 130 ;; Branch 1 ("follow right pointer") is used otherwise. |
135 (let* ((branch (if (< n 0) 0 1)) | 131 (let* ((branch (if (< n 0) 0 1)) |
136 (node (aref ewoc--current-dll branch))) | 132 (node (aref dll branch))) |
137 (if (< n 0) (setq n (- -1 n))) | 133 (if (< n 0) (setq n (- -1 n))) |
138 (while (and (not (eq ewoc--current-dll node)) (> n 0)) | 134 (while (and (not (eq dll node)) (> n 0)) |
139 (setq node (aref node branch)) | 135 (setq node (aref node branch)) |
140 (setq n (1- n))) | 136 (setq n (1- n))) |
141 (unless (eq ewoc--current-dll node) node))) | 137 (unless (eq dll node) node))) |
142 | 138 |
143 (defun ewoc-location (node) | 139 (defun ewoc-location (node) |
144 "Return the start location of NODE." | 140 "Return the start location of NODE." |
145 (ewoc--node-start-marker node)) | 141 (ewoc--node-start-marker node)) |
146 | 142 |
153 (:conc-name ewoc--)) | 149 (:conc-name ewoc--)) |
154 buffer pretty-printer header footer dll last-node hf-pp) | 150 buffer pretty-printer header footer dll last-node hf-pp) |
155 | 151 |
156 (defmacro ewoc--set-buffer-bind-dll-let* (ewoc varlist &rest forms) | 152 (defmacro ewoc--set-buffer-bind-dll-let* (ewoc varlist &rest forms) |
157 "Execute FORMS with ewoc--buffer selected as current buffer, | 153 "Execute FORMS with ewoc--buffer selected as current buffer, |
158 `ewoc--current-dll' bound to the dll, and VARLIST bound as in a let*. | 154 `dll' bound to the dll, and VARLIST bound as in a let*. |
159 `ewoc--current-dll' will be bound when VARLIST is initialized, but | 155 `dll' will be bound when VARLIST is initialized, but |
160 the current buffer will *not* have been changed. | 156 the current buffer will *not* have been changed. |
161 Return value of last form in FORMS." | 157 Return value of last form in FORMS." |
162 (let ((hnd (make-symbol "ewoc"))) | 158 (let ((hnd (make-symbol "ewoc"))) |
163 `(let* ((,hnd ,ewoc) | 159 `(let* ((,hnd ,ewoc) |
164 (ewoc--current-dll (ewoc--dll ,hnd)) | 160 (dll (ewoc--dll ,hnd)) |
165 ,@varlist) | 161 ,@varlist) |
166 (with-current-buffer (ewoc--buffer ,hnd) | 162 (with-current-buffer (ewoc--buffer ,hnd) |
167 ,@forms)))) | 163 ,@forms)))) |
168 | 164 |
169 (defmacro ewoc--set-buffer-bind-dll (ewoc &rest forms) | 165 (defmacro ewoc--set-buffer-bind-dll (ewoc &rest forms) |
174 BUT if it is the header or the footer in EWOC return nil instead." | 170 BUT if it is the header or the footer in EWOC return nil instead." |
175 (unless (or (eq node (ewoc--header ewoc)) | 171 (unless (or (eq node (ewoc--header ewoc)) |
176 (eq node (ewoc--footer ewoc))) | 172 (eq node (ewoc--footer ewoc))) |
177 node)) | 173 node)) |
178 | 174 |
179 (defun ewoc--adjust (beg end node) | 175 (defun ewoc--adjust (beg end node dll) |
180 ;; "Manually reseat" markers for NODE and its successors (including footer | 176 ;; "Manually reseat" markers for NODE and its successors (including footer |
181 ;; and dll), in the case where they originally shared start position with | 177 ;; and dll), in the case where they originally shared start position with |
182 ;; BEG, to END. BEG and END are buffer positions describing NODE's left | 178 ;; BEG, to END. BEG and END are buffer positions describing NODE's left |
183 ;; neighbor. This operation is functionally equivalent to temporarily | 179 ;; neighbor. This operation is functionally equivalent to temporarily |
184 ;; setting these nodes' markers' insertion type to t around the pretty-print | 180 ;; setting these nodes' markers' insertion type to t around the pretty-print |
185 ;; call that precedes the call to `ewoc--adjust', and then changing them back | 181 ;; call that precedes the call to `ewoc--adjust', and then changing them back |
186 ;; to nil. | 182 ;; to nil. |
187 (when (< beg end) | 183 (when (< beg end) |
188 (let (m) | 184 (let (m) |
189 (while (and (= beg (setq m (ewoc--node-start-marker node))) | 185 (while (and (= beg (setq m (ewoc--node-start-marker node))) |
186 ;; The "dummy" node `dll' actually holds the marker that | |
187 ;; points to the end of the footer, so we check `dll' | |
188 ;; *after* reseating the marker. | |
190 (progn | 189 (progn |
191 (set-marker m end) | 190 (set-marker m end) |
192 (not (eq ewoc--current-dll node)))) | 191 (not (eq dll node)))) |
193 (setq node (ewoc--node-right node)))))) | 192 (setq node (ewoc--node-right node)))))) |
194 | 193 |
195 (defun ewoc--insert-new-node (node data pretty-printer) | 194 (defun ewoc--insert-new-node (node data pretty-printer) |
196 "Insert before NODE a new node for DATA, displayed by PRETTY-PRINTER. | 195 "Insert before NODE a new node for DATA, displayed by PRETTY-PRINTER. |
197 Call PRETTY-PRINTER with point at NODE's start, thus pushing back | 196 Call PRETTY-PRINTER with point at NODE's start, thus pushing back |
201 (copy-marker (ewoc--node-start-marker node)) data))) | 200 (copy-marker (ewoc--node-start-marker node)) data))) |
202 (setf (ewoc--node-left elemnode) (ewoc--node-left node) | 201 (setf (ewoc--node-left elemnode) (ewoc--node-left node) |
203 (ewoc--node-right elemnode) node | 202 (ewoc--node-right elemnode) node |
204 (ewoc--node-right (ewoc--node-left node)) elemnode | 203 (ewoc--node-right (ewoc--node-left node)) elemnode |
205 (ewoc--node-left node) elemnode) | 204 (ewoc--node-left node) elemnode) |
206 (ewoc--refresh-node pretty-printer elemnode) | 205 (ewoc--refresh-node pretty-printer elemnode dll) |
207 elemnode))) | 206 elemnode))) |
208 | 207 |
209 (defun ewoc--refresh-node (pp node) | 208 (defun ewoc--refresh-node (pp node dll) |
210 "Redisplay the element represented by NODE using the pretty-printer PP." | 209 "Redisplay the element represented by NODE using the pretty-printer PP." |
211 (let ((inhibit-read-only t) | 210 (let ((inhibit-read-only t) |
212 (m (ewoc--node-start-marker node)) | 211 (m (ewoc--node-start-marker node)) |
213 (R (ewoc--node-right node))) | 212 (R (ewoc--node-right node))) |
214 ;; First, remove the string from the buffer: | 213 ;; First, remove the string from the buffer: |
215 (delete-region m (ewoc--node-start-marker R)) | 214 (delete-region m (ewoc--node-start-marker R)) |
216 ;; Calculate and insert the string. | 215 ;; Calculate and insert the string. |
217 (goto-char m) | 216 (goto-char m) |
218 (funcall pp (ewoc--node-data node)) | 217 (funcall pp (ewoc--node-data node)) |
219 (ewoc--adjust m (point) R))) | 218 (ewoc--adjust m (point) R dll))) |
220 | 219 |
221 (defun ewoc--wrap (func) | 220 (defun ewoc--wrap (func) |
222 (lexical-let ((ewoc--user-pp func)) | 221 (lexical-let ((ewoc--user-pp func)) |
223 (lambda (data) | 222 (lambda (data) |
224 (funcall ewoc--user-pp data) | 223 (funcall ewoc--user-pp data) |
282 | 281 |
283 (defun ewoc-enter-first (ewoc data) | 282 (defun ewoc-enter-first (ewoc data) |
284 "Enter DATA first in EWOC. | 283 "Enter DATA first in EWOC. |
285 Return the new node." | 284 Return the new node." |
286 (ewoc--set-buffer-bind-dll ewoc | 285 (ewoc--set-buffer-bind-dll ewoc |
287 (ewoc-enter-after ewoc (ewoc--node-nth 0) data))) | 286 (ewoc-enter-after ewoc (ewoc--node-nth dll 0) data))) |
288 | 287 |
289 (defun ewoc-enter-last (ewoc data) | 288 (defun ewoc-enter-last (ewoc data) |
290 "Enter DATA last in EWOC. | 289 "Enter DATA last in EWOC. |
291 Return the new node." | 290 Return the new node." |
292 (ewoc--set-buffer-bind-dll ewoc | 291 (ewoc--set-buffer-bind-dll ewoc |
293 (ewoc-enter-before ewoc (ewoc--node-nth -1) data))) | 292 (ewoc-enter-before ewoc (ewoc--node-nth dll -1) data))) |
294 | 293 |
295 (defun ewoc-enter-after (ewoc node data) | 294 (defun ewoc-enter-after (ewoc node data) |
296 "Enter a new element DATA after NODE in EWOC. | 295 "Enter a new element DATA after NODE in EWOC. |
297 Return the new node." | 296 Return the new node." |
298 (ewoc--set-buffer-bind-dll ewoc | 297 (ewoc--set-buffer-bind-dll ewoc |
299 (ewoc-enter-before ewoc (ewoc--node-next node) data))) | 298 (ewoc-enter-before ewoc (ewoc--node-next dll node) data))) |
300 | 299 |
301 (defun ewoc-enter-before (ewoc node data) | 300 (defun ewoc-enter-before (ewoc node data) |
302 "Enter a new element DATA before NODE in EWOC. | 301 "Enter a new element DATA before NODE in EWOC. |
303 Return the new node." | 302 Return the new node." |
304 (ewoc--set-buffer-bind-dll ewoc | 303 (ewoc--set-buffer-bind-dll ewoc |
307 (defun ewoc-next (ewoc node) | 306 (defun ewoc-next (ewoc node) |
308 "Return the node in EWOC that follows NODE. | 307 "Return the node in EWOC that follows NODE. |
309 Return nil if NODE is nil or the last element." | 308 Return nil if NODE is nil or the last element." |
310 (when node | 309 (when node |
311 (ewoc--filter-hf-nodes | 310 (ewoc--filter-hf-nodes |
312 ewoc (let ((ewoc--current-dll (ewoc--dll ewoc))) | 311 ewoc (ewoc--node-next (ewoc--dll ewoc) node)))) |
313 (ewoc--node-next node))))) | |
314 | 312 |
315 (defun ewoc-prev (ewoc node) | 313 (defun ewoc-prev (ewoc node) |
316 "Return the node in EWOC that precedes NODE. | 314 "Return the node in EWOC that precedes NODE. |
317 Return nil if NODE is nil or the first element." | 315 Return nil if NODE is nil or the first element." |
318 (when node | 316 (when node |
319 (ewoc--filter-hf-nodes | 317 (ewoc--filter-hf-nodes |
320 ewoc (let ((ewoc--current-dll (ewoc--dll ewoc))) | 318 ewoc (ewoc--node-prev (ewoc--dll ewoc) node)))) |
321 (ewoc--node-prev node))))) | |
322 | 319 |
323 (defun ewoc-nth (ewoc n) | 320 (defun ewoc-nth (ewoc n) |
324 "Return the Nth node. | 321 "Return the Nth node. |
325 N counts from zero. Return nil if there is less than N elements. | 322 N counts from zero. Return nil if there is less than N elements. |
326 If N is negative, return the -(N+1)th last element. | 323 If N is negative, return the -(N+1)th last element. |
328 and (ewoc-nth ewoc -1) returns the last node. | 325 and (ewoc-nth ewoc -1) returns the last node. |
329 Use `ewoc-data' to extract the data from the node." | 326 Use `ewoc-data' to extract the data from the node." |
330 ;; Skip the header (or footer, if n is negative). | 327 ;; Skip the header (or footer, if n is negative). |
331 (setq n (if (< n 0) (1- n) (1+ n))) | 328 (setq n (if (< n 0) (1- n) (1+ n))) |
332 (ewoc--filter-hf-nodes ewoc | 329 (ewoc--filter-hf-nodes ewoc |
333 (let ((ewoc--current-dll (ewoc--dll ewoc))) | 330 (ewoc--node-nth (ewoc--dll ewoc) n))) |
334 (ewoc--node-nth n)))) | |
335 | 331 |
336 (defun ewoc-map (map-function ewoc &rest args) | 332 (defun ewoc-map (map-function ewoc &rest args) |
337 "Apply MAP-FUNCTION to all elements in EWOC. | 333 "Apply MAP-FUNCTION to all elements in EWOC. |
338 MAP-FUNCTION is applied to the first element first. | 334 MAP-FUNCTION is applied to the first element first. |
339 If MAP-FUNCTION returns non-nil the element will be refreshed (its | 335 If MAP-FUNCTION returns non-nil the element will be refreshed (its |
346 If more than two arguments are given, the remaining | 342 If more than two arguments are given, the remaining |
347 arguments will be passed to MAP-FUNCTION." | 343 arguments will be passed to MAP-FUNCTION." |
348 (ewoc--set-buffer-bind-dll-let* ewoc | 344 (ewoc--set-buffer-bind-dll-let* ewoc |
349 ((footer (ewoc--footer ewoc)) | 345 ((footer (ewoc--footer ewoc)) |
350 (pp (ewoc--pretty-printer ewoc)) | 346 (pp (ewoc--pretty-printer ewoc)) |
351 (node (ewoc--node-nth 1))) | 347 (node (ewoc--node-nth dll 1))) |
352 (save-excursion | 348 (save-excursion |
353 (while (not (eq node footer)) | 349 (while (not (eq node footer)) |
354 (if (apply map-function (ewoc--node-data node) args) | 350 (if (apply map-function (ewoc--node-data node) args) |
355 (ewoc--refresh-node pp node)) | 351 (ewoc--refresh-node pp node dll)) |
356 (setq node (ewoc--node-next node)))))) | 352 (setq node (ewoc--node-next dll node)))))) |
357 | 353 |
358 (defun ewoc-delete (ewoc &rest nodes) | 354 (defun ewoc-delete (ewoc &rest nodes) |
359 "Delete NODES from EWOC." | 355 "Delete NODES from EWOC." |
360 (ewoc--set-buffer-bind-dll-let* ewoc | 356 (ewoc--set-buffer-bind-dll-let* ewoc |
361 ((L nil) (R nil) (last (ewoc--last-node ewoc))) | 357 ((L nil) (R nil) (last (ewoc--last-node ewoc))) |
363 ;; If we are about to delete the node pointed at by last-node, | 359 ;; If we are about to delete the node pointed at by last-node, |
364 ;; set last-node to nil. | 360 ;; set last-node to nil. |
365 (when (eq last node) | 361 (when (eq last node) |
366 (setf last nil (ewoc--last-node ewoc) nil)) | 362 (setf last nil (ewoc--last-node ewoc) nil)) |
367 (delete-region (ewoc--node-start-marker node) | 363 (delete-region (ewoc--node-start-marker node) |
368 (ewoc--node-start-marker (ewoc--node-next node))) | 364 (ewoc--node-start-marker (ewoc--node-next dll node))) |
369 (set-marker (ewoc--node-start-marker node) nil) | 365 (set-marker (ewoc--node-start-marker node) nil) |
370 (setf L (ewoc--node-left node) | 366 (setf L (ewoc--node-left node) |
371 R (ewoc--node-right node) | 367 R (ewoc--node-right node) |
372 ;; Link neighbors to each other. | 368 ;; Link neighbors to each other. |
373 (ewoc--node-right L) R | 369 (ewoc--node-right L) R |
382 is called. PREDICATE must restore the current buffer before it returns | 378 is called. PREDICATE must restore the current buffer before it returns |
383 if it changes it. | 379 if it changes it. |
384 The PREDICATE is called with the element as its first argument. If any | 380 The PREDICATE is called with the element as its first argument. If any |
385 ARGS are given they will be passed to the PREDICATE." | 381 ARGS are given they will be passed to the PREDICATE." |
386 (ewoc--set-buffer-bind-dll-let* ewoc | 382 (ewoc--set-buffer-bind-dll-let* ewoc |
387 ((node (ewoc--node-nth 1)) | 383 ((node (ewoc--node-nth dll 1)) |
388 (footer (ewoc--footer ewoc)) | 384 (footer (ewoc--footer ewoc)) |
389 (goodbye nil) | 385 (goodbye nil) |
390 (inhibit-read-only t)) | 386 (inhibit-read-only t)) |
391 (while (not (eq node footer)) | 387 (while (not (eq node footer)) |
392 (unless (apply predicate (ewoc--node-data node) args) | 388 (unless (apply predicate (ewoc--node-data node) args) |
393 (push node goodbye)) | 389 (push node goodbye)) |
394 (setq node (ewoc--node-next node))) | 390 (setq node (ewoc--node-next dll node))) |
395 (apply 'ewoc-delete ewoc goodbye))) | 391 (apply 'ewoc-delete ewoc goodbye))) |
396 | 392 |
397 (defun ewoc-locate (ewoc &optional pos guess) | 393 (defun ewoc-locate (ewoc &optional pos guess) |
398 "Return the node that POS (a buffer position) is within. | 394 "Return the node that POS (a buffer position) is within. |
399 POS may be a marker or an integer. It defaults to point. | 395 POS may be a marker or an integer. It defaults to point. |
401 | 397 |
402 If POS points before the first element, the first node is returned. | 398 If POS points before the first element, the first node is returned. |
403 If POS points after the last element, the last node is returned. | 399 If POS points after the last element, the last node is returned. |
404 If the EWOC is empty, nil is returned." | 400 If the EWOC is empty, nil is returned." |
405 (unless pos (setq pos (point))) | 401 (unless pos (setq pos (point))) |
406 (ewoc--set-buffer-bind-dll-let* ewoc | 402 (ewoc--set-buffer-bind-dll ewoc |
407 ((footer (ewoc--footer ewoc))) | |
408 | 403 |
409 (cond | 404 (cond |
410 ;; Nothing present? | 405 ;; Nothing present? |
411 ((eq (ewoc--node-nth 1) (ewoc--node-nth -1)) | 406 ((eq (ewoc--node-nth dll 1) (ewoc--node-nth dll -1)) |
412 nil) | 407 nil) |
413 | 408 |
414 ;; Before second elem? | 409 ;; Before second elem? |
415 ((< pos (ewoc--node-start-marker (ewoc--node-nth 2))) | 410 ((< pos (ewoc--node-start-marker (ewoc--node-nth dll 2))) |
416 (ewoc--node-nth 1)) | 411 (ewoc--node-nth dll 1)) |
417 | 412 |
418 ;; After one-before-last elem? | 413 ;; After one-before-last elem? |
419 ((>= pos (ewoc--node-start-marker (ewoc--node-nth -2))) | 414 ((>= pos (ewoc--node-start-marker (ewoc--node-nth dll -2))) |
420 (ewoc--node-nth -2)) | 415 (ewoc--node-nth dll -2)) |
421 | 416 |
422 ;; We now know that pos is within a elem. | 417 ;; We now know that pos is within a elem. |
423 (t | 418 (t |
424 ;; Make an educated guess about which of the three known | 419 ;; Make an educated guess about which of the three known |
425 ;; node'es (the first, the last, or GUESS) is nearest. | 420 ;; node'es (the first, the last, or GUESS) is nearest. |
426 (let* ((best-guess (ewoc--node-nth 1)) | 421 (let* ((best-guess (ewoc--node-nth dll 1)) |
427 (distance (abs (- pos (ewoc--node-start-marker best-guess))))) | 422 (distance (abs (- pos (ewoc--node-start-marker best-guess))))) |
428 (when guess | 423 (when guess |
429 (let ((d (abs (- pos (ewoc--node-start-marker guess))))) | 424 (let ((d (abs (- pos (ewoc--node-start-marker guess))))) |
430 (when (< d distance) | 425 (when (< d distance) |
431 (setq distance d) | 426 (setq distance d) |
432 (setq best-guess guess)))) | 427 (setq best-guess guess)))) |
433 | 428 |
434 (let* ((g (ewoc--node-nth -1)) ;Check the last elem | 429 (let* ((g (ewoc--node-nth dll -1)) ;Check the last elem |
435 (d (abs (- pos (ewoc--node-start-marker g))))) | 430 (d (abs (- pos (ewoc--node-start-marker g))))) |
436 (when (< d distance) | 431 (when (< d distance) |
437 (setq distance d) | 432 (setq distance d) |
438 (setq best-guess g))) | 433 (setq best-guess g))) |
439 | 434 |
452 ;; Is pos after the guess? | 447 ;; Is pos after the guess? |
453 ((>= pos | 448 ((>= pos |
454 (ewoc--node-start-marker best-guess)) | 449 (ewoc--node-start-marker best-guess)) |
455 ;; Loop until we are exactly one node too far down... | 450 ;; Loop until we are exactly one node too far down... |
456 (while (>= pos (ewoc--node-start-marker best-guess)) | 451 (while (>= pos (ewoc--node-start-marker best-guess)) |
457 (setq best-guess (ewoc--node-next best-guess))) | 452 (setq best-guess (ewoc--node-next dll best-guess))) |
458 ;; ...and return the previous node. | 453 ;; ...and return the previous node. |
459 (ewoc--node-prev best-guess)) | 454 (ewoc--node-prev dll best-guess)) |
460 | 455 |
461 ;; Pos is before best-guess | 456 ;; Pos is before best-guess |
462 (t | 457 (t |
463 (while (< pos (ewoc--node-start-marker best-guess)) | 458 (while (< pos (ewoc--node-start-marker best-guess)) |
464 (setq best-guess (ewoc--node-prev best-guess))) | 459 (setq best-guess (ewoc--node-prev dll best-guess))) |
465 best-guess))))))) | 460 best-guess))))))) |
466 | 461 |
467 (defun ewoc-invalidate (ewoc &rest nodes) | 462 (defun ewoc-invalidate (ewoc &rest nodes) |
468 "Call EWOC's pretty-printer for each element in NODES. | 463 "Call EWOC's pretty-printer for each element in NODES. |
469 Delete current text first, thus effecting a \"refresh\"." | 464 Delete current text first, thus effecting a \"refresh\"." |
470 (ewoc--set-buffer-bind-dll-let* ewoc | 465 (ewoc--set-buffer-bind-dll-let* ewoc |
471 ((pp (ewoc--pretty-printer ewoc))) | 466 ((pp (ewoc--pretty-printer ewoc))) |
472 (save-excursion | 467 (save-excursion |
473 (dolist (node nodes) | 468 (dolist (node nodes) |
474 (ewoc--refresh-node pp node))))) | 469 (ewoc--refresh-node pp node dll))))) |
475 | 470 |
476 (defun ewoc-goto-prev (ewoc arg) | 471 (defun ewoc-goto-prev (ewoc arg) |
477 "Move point to the ARGth previous element in EWOC. | 472 "Move point to the ARGth previous element in EWOC. |
478 Don't move if we are at the first element, or if EWOC is empty. | 473 Don't move if we are at the first element, or if EWOC is empty. |
479 Return the node we moved to." | 474 Return the node we moved to." |
483 ;; If we were past the last element, first jump to it. | 478 ;; If we were past the last element, first jump to it. |
484 (when (>= (point) (ewoc--node-start-marker (ewoc--node-right node))) | 479 (when (>= (point) (ewoc--node-start-marker (ewoc--node-right node))) |
485 (setq arg (1- arg))) | 480 (setq arg (1- arg))) |
486 (while (and node (> arg 0)) | 481 (while (and node (> arg 0)) |
487 (setq arg (1- arg)) | 482 (setq arg (1- arg)) |
488 (setq node (ewoc--node-prev node))) | 483 (setq node (ewoc--node-prev dll node))) |
489 ;; Never step above the first element. | 484 ;; Never step above the first element. |
490 (unless (ewoc--filter-hf-nodes ewoc node) | 485 (unless (ewoc--filter-hf-nodes ewoc node) |
491 (setq node (ewoc--node-nth 1))) | 486 (setq node (ewoc--node-nth dll 1))) |
492 (ewoc-goto-node ewoc node)))) | 487 (ewoc-goto-node ewoc node)))) |
493 | 488 |
494 (defun ewoc-goto-next (ewoc arg) | 489 (defun ewoc-goto-next (ewoc arg) |
495 "Move point to the ARGth next element in EWOC. | 490 "Move point to the ARGth next element in EWOC. |
496 Return the node (or nil if we just passed the last node)." | 491 Return the node (or nil if we just passed the last node)." |
497 (ewoc--set-buffer-bind-dll-let* ewoc | 492 (ewoc--set-buffer-bind-dll-let* ewoc |
498 ((node (ewoc-locate ewoc (point)))) | 493 ((node (ewoc-locate ewoc (point)))) |
499 (while (and node (> arg 0)) | 494 (while (and node (> arg 0)) |
500 (setq arg (1- arg)) | 495 (setq arg (1- arg)) |
501 (setq node (ewoc--node-next node))) | 496 (setq node (ewoc--node-next dll node))) |
502 ;; Never step below the first element. | 497 ;; Never step below the first element. |
503 ;; (unless (ewoc--filter-hf-nodes ewoc node) | 498 ;; (unless (ewoc--filter-hf-nodes ewoc node) |
504 ;; (setq node (ewoc--node-nth -2))) | 499 ;; (setq node (ewoc--node-nth dll -2))) |
505 (ewoc-goto-node ewoc node))) | 500 (ewoc-goto-node ewoc node))) |
506 | 501 |
507 (defun ewoc-goto-node (ewoc node) | 502 (defun ewoc-goto-node (ewoc node) |
508 "Move point to NODE in EWOC." | 503 "Move point to NODE in EWOC." |
509 (ewoc--set-buffer-bind-dll ewoc | 504 (ewoc--set-buffer-bind-dll ewoc |
518 Note that `ewoc-invalidate' is more efficient if only a small | 513 Note that `ewoc-invalidate' is more efficient if only a small |
519 number of elements needs to be refreshed." | 514 number of elements needs to be refreshed." |
520 (ewoc--set-buffer-bind-dll-let* ewoc | 515 (ewoc--set-buffer-bind-dll-let* ewoc |
521 ((footer (ewoc--footer ewoc))) | 516 ((footer (ewoc--footer ewoc))) |
522 (let ((inhibit-read-only t)) | 517 (let ((inhibit-read-only t)) |
523 (delete-region (ewoc--node-start-marker (ewoc--node-nth 1)) | 518 (delete-region (ewoc--node-start-marker (ewoc--node-nth dll 1)) |
524 (ewoc--node-start-marker footer)) | 519 (ewoc--node-start-marker footer)) |
525 (goto-char (ewoc--node-start-marker footer)) | 520 (goto-char (ewoc--node-start-marker footer)) |
526 (let ((pp (ewoc--pretty-printer ewoc)) | 521 (let ((pp (ewoc--pretty-printer ewoc)) |
527 (node (ewoc--node-nth 1))) | 522 (node (ewoc--node-nth dll 1))) |
528 (while (not (eq node footer)) | 523 (while (not (eq node footer)) |
529 (set-marker (ewoc--node-start-marker node) (point)) | 524 (set-marker (ewoc--node-start-marker node) (point)) |
530 (funcall pp (ewoc--node-data node)) | 525 (funcall pp (ewoc--node-data node)) |
531 (setq node (ewoc--node-next node))))) | 526 (setq node (ewoc--node-next dll node))))) |
532 (set-marker (ewoc--node-start-marker footer) (point)))) | 527 (set-marker (ewoc--node-start-marker footer) (point)))) |
533 | 528 |
534 (defun ewoc-collect (ewoc predicate &rest args) | 529 (defun ewoc-collect (ewoc predicate &rest args) |
535 "Select elements from EWOC using PREDICATE. | 530 "Select elements from EWOC using PREDICATE. |
536 Return a list of all selected data elements. | 531 Return a list of all selected data elements. |
543 changes it. | 538 changes it. |
544 If more than two arguments are given the | 539 If more than two arguments are given the |
545 remaining arguments will be passed to PREDICATE." | 540 remaining arguments will be passed to PREDICATE." |
546 (ewoc--set-buffer-bind-dll-let* ewoc | 541 (ewoc--set-buffer-bind-dll-let* ewoc |
547 ((header (ewoc--header ewoc)) | 542 ((header (ewoc--header ewoc)) |
548 (node (ewoc--node-nth -2)) | 543 (node (ewoc--node-nth dll -2)) |
549 result) | 544 result) |
550 (while (not (eq node header)) | 545 (while (not (eq node header)) |
551 (if (apply predicate (ewoc--node-data node) args) | 546 (if (apply predicate (ewoc--node-data node) args) |
552 (push (ewoc--node-data node) result)) | 547 (push (ewoc--node-data node) result)) |
553 (setq node (ewoc--node-prev node))) | 548 (setq node (ewoc--node-prev dll node))) |
554 (nreverse result))) | 549 (nreverse result))) |
555 | 550 |
556 (defun ewoc-buffer (ewoc) | 551 (defun ewoc-buffer (ewoc) |
557 "Return the buffer that is associated with EWOC. | 552 "Return the buffer that is associated with EWOC. |
558 Return nil if the buffer has been deleted." | 553 Return nil if the buffer has been deleted." |
571 (foot (ewoc--footer ewoc)) | 566 (foot (ewoc--footer ewoc)) |
572 (hf-pp (ewoc--hf-pp ewoc))) | 567 (hf-pp (ewoc--hf-pp ewoc))) |
573 (setf (ewoc--node-data head) header | 568 (setf (ewoc--node-data head) header |
574 (ewoc--node-data foot) footer) | 569 (ewoc--node-data foot) footer) |
575 (save-excursion | 570 (save-excursion |
576 (ewoc--refresh-node hf-pp head) | 571 (ewoc--refresh-node hf-pp head dll) |
577 (ewoc--refresh-node hf-pp foot)))) | 572 (ewoc--refresh-node hf-pp foot dll)))) |
578 | 573 |
579 | 574 |
580 (provide 'ewoc) | 575 (provide 'ewoc) |
581 | 576 |
582 ;; Local Variables: | 577 ;; Local Variables: |