[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47. Extents

An extent is a region of text (a start position and an end position) that is displayed in a particular face and can have certain other properties such as being read-only. Extents can overlap each other. XEmacs efficiently handles buffers with large numbers of extents in them.

Function: extentp object

This returns t if object is an extent.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.1 Introduction to Extents

An extent is a region of text within a buffer or string that has certain properties associated with it. The properties of an extent primarily affect the way the text contained in the extent is displayed. Extents can freely overlap each other in a buffer or string. Extents are invisible to functions that merely examine the text of a buffer or string.

Please note: An alternative way to add properties to a buffer or string is to use text properties. See section Text Properties.

An extent is logically a Lisp object consisting of a start position, an end position, a buffer or string to which these positions refer, and a property list. As text is inserted into a buffer, the start and end positions of the extent are automatically adjusted as necessary to keep the extent referring to the same text in the buffer. If text is inserted at the boundary of an extent, the extent’s start-open and end-open properties control whether the text is included as part of the extent. If the text bounded by an extent is deleted, the extent becomes detached; its start and end positions are no longer meaningful, but it maintains all its other properties and can later be reinserted into a buffer. (None of these considerations apply to strings, because text cannot be inserted into or deleted from a string.)

Each extent has a face or list of faces associated with it, which controls the way in which the text bounded by the extent is displayed. If an extent’s face is nil or its properties are partially undefined, the corresponding properties from the default face for the frame is used. If two or more extents overlap, or if a list of more than one face is specified for a particular extent, the corresponding faces are merged to determine the text’s displayed properties. Every extent has a priority that determines which face takes precedence if the faces conflict. (If two extents have the same priority, the one that comes later in the display order takes precedence. See section display order.) Higher-numbered priority values correspond to a higher priority, and priority values can be negative. Every extent is created with a priority of 0, but this can be changed with set-extent-priority. Within a single extent with a list of faces, faces earlier in the list have a higher priority than faces later in the list.

Extents can be set to respond specially to key and mouse events within the extent. An extent’s keymap property controls the effect of key and mouse strokes within the extent’s text, and the mouse-face property controls whether the extent is highlighted when the mouse moves over it. See section Interaction of Extents with Keyboard and Mouse Events.

An extent can optionally have a begin-glyph or end-glyph associated with it. A begin-glyph or end-glyph is a pixmap or string that will be displayed either at the start or end of an extent or in the margin of the line that the start or end of the extent lies in, depending on the extent’s layout policy. Begin-glyphs and end-glyphs are used to implement annotations, and you should use the annotation API functions in preference to the lower-level extent functions. For more information, See section Annotations.

If an extent has its detachable property set, it will become detached (i.e. no longer in the buffer) when all its text is deleted. Otherwise, it will simply shrink down to zero-length and sit in the same place in the buffer. By default, the detachable property is set on newly-created extents. See section Detached Extents.

If an extent has its duplicable property set, it will be remembered when a string is created from text bounded by the extent. When the string is re-inserted into a buffer, the extent will also be re-inserted. This mechanism is used in the kill, yank, and undo commands. See section Duplicable Extents.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.2 Creating and Modifying Extents

Function: make-extent from to &optional buffer-or-string

This function makes an extent for the range [from, to) in buffer-or-string (a buffer or string). buffer-or-string defaults to the current buffer. Insertions at point to will be outside of the extent; insertions at from will be inside the extent, causing the extent to grow (see section Extent Endpoints). This is the same way that markers behave. The extent is initially detached if both from and to are nil, and in this case buffer-or-string defaults to nil, meaning the extent is in no buffer or string (see section Detached Extents).

Function: delete-extent extent

This function removes extent from its buffer and destroys it. This does not modify the buffer’s text, only its display properties. The extent cannot be used thereafter. To remove an extent in such a way that it can be re-inserted later, use detach-extent. See section Detached Extents.

Function: extent-object extent

This function returns the buffer or string that extent is in. If the return value is nil, this means that the extent is detached; however, a detached extent will not necessarily return a value of nil.

Function: extent-live-p object

This function returns t if object is an extent that has not been deleted, and nil otherwise.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.3 Extent Endpoints

Every extent has a start position and an end position, and logically affects the characters between those positions. Normally the start and end positions must both be valid positions in the extent’s buffer or string. However, both endpoints can be nil, meaning the extent is detached. See section Detached Extents.

Whether the extent overlaps its endpoints is governed by its start-open and end-open properties. Insertion of a character at a closed endpoint will expand the extent to include that character; insertion at an open endpoint will not. Similarly, functions such as extent-at that scan over all extents overlapping a particular position will include extents with a closed endpoint at that position, but not extents with an open endpoint.

Note that the start-closed and end-closed properties are equivalent to start-open and end-open with the opposite sense.

Both endpoints can be equal, in which case the extent includes no characters but still exists in the buffer or string. Zero-length extents are used to represent annotations (see section Annotations) and can be used as a more powerful form of a marker. Deletion of all the characters in an extent may or may not result in a zero-length extent; this depends on the detachable property (see section Detached Extents). Insertion at the position of a zero-length extent expands the extent if both endpoints are closed; goes before the extent if it has the start-open property; and goes after the extent if it has the end-open property. Zero-length extents with both the start-open and end-open properties are treated as if their starting point were closed. Deletion of a character on a side of a zero-length extent whose corresponding endpoint is closed causes the extent to be detached if its detachable property is set; if the corresponding endpoint is open, the extent remains in the buffer, moving as necessary.

Extents are ordered within a buffer or string by increasing start position, and then by decreasing end position (this is called the display order).

Function: extent-start-position extent

This function returns the start position of extent.

Function: extent-end-position extent

This function returns the end position of extent.

Function: extent-length extent

This function returns the length of extent in characters. If the extent is detached, this returns 0. If the extent is not detached, this is equivalent to

 
(- (extent-end-position extent) (extent-start-position extent))
Function: set-extent-endpoints extent start end &optional buffer-or-string

This function sets the start and end position of extent to start and end. If both are nil, this is equivalent to detach-extent.

buffer-or-string specifies the new buffer or string that the extent should be in, and defaults to extent’s buffer or string. (If nil, and extent is in no buffer and no string, it defaults to the current buffer.)

See documentation on detach-extent for a discussion of undo recording.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.4 Finding Extents

The following functions provide a simple way of determining the extents in a buffer or string. A number of more sophisticated primitives for mapping over the extents in a range of a buffer or string are also provided (see section Mapping Over Extents). When reading through this section, keep in mind the way that extents are ordered (see section Extent Endpoints).

Function: extent-list &optional buffer-or-string from to flags property value

This function returns a list of the extents in buffer-or-string. buffer-or-string defaults to the current buffer if omitted. from and to can be used to limit the range over which extents are returned; if omitted, all extents in the buffer or string are returned.

More specifically, if a range is specified using from and to, only extents that overlap the range (i.e. begin or end inside of the range) are included in the list. from and to default to the beginning and end of buffer-or-string, respectively.

flags controls how end cases are treated. For a discussion of this, and exactly what “overlap” means, see map-extents.

The optional arguments property and value can be used to further restrict which extents are returned. They have the same meaning as for map-extents.

If you want to map a function over the extents in a buffer or string, consider using map-extents or mapcar-extents instead.

See also the function extents-at.

Functions that create extents must be prepared for the possibility that there are other extents in the same area, created by other functions. To deal with this, functions typically mark their own extents by setting a particular property on them. The following function makes it easier to locate those extents.

Function: extent-at pos &optional object property before at-flag

This function finds the “smallest” extent (i.e., the last one in the display order) at (i.e., overlapping) pos in object (a buffer or string) having property set. object defaults to the current buffer. property defaults to nil, meaning that any extent will do. Returns nil if there is no matching extent at pos. If the fourth argument before is not nil, it must be an extent; any returned extent will precede that extent. This feature allows extent-at to be used by a loop over extents.

at-flag controls how end cases are handled (i.e. what “at” really means), and should be one of:

nil
after

An extent is at pos if it covers the character after pos. This is consistent with the way that text properties work.

before

An extent is at pos if it covers the character before pos.

at

An extent is at pos if it overlaps or abuts pos. This includes all zero-length extents at pos.

Note that in all cases, the start-openness and end-openness of the extents considered is ignored. If you want to pay attention to those properties, you should use map-extents, which gives you more control.

The following low-level functions are provided for explicitly traversing the extents in a buffer according to the display order. These functions are mostly intended for debugging—in normal operation, you should probably use mapcar-extents or map-extents, or loop using the before argument to extent-at, rather than creating a loop using next-extent.

Function: next-extent extent

Given an extent extent, this function returns the next extent in the buffer or string’s display order. If extent is a buffer or string, this returns the first extent in the buffer or string.

Function: previous-extent extent

Given an extent extent, this function returns the previous extent in the buffer or string’s display order. If extent is a buffer or string, this returns the last extent in the buffer or string.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.5 Mapping Over Extents

The most basic and general function for mapping over extents is called map-extents. You should read through the definition of this function to familiarize yourself with the concepts and optional arguments involved. However, in practice you may find it more convenient to use the function mapcar-extents or to create a loop using the before argument to extent-at (see section Finding Extents).

Function: map-extents function &optional object from to maparg flags property value

This function maps function over the extents which overlap a region in object. object is normally a buffer or string but could be an extent (see below). The region is normally bounded by [from, to) (i.e. the beginning of the region is closed and the end of the region is open), but this can be changed with the flags argument (see below for a complete discussion).

function is called with the arguments (extent, maparg). The arguments object, from, to, maparg, and flags are all optional and default to the current buffer, the beginning of object, the end of object, nil, and nil, respectively. map-extents returns the first non-nil result produced by function, and no more calls to function are made after it returns non-nil.

If object is an extent, from and to default to the extent’s endpoints, and the mapping omits that extent and its predecessors. This feature supports restarting a loop based on map-extents. Note: object must be attached to a buffer or string, and the mapping is done over that buffer or string.

An extent overlaps the region if there is any point in the extent that is also in the region. (For the purpose of overlap, zero-length extents and regions are treated as closed on both ends regardless of their endpoints’ specified open/closedness.) Note that the endpoints of an extent or region are considered to be in that extent or region if and only if the corresponding end is closed. For example, the extent [5,7] overlaps the region [2,5] because 5 is in both the extent and the region. However, (5,7] does not overlap [2,5] because 5 is not in the extent, and neither [5,7] nor (5,7] overlaps the region [2,5) because 5 is not in the region.

The optional flags can be a symbol or a list of one or more symbols, modifying the behavior of map-extents. Allowed symbols are:

end-closed

The region’s end is closed.

start-open

The region’s start is open.

all-extents-closed

Treat all extents as closed on both ends for the purpose of determining whether they overlap the region, irrespective of their actual open- or closedness.

all-extents-open

Treat all extents as open on both ends.

all-extents-closed-open

Treat all extents as start-closed, end-open.

all-extents-open-closed

Treat all extents as start-open, end-closed.

start-in-region

In addition to the above conditions for extent overlap, the extent’s start position must lie within the specified region. Note that, for this condition, open start positions are treated as if 0.5 was added to the endpoint’s value, and open end positions are treated as if 0.5 was subtracted from the endpoint’s value.

end-in-region

The extent’s end position must lie within the region.

start-and-end-in-region

Both the extent’s start and end positions must lie within the region.

start-or-end-in-region

Either the extent’s start or end position must lie within the region.

negate-in-region

The condition specified by a *-in-region flag must not hold for the extent to be considered.

At most one of all-extents-closed, all-extents-open, all-extents-closed-open, and all-extents-open-closed may be specified.

At most one of start-in-region, end-in-region, start-and-end-in-region, and start-or-end-in-region may be specified.

If optional arg property is non-nil, only extents with that property set on them will be visited. If optional arg value is non-nil, only extents whose value for that property is eq to value will be visited.

If you want to map over extents and accumulate a list of results, the following function may be more convenient than map-extents.

Function: mapcar-extents function &optional predicate buffer-or-string from to flags property value

This function applies function to all extents which overlap a region in buffer-or-string. The region is delimited by from and to. function is called with one argument, the extent. A list of the values returned by function is returned. An optional predicate may be used to further limit the extents over which function is mapped. The optional arguments flags, property, and value may also be used to control the extents passed to predicate or function, and have the same meaning as in map-extents.

Function: map-extent-children function &optional object from to maparg flags property value

This function is similar to map-extents, but differs in that:

Thus, this function may be used to walk a tree of extents in a buffer:

 
(defun walk-extents (buffer &optional ignore)
  (map-extent-children 'walk-extents buffer))
Function: extent-in-region-p extent &optional from to flags

This function returns t if map-extents would visit extent if called with the given arguments.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.6 Properties of Extents

Each extent has a property list associating property names with values. Some property names have predefined meanings, and can usually only assume particular values. Assigning other values to such a property either cause the value to be converted into a legal value (e.g., assigning anything but nil to a Boolean property will cause the value of t to be assigned to the property) or will cause an error. Property names without predefined meanings can be assigned any value. An undefined property is equivalent to a property with a value of nil, or with a particular default value in the case of properties with predefined meanings. Note that, when an extent is created, the end-open and detachable properties are set on it.

If an extent has a parent, all of its properties actually derive from that parent (or from the root ancestor if the parent in turn has a parent), and setting a property of the extent actually sets that property on the parent. See section Extent Parents.

Function: extent-property extent property &optional default

This function returns extent’s value for property, or default if no such property exists.

Function: extent-properties extent

This function returns a list of all of extent’s properties that do not have the value of nil (or the default value, for properties with predefined meanings).

Function: set-extent-property extent property value

This function sets property to value in extent. (If property has a predefined meaning, only certain values are allowed, and some values may be converted to others before being stored.)

Function: set-extent-properties extent plist

Change some properties of extent. plist is a property list. This is useful to change many extent properties at once.

The following table lists the properties with predefined meanings, along with their allowable values.

detached

(Boolean) Whether the extent is detached. Setting this is the same as calling detach-extent. See section Detached Extents.

destroyed

(Boolean) Whether the extent has been deleted. Setting this is the same as calling delete-extent.

priority

(integer) The extent’s redisplay priority. Defaults to 0. See section priority. This property can also be set with set-extent-priority and accessed with extent-priority.

start-open

(Boolean) Whether the start position of the extent is open, meaning that characters inserted at that position go outside of the extent. See section Extent Endpoints.

start-closed

(Boolean) Same as start-open but with the opposite sense. Setting this property clears start-open and vice-versa.

end-open

(Boolean) Whether the end position of the extent is open, meaning that characters inserted at that position go outside of the extent. This is t by default. See section Extent Endpoints.

end-closed

(Boolean) Same as end-open but with the opposite sense. Setting this property clears end-open and vice-versa.

read-only

(Boolean) Whether text within this extent will be unmodifiable.

face

(face, face name, list of faces or face names, or nil) The face in which to display the extent’s text. This property can also be set with set-extent-face and accessed with extent-face. Note that if a list of faces is specified, the faces are merged together, with faces earlier in the list having priority over faces later in the list.

mouse-face

(face, face name, list of faces or face names, or nil) The face used to display the extent when the mouse moves over it. This property can also be set with set-extent-mouse-face and accessed with extent-mouse-face. Note that if a list of faces is specified, the faces are merged together, with faces earlier in the list having priority over faces later in the list. See section Interaction of Extents with Keyboard and Mouse Events.

pointer

(pointer glyph) The glyph used as the pointer when the mouse moves over the extent. This takes precedence over the text-pointer-glyph and nontext-pointer-glyph variables. If for any reason this glyph is an invalid pointer, the standard glyphs will be used as fallbacks. See section External Glyphs.

detachable

(Boolean) Whether this extent becomes detached when all of the text it covers is deleted. This is t by default. See section Detached Extents.

duplicable

(Boolean) Whether this extent should be copied into strings, so that kill, yank, and undo commands will restore or copy it. See section Duplicable Extents.

unique

(Boolean) Meaningful only in conjunction with duplicable. When this is set, there may be only one instance of this extent attached at a time. See section Duplicable Extents.

invisible

(Boolean) If t, text under this extent will not be displayed – it will look as if the text and the begin-glyph is not there at all. The end-glyph will still be displayed.

keymap

(keymap or nil) This keymap is consulted for mouse clicks on this extent or keypresses made while point is within the extent. See section Interaction of Extents with Keyboard and Mouse Events.

copy-function

This is a hook that is run when a duplicable extent is about to be copied from a buffer to a string (or the kill ring). See section Duplicable Extents.

paste-function

This is a hook that is run when a duplicable extent is about to be copied from a string (or the kill ring) into a buffer. See section Duplicable Extents.

begin-glyph

(glyph or nil) This extent’s begin glyph. See section Annotations.

end-glyph

(glyph or nil) This extent’s end glyph. See section Annotations.

begin-glyph-layout

(text, whitespace, inside-margin, or outside-margin) The layout policy for this extent’s begin glyph. Defaults to text. See section Annotations.

end-glyph-layout

(text, whitespace, inside-margin, or outside-margin) The layout policy for this extent’s end glyph. Defaults to text. See section Annotations.

initial-redisplay-function

(any funcallable object) The function to be called the first time (a part of) the extent is redisplayed. It will be called with the extent as its argument.

This is used by lazy-shot to implement lazy font-locking. The functionality is still experimental, and may change without further notice.

The following convenience functions are provided for accessing particular properties of an extent.

Function: extent-face extent

This function returns the face property of extent. This might also return a list of face names. Do not modify this list directly! Instead, use set-extent-face.

Note that you can use eq to compare lists of faces as returned by extent-face. In other words, if you set the face of two different extents to two lists that are equal but not eq, then the return value of extent-face on the two extents will return the identical list.

Function: extent-mouse-face extent

This function returns the mouse-face property of extent. This might also return a list of face names. Do not modify this list directly! Instead, use set-extent-mouse-face.

Note that you can use eq to compare lists of faces as returned by extent-mouse-face, just like for extent-face.

Function: extent-priority extent

This function returns the priority property of extent.

Function: extent-keymap extent

This function returns the keymap property of extent.

Function: extent-begin-glyph-layout extent

This function returns the begin-glyph-layout property of extent, i.e. the layout policy associated with the extent’s begin glyph.

Function: extent-end-glyph-layout extent

This function returns the end-glyph-layout property of extent, i.e. the layout policy associated with the extent’s end glyph.

Function: extent-begin-glyph extent

This function returns the begin-glyph property of extent, i.e. the glyph object displayed at the beginning of extent. If there is none, nil is returned.

Function: extent-end-glyph extent

This function returns the end-glyph property of extent, i.e. the glyph object displayed at the end of extent. If there is none, nil is returned.

The following convenience functions are provided for setting particular properties of an extent.

Function: set-extent-priority extent priority

This function sets the priority property of extent to priority.

Function: set-extent-face extent face

This function sets the face property of extent to face.

Function: set-extent-mouse-face extent face

This function sets the mouse-face property of extent to face.

Function: set-extent-keymap extent keymap

This function sets the keymap property of extent to keymap. keymap must be either a keymap object, or nil.

Function: set-extent-begin-glyph-layout extent layout

This function sets the begin-glyph-layout property of extent to layout.

Function: set-extent-end-glyph-layout extent layout

This function sets the end-glyph-layout property of extent to layout.

Function: set-extent-begin-glyph extent begin-glyph &optional layout

This function sets the begin-glyph and glyph-layout properties of extent to begin-glyph and layout, respectively. (layout defaults to text if not specified.)

Function: set-extent-end-glyph extent end-glyph &optional layout

This function sets the end-glyph and glyph-layout properties of extent to end-glyph and layout, respectively. (layout defaults to text if not specified.)

Function: set-extent-initial-redisplay-function extent function

This function sets the initial-redisplay-function property of the extent to function.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.7 Detached Extents

A detached extent is an extent that is not attached to a buffer or string but can be re-inserted. Detached extents have a start position and end position of nil. Extents can be explicitly detached using detach-extent. An extent is also detached when all of its characters are all killed by a deletion, if its detachable property is set; if this property is not set, the extent becomes a zero-length extent. (Zero-length extents with the detachable property set behave specially. See section zero-length extents.)

Function: detach-extent extent

This function detaches extent from its buffer or string. If extent has the duplicable property, its detachment is tracked by the undo mechanism. See section Duplicable Extents.

Function: extent-detached-p extent

This function returns nil if extent is detached, and t otherwise.

Function: copy-extent extent &optional object

This function makes a copy of extent. It is initially detached. Optional argument object defaults to extent’s object (normally a buffer or string, but could be nil).

Function: insert-extent extent &optional start end no-hooks object

This function inserts extent from start to end in object (a buffer or string). If extent is detached from a different buffer or string, or in most cases when extent is already attached, the extent will first be copied as if with copy-extent. This function operates the same as if insert were called on a string whose extent data calls for extent to be inserted, except that if no-hooks is non-nil, extent’s paste-function will not be invoked. See section Duplicable Extents.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.8 Extent Parents

An extent can have a parent extent set for it. If this is the case, the extent derives all its properties from that extent and has no properties of its own. The only “properties” that the extent keeps are the buffer or string it refers to and the start and end points. (More correctly, the extent’s own properties are shadowed. If you later change the extent to have no parent, its own properties will become visible again.)

It is possible for an extent’s parent to itself have a parent, and so on. Through this, a whole tree of extents can be created, all deriving their properties from one root extent. Note, however, that you cannot create an inheritance loop—this is explicitly disallowed.

Parent extents are used to implement the extents over the modeline.

Function: set-extent-parent extent parent

This function sets the parent of extent to parent. If parent is nil, the extent is set to have no parent.

Function: extent-parent extent

This function return the parents (if any) of extent, or nil.

Function: extent-children extent

This function returns a list of the children (if any) of extent. The children of an extent are all those extents whose parent is that extent. This function does not recursively trace children of children.

Function: extent-descendants extent

This function returns a list of all descendants of extent, including extent. This recursively applies extent-children to any children of extent, until no more children can be found.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.9 Duplicable Extents

If an extent has the duplicable property, it will be copied into strings, so that kill, yank, and undo commands will restore or copy it.

Specifically:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

47.10 Interaction of Extents with Keyboard and Mouse Events

If an extent has the mouse-face property set, it will be highlighted when the mouse passes over it. This includes the begin-glyph, but not the end-glyph. Highlighting is accomplished by merging the extent’s face with the face or faces specified by the mouse-face property. The effect is as if a pseudo-extent with the mouse-face face were inserted after the extent in the display order (see section Extent Endpoints, display order).

Variable: mouse-highlight-priority

This variable holds the priority to use when merging in the highlighting pseudo-extent. The default is 1000. This is purposely set very high so that the highlighting pseudo-extent shows up even if there are other extents with various priorities at the same location.

You can also explicitly cause an extent to be highlighted. Only one extent at a time can be highlighted in this fashion, and any other highlighted extent will be de-highlighted.

Function: highlight-extent extent &optional highlight-p

This function highlights (if highlight-p is non-nil) or de-highlights (if highlight-p is nil) extent, if extent has the mouse-face property. (Nothing happens if extent does not have the mouse-face property.)

Function: force-highlight-extent extent &optional highlight-p

This function is similar to highlight-extent but highlights or de-highlights the extent regardless of whether it has the mouse-face property.

If an extent has a keymap property, this keymap will be consulted for mouse clicks on the extent and keypresses made while point is within the extent. The behavior of mouse clicks and keystrokes not defined in the keymap is as normal for the buffer.


To make an extent atomic, set its atomic property.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Aidan Kehoe on December 27, 2016 using texi2html 1.82.