emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/zones 0d7e975 06/43: no summary available


From: Stefan Monnier
Subject: [elpa] externals/zones 0d7e975 06/43: no summary available
Date: Sun, 28 Oct 2018 15:05:53 -0400 (EDT)

branch: externals/zones
commit 0d7e975c3048f19fbc56f4931f2516f4bfd343da
Author: DrewAdams <address@hidden>
Commit: Alex Schroeder <address@hidden>

    no summary available
---
 zones.el | 1505 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 1360 insertions(+), 145 deletions(-)

diff --git a/zones.el b/zones.el
index a332766..cfedde0 100644
--- a/zones.el
+++ b/zones.el
@@ -1,102 +1,573 @@
-;;; zones.el --- Zones of text - like multiple regions.
-;; 
+;;; zones.el --- Zones of text - like multiple regions
+;;
 ;; Filename: zones.el
-;; Description: Zones of text - like multiple regions.
+;; Description:  Zones of text - like multiple regions
 ;; Author: Drew Adams
 ;; Maintainer: Drew Adams
-;; Copyright (C) 2015, Drew Adams, all rights reserved.
-;; Created: Tue Aug  4 08:54:06 2015 (-0700)
-;; Version: 2015.08.08
+;; Copyright (C) 2010-2015, Drew Adams, all rights reserved.
+;; Created: Sun Apr 18 12:58:07 2010 (-0700)
+;; Version: 2015-08-16
 ;; Package-Requires: ()
-;; Last-Updated: Sat Aug 15 14:34:39 2015 (-0700)
+;; Last-Updated: Sun Aug 16 19:49:10 2015 (-0700)
 ;;           By: dradams
-;;     Update #: 215
+;;     Update #: 1539
 ;; URL: http://www.emacswiki.org/zones.el
 ;; Doc URL: http://www.emacswiki.org/Zones
-;; Keywords: region zone
-;; Compatibility: GNU Emacs 20.x, 21.x, 22.x, 23.x, 24.x, 25.x, 
-;; 
+;; Doc URL: http://www.emacswiki.org/MultipleNarrowings
+;; Keywords: narrow restriction widen region zone
+;; Compatibility: GNU Emacs 20.x, 21.x, 22.x, 23.x, 24.x, 25.x,
+;;
 ;; Features that might be required by this library:
 ;;
 ;;   None
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; 
-;;; Commentary: 
-;; 
-;;    Zones of text - like multiple regions.
-;;
-;;  A zone is a list of two buffer positions followed by a possibly
-;;  empty list of extra information: (POS1 POS2 . EXTRA).  A zone
-;;  represents the text between its two positions, just as an Emacs
-;;  region is the text between point and mark.
-;;
-;;  The positions of a zone can be natural numbers (1, 2, 3,...) or
-;;  markers from the same buffer.  (Behavior is undefined if a zone
-;;  has markers from different buffers.)
-;;
-;;  Zone union and intersection operations (`zzz-zone-union',
-;;  `zzz-zone-intersection') each act on a list of zones, returning
+;;
+;;; Commentary:
+;;
+;;     Zones of text - like multiple regions.
+;;
+;;    More description below.
+ 
+;;(@> "Index")
+;;
+;;  Index
+;;  -----
+;;
+;;  If you have library `linkd.el' and Emacs 22 or later, load
+;;  `linkd.el' and turn on `linkd-mode' now.  It lets you easily
+;;  navigate around the sections of this doc.  Linkd mode will
+;;  highlight this Index, as well as the cross-references and section
+;;  headings throughout this file.  You can get `linkd.el' here:
+;;  http://dto.freeshell.org/notebook/Linkd.html.
+;;
+;;  (@> "Things Defined Here")
+;;  (@> "Documentation")
+;;    (@> "Compatibility")
+;;    (@> "Coalesced Zones")
+;;    (@> "Izone Commands")
+;;    (@> "Izone List Variables")
+;;    (@> "Keys")
+;;    (@> "Command `zz-narrow-repeat'")
+;;    (@> "Define Your Own Commands")
+;;  (@> "Change log")
+ 
+;;(@* "Things Defined Here")
+;;
+;;  Things Defined Here
+;;  -------------------
+;;
+;;  Commands defined here:
+;;
+;;    `zz-izone-add', `zz-izone-add-and-coalesce', `zz-izone-delete',
+;;    `zz-izones-coalesce', `zz-narrow', `zz-narrow-repeat',
+;;    `zz-select-region', `zz-select-region-repeat'.
+;;
+;;  Non-interactive functions defined here:
+;;
+;;    `zz-buffer-of-markers', `zz-car-<', `zz-every',
+;;    `zz-izone-has-other-buffer-marker-p', `zz-izone-limits',
+;;    `zz-izone-limits-in-bufs', `zz-izones', `zz-izones-from-zones',
+;;    `zz-izones-p', `zz-izones-renumber', `zz-marker-from-object',
+;;    `zz-markerize', `zz-max', `zz-min', `zz-narrowing-lighter',
+;;    `zz-number-or-marker-p', `zz-rassoc-delete-all',
+;;    `zz-readable-marker', `zz-readable-marker-p',
+;;    `zz-read-any-variable', `zz-read-bufs', `zz-regexp-car-member',
+;;    `zz-remove-if', `zz-remove-if-not',
+;;    `zz-remove-izones-w-other-buffer-markers',
+;;    `zz-remove-zones-w-other-buffer-markers', `zz-repeat-command',
+;;    `zz-set-intersection', `zz-set-union', `zz-some',
+;;    `zz-string-match-p', `zz-two-zone-intersection',
+;;    `zz-two-zone-union', `zz-zones-complement',
+;;    `zz-zone-has-other-buffer-marker-p', `zz-zone-intersection',
+;;    `zz-zone-intersection-1', `zz-zone-ordered',
+;;    `zz-zones-overlap-p', `zz-zones-same-buffer-p',
+;;    `zz-zone-union', `zz-zone-union-1'.
+;;
+;;  Internal variables defined here:
+;;
+;;    `zz-izones', `zz-izones-var', `zz-lighter-narrowing-part',
+;;    `zz-izone-add-anyway-p'.
+;;
+;;
+;;  ***** NOTE: This EMACS PRIMITIVE has been ADVISED HERE:
+;;
+;;    `narrow-to-region'.
+;;
+;;
+;;  ***** NOTE: The following functions defined in `lisp.el' and
+;;              `page.el' have been REDEFINED here:
+;;
+;;    `narrow-to-defun', `narrow-to-page'.
+ 
+;;(@* "Documentation")
+;;
+;;  Documentation
+;;  -------------
+;;
+;;  Library `zones.el' lets you easily define and subsequently act on
+;;  multiple zones of buffer text.  You can think of this as enlarging
+;;  the notion of "region".  In effect, it can remove the requirement
+;;  of target text being a contiguous sequence of characters.  A set
+;;  of buffer zones is, in effect, a (typically) noncontiguous
+;;  "region" of text.
+;;
+;;
+;;(@* "Compatibility")
+;;  ** Compatibility **
+;;
+;;  Some of the functions defined here are not available for Emacs
+;;  versions prior to Emacs 22.  Others are not available for versions
+;;  prior to Emacs 23.  This is mentioned where applicable.
+;;
+;;
+;;(@* "Zones")
+;;  ** Zones **
+;;
+;;  A "zone" is a basic zone or an izone.  A zone represents the text
+;;  between its two positions, just as an Emacs region is the text
+;;  between point and mark.
+;;
+;;  A "basic zone" is a list of two buffer positions followed by a
+;;  possibly empty list of extra information: (POS1 POS2 . EXTRA).
+;;
+;;  An "izone" is a list whose first element is an identifier that is
+;;  is a natural number (1, 2, 3,...)  and whose cdr is a basic zone:
+;;  (ID POS1 POS2 . EXTRA).
+;;
+;;  The positions of a zone can be natural numbers (1, 2, 3,...),
+;;  markers for the same buffer, or readable markers for the same
+;;  buffer.  (Behavior is undefined if a zone has markers for
+;;  different buffers.)  Each position of a given zone can take any of
+;;  these forms.
+;;
+;;  A "readable marker" is a list (marker BUFFER POSITION), where
+;;  BUFFER is a buffer name (string) and where POSITION is a buffer
+;;  position (number only).
+;;
+;;  The positions of a zone can be in either numeric order.  The
+;;  positions are also called the zone "limits".  The lower limit is
+;;  called the zone "beginning"; the upper limit is called its "end".
+;;
+;;
+;;(@* "Coalesced Zones")
+;;  ** Coalesced Zones **
+;;
+;;  A list of zones can contain zones that overlap or are adjacent
+;;  (the end of one is one less than the beginning of the other).
+;;
+;;  Basic-zone union and intersection operations (`zz-zone-union',
+;;  `zz-zone-intersection') each act on a list of zones, returning
 ;;  another such list, but which has POS1 <= POS2 in each of its
 ;;  zones, and which lists its zones in ascending order of their cars.
+;;  For basic-zone union, the resulting zones are said to be
+;;  "coalesced".
 ;;
-;;  The extra info in the zones resulting from zone union or zone
+;;  The extra info in the zones that result from zone union or
 ;;  intersection is just the set union or set intersection of the
 ;;  extra info in the zones that are combined.
 ;;
-;;  See also library `wide-n.el', which provides some commands that
-;;  make use of `zones.el'.
+;;  After a list of zones has been altered by `zz-zone-union' or
+;;  `zz-zone-intersection':
 ;;
+;;  * Each zone in the result list is ordered so that its first
+;;    element is smaller than its second.
 ;;
-;;  Non-interactive functions defined here:
+;;  * The zones in the result list have been sorted in ascending order
+;;    by their first elements.
+;;
+;;  * The zones in the result list are not adjacent and do not
+;;    overlap: there is some other buffer text (i.e., not in any zone)
+;;    between any two zones in the result.
+;;
+;;
+;;(@* "Izone Commands")
+;;  ** Izone Commands **
+;;
+;;  Commands that manipulate lists of zones generally use izones,
+;;  because they make use of the zone identifiers.
+;;
+;;  Things you can do with izones:
+;;
+;;  * Narrow the buffer to any of them.  Cycle among narrowings.  If
+;;    you use library `icicles.el' then you can also navigate among
+;;    them in any order, and using completion against BEG-END range
+;;    names.
+;;
+;;  * Select any of them as the active region.  Cycle among regions.
+;;
+;;  * Search them (they are automatically coalesced first).  For this
+;;    you need library `isearch-prop.el'.
+;;
+;;  * Highlight and unhighlight them.  For this you need library
+;;    `highlight.el' or library `facemenu+.el' (different kinds of
+;;    highlighting).
+;;
+;;  * Push the active region to a list of izones.
 ;;
-;;    `zzz-buffer-of-markers', `zzz-car-<', `zzz-zone-complement',
-;;    `zzz-every', `zzz-max', `zzz-min', `zzz-ordered-zone',
-;;    `zzz-remove-if', `zzz-remove-if-other-buffer-markers',
-;;    `zzz-set-union', `zzz-set-intersection', `zzz-some',
-;;    `zzz-two-zone-intersection', `zzz-two-zone-union',
-;;    `zzz-zone-intersection', `zzz-zone-intersection-1',
-;;    `zzz-zones-overlap-p', `zzz-zones-same-buffer-p',
-;;    `zzz-zone-union', `zzz-zone-union-1'.
-;; 
+;;  * Delete an izone from a list of izones.
+;;
+;;  * Make an izone variable persistent, in a bookmark.  Use the
+;;    bookmark to restore it in a subsequent Emacs session.  For this
+;;    you need library `bookmark+.el'.
+;;
+;;
+;;(@* "Izone List Variables")
+;;  ** Izone List Variables **
+;;
+;;  Commands that use izones generally use a variable that holds a
+;;  list of them.  By default, this is the buffer-local variable
+;;  `zz-izones'.  But such a variable can be buffer-local or global.
+;;  If it is global then it can use markers and readable markers for
+;;  different buffers.
+;;
+;;  The value of variable `zz-izones-var' is the variable currently
+;;  being used by default for izone commands.  The default value is
+;;  `zz-izones'.
+;;
+;;  Sometimes a command prompts you for the izones variable to use, if
+;;  you use a prefix argument.  You can have any number of izones
+;;  variables, and their values can be buffer-local or global
+;;  variables.
+;;
+;;  The particular prefix arg determines whether the variable, if not
+;;  yet bound, is made buffer-local, and whether `zz-izones-var' is
+;;  set to the variable symbol:
+;;
+;;   prefix arg         buffer-local   set `zz-izones-var'
+;;   ----------         ------------   -------------------
+;;    Plain `C-u'        yes            yes
+;;    > 0 (e.g. `C-1')   yes            no
+;;    = 0 (e.g. `C-0')   no             yes
+;;    < 0 (e.g. `C--')   no             no
+;;
+;;  For example, `C-u C-x n s' (`zz-izone-add') prompts you for a
+;;  different variable to use, in place of the current value of
+;;  `zz-izones-var'.  The variable you enter is made buffer-local and
+;;  it becomes the new default izones variable for the buffer; that
+;;  is, `zz-izones-var' is set to the variable symbol.
+;;
+;;  As another example, suppose that `zz-izones-var' is `zz-izones',
+;;  the default value and buffer-local by design.  If you then use
+;;  `C-- C-x n s' and enter a variable name at the prompt, that
+;;  variable is not made buffer-local, and `zz-izones-var' is not set
+;;  to that variable.  The active region is pushed to the variable,
+;;  but because `zz-izones-var' is unchanged, a subsequent `C-x n s'
+;;  (no prefix arg) pushes to `zz-izones'.
+;;
+;;
+;;(@* "Keys")
+;;  ** Keys **
+;;
+;;  Most of the commands that manipulate izones are bound on keymap
+;;  `narrow-map'.  They are available on prefix key `C-x n', along
+;;  with the narrowing/widening keys `C-x n d', `C-x n n', `C-x n p',
+;;  and `C-x n w':
+;;
+;;  C-x n C-d `zz-izone-delete' - Delete an izone from current var
+;;  C-x n d   `narrow-to-defun'
+;;  C-x n h   `hlt-highlight-regions' - Highlight izones
+;;  C-x n H   `hlt-highlight-regions-in-buffers' - in multiple buffers
+;;  C-x n n   `narrow-to-region'
+;;  C-x n p   `narrow-to-page'
+;;  C-x n r   `zz-select-region-repeat' - Cycle as active regions
+;;  C-x n s   `zz-izone-add' - Add to current izones variable
+;;  C-x n S   `zz-izone-add-and-coalesce' - Add izone; coalesce izones
+;;  C-x n u   `zz-izones-coalesce' - Coalesce izones
+;;  C-x n w   `widen'
+;;  C-x n x   `zz-narrow-repeat' - Cycle as buffer narrowings
+;;
+;;
+;;(@* "Command `zz-narrow-repeat'")
+;;  ** Command `zz-narrow-repeat' **
+;;
+;;  Library `zones.el' modifies commands `narrow-to-region',
+;;  `narrow-to-defun', and `narrow-to-page' (`C-x n n', `C-x n d',
+;;  and `C-x n p') so that the current buffer restriction
+;;  (narrowing) is added to the izone list the current buffer (by
+;;  default, buffer-local variable `zz-izones').
+;;
+;;  You can then use `C-x n x' to cycle among previous buffer
+;;  narrowings.  Repeating `x' repeats the action: `C-x n x x x x'
+;;  etc.  Each time you hit `x' a different narrowing is made current.
+;;  This gives you an easy way to browse your past narrowings.
+;;
+;;  If the izone variable is not buffer-local then `zz-narrow-repeat'
+;;  can cycle among the narrowings in different buffers, switching the
+;;  buffer accordingly.
+;;
+;;  Invoking `C-x n x' with a prefix argument changes the behavior
+;;  as follows:
+;;
+;;  * A plain prefix arg (`C-u') widens the buffer completely.
+;;
+;;  * A zero numeric prefix arg (e.g `C-0') widens completely and
+;;    resets (empties) the current izone variable.
+;;
+;;  * A numeric prefix arg N takes you directly to the abs(N)th
+;;    previous buffer narrowing.  That is, it widens abs(N) times.
+;;    Positive and negative args work the same, except that a negative
+;;    arg also pops entries off the ring: it removes the ring entries
+;;    from the most recent back through the (-)Nth one.
+;;
+;;  By default, `C-x n x' is bound to command `zz-narrow-repeat'.
+;;  (For Emacs versions prior to 22 it is bound by default to
+;;  `zz-narrow', which is a non-repeatable version.  Repeatability is
+;;  not available before Emacs 22.)
+;;
+;;  The mode-line lighter `Narrow' is still used for the ordinary
+;;  Emacs narrowing commands.  But for `zz-narrow-repeat' (`C-x n x')
+;;  the current narrowing is indicated in the lighter by an
+;;  identifying number: `Narrow-1', `Narrow-2', and so on.  `mouse-2'
+;;  on the `Narrow' part still widens completely, but `mouse-2' on the
+;;  `-NUM' part uses `zz-narrow-repeat' to cycle to the next
+;;  narrowing.
+;;
+;;
+;;(@* "Define Your Own Commands")
+;;  ** Define Your Own Commands **
+;;
+;;  Pretty much anything you can do with the Emacs region you can do
+;;  with a set of zones (i.e., with a non-contiguous "region").  But
+;;  existing Emacs commands that act on the region do not know about
+;;  non-contiguous regions.  What you will need to do is define new
+;;  commands that take these into account.
+;;
+;;  You can define your own commands that iterate over a list of
+;;  izones in a given buffer, or over such lists in a set of buffers.
+;;  Utility functions `zz-izone-limits', `zz-izone-limits-in-bufs',
+;;  and `zz-read-bufs' can help with this.
+;;
+;;  As examples of such commands, if you use library `highlight.el'
+;;  then you can use `C-x n h' (command `hlt-highlight-regions') to
+;;  highlight the izones recorded for the current buffer.  You can use
+;;  `C-x n H' (command `hlt-highlight-regions-in-buffers') to do the
+;;  same across a set of buffers that you specify (or across all
+;;  visible buffers).  If option `hlt-auto-faces-flag' is non-nil then
+;;  each region gets a different face.  Otherwise, all of the regions
+;;  are highlighted with the same face.  Complementary (unbound)
+;;  commands `hlt-unhighlight-regions' and
+;;  `hlt-unhighlight-regions-in-buffers' unhighlight.
+;;
+;;  Defining your own command can be simple or somewhat complex,
+;;  depending on how the region is used in the code for the
+;;  corresponding region-action Emacs command.  The definition of
+;;  `hlt-highlight-regions' just calls existing function
+;;  `hlt-highlight-region' once for each recorded region:
+;;
+;; (defun hlt-highlight-regions (&optional regions face msgp mousep
+;;                                         buffers)
+;;   "Apply `hlt-highlight-region' to regions in `zz-izones'."
+;;   (interactive (list (zz-izone-limits) nil t current-prefix-arg))
+;;   (dolist (start+end  regions)
+;;     (hlt-highlight-region (nth 0 start+end) (nth 1 start+end)
+;;                           face msgp mousep buffers)))
+;;    
+;;  That's it - just iterate over `zz-izones' with a function that
+;;  takes the region as an argument.  What `zones.el' offers in this
+;;  regard is a way to easily define a set of buffer zones.
+ 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; 
+;;
 ;;; Change Log:
 ;;
+;;(@* "Change log")
+;;
+;; 2015/08/16 dadams
+;;     Merged content of wide-n.el here (wide-n.el is obsolete now - this 
replaces it).
+;;     Added: zz-zone-has-other-buffer-marker-p.
+;;     Renamed:
+;;      wide-n                                 to zz-narrow
+;;      wide-n-add-to-union                    to zz-izone-add-and-coalesce
+;;      wide-n-delete                          to zz-izone-delete
+;;      wide-n-highlight-lighter               to zz-narrowing-lighter
+;;      wide-n-lighter-narrow-part             to zz-lighter-narrowing-part
+;;      wide-n-limits                          to zz-izone-limits
+;;      wide-n-limits-in-bufs                  to zz-izone-limits-in-bufs
+;;      wide-n-marker-from-object              to zz-marker-from-object
+;;      wide-n-markerize                       to zz-markerize
+;;      wide-n-mem-regexp                      to zz-regexp-car-member
+;;      wide-n-number-or-marker-p              to zz-number-or-marker-p
+;;      wide-n-other-buffer-marker-p           to 
zz-izone-has-other-buffer-marker-p
+;;      wide-n-push                            to zz-izone-add
+;;      wide-n-push-anyway-p                   to zz-izone-add-anyway-p
+;;      wide-n-rassoc-delete-all               to zz-rassoc-delete-all
+;;      wide-n-readable-marker                 to zz-readable-marker
+;;      wide-n-readable-marker-p               to zz-readable-marker-p
+;;      wide-n-read-any-variable               to zz-read-any-variable
+;;      wide-n-read-bufs                       to zz-read-bufs
+;;      wide-n-remove-if                       to zz-remove-if
+;;      wide-n-remove-if-other-buffer-markers  to 
zz-remove-izones-w-other-buffer-markers
+;;      wide-n-remove-if-not                   to zz-remove-if-not
+;;      wide-n-renumber                        to zz-izones-renumber
+;;      wide-n-repeat                          to zz-narrow-repeat
+;;      wide-n-repeat-command                  to zz-repeat-command
+;;      wide-n-restrictions                    to zz-izones
+;;      wide-n-restrictions-from-zones         to zz-izones-from-zones
+;;      wide-n-restrictions-p                  to zz-izones-p
+;;      wide-n-restrictions-var                to zz-izones-var
+;;      wide-n-select-region                   to zz-select-region
+;;      wide-n-select-region-repeat            to zz-select-region-repeat
+;;      wide-n-string-match-p                  to zz-string-match-p
+;;      wide-n-unite                           to zz-izones-coalesce
+;;      zzz-buffer-of-markers                  to zz-buffer-of-markers
+;;      zzz-car-<                              to zz-car-<
+;;      zzz-every                              to zz-every
+;;      zzz-max                                to zz-max
+;;      zzz-min                                to zz-min
+;;      zzz-ordered-zone                       to zz-zone-ordered
+;;      zzz-remove-if                          to zz-remove-if
+;;      zzz-remove-if-other-buffer-markers     to 
zz-remove-zones-w-other-buffer-markers
+;;      zzz-set-union                          to zz-set-union
+;;      zzz-set-intersection                   to zz-set-intersection
+;;      zzz-some                               to zz-some
+;;      zzz-two-zone-intersection              to zz-two-zone-intersection
+;;      zzz-two-zone-union                     to zz-two-zone-union
+;;      zzz-zone-complement                    to zz-zones-complement
+;;      zzz-zone-intersection(-1)              to zz-zone-intersection(-1)
+;;      zzz-zones-overlap-p                    to zz-zones-overlap-p
+;;      zzz-zones-same-buffer-p                to zz-zones-same-buffer-p
+;;      zzz-zone-union(-1)                     to zz-zone-union(-1)
+;;
+;;     Added Emacs 20 compatibility.
+;;     zz-narrow: If only one narrowing and buffer is narrowed, widen.  (Do 
not widen if already widened.)
+;;                Protect Emacs 20 from wide-n-highlight-lighter call with 
(boundp 'mode-line-modes).
+;;     narrow-to-region: Explicitly provide START and END for Emacs 20, 
because they are nil.
+;;     zz-izone-delete: Fixed free variable vAR (to VARIABLE).
+;;     Bind C-x n r to zz-select-region, not zz-select-region-repeat, if < 
Emacs 22.
+;; 2015/08/15 dadams
+;;     wide-n-delete: VAR -> VARIABLE (typo, free var).
+;;     wide-n-(delete|push): Fixed for 1-based, not 0-based, since removed 
"all" entry on 8/12.
+;;     wide-n-read-any-variable: Added REQUIRE-MATCH arg.  Provide both 
DEFAULT-VALUE and SYMB as defaults.
+;;     wide-n-(delete|push|unite|add-to-union): Provide 
wide-n-restrictions-var as default when reading var.
 ;; 2015/08/14 dadams
-;;     Added: zzz-remove-if, zzz-remove-if-other-buffer-markers.
-;;     zzz-zone-union:
-;;       Added optional arg BUFFER.  Filter with 
zzz-remove-if-other-buffer-markers.
+;;     Added: wide-n-remove-if-other-buffer-markers, wide-n-remove-if, 
wide-n-other-buffer-marker-p.
+;;     Added: zzz-remove-if, zzz-remove-if-other-buffer-markers (in file 
zones.el).
+;;     zzz-zone-union: Added optional arg BUFFER.  Filter with 
zzz-remove-if-other-buffer-markers.
+;;     wide-n-select-region, wide-n: pop-to-buffer of restriction when 
appropriate.
+;;     wide-n-push, wide-n-delete: Added args NOT-BUF-LOCAL-P, SET-VAR-P.  
Changed prefix arg behavior.
+;;     wide-n-add-to-union, narrow-to-(region|defun|page):
+;;       Add nil args for NOT-BUF-LOCAL-P, SET-VAR-P in call to wide-n-push.
+;;     wide-n-restrictions-p: Test identifier with numberp, not 
wide-n-number-or-marker-p.
+;;     wide-n-limits: Added optional args BUFFER, ONLY-ONE-BUFFER-P. Use 
wide-n-remove-if-other-buffer-markers.
+;;     wide-n-limits-in-bufs:
+;;       Changed optional arg from RESTRICTIONS to VARIABLE (default: 
wide-n-restrictions-var).
+;;       Corrected case when BUFFERS is nil.
+;;       Pass buffer and non-nil ONLY-ONE-BUFFER-P to wide-n-limits.
+;; 2015/08/13 dadams
+;;     Version 2014.08.13.
+;;     Added: wide-n-marker-from-object.
+;;     wide-n-markerize: Convert also readable-marker objects.
+;;     wide-n-restrictions-p: Us wide-n-number-or-marker-p, not 
number-or-marker-p (support readable markers).
+;;     wide-n-push, wide-n-add-to-union, interactive spec: VARIABLE defaults 
to wide-n-restrictions-var value.
+;;     wide-n-add-to-union: VARIABLE defaults to wide-n-restrictions-var value 
non-interactively too.
+;; 2015/08/12 dadams
+;;     wide-n-restrictions, wide-n-select-region, wide-n, wide-n-markerize, 
wide-n-push, wide-n-restrictions-p,
+;;       wide-n-delete, wide-n-renumber, wide-n-limits, 
wide-n-restrictions-from-zones, wide-n-unite:
+;;         INCOMPATIBLE CHANGE: wide-n-restrictions no longer has an "all" 
entry.
+;; 2015/08/10 dadams
+;;     wide-n-markerize: Corrected for format change - second marker is caddr, 
not cddr.
 ;; 2015/08/09 dadams
-;;     Added: zzz-zone-complement.
+;;     Added: zzz-zone-complement (in file zones.el).
+;; 2015/08/08 dadams
+;;     Added: wide-n-unite, wide-n-add-to-union, 
wide-n-restrictions-from-zones.
+;;     Bind wide-n-unite to C-x n u and wide-n-add-to-union to C-x n S.
+;;     wide-n-push, wide-n-delete: Return new value of VARIABLE.
+;;     wide-n-push: Change optional arg NOMSG to MSGP (invert the sense).
+;;     Soft-require zones.el.
+;;     Bind hlt-highlight-regions to C-x n h and 
hlt-highlight-regions-in-buffers to C-x n H.
+;; 2015/08/07 dadams
+;;     Added: wide-n-select-region, wide-n-select-region-repeat.
+;;     Bind wide-n-select-region-repeat to C-x n r.
+;;     wide-n-push, wide-n-delete: Prefix arg >= 0: make var buffer-local; <= 
0: set wide-n-restrictions-var.
 ;; 2015/08/05 dadams
+;;     Added: wide-n-restrictions-p, wide-n-restrictions-var, 
wide-n-read-any-variable.
+;;     wide-n-restrictions (function): Now returns the value of the current 
wide-n-restrictions-var variable.
+;;     wide-n: Use wide-n-restrictions-var, not wide-n-restrictions.
+;;     wide-n-push, wide-n-delete:
+;;       Added optional arg VARIABLE.  Prefix arg reads it.  Use it and maybe 
set wide-n-restrictions-var to it.
+;;       Raise error if var is not wide-n-restrictions-p.
+;;     wide-n-renumber: Added optional arg VARIABLE.
+;;     wide-n-limits(-in-bufs): Added optional arg RESTRICTIONS.
+;;     wide-n, wide-n-renumber, wide-n-markerize: FIX: (car (cddr...)), not 
cddr.
+;; 2015/08/01 dadams
+;;     wide-n-start+end: Fix: use list, not cons.
+;; 2015/07/31 dadams
+;;     Renamed: wide-n-start.end to wide-n-start+end.  Added: function 
wide-n-restrictions.
+;;     wide-n-restrictions: INCOMPATIBLE CHANGE: The format is now (NUM START 
END), not (NUM START . END).
+;; 2015/07/11 dadams
+;;     Added: wide-n-limits, wide-n-limits-in-bufs, wide-n-start.end, 
wide-n-read-bufs, wide-n-remove-if-not.
+;;     Made wide-n-push interactive.
+;;     Bind wide-n-delete to C-x n C-d and wide-n-push to C-x n s.
+;; 2014/08/12 dadams
+;;     Added: wide-n-delete, wide-n-renumber.
+;;     wide-n: Added optional arg MSGP.
+;;     wide-n-push: Added optional arg NOMSG.
+;; 2014/05/30 dadams
+;;     Added: wide-n-lighter-narrow-part, wide-n-highlight-lighter, 
wide-n-string-match-p, wide-n-mem-regexp,
+;;            wide-n-rassoc-delete-all.
+;;     wide-n-restrictions: INCOMPATIBLE CHANGE: The format is now (NUM START 
. END), not (START . END).
+;;     wide-n: Set wide-n-lighter-narrow-part.  Use wide-n-highlight-lighter.  
Bind wide-n-push-anyway-p
+;;             around narrow-to-region.
+;;     wide-n-markerize, wide-n-push: Use new wide-n-restrictions format.
+;;     wide-n-push: Added message about restriction.
+;; 2011/04/09 dadams
+;;     narrow-to-region defadvice:
+;;       Use ad-get-arg - don't refer to args by name (work around Emacs bug 
#8457).
+;; 2011/01/04 dadams
+;;     Added autoload cookies (for commands).
+;; 2010/04/26 dadams
+;;     Added: wide-n-push, wide-n-push-anyway-p.
+;;     narrow-to-*: Call wide-n-push when interactive or wide-n-push-anyway-p.
+;; 2010/04/24 dadams
+;;     Added: wide-n-markerize.
+;;     Use non-destructive operations (again, as initially).
+;;       wide-n-restrictions: Use (all) cons as init value.
+;;       wide-n, narrow-to-region: Don't initialize to (all).
+;;       wide-n: Use append, not nconc.
+;;       narrow-to-region: Use remove, not delete.
+;;     wide-n: Use wide-n-markerize.
+;; 2010/04/21 dadams
+;;     Bind non-repeatable version, wide-n, in Emacs 21.
+;; 2010/04/19 dadams
+;;     wide-n, narrow-to-region, wide-n-restrictions:
+;;       Use nil default val & use make-local-variable, so can use destructive 
ops.
+;;     narrow-to-region: Use delete, not remove.
+;;     Zero prefix arg now widens completely and empties ring.
+;;     Negative prefix arg now pops the ring.
+;;     Added: standard definitions of narrow-to-(defun|page).
+;;     Use narrow-map if defined.
+;; 2010/04/18 dadams
 ;;     Created.
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; 
+;;
 ;; This program is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation, either version 3 of the License, or (at
 ;; your option) any later version.
-;; 
+;;
 ;; This program is distributed in the hope that it will be useful, but
 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ;; General Public License for more details.
-;; 
+;;
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
-;; 
+;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; 
+;;
 ;;; Code:
 
+;; Quiet the byte-compiler.
+(defvar mode-line-modes)                ; Emacs 22+
+(defvar narrow-map)                     ; Emacs 23+
 
-;;;;;;;;;;;;;;;;;;;;;;
-
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+ 
 (defgroup zones nil
   "Zones of text - like multiple regions."
-  :prefix "zzz-"
+  :prefix "zz-"
   :group 'editing
   :link `(url-link :tag "Send Bug Report"
                    ,(concat "mailto:"; "drew.adams" "@" "oracle" ".com?subject=\
@@ -107,7 +578,45 @@ Don't forget to mention your Emacs and library versions."))
   :link '(url-link :tag "Description" "http://www.emacswiki.org/Zones";)
   :link '(emacs-commentary-link :tag "Commentary" "zones"))
 
-(defun zzz-ordered-zone (zone)
+(defvar zz-lighter-narrowing-part ""
+  "String to append to \" Narrow\" in mode-line lighter.")
+(make-variable-buffer-local 'zz-lighter-narrowing-part)
+
+(defvar zz-izones-var 'zz-izones
+  "The izones variable currently being used.
+The variable can be buffer-local or not.  If not, then its value can
+include markers from multiple buffers.")
+
+(defvar zz-izones ()
+  "List of izones.
+Each entry is a list (NUM START END), where NUM is a counter
+identifying this izone, and START and END are its limits.")
+(make-variable-buffer-local 'zz-izones)
+
+;; Not used.  Could use this if really needed.
+(defun zz-izones ()
+  "Value of current `zz-izones-var' variable, in latest format.
+If the value has elements of old format, (NUM START . END), it is
+converted to use the new format, with elements (NUM START END).
+
+This is a destructive operation.  The value of the variable is updated
+to use the new format, and that value is returned."
+  (let ((oldval  (symbol-value zz-izones-var))
+        (newval  ()))
+    (dolist (elt  oldval) (unless (consp (cddr elt)) (setcdr (cdr elt) (list 
(cddr elt)))))
+    (symbol-value zz-izones-var)))
+
+(defvar zz-izone-add-anyway-p nil
+  "Non-nil means narrowing always updates current `zz-izones-var'.
+Normally, if a narrowing command is called non-interactively then the
+region limits are not pushed to the variable that is the current value
+of `zz-izones-var'.  A non-nil value here overrides the push
+inhibition.  You can bind this to non-nil in Lisp code to populate the
+current `zz-izones-var' during narrowing.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun zz-zone-ordered (zone)
   "Return ZONE or ZONE with its car and cadr reversed, so car <= cadr.
 The cddr of ZONE remains as it was."
   (let ((beg    (car  zone))
@@ -115,33 +624,29 @@ The cddr of ZONE remains as it was."
         (extra  (cddr zone)))
     (if (<= beg end) zone `(,end ,beg ,@extra))))
 
-(defun zzz-zones-overlap-p (zone1 zone2)
+(defun zz-zones-overlap-p (zone1 zone2)
   "Return non-nil if ZONE1 and  ZONE2 overlap.
 Assumes that each zone is ordered (its car <= its cadr).
 The cddrs are ignored.
 
 Zones that use markers do not overlap if the marker buffers differ."
-  (and (zzz-zones-same-buffer-p zone1 zone2)
-       (progn (when (< (car zone2) (car zone1))
-                (setq zone1 (prog1 zone2 (setq zone2 zone1))))
+  (and (zz-zones-same-buffer-p zone1 zone2)
+       (progn (when (< (car zone2) (car zone1)) (setq zone1 (prog1 zone2 (setq 
zone2 zone1))))
               (<= (car zone2) (cadr zone1)))))
 
-(defun zzz-zones-same-buffer-p (zone1 zone2)
+(defun zz-zones-same-buffer-p (zone1 zone2)
   "Return non-nil if ZONE1 and ZONE2 apply to the same buffer.
 This is the case if they do not contain markers or the markers are
 from the same buffer."
   (let* ((car1   (car zone1))
          (cadr1  (cadr zone1))
-         (mkr1   (or (and (markerp car1)   car1)
-                     (and (markerp cadr1)  cadr1)))
+         (mkr1   (or (and (markerp car1)   car1)  (and (markerp cadr1)  
cadr1)))
          (car2   (car zone2))
          (cadr2  (cadr zone2))
-         (mkr2   (or (and (markerp car2)   car2)
-                     (and (markerp cadr2)  cadr2))))
-    (or (not (and mkr1  mkr2))
-        (eq (marker-buffer mkr1) (marker-buffer mkr2)))))
+         (mkr2   (or (and (markerp car2)   car2)  (and (markerp cadr2)  
cadr2))))
+    (or (not (and mkr1  mkr2))  (eq (marker-buffer mkr1) (marker-buffer 
mkr2)))))
 
-(defun zzz-zone-complement (zones &optional beg end)
+(defun zz-zones-complement (zones &optional beg end)
   "Return a list of zones that is the complement of ZONES, from BEG to END.
 ZONES is assumed to be a union, i.e., sorted by car, with no overlaps.
 Any extra info in a zone of ZONES, i.e., after the cadr, is ignored."
@@ -153,25 +658,24 @@ Any extra info in a zone of ZONES, i.e., after the cadr, 
is ignored."
       (setq beg  (cadr zone)))
     (setq res  (nreverse (push (list beg end) res)))))
 
-(defun zzz-two-zone-union (zone1 zone2)
+(defun zz-two-zone-union (zone1 zone2)
   "Return the union of ZONE1 and ZONE2, or nil if they do not overlap.
 Assumes that each zone is ordered (its car <= its cadr).
 
 The cddr of a non-nil result (its EXTRA information, which must be a
 list) is the union of the EXTRA information of each zone:
 
- (zzz-set-union (cddr zone1) (cddr zone2))
+ (zz-set-union (cddr zone1) (cddr zone2))
 
 This is a non-destructive operation: The result is a new list."
-  (and (zzz-zones-overlap-p zone1 zone2)
-       `(,(zzz-min (car zone1)  (car zone2))
-         ,(zzz-max (cadr zone1) (cadr zone2))
-         ,@(zzz-set-union (cddr zone1) (cddr zone2)))))
+  (and (zz-zones-overlap-p zone1 zone2)  `(,(zz-min (car zone1)  (car zone2))
+                                            ,(zz-max (cadr zone1) (cadr zone2))
+                                            ,@(zz-set-union (cddr zone1) (cddr 
zone2)))))
 
-(defun zzz-zone-union (zones &optional buffer)
-  "Return the union of the zones in list ZONES.
+(defun zz-zone-union (zones &optional buffer)
+  "Return the union (coalescence) of the zones in list ZONES.
 Each element of ZONES is a list of two zone limits, possibly followed
-by entra info: (LIMIT1 LIMIT2 . EXTRA), where EXTRA is a list.
+by extra info: (LIMIT1 LIMIT2 . EXTRA), where EXTRA is a list.
 
 The limits do not need to be in numerical order.
 
@@ -184,24 +688,24 @@ which is its car.  (This is a non-destructive operation.)
 Each zone in ZONES is first ordered, so that its car <= its cadr.
 The resulting zones are then sorted by their cars.
 
-`zzz-two-zone-union' is then applied recursively to combine
-overlapping zones.  This means also that any EXTRA info is combined
-when zones are merged together."
-  (let* ((filtered-zones  (zzz-remove-if-other-buffer-markers zones))
-         (flipped-zones   (mapcar #'zzz-ordered-zone filtered-zones))
-         (sorted-zones    (sort flipped-zones #'zzz-car-<)))
-    (zzz-zone-union-1 sorted-zones)))
+`zz-two-zone-union' is then applied recursively to coalesce
+overlapping or adjacent zones.  This means also that any EXTRA info is
+combined whenever zones are merged together."
+  (let* ((filtered-zones  (zz-remove-zones-w-other-buffer-markers zones))
+         (flipped-zones   (mapcar #'zz-zone-ordered filtered-zones))
+         (sorted-zones    (sort flipped-zones #'zz-car-<)))
+    (zz-zone-union-1 sorted-zones)))
 
-(defun zzz-zone-union-1 (zones)
-  "Helper for `zzz-zone-union'."
+(defun zz-zone-union-1 (zones)
+  "Helper for `zz-zone-union'."
   (if (null (cdr zones))
       zones
-    (let ((new  (zzz-two-zone-union (car zones) (cadr zones))))
+    (let ((new  (zz-two-zone-union (car zones) (cadr zones))))
       (if new
-          (zzz-zone-union-1 (cons new (cddr zones)))
-        (cons (car zones) (zzz-zone-union-1 (cdr zones)))))))
+          (zz-zone-union-1 (cons new (cddr zones)))
+        (cons (car zones) (zz-zone-union-1 (cdr zones)))))))
 
-(defun zzz-car-< (zone1 zone2)
+(defun zz-car-< (zone1 zone2)
   "Return non-nil if car of ZONE1 < car of ZONE2.
 Each car can be a number or a marker.
 
@@ -218,13 +722,13 @@ Each car can be a number or a marker.
          (b1  (and m1  (marker-buffer p1)))
          (b2  (and m2  (marker-buffer p2))))
     (cond ((and (not m1)  (not m2)) (< p1 p2))
-          ((and m1  m2) (if (eq b1 b2)
-                            (< p1 p2)
-                          (string< (buffer-name b1) (buffer-name b2))))
-          (m1 (and (eq (current-buffer) b1)  (< p1 p2)))
-          (m2 (or (not (eq (current-buffer) b2))  (< p1 p2))))))
+          ((and m1  m2)   (if (eq b1 b2)
+                              (< p1 p2)
+                            (string< (buffer-name b1) (buffer-name b2))))
+          (m1             (and (eq (current-buffer) b1)  (< p1 p2)))
+          (m2             (or (not (eq (current-buffer) b2))  (< p1 p2))))))
 
-(defun zzz-two-zone-intersection (zone1 zone2)
+(defun zz-two-zone-intersection (zone1 zone2)
   "Return intersection of ZONE1 and ZONE2.
 \(The result is nil if they do not overlap.)
 Assumes that each zone is ordered (its car <= its cadr).
@@ -232,18 +736,17 @@ Assumes that each zone is ordered (its car <= its cadr).
 The cddr of a non-nil result (its EXTRA information) is
 the intersection of the EXTRA information of each zone:
 
- (zzz-set-intersection (cddr zone1) (cddr zone2))
+ (zz-set-intersection (cddr zone1) (cddr zone2))
 
 This is a non-destructive operation: The result is a new list."
-  (and (zzz-zones-overlap-p zone1 zone2)
-       `(,(zzz-max (car zone1)  (car zone2))
-         ,(zzz-min (cadr zone1) (cadr zone2))
-         ,@(zzz-set-intersection (cddr zone1) (cddr zone2)))))
+  (and (zz-zones-overlap-p zone1 zone2)  `(,(zz-max (car zone1)  (car zone2))
+                                            ,(zz-min (cadr zone1) (cadr zone2))
+                                            ,@(zz-set-intersection (cddr 
zone1) (cddr zone2)))))
 
-(defun zzz-zone-intersection (zones)
+(defun zz-zone-intersection (zones)
   "Return the intersection of the zones in list ZONES.
 Each element of ZONES is a list of two zone limits, possibly followed
-by entra info: (LIMIT1 LIMIT2 . EXTRA), where EXTRA is a list.
+by extra info: (LIMIT1 LIMIT2 . EXTRA), where EXTRA is a list.
 
 The limits do not need to be in numerical order.
 
@@ -253,22 +756,22 @@ which is its car.  (This is a non-destructive operation.)
 Each zone in ZONES is first ordered, so that its car <= its cadr.
 The resulting zones are then sorted by their cars.
 
-`zzz-two-zone-intersection' is then applied recursively to combine
+`zz-two-zone-intersection' is then applied recursively to combine
 overlapping zones.  This means also that any EXTRA info is combined
 when zones are merged together."
-  (let* ((flipped-zones  (mapcar #'zzz-ordered-zone zones))
+  (let* ((flipped-zones  (mapcar #'zz-zone-ordered zones))
          (sorted-zones   (sort flipped-zones (lambda (z1 z2) (< (car z1) (car 
z2))))))
-    (zzz-zone-intersection-1 sorted-zones)))
+    (zz-zone-intersection-1 sorted-zones)))
 
-(defun zzz-zone-intersection-1 (zones)
-  "Helper for `zzz-zone-intersection'."
+(defun zz-zone-intersection-1 (zones)
+  "Helper for `zz-zone-intersection'."
   (if (null (cdr zones))
       zones
-    (let ((new  (zzz-two-zone-intersection (car zones) (cadr zones))))
-      (and new  (zzz-zone-intersection-1 (cons new (cddr zones)))))))
+    (let ((new  (zz-two-zone-intersection (car zones) (cadr zones))))
+      (and new  (zz-zone-intersection-1 (cons new (cddr zones)))))))
 
 ;; From `cl-seq.el', function `union', without keyword treatment.
-(defun zzz-set-union (list1 list2)
+(defun zz-set-union (list1 list2)
   "Combine LIST1 and LIST2 using a set-union operation.
 The result list contains all items that appear in either LIST1 or
 LIST2.  This is a non-destructive function: it copies the data if
@@ -277,66 +780,59 @@ necessary."
         ((null list2)         list1)
         ((equal list1 list2)  list1)
         (t
-         (unless (>= (length list1) (length list2))
-           (setq list1  (prog1 list2 (setq list2  list1)))) ; Swap them.
+         (unless (>= (length list1) (length list2)) (setq list1  (prog1 list2 
(setq list2  list1)))) ; Swap.
          (while list2
-           (unless (member (car list2) list1)  (setq list1  (cons (car list2) 
list1)))
+           (unless (member (car list2) list1) (setq list1  (cons (car list2) 
list1)))
            (setq list2  (cdr list2)))
          list1)))
 
 ;; From `cl-seq.el', function `intersection', without keyword treatment.
-(defun zzz-set-intersection (list1 list2)
+(defun zz-set-intersection (list1 list2)
   "Set intersection of lists LIST1 and LIST2.
 This is a non-destructive operation: it copies the data if necessary."
   (and list1  list2
        (if (equal list1 list2)
            list1
          (let ((result  ()))
-           (unless (>= (length list1) (length list2))
-             (setq list1  (prog1 list2 (setq list2  list1)))) ; Swap them.
+           (unless (>= (length list1) (length list2)) (setq list1  (prog1 
list2 (setq list2  list1)))) ; Swap.
            (while list2
-             (when (member (car list2) list1)
-               (setq result  (cons (car list2) result)))
+             (when (member (car list2) list1) (setq result  (cons (car list2) 
result)))
              (setq list2  (cdr list2)))
            result))))
 
-(defun zzz-min (&rest ns)
+(defun zz-min (&rest ns)
   "Like `min', but if the args include a marker then return a marker.
 Raise an error if the args include markers from different buffers."
-  (let ((buf  (zzz-buffer-of-markers ns))
+  (let ((buf  (zz-buffer-of-markers ns))
         (min  (apply #'min ns)))
     (if (not buf)
         min
       (with-current-buffer (get-buffer-create buf)
         (set-marker (copy-marker min) min buf)))))
 
-(defun zzz-max (&rest ns)
+(defun zz-max (&rest ns)
   "Like `max', but if the args include a marker then return a marker.
 Raise an error if the args include markers from different buffers."
-  (let ((buf  (zzz-buffer-of-markers ns))
+  (let ((buf  (zz-buffer-of-markers ns))
         (max  (apply #'max ns)))
     (if (not buf)
         max
-      (with-current-buffer (get-buffer-create buf)
-        (set-marker (copy-marker max) max buf)))))
+      (with-current-buffer (get-buffer-create buf) (set-marker (copy-marker 
max) max buf)))))
 
-(defun zzz-buffer-of-markers (ns)
+(defun zz-buffer-of-markers (ns)
   "Return the buffer of the markers in list NS, or nil if no markers.
 Raise an error if NS contains markers from different buffers."
-  (let ((mkr  (zzz-some #'markerp ns)))
+  (let ((mkr  (zz-some #'markerp ns)))
     (and mkr
          (progn
-           (unless (zzz-every (lambda (nn)
-                                (or (not (markerp nn))
-                                    (eq (marker-buffer nn) (marker-buffer 
mkr))))
-                              ns)
+           (unless (zz-every (lambda (nn) (or (not (markerp nn)) (eq 
(marker-buffer nn) (marker-buffer mkr)))) ns)
              (error "List contains markers from different buffers"))
            t)
          (marker-buffer mkr))))
 
 ;; Similar to `every' in `cl-extra.el', without non-list sequences and multiple
 ;; sequences.
-(defun zzz-every (predicate list)
+(defun zz-every (predicate list)
   "Return t if PREDICATE is true for all elements of LIST; else nil."
   (while (and list  (funcall predicate (car list)))  (setq list  (cdr list)))
   (null list))
@@ -344,36 +840,755 @@ Raise an error if NS contains markers from different 
buffers."
 ;; Same as `bmkp-some' in `bookmark+-1.el'.
 ;; Similar to `some' in `cl-extra.el', without non-list sequences and multiple
 ;; sequences.
-(defun zzz-some (predicate list)
+(defun zz-some (predicate list)
   "Return non-nil if PREDICATE is true for some element of LIST; else nil.
 Return the first non-nil value returned by PREDICATE."
   (let (res)
-    (catch 'zzz-some
-      (while list
-        (when (funcall predicate (setq res  (pop list))) (throw 'zzz-some 
res)))
+    (catch 'zz-some
+      (while list (when (funcall predicate (setq res  (pop list))) (throw 
'zz-some res)))
       (setq res  nil))
     res))
 
-(defun zzz-remove-if-other-buffer-markers (zones &optional buffer)
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;###autoload
+(defun zz-select-region (arg &optional msgp)
+  "Select a region from among the current set of izones.
+The izones are those in the current `zz-izones-var'.
+With no prefix arg, select the previous recorded izone.
+With a numeric prefix arg N, select the Nth previous izone.
+
+Note that if the value of `zz-izones-var' is not buffer-local then you
+can use this command to cycle among regions in multiple buffers."
+  (interactive "p\np")
+  (let* ((var   zz-izones-var)
+         (val   (symbol-value var))
+         (cntr  (abs arg)))
+    (unless (cadr val) (error "No region to select"))
+    (let ((latest  ()))
+      (while (> cntr 0)
+        (push (nth (1- cntr) val) latest)
+        (setq cntr  (1- cntr)))
+      (setq latest  (nreverse latest))
+      (setq val  (set var (append (nthcdr arg val) latest))
+            val  (set var (mapcar #'zz-markerize val)))
+      (let* ((zz-izone-add-anyway-p  t)
+             (izone                  (car val))
+             (beg                    (nth 1 izone))
+             (end                    (nth 2 izone))
+             (other-buf              nil))
+        (when (and (not (local-variable-p var))
+                   (setq other-buf  (zz-izone-has-other-buffer-marker-p 
izone)) ; Returns marker or nil.
+                   (or (not (markerp beg))  (not (markerp end))  (eq 
(marker-buffer beg) (marker-buffer end)))
+                   (setq other-buf  (marker-buffer other-buf)))
+          (pop-to-buffer other-buf))
+        (goto-char beg)
+        (push-mark end nil t)
+        (when msgp
+          (message "Region #%d restored%s" (caar val) (if other-buf (format " 
in `%s'" other-buf) "")))))))
+
+;; This is a non-destructive operation.
+;;
+;;;###autoload
+(defun zz-narrow (arg &optional msgp)
+  "Widen to a previous buffer restriction (narrowing).
+The candidates are the izones in the current `zz-izones-var'.
+
+With no prefix arg, widen to the previous narrowing.
+With a plain prefix arg (`C-u'), widen completely.
+With a zero  prefix arg (`C-0'), widen completely and reset (empty)
+ the list of izones for this buffer.
+With a numeric prefix arg N, widen abs(N) times (to the abs(N)th
+ previous narrowing).  Positive and negative args work the same,
+ except that a negative arg also pops entries off the ring: it removes
+ the ring entries from the most recent back through the (-)Nth one."
+  (interactive "P\np")
+  (let* ((var  zz-izones-var)
+         (val  (symbol-value var)))
+    (unless val (error "No previous narrowing"))
+    (cond ((or (consp arg)  (and (null (cdr val))
+                                 (/= (- (point-max) (point-min)) 
(buffer-size)))) ; = `buffer-narrowed-p'.
+           (widen)
+           (when (boundp 'mode-line-modes)
+             (setq zz-lighter-narrowing-part  "")
+             (zz-narrowing-lighter))
+           (when msgp (message "No longer narrowed")))
+          ((= (prefix-numeric-value arg) 0)
+           (set var ())
+           (widen)
+           (when (boundp 'mode-line-modes)
+             (setq zz-lighter-narrowing-part  "")
+             (zz-narrowing-lighter))
+           (when msgp (message "No longer narrowed; no more narrowings")))
+          (t
+           (setq arg  (prefix-numeric-value arg))
+           (let ((latest  ())
+                 (cntr    (abs arg)))
+             (while (> cntr 0)
+               (push (nth (1- cntr) val) latest)
+               (setq cntr  (1- cntr)))
+             (setq latest  (nreverse latest))
+             (when (< arg 0) (setq arg     (abs arg)
+                                   latest  ()))
+             (setq val                         (set var (append (nthcdr arg 
val) latest))
+                   val                         (set var (mapcar #'zz-markerize 
val))
+                   zz-lighter-narrowing-part  (format "-%d" (caar val)))
+             (condition-case err
+                 (let* ((zz-izone-add-anyway-p  t)
+                        (izone                  (car val))
+                        (beg                    (nth 1 izone))
+                        (end                    (nth 2 izone))
+                        (other-buf              nil))
+                   (when (and (not (local-variable-p var))
+                              (setq other-buf  
(zz-izone-has-other-buffer-marker-p izone)) ; Marker or nil.
+                              (or (not (markerp beg))  (not (markerp end))
+                                  (eq (marker-buffer beg) (marker-buffer 
end))) ; Same other buffer.
+                              (setq other-buf  (marker-buffer other-buf)))
+                     (pop-to-buffer other-buf))
+                   (narrow-to-region beg end)
+                   (when (boundp 'mode-line-modes) (zz-narrowing-lighter)))
+               (args-out-of-range (set var  (cdr val))
+                                  (error "Restriction removed because of 
invalid limits"))
+               (error (error "%s" (error-message-string err)))))))))
+
+(defun zz-narrowing-lighter ()
+  "Update minor-mode mode-line lighter to reflect narrowing/widening.
+Put `zz-narrow' on `mouse-2' for the lighter suffix."
+  (let* ((%n-cons  (zz-regexp-car-member "%n\\(.*\\)\\'" mode-line-modes)))
+    (when %n-cons
+      (setcar %n-cons (replace-regexp-in-string
+                       "%n\\(.*\\)"
+                       (if (/= (- (point-max) (point-min)) (buffer-size)) ; 
`buffer-narrowed-p', for older Emacs
+                           zz-lighter-narrowing-part
+                         "")
+                       (car %n-cons) nil nil 1))
+      (when (> (length (car %n-cons)) 2)
+        (set-text-properties 2
+                             (length (car %n-cons))
+                             '(local-map (keymap (mode-line keymap (mouse-2 . 
zz-narrow)))
+                               mouse-face mode-line-highlight
+                               help-echo "mouse-2: Next Restriction")
+                             (car %n-cons)))
+      ;; Dunno why we need to do this.  Tried adjusting `rear-sticky' and 
`front-sticky',
+      ;; but without this the whole field (not just the suffix) gets changed, 
in effect, to the above spec.
+      (set-text-properties 0 2 '(local-map (keymap (mode-line keymap (mouse-2 
. mode-line-widen)))
+                                 mouse-face mode-line-highlight help-echo 
"mouse-2: Widen")
+                           (car %n-cons)))))
+
+(defun zz-regexp-car-member (regexp xs)
+  "Like `member', but tests by matching REGEXP against cars."
+  (and (consp xs)  (if (and (stringp (car xs))  (zz-string-match-p regexp (car 
xs)))
+                       xs
+                     (zz-regexp-car-member regexp (cdr xs)))))
+
+;;;###autoload
+(defun zz-izone-add (start end &optional variable not-buf-local-p set-var-p 
msgp) ; Bound to `C-x n s'.
+  "Add an izone for the text from START to END to the izones of VARIABLE.
+Return the new value of VARIABLE.
+
+This is a destructive operation: The list structure of the variable
+value can be modified.
+
+VARIABLE defaults to the value of `zz-izones-var'.
+START and END are as for `narrow-to-region'.
+
+With a prefix arg you are prompted for a different variable to use, in
+place of the current value of `zz-izones-var'.  The particular prefix
+arg determines whether the variable, if unbound, is made buffer-local,
+and whether `zz-izones-var' is set to the variable symbol:
+
+  prefix arg          buffer-local   set `zz-izones-var'
+  ----------          ------------   -------------------
+   Plain `C-u'         yes            yes
+   > 0 (e.g. `C-1')    yes            no
+   = 0 (e.g. `C-0')    no             yes
+   < 0 (e.g. `C--')    no             no
+
+Non-interactively:
+* VARIABLE is the optional izones variable to use.
+* Non-nil NOT-BUF-LOCAL-P means do not make VARIABLE buffer-local.
+* Non-nil SET-VAR-P means set `zz-izones-var' to VARIABLE.
+* Non-nil MSGP means echo the region size."
+  (interactive (let* ((beg    (region-beginning))
+                      (end    (region-end))
+                      (var    (or (and current-prefix-arg  
(zz-read-any-variable "Variable: " zz-izones-var))
+                                  zz-izones-var))
+                      (npref  (prefix-numeric-value current-prefix-arg))
+                      (nloc   (and current-prefix-arg  (<= npref 0)  (not 
(boundp var))))
+                      (setv   (and current-prefix-arg  (or (consp 
current-prefix-arg)  (= npref 0)))))
+                 (list beg end var nloc setv t)))
+  (let* ((mrk1    (make-marker))
+         (mrk2    (make-marker))
+         (var     (or variable  zz-izones-var))
+         (IGNORE  (unless (or not-buf-local-p  (boundp var)) 
(make-local-variable var)))
+         (IGNORE  (when set-var-p (setq zz-izones-var  var)))
+         (IGNORE  (unless (boundp var) (set var ())))
+         (val     (symbol-value var))
+         sans-id  id-cons  id)
+    (unless (zz-izones-p val) (error "Not an izones variable: `%s', value: 
`%S'" var val))
+    (move-marker mrk1 start)
+    (move-marker mrk2 end)
+    (setq sans-id  (list mrk1 mrk2)
+          id-cons  (rassoc sans-id val)
+          id       (if id-cons (car id-cons) (1+ (length val))) ; 1-based, not 
0-based.
+          val      (set var (zz-rassoc-delete-all sans-id val))) ; Destructive 
operation.
+    (unless (and (= mrk1 1)  (= mrk2 (1+ (buffer-size)))) (set var `((,id 
,mrk1 ,mrk2) ,@val)))
+    (when msgp (message "%s region: %d to %d" (if (interactive-p) "Recorded" 
"Narrowed")
+                        (marker-position mrk1) (marker-position mrk2)))
+    (symbol-value var)))
+
+;;;###autoload
+(defun zz-izone-delete (n &optional variable not-buf-local-p set-var-p msgp) ; 
Bound to `C-x n C-d'.
+  "Delete the izone numbered N from VARIABLE, and renumber those remaining.
+Return the new value of VARIABLE.
+
+This is a destructive operation: The list structure of the variable
+value can be modified.
+
+You are prompted for the number N.
+VARIABLE defaults to the value of `zz-izones-var'.
+
+With a prefix arg you are prompted for a different variable to use, in
+place of the current value of `zz-izones-var'.  The
+particular prefix arg determines whether the variable, if unbound, is
+made buffer-local, and whether `zz-izones-var' is set to the
+variable symbol:
+
+  prefix arg          buffer-local   set `zz-izones-var'
+  ----------          ------------   -------------------
+   Plain `C-u'         yes            yes
+   > 0 (e.g. `C-1')    yes            no
+   = 0 (e.g. `C-0')    no             yes
+   < 0 (e.g. `C--')    no             no
+
+Non-nil optional arg NOMSG means do not display a status message."
+  (interactive
+   (let* ((var     (or (and current-prefix-arg  (zz-read-any-variable 
"Variable: " zz-izones-var))
+                       zz-izones-var))
+          (npref   (prefix-numeric-value current-prefix-arg))
+          (nloc    (and current-prefix-arg  (<= npref 0)  (not (boundp var))))
+          (setv    (and current-prefix-arg  (or (consp current-prefix-arg)  (= 
npref 0))))
+          ;; Repeat all of the variable tests and actions, since we need to 
have the value, for its length.
+          (IGNORE  (unless nloc (make-local-variable var)))
+          (IGNORE  (when setv (setq zz-izones-var var)))
+          (IGNORE  (unless (boundp var) (set var ())))
+          (val     (symbol-value var))
+          (IGNORE  (unless (zz-izones-p val)
+                     (error "Not an izones variable: `%s', value: `%S'" var 
val)))
+          (IGNORE  (unless val (error "No izones - variable `%s' is empty" 
var)))
+          (len     (length val))
+          (num     (if (= len 1) 1 (read-number (format "Delete izone number 
(1 to %d): " len)))))
+     (while (or (< num 1)  (> num len))
+       (setq num  (read-number (format "Number must be between 1 and %d: " 
len))))
+     (list num var nloc setv t)))
+  (unless variable (setq variable  zz-izones-var))
+  (unless (or not-buf-local-p  (boundp variable)) (make-local-variable 
variable))
+  (when set-var-p (setq zz-izones-var variable))
+  (let ((val  (symbol-value variable)))
+    (unless (zz-izones-p val) (error "Not an izones variable: `%s', value: 
`%S'" variable val))
+    (unless val (error "No izones - variable `%s' is empty" variable))
+    (set variable (assq-delete-all n val)))
+  (zz-izones-renumber variable)
+  (when msgp (message "Deleted izone number %d" n))
+  (symbol-value variable))
+
+(defun zz-markerize (izone)
+  "Convert IZONE to use markers.
+IZONE is a list of an identifier (a number) and two buffer
+positions (numbers, markers, or readable-marker objects).  Positions
+that are numbers or readable-marker objects are converted to markers.
+
+This is a non-destructive operation: it returns a new list."
+  (let ((ii   1)
+        buf posn)
+    (while (<  ii 3)
+      (setq posn  (nth ii izone))
+      (when (and (not (markerp posn))  (or (numberp posn)  
(zz-readable-marker-p posn)))
+        (setcar (nthcdr ii  izone) (zz-marker-from-object posn)))
+      (setq ii  (1+ ii))))
+  izone)
+
+(defun zz-marker-from-object (object &optional buffer)
+  "Return equivalent marker for OBJECT.
+This is a non-destructive operation: OBJECT is not modified.
+
+If OBJECT is a marker then return it.
+If it is a number then return (copy-marker OBJECT).
+If it is a readable-marker sexp then return an equivalent real marker.
+Otherwise, return nil.
+
+A readable marker is a sexp of form (marker BUFFER POSITION), where
+BUFFER is a buffer name (string) and POSITION is buffer
+position (number)."
+  (cond ((markerp object) object)
+        ((numberp object) (copy-marker object))
+        ((zz-readable-marker-p object)
+         (with-current-buffer (get-buffer-create (nth 1 object)) (copy-marker 
(nth 2 object))))
+        (t nil)))
+
+(defun zz-number-or-marker-p (position)
+  "Return non-nil if POSITION is a number, marker, or readable-marker object."
+  (or (number-or-marker-p position)  (zz-readable-marker-p position)))
+
+(defun zz-readable-marker-p (object)
+  "Return non-nil if OBJECT is a readable marker.
+That is, it has form (marker BUFFER POSITION), where BUFFER is a
+buffer name (string) and POSITION is a buffer position (number).
+OBJECT is returned."
+  (and (consp object)  (consp (cdr object))  (consp (cddr object))
+       (eq 'marker (nth 0 object))  (stringp (nth 1 object))  (numberp (nth 2 
object))
+       object))
+
+(defun zz-readable-marker (number-or-marker &optional buffer)
+  "Return a readable-marker object equivalent to NUMBER-OR-MARKER, or nil.
+Return nil if NUMBER-OR-MARKER is not `number-or-marker-p'.
+
+This is a non-destructive operation.
+
+Optional arg BUFFER is a buffer or a buffer name (default: name of
+current buffer).  It is used as the marker buffer when
+`number-or-marker-p' is a number.
+
+A readable-marker object is a sexp of form (marker BUFFER POSITION),
+where BUFFER is a buffer name (string) and POSITION is buffer
+position (number)."
+  (let* ((buf   (get-buffer (or buffer  (current-buffer))))
+         (buf   (and buf  (buffer-name buf)))
+         (mrkr  (and (number-or-marker-p number-or-marker)
+                     (if (markerp number-or-marker)
+                         number-or-marker
+                       (with-current-buffer buf (copy-marker 
number-or-marker))))))
+    (and mrkr  `(marker ,buf ,(marker-position mrkr)))))
+
+(defun zz-izones-p (value)
+  "Return non-nil if VALUE is a list of izones.
+That is, non-nil means that VALUE has the form of `zz-izones'."
+  (and (listp value)  (listp (cdr (last value))) ; Proper list.
+       (let ((res  t))
+         (catch 'zz-izones-p
+           (dolist (nn  value)
+             (unless (setq res  (and (consp nn)  (condition-case nil
+                                                     (and (numberp (nth 0 nn))
+                                                          
(zz-number-or-marker-p (nth 1 nn))
+                                                          
(zz-number-or-marker-p (nth 2 nn)))
+                                                   (error nil))))
+               (throw 'zz-izones-p nil))))
+         res)))
+
+(defun zz-rassoc-delete-all (value alist)
+  "Delete from ALIST all elements whose cdr is `equal' to VALUE.
+Elements of ALIST that are not conses are ignored.
+Return the modified alist.
+This is a destructive operation."
+  (while (and (consp (car alist))  (equal (cdar alist) value)) (setq alist  
(cdr alist)))
+  (let ((tail  alist)
+        tail-cdr)
+    (while (setq tail-cdr  (cdr tail))
+      (if (and (consp (car tail-cdr))  (equal (cdar tail-cdr) value))
+         (setcdr tail (cdr tail-cdr))
+       (setq tail  tail-cdr))))
+  alist)
+
+
+(defun zz-izones-renumber (&optional variable)
+  "Renumber the izones of this buffer in the current `zz-izones-var'.
+This is a destructive operation: The list structure of the variable
+value can be modified."
+  (let* ((var   (or variable  zz-izones-var))
+         (orig  (symbol-value var)))
+    (set var ())
+    (dolist (nn  orig) (zz-izone-add (cadr nn) (car (cddr nn)) var))))
+
+;;; Non-destructive version.
+;;;
+;;; (defun zz-izone-limits-in-bufs (buffers &optional variable)
+;;;   "Return a list of all `zz-izone-limits' for each buffer in BUFFERS.
+;;; That is, return a list of all currently recorded buffer narrowings for
+;;; BUFFERS.  If BUFFERS is nil then return the narrowings for the current
+;;; buffer.
+;;;
+;;; This is a non-destructive operation: The list returned is independent
+;;; of the `zz-izone-limits' list in each of the buffers.
+;;;
+;;; Optional arg VARIABLE is the izones variable to use.  If nil,
+;;; use the value of `zz-izones-var'.  The variable is evaluated in each
+;;; buffer (or in the current buffer, if BUFFERS is nil)."
+;;;
+;;;   (let ((limits  ()))
+;;;     (dolist (buf  (or (reverse buffers)  (list (current-buffer)))) ; 
Reverse so we keep the order.
+;;;       (with-current-buffer buf
+;;;         (setq limits  (append (zz-izone-limits (symbol-value (or variable  
zz-izones-var))
+;;;                                              buf
+;;;                                              'ONLY-THIS-BUFFER)
+;;;                               limits))))
+;;;     limits))
+
+(defun zz-izone-limits-in-bufs (buffers &optional variable)
+  "Return a list of all `zz-izone-limits' for each buffer in BUFFERS.
+That is, return a list of all recorded buffer narrowings for BUFFERS.
+If BUFFERS is nil then return the narrowings for the current buffer.
+
+This is a destructive operation: The list returned can have as
+sublists the `zz-izone-limits' lists of BUFFERS.
+
+Optional arg VARIABLE is the izones variable to use.  If nil, use the
+value of `zz-izones-var'.  The variable is evaluated in each
+buffer (or in the current buffer, if BUFFERS is nil)."
+  (let ((limits  ()))
+    (dolist (buf  (or buffers  (list (current-buffer))))
+      (with-current-buffer buf
+        (setq limits  (nconc limits
+                             (zz-izone-limits (symbol-value (or variable  
zz-izones-var)) buf 'THISBUF)))))
+    limits))
+
+(defun zz-izone-limits (&optional izones buffer only-one-buffer-p)
+  "Return a list like IZONES, but with no identifiers.
+That is, return a list of zones, (LIMIT1 LIMIT2).
+
+This is a non-destructive operation: A new list is returned.
+
+Each limit can be a number or a marker (but see ONLY-ONE-BUFFER-P).
+The conses are new - they do not share with any conses with IZONES.
+
+Optional input list IZONES has the same structure as `zz-izones'.  If
+IZONES is nil then the variable that is the value of `zz-izones-var'
+is used.  It is evaluated in BUFFER (default: current buffer) to
+obtain the izones.
+
+Non-nil optional arg ONLY-ONE-BUFFER-P means remove any izones that
+contain markers for a buffer other than BUFFER."
+  (unless buffer (setq buffer  (current-buffer)))
+  (let ((restrs  (or izones  (with-current-buffer buffer (symbol-value 
zz-izones-var)))))
+    (when only-one-buffer-p (setq restrs  
(zz-remove-izones-w-other-buffer-markers restrs)))
+    (delq nil (mapcar #'cdr restrs))))
+
+;; Useful for commands that want to act on regions in multiple buffers.
+(defun zz-read-bufs ()
+  "Read names of buffers, one at a time.  `C-g' ends reading."
+  (let ((bufs  ())
+        buf)
+    (while (condition-case nil
+               (setq buf  (read-buffer "Buffer (C-g to end): "
+                                       (and (not (member (buffer-name 
(current-buffer)) bufs))
+                                            (current-buffer))
+                                       t))
+             (quit nil))
+      (push buf bufs))
+    (delq nil (mapcar #'get-buffer (nreverse bufs)))))
+
+(defun zz-remove-zones-w-other-buffer-markers (zones &optional buffer)
   "Return ZONES, but remove any that use markers for another buffer.
 BUFFER is the buffer to compare with (default: current buffer).
 This is a non-destructive operation: a (shallow) copy is returned."
   (unless buffer (setq buffer  (current-buffer)))
-  (let (m1 m2)
-    (zzz-remove-if
-     `(lambda (zone)
-        (setq m1  (car zone)
-              m2  (cadr zone))
-        (or (and (markerp m1)  (not (eq ',buffer (marker-buffer m1))))
-            (and (markerp m2)  (not (eq ',buffer (marker-buffer m2))))))
-     zones)))
-
-(defun zzz-remove-if (pred xs)
+  (zz-remove-if `(lambda (zone) (zz-zone-has-other-buffer-marker-p restr 
',buffer)) zones))
+
+(defun zz-remove-izones-w-other-buffer-markers (izones &optional buffer)
+  "Return IZONES, but remove any that use markers for another buffer.
+BUFFER is the buffer to compare with (default: current buffer).
+This is a non-destructive operation: a (shallow) copy is returned."
+  (unless buffer (setq buffer  (current-buffer)))
+  (zz-remove-if `(lambda (restr) (zz-izone-has-other-buffer-marker-p restr 
',buffer)) izones))
+
+(defun zz-zone-has-other-buffer-marker-p (zone &optional buffer)
+  "Return non-nil if basic ZONE has a marker for another buffer.
+The first marker in the zone is returned.
+BUFFER is the buffer to compare with (default: current buffer)."
+  (unless buffer (setq buffer  (current-buffer)))
+  (let ((m1  (nth 0 zone))
+        (m2  (nth 1 zone)))
+    (or (and (markerp m1)  (not (eq buffer (marker-buffer m1)))  m1)
+        (and (markerp m2)  (not (eq buffer (marker-buffer m2)))  m2))))
+
+(defun zz-izone-has-other-buffer-marker-p (izone &optional buffer)
+  "Return non-nil if IZONE has a marker for another buffer.
+The first marker in the izone is returned.
+BUFFER is the buffer to compare with (default: current buffer)."
+  (unless buffer (setq buffer  (current-buffer)))
+  (let ((m1  (nth 1 izone))
+        (m2  (nth 2 izone)))
+    (or (and (markerp m1)  (not (eq buffer (marker-buffer m1)))  m1)
+        (and (markerp m2)  (not (eq buffer (marker-buffer m2)))  m2))))
+
+(defun zz-remove-if (pred xs)
   "A copy of list XS with no elements that satisfy predicate PRED."
   (let ((result  ()))
     (dolist (x xs) (unless (funcall pred x) (push x result)))
     (nreverse result)))
 
+;; Useful for commands that want to act on  regions in multiple buffers (e.g., 
visible buffers only).
+;;
+;; Same as `icicle-remove-if-not' etc.
+(defun zz-remove-if-not (pred xs)
+  "A copy of list XS with only elements that satisfy predicate PRED."
+  (let ((result  ()))
+    (dolist (x xs) (when (funcall pred x) (push x result)))
+    (nreverse result)))
+
+;; Like `read-any-variable' in `strings.el', but passes REQUIRE-MATCH arg to 
`completing-read'.
+(defun zz-read-any-variable (prompt &optional default-value require-match)
+  "Read the name of a variable and return it as a symbol.
+Prompts with string PROMPT.  By default, returns DEFAULT-VALUE if
+non-nil.  If DEFAULT-VALUE is nil and the nearest symbol to the cursor
+is a variable, then return that by default.
+
+Unlike `read-variable', which reads only user options, this reads the
+name of any variable.  If optional arg REQUIRE-MATCH is nil then it
+reads any symbol, but it provides completion against variable names."
+  (let ((symb                          (cond ((fboundp 'symbol-nearest-point) 
(symbol-nearest-point))
+                                             ((fboundp 'symbol-at-point) 
(symbol-at-point))
+                                             (t nil)))
+        (enable-recursive-minibuffers  t))
+    (when (and default-value  (symbolp default-value))
+      (setq default-value  (symbol-name default-value)))
+    (intern (completing-read prompt obarray 'boundp require-match nil 
'minibuffer-history
+                             (let ((var-at-pt  (and symb  (boundp symb)  
(symbol-name symb))))
+                               (if (and default-value  var-at-pt  (> 
emacs-major-version 22))
+                                   (list default-value var-at-pt)
+                                 (or default-value  var-at-pt)))
+                             t))))
+
+;; Same as `tap-string-match-p' in `thingatpt+.el' and `icicle-string-match-p' 
in `icicles-fn.el'.
+(if (fboundp 'string-match-p)
+    (defalias 'zz-string-match-p 'string-match-p) ; Emacs 23+
+  (defun zz-string-match-p (regexp string &optional start)
+    "Like `string-match', but this saves and restores the match data."
+    (save-match-data (string-match regexp string start))))
+
+(defun zz-repeat-command (command)
+  "Repeat COMMAND."
+ (let ((repeat-previous-repeated-command  command)
+       (repeat-message-function           'ignore)
+       (last-repeatable-command           'repeat))
+   (repeat nil)))
+
+;;;###autoload
+(defun zz-narrow-repeat (arg)              ; Bound to `C-x n x'.
+  "Cycle to the next buffer restriction (narrowing).
+This is a repeatable version of `zz-narrow'.
+
+Note that if the value of `zz-izones-var' is not buffer-local then you
+can use this command to cycle among regions in multiple buffers."
+  (interactive "P")
+  (require 'repeat)
+  (zz-repeat-command 'zz-narrow))
+
+;;;###autoload
+(defun zz-select-region-repeat (arg) ; Bound to `C-x n r'.
+  "Cycle to the next region.
+This is a repeatable version of `zz-select-region'."
+  (interactive "P")
+  (require 'repeat)
+  (zz-repeat-command 'zz-select-region))
+
+(defun zz-izones-from-zones (zones)
+  "Return a list of regions like `zz-izones', based on ZONES.
+Each zone in the list ZONES has the form (LIMIT1 LIMIT2 . EXTRA),
+where each of the limits is a buffer position (a number or marker) and
+EXTRA is a list.
+
+This is a non-destructive operation.  A new list is returned.
+
+\(zz-izones-from-zones (zz-izone-limits)) = zz-izones
+and
+\(zz-izone-limits (zz-izones-from-zones ZONES)) = ZONES"
+  (let ((ii  0))
+    (nreverse (mapcar (lambda (zz) (cons (setq ii  (1+ ii)) zz)) zones))))
+
+;;;###autoload
+(defun zz-izones-coalesce (&optional variable msgp)
+  "Coalesce the izones of VARIABLE.
+A non-destructive operation: The new value of VARIABLE is a new list.
+Return the new value of VARIABLE.
+
+VARIABLE defaults to the value of `zz-izones-var'.
+With a prefix arg you are prompted for a different variable to use, in
+place of the current value of `zz-izones-var'.  If the prefix arg is
+non-negative (>= 0) then make the variable buffer-local.  If the
+prefix arg is non-positive (<= 0) then set `zz-izones-var' to that
+variable symbol.  (Zero: do both.)
+
+Non-interactively:
+* VARIABLE is the optional izones variable to use.
+* Non-nil MSGP show status message."
+  (interactive (let* ((var    (and current-prefix-arg  (zz-read-any-variable 
"Variable: " zz-izones-var)))
+                      (npref  (prefix-numeric-value current-prefix-arg)))
+                 (when (and current-prefix-arg  (>= npref 0)) 
(make-local-variable var))
+                 (when (and current-prefix-arg  (<= npref 0)) (setq 
zz-izones-var var))
+                 (list var t)))
+  (let* ((var         (or variable  zz-izones-var))
+         (IGNORE      (unless (boundp var) (set var ())))
+         (val         (symbol-value var))
+         (IGNORE      (unless (zz-izones-p val)
+                        (error "Not an izones variable: `%s', value: `%S'" var 
val)))
+         (zone-union  (zz-zone-union (zz-izone-limits val))))
+    (set var  (zz-izones-from-zones zone-union))
+    (when msgp (message "Restrictions united for `%s'" var))
+    (symbol-value var)))
+
+;;;###autoload
+(defun zz-izone-add-and-coalesce (start end &optional variable msgp)
+  "Add an izone from START to END to those of VARIABLE, and coalesce.
+Use `zz-izone-add', then apply `zz-izones-coalesce'.
+Return the new value of VARIABLE.
+
+This is a destructive operation: The list structure of the variable
+value can be modified.
+
+VARIABLE defaults to the value of `zz-izones-var'.
+START and END are as for `narrow-to-region'.
+
+With a prefix arg you are prompted for a different variable to use, in
+place of the current value of `zz-izones-var'.  If the prefix arg is
+non-negative (>= 0) then make the variable buffer-local.  If the
+prefix arg is non-positive (<= 0) then set `zz-izones-var' to that
+variable symbol.  (Zero: do both.)
+
+Non-interactively:
+* VARIABLE is the optional izones variable to use.
+* Non-nil MSGP means echo the size of the added zone."
+  (interactive (let ((beg    (region-beginning))
+                     (end    (region-end))
+                     (var    (or (and current-prefix-arg  
(zz-read-any-variable "Variable: " zz-izones-var))
+                                 zz-izones-var))
+                     (npref  (prefix-numeric-value current-prefix-arg)))
+                 (when (and current-prefix-arg  (>= npref 0)) 
(make-local-variable var))
+                 (when (and current-prefix-arg  (<= npref 0)) (setq 
zz-izones-var var))
+                 (list beg end var t)))
+  (unless variable (setq variable  zz-izones-var))
+  (zz-izone-add start end variable nil nil msgp)
+  (zz-izones-coalesce variable msgp)
+  (symbol-value variable))
+
+
+;;---------------------
+
+(cond ((boundp 'narrow-map)
+       (define-key narrow-map "\C-d" 'zz-izone-delete)
+       (when (fboundp 'hlt-highlight-regions)
+         (define-key narrow-map "h"  'hlt-highlight-regions))
+       (when (fboundp 'hlt-highlight-regions)
+         (define-key narrow-map "H"  'hlt-highlight-regions-in-buffers))
+       (define-key narrow-map "r"    (if (> emacs-major-version 21) 
'zz-select-region-repeat 'zz-select-region))
+       (define-key narrow-map "s"    'zz-izone-add)
+       (define-key narrow-map "S"    'zz-izone-add-and-coalesce)
+       (define-key narrow-map "u"    'zz-izones-coalesce)
+       (define-key narrow-map "x"    'zz-narrow-repeat))
+      (t
+       (define-key ctl-x-map "n\C-d" 'zz-izone-delete)
+       (when (fboundp 'hlt-highlight-regions)
+         (define-key ctl-x-map "nh"  'hlt-highlight-regions))
+       (when (fboundp 'hlt-highlight-regions)
+         (define-key ctl-x-map "nH"  'hlt-highlight-regions-in-buffers))
+       (define-key ctl-x-map "nr"    (if (> emacs-major-version 21) 
'zz-select-region-repeat 'zz-select-region))
+       (define-key ctl-x-map "ns"    'zz-izone-add)
+       (define-key ctl-x-map "nS"    'zz-izone-add-and-coalesce)
+       (define-key ctl-x-map "nu"    'zz-izones-coalesce)
+       (define-key ctl-x-map "nx"    (if (> emacs-major-version 21) 
'zz-narrow-repeat 'zz-narrow))))
+
+
+;; Call `zz-izone-add' if interactive or if `zz-izone-add-anyway-p'.
+;;
+(defadvice narrow-to-region (before zz-izone-add activate)
+  "Push the region limits to the current `zz-izones-var'.
+You can use `C-x n x' to widen to a previous buffer restriction.
+
+This is a destructive operation. The list structure of the variable
+value can be modified."
+  (when (or (interactive-p)  zz-izone-add-anyway-p)
+    (let ((start  (ad-get-arg 0))
+          (end    (ad-get-arg 1)))
+      (unless start (setq start  (region-beginning))) ; Needed for Emacs 20.
+      (unless end   (setq end    (region-end)))
+      (zz-izone-add start end nil nil nil 'MSG))))
+
+
+;; REPLACE ORIGINAL in `lisp.el'.
+;;
+;; Call `zz-izone-add' if interactive or `zz-izone-add-anyway-p'.
+;;
+;;;###autoload
+(defun narrow-to-defun (&optional arg)
+  "Make text outside current defun invisible.
+The visible defun is the one that contains point or follows point.
+Optional ARG is ignored.
+
+This is a destructive operation. The list structure of the variable
+that is the value of `zz-izones-var' can be modified."
+  (interactive)
+  (save-excursion
+    (widen)
+    (let ((opoint  (point))
+         beg end)
+      ;; Try first in this order for the sake of languages with nested 
functions
+      ;; where several can end at the same place as with the offside rule, 
e.g. Python.
+      (beginning-of-defun)
+      (setq beg  (point))
+      (end-of-defun)
+      (setq end  (point))
+      (while (looking-at "^\n")
+       (forward-line 1))
+      (unless (> (point) opoint)
+       ;; `beginning-of-defun' moved back one defun, so we got the wrong one.
+       (goto-char opoint)
+       (end-of-defun)
+       (setq end  (point))
+       (beginning-of-defun)
+       (setq beg  (point)))
+      (goto-char end)
+      (re-search-backward "^\n" (- (point) 1) t)
+      (when (or (interactive-p)  zz-izone-add-anyway-p) (zz-izone-add beg end 
nil nil nil 'MSG))
+      (narrow-to-region beg end))))
+
+
+;; REPLACE ORIGINAL in `page.el'.
+;;
+;; Call `zz-izone-add' if interactive or `zz-izone-add-anyway-p'.
+;;
+;;;###autoload
+(defun narrow-to-page (&optional arg)
+  "Make text outside current page invisible.
+A numeric arg specifies to move forward or backward by that many pages,
+thus showing a page other than the one point was originally in.
+
+This is a destructive operation. The list structure of the variable
+that is the value of `zz-izones-var' can be modified."
+  (interactive "P")
+  (setq arg  (if arg (prefix-numeric-value arg) 0))
+  (save-excursion
+    (widen)
+    (if (> arg 0)
+       (forward-page arg)
+      (if (< arg 0)
+         (let ((adjust  0)
+               (opoint  (point)))
+           ;; If not now at the beginning of a page, move back one extra time, 
to get to start of this page.
+           (save-excursion
+             (beginning-of-line)
+             (or (and (looking-at page-delimiter)  (eq (match-end 0) opoint))
+                 (setq adjust 1)))
+           (forward-page (- arg adjust)))))
+    ;; Find the end of the page.
+    (set-match-data nil)
+    (forward-page)
+    ;; If we stopped due to end of buffer, stay there.
+    ;; If we stopped after a page delimiter, put end of restriction at the 
beginning of that line.
+    ;; Before checking the match that was found, verify that `forward-page' 
actually set the match data.
+    (if (and (match-beginning 0)  (save-excursion (goto-char (match-beginning 
0))
+                                                  (looking-at page-delimiter)))
+       (goto-char (match-beginning 0)))
+    (let ((beg  (point))
+          (end  (progn
+                  ;; Find the top of the page.
+                  (forward-page -1)
+                  ;; If we found beginning of buffer, stay there.
+                  ;; If extra text follows page delimiter on same line, 
include it.
+                  ;; Otherwise, show text starting with following line.
+                  (when (and (eolp)  (not (bobp))) (forward-line 1))
+                  (point))))
+      (when (or (interactive-p)  zz-izone-add-anyway-p) (zz-izone-add beg end 
nil nil nil 'MSG))
+      (narrow-to-region beg end))))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (provide 'zones)



reply via email to

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