谢谢你,德鲁。
事实证明,zones 最接近我的需要,尽管 icicles 和 isearch+ 也都很有用。
至于区域,事实证明它的 zz-zones-complement 函数似乎没有返回正确的信息。
但是,我编写了自己的函数,我可以使用它来代替它。
我现在这样做是为了在之前通过 zone.el 添加的所有区域的补充上运行任意 lisp 代码...
(defun my-complement-zones (&optional zones)
(unless zones
(setq zones zz-izones))
(zz-unite-zones 'zones)
(let ((result ())
(end (copy-marker (point-min)))
(n 0)
(a nil)
(b nil))
(dolist (item (reverse zones))
(setq n (1+ n))
(setq a (cadr item))
(setq b (caddr item))
(setq result (append (list (list n end a)) result))
(setq end b))
(when (< (marker-position end) (point-max))
(setq result (append (list (list (1+ n) end (copy-marker (point-max)))) result)))
result))
;; Each element has three values: an index followed by the start
;; and end markers for each region. To traverse this structure,
;; do the following ...
(dolist (region (my-complement-zones))
(let ((idx (car region))
(start (cadr region))
(end (caddr region)))
;; At this point, "start" is a marker pointing to the
;; beginning of the given zone, and "end" is a marker pointing
;; its endpoint. I can use these for inputs to any region-aware
;; elisp commands, or for any functions that I might want to
;; write which operate on each given region.
;;
;; ... etc. ...
))
... 这是我编写的一个函数,它将遍历区域列表并将 lambda 应用于每个区域。无论我们是使用原始的 zz-izones 还是使用我的函数生成的补码,它都可以等效地工作:
;; Helper function
(defun funcallable (func)
(and func
(or (functionp func)
(and (symbolp func)
(fboundp func)))))
;; Traverse a list of zones such as zz-izones, and apply a lambda
;; to each zone in the list. Works equivalently with the output of
;; `my-complement-zones'.
(defun traverse-zones (func &optional zones)
(when (funcallable func)
(unless zones
(setq zones zz-izones))
(zz-unite-zones 'zones) ;; not sure if this is really necessary
(dolist (zone zones)
(let ((i (car zone))
(s (cadr zone))
(e (caddr zone)))
(funcall func i s e)))))
为了说明 zz-izones 和 zz-zones-complement 的输出之间的结构差异,下面是我在名为“foo”的缓冲区中创建的 zz-izones 结构的示例:
((4 #<marker at 1202 in foo> #<marker at 1266 in foo>) (3 #<marker at 689 in foo> #<marker at 1132 in foo>) (2 #<marker at 506 in foo> #<marker at 530 in foo>) (1 #<marker at 3 in foo> #<marker at 446 in foo>))
这是相同 zz-izones 列表的 (zz-zones-complement zz-izones) 的样子...
((1 4) (#<marker at 1202 in foo> 3) (#<marker at 689 in foo> 2) (#<marker at 506 in foo> 1) (#<marker at 3 in foo> 1266)
请注意,zz-izones 中的每个条目都包含一个索引和两个标记。但是,在其补码中,每个条目要么是两个整数,要么是一个标记和一个整数。这些结构不是同构的。
附加信息
对于(zz-zone-union (zz-izone-limits zz-izones nil t)) ...
((#<marker at 3 in foo> #<marker at 446 in foo>) (#<marker at 506 in foo> #<marker at 530 in foo>) (#<marker at 689 in foo> #<marker at 1132 in foo>) (#<marker at 1202 in foo> #<marker at 1266 in foo>)
对于(zz-zones-complement (zz-zone-union (zz-izone-limits zz-izones nil t)))
((1 #<marker at 3 in foo>) (#<marker at 446 in foo> #<marker at 506 in foo>) (#<marker at 530 in foo> #<marker at 689 in foo>) (#<marker at 1132 in foo> #<marker at 1202 in foo>) (#<marker at 1266 in foo> 1266))
我想如果我将第一个条目中的“1”转换为(copy-marker (point-min)),并将最后一项中的“1266”转换为(copy-marker (point-max)),我想我可以使用这个补码......除非我正在处理特定情况我处理的是标记还是点都没有关系。
标记是理想的,因为这样我可以在生成补码后更改缓冲区,并且我不必担心补码结构中的数字点值不再指向它最初指向的位置。