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

24. Buffers


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

24.1 Introduction to Buffers

A buffer is logically just a Lisp object that holds some text. In this, it is like a string, but a buffer is optimized for frequent insertion and deletion, while a string is not. Furthermore:

  1. Buffers are permanent objects, i.e. once you create them, they remain around, and need to be explicitly deleted before they go away.
  2. Each buffer has a unique name, which is a string. Buffers are normally referred to by name. In this respect, they are like symbols.
  3. Buffers have a default insertion position, called point. Inserting text (unless you explicitly give a position) goes at point, and moves point forward past the text. This is what is going on when you type text into Emacs.
  4. Buffers have lots of extra properties associated with them.
  5. Buffers can be displayed. What this means is that there exist a number of windows, which are objects that correspond to some visible section of your display, and each window has an associated buffer, and the current contents of the buffer are shown in that section of the display. The redisplay mechanism (which takes care of doing this) knows how to look at the text of a buffer and come up with some reasonable way of displaying this. Many of the properties of a buffer control how the buffer’s text is displayed.
  6. One buffer is distinguished and called the current buffer. It is stored in the variable current_buffer. Buffer operations operate on this buffer by default. When you are typing text into a buffer, the buffer you are typing into is always current_buffer. Switching to a different window changes the current buffer. Note that Lisp code can temporarily change the current buffer using set-buffer (often enclosed in a save-excursion so that the former current buffer gets restored when the code is finished). However, calling set-buffer will NOT cause a permanent change in the current buffer. The reason for this is that the top-level event loop sets current_buffer to the buffer of the selected window, each time it finishes executing a user command.

Make sure you understand the distinction between current buffer and buffer of the selected window, and the distinction between point of the current buffer and window-point of the selected window. (This latter distinction is explained in detail in the section on windows.)


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

24.2 Buffer Lists

Recall earlier that buffers are permanent objects, i.e. that they remain around until explicitly deleted. This entails that there is a list of all the buffers in existence. This list is actually an assoc-list (mapping from the buffer’s name to the buffer) and is stored in the global variable Vbuffer_alist.

The order of the buffers in the list is important: the buffers are ordered approximately from most-recently-used to least-recently-used. Switching to a buffer using switch-to-buffer, pop-to-buffer, etc. and switching windows using other-window, etc. usually brings the new current buffer to the front of the list. switch-to-buffer, other-buffer, etc. look at the beginning of the list to find an alternative buffer to suggest. You can also explicitly move a buffer to the end of the list using bury-buffer.

In addition to the global ordering in Vbuffer_alist, each frame has its own ordering of the list. These lists always contain the same elements as in Vbuffer_alist although possibly in a different order. buffer-list normally returns the list for the selected frame. This allows you to work in separate frames without things interfering with each other.

The standard way to look up a buffer given a name is get-buffer, and the standard way to create a new buffer is get-buffer-create, which looks up a buffer with a given name, creating a new one if necessary. These operations correspond exactly with the symbol operations intern-soft and intern, respectively. You can also force a new buffer to be created using generate-new-buffer, which takes a name and (if necessary) makes a unique name from this by appending a number, and then creates the buffer. This is basically like the symbol operation gensym.


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

24.3 Markers and Extents

Among the things associated with a buffer are things that are logically attached to certain buffer positions. This can be used to keep track of a buffer position when text is inserted and deleted, so that it remains at the same spot relative to the text around it; to assign properties to particular sections of text; etc. There are two such objects that are useful in this regard: they are markers and extents.

A marker is simply a flag placed at a particular buffer position, which is moved around as text is inserted and deleted. Markers are used for all sorts of purposes, such as the mark that is the other end of textual regions to be cut, copied, etc.

An extent is similar to two markers plus some associated properties, and is used to keep track of regions in a buffer as text is inserted and deleted, and to add properties (e.g. fonts) to particular regions of text. The external interface of extents is explained elsewhere.

The important thing here is that markers and extents simply contain buffer positions in them as integers, and every time text is inserted or deleted, these positions must be updated. In order to minimize the amount of shuffling that needs to be done, the positions in markers and extents (there’s one per marker, two per extent) are stored in Membpos’s. This means that they only need to be moved when the text is physically moved in memory; since the gap structure tries to minimize this, it also minimizes the number of marker and extent indices that need to be adjusted. Look in ‘insdel.c’ for the details of how this works.

One other important distinction is that markers are temporary while extents are permanent. This means that markers disappear as soon as there are no more pointers to them, and correspondingly, there is no way to determine what markers are in a buffer if you are just given the buffer. Extents remain in a buffer until they are detached (which could happen as a result of text being deleted) or the buffer is deleted, and primitives do exist to enumerate the extents in a buffer.


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

24.4 The Buffer Object

Buffers contain fields not directly accessible by the Lisp programmer. We describe them here, naming them by the names used in the C code. Many are accessible indirectly in Lisp programs via Lisp primitives.

name

The buffer name is a string that names the buffer. It is guaranteed to be unique. See (lispref)Buffer Names section ‘Buffer Names’ in XEmacs Lisp Reference Manual.

save_modified

This field contains the time when the buffer was last saved, as an integer. See (lispref)Buffer Modification section ‘Buffer Modification’ in XEmacs Lisp Reference Manual.

modtime

This field contains the modification time of the visited file. It is set when the file is written or read. Every time the buffer is written to the file, this field is compared to the modification time of the file. See (lispref)Buffer Modification section ‘Buffer Modification’ in XEmacs Lisp Reference Manual.

auto_save_modified

This field contains the time when the buffer was last auto-saved.

last_window_start

This field contains the window-start position in the buffer as of the last time the buffer was displayed in a window.

undo_list

This field points to the buffer’s undo list. See (lispref)Undo section ‘Undo’ in XEmacs Lisp Reference Manual.

syntax_table_v

This field contains the syntax table for the buffer. See (lispref)Syntax Tables section ‘Syntax Tables’ in XEmacs Lisp Reference Manual.

downcase_table

This field contains the conversion table for converting text to lower case. See (lispref)Case Tables section ‘Case Tables’ in XEmacs Lisp Reference Manual.

upcase_table

This field contains the conversion table for converting text to upper case. See (lispref)Case Tables section ‘Case Tables’ in XEmacs Lisp Reference Manual.

case_canon_table

This field contains the conversion table for canonicalizing text for case-folding search. See (lispref)Case Tables section ‘Case Tables’ in XEmacs Lisp Reference Manual.

case_eqv_table

This field contains the equivalence table for case-folding search. See (lispref)Case Tables section ‘Case Tables’ in XEmacs Lisp Reference Manual.

display_table

This field contains the buffer’s display table, or nil if it doesn’t have one. See (lispref)Display Tables section ‘Display Tables’ in XEmacs Lisp Reference Manual.

markers

This field contains the chain of all markers that currently point into the buffer. Deletion of text in the buffer, and motion of the buffer’s gap, must check each of these markers and perhaps update it. See (lispref)Markers section ‘Markers’ in XEmacs Lisp Reference Manual.

backed_up

This field is a flag that tells whether a backup file has been made for the visited file of this buffer.

mark

This field contains the mark for the buffer. The mark is a marker, hence it is also included on the list markers. See (lispref)The Mark section ‘The Mark’ in XEmacs Lisp Reference Manual.

mark_active

This field is non-nil if the buffer’s mark is active.

local_var_alist

This field contains the association list describing the variables local in this buffer, and their values, with the exception of local variables that have special slots in the buffer object. (Those slots are omitted from this table.) See (lispref)Buffer-Local Variables section ‘Buffer-Local Variables’ in XEmacs Lisp Reference Manual.

modeline_format

This field contains a Lisp object which controls how to display the mode line for this buffer. See (lispref)Modeline Format section ‘Modeline Format’ in XEmacs Lisp Reference Manual.

base_buffer

This field holds the buffer’s base buffer (if it is an indirect buffer), or nil.


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

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