I know there are a few different packages for selecting multiple regions in gnu emacs. What I'm looking for is a way to select multiple regions, operate on them, and then select the inverse of the previously marked regions in order to then operate on them.
As an example, suppose that I have the following data in a buffer:
Line A
Line B
Line C
Line D
Line E
Line F
What I want to do is the following:
Steps 1, 2, and 4 are trivial, and they simply depend on the choice of multiple-region-marking code I decide to use.
But what about step 3? Is there any multiple-region-marking package which allows me to switch to the inverse of what was previously marked?
Your question is general. My answer will likely fit some of it, but maybe not all.
Library zones.el
(see Zones) lets you define and manipulate multiple zones (in effect, multiple regions) of text, across multiple buffers. You can do these kinds of things with them:
isearch-prop.el
(see Isearch+).highlight.el
) or library facemenu+.el
(see Facemenu+).Library Isearch+ (including isearch-prop.el
) lets you search both zones as defined by zones.el
and zones defined by text or overlay properties (any properties), and it facilitates applying properties to zones of text.
thingatpt+.el
then you can easily define additional things.If you use Icicles then you can use Icicles search on a set of search contexts in buffers or files. You can define search contexts in various ways, including using a regexp. There too you can search the complement of a set of search contexts. And you can use incremental narrowing of matching search contexts, and when doing that you can also subtract sets of matches using complementing.
UPDATED after your remarks -
You apparently want to complement a list of non-basic zones (what I call "izones"), which are each a number as identifier followed by the two zone limits. (Basic zones have only the limits and not the identifier, and function zz-zones-complement
returns a list of basic zones.)
This is how I would define that complement function:
(defun zz-complement-izones (izones &optional beg end)
"Complement IZONES, which is a list like `zz-izones'.
Such a list is also returned, that is, zones that have identifiers."
(zz-izones-from-zones
(zz-zones-complement (zz-zone-union (zz-izone-limits izones nil t)))))
That just uses predefined function zz-zones-complement
after stripping the zone identifiers and coalescing the zones. Predefined function zz-izones-from-zones
gives the zones identifiers, making the result a list of izones.
And you want a function that maps a function over a list of zones, applying it to each zone in the list - what your function traverse-zones
does.
Here is a version (untested) of such a map function that expects zones of the form that you are using, that is, izones (zones that have a number identifier) and maps a 3-ary function over them. It is similar to your traverse-zones
(but see the comment):
(defun map-izones (function &optional izones)
"Map 3-ary FUNCTION over IZONES.
FUNCTION is applied to the first three elements of each zone.
IZONES is a list like `zz-izones', that is, zones with identifiers."
;; Do you really want this? It prohibits mapping over an empty list of zones.
;; (unless izones) (setq izones zz-izones)
(when (and (functionp function) (zz-izones-p izones))
(setq izones (zz-unite-zones izones))
(dolist (izone izones) (funcall function (car izone) (cadr izone) (caddr izone)))))
And here is an (untested) version that maps a binary function over a list of zones. The zones in the list can be either all basic zones or all izones. This seems more useful to me, as the identifiers are generally not very useful in such a context.
(defun map-zones (function &optional zones)
"Map binary FUNCTION over ZONES, applying it to the limits of each zone.
ZONES can be a list of basic zones or a list like `zz-izones', that
is, zones that have identifiers."
(when (functionp function)
(when (zz-izones-p zones)
(setq zones (zz-izone-limits zones nil 'ONLY-THIS-BUFFER)))
(setq zones (zz-zone-union zones))
(dolist (zone zones) (funcall function (car zone) (cadr zone)))))
Hope this helps.