For Development HEAD DRAFTSearch (procedure/syntax/module):

12.69 text.gap-buffer - Gap buffer

Module: text.gap-buffer

This module provides a gap buffer, a data structure useful for editable text.

A gap buffer is a vector of characters with a “cursor”, where you can insert or delete a character in O(1) time. Most of the editing API operate on the current cursor position.

Function: make-gap-buffer :key initial-capacity

{text.gap-buffer} Creates a fresh gap buffer and returns it. The initial content is empty.

The keyword argument initial-capacity must be a positive exact integer if given, and specifies the initial capacity of the buffer. The buffer is automatically extended if necessary, so the argument is only a hint; if you know you’ll insert a long string, for example, you can create a buffer that’s large enough to hold it to avoid reallocation overhead.

Function: string->gap-buffer string :optional pos whence start end

{text.gap-buffer} Creates a gap buffer that contains the given string, and returns it.

The initial cursor position is set at the end of the string by default. The pos and whence argument can set the initial cursor position. The whence argument must be either a symbol beginning or a symbol end, and pos must be an exact integer offset from the whence. For example, pos = 10 and whence = beginning sets the cursor at the 10th character of the string from the beginning, and pos = -1 and whence = end sets the cursor position at one character before the end of the string. If the combination of pos and whence points the outside of the string, an error is signaled.

The optional start and end trims the input string before creating the gap buffer.

Function: gap-buffer? obj

{text.gap-buffer} Returns #t iff obj is a gap buffer.

Function: gap-buffer-copy gbuf

{text.gap-buffer} Returns a fresh copy of a gap buffer gbuf, with the same content and cursor position.

Function: gap-buffer->string gbuf :optional start end
Function: gap-buffer->generator gbuf :optional start end

{text.gap-buffer} Retrieve the content of a gap buffer gbuf as a string or a generator of characters, respectively. The optional start and end arguments are nonnegative exact integers of character index in the content of the buffer, and limits the output within the specified range.

If you modify the content of gap buffer before the returned generator is exhausted, consistent behavior isn’t guaranteed.

Function: gap-buffer-pos gbuf

{text.gap-buffer} Returns the current cursor position of gbuf, in a nonnegative exact integer.

Function: gap-buffer-pos-at-end? gbuf pos

{text.gap-buffer} Returns #t if pos, a position in nonnegative integer, is at the end of gbuf, #f otherwise.

Function: gap-buffer-capacity gbuf

{text.gap-buffer} Returns the currently allocated storage size of gbuf, in character count. If you insert more characters into gbuf, the storage is automatically expanded.

Function: gap-buffer-content-length gbuf

{text.gap-buffer} Returns the length of current content of gbuf, in the number of characters.

Function: gap-buffer-gap-at? gbuf whence

{text.gap-buffer} The whence argument must be either a symbol beginning or a symbol end. Returns #t iff the current cursor position of gbuf is at the beginning or at the end, respectively.

Function: gap-buffer-ref gbuf index :optional fallback

{text.gap-buffer} Returns index-th character of gbuf. If index is out of range, fallback is returned if given, or an error is raised.

Function: gap-buffer-set! gbuf index char

{text.gap-buffer} Replaces index-th character of gbuf with char. If index is out of range, an error is signaled.

Function: gap-buffer-move! gbuf pos :optional whence

{text.gap-buffer} Moves the cursor position of gbuf to a position pos, which must be an exact integer. The position pos is relative to whence, which must be either one of the symbols beginning, current or end. If omitted, beginning is assumed.

Function: gap-buffer-insert! gbuf content

{text.gap-buffer} Inserts content, which must be a character or a string, at the current cursor position of gbuf. The current cursor position is moved to the end of the inserted content.

Function: gap-buffer-delete! gbuf size

{text.gap-buffer} Delets size characters from the current cursor position of gbuf. The size argument must be a nonnegative exact integer. It is an error if size overruns.

Function: gap-buffer-clear! gbuf

{text.gap-buffer} Makes gbuf empty.

Function: gap-buffer-replace! gbuf size content

{text.gap-buffer} This is a combination of (gap-buffer-delete! gbuf size) and (gap-buffer-insert! gbuf content). The size argument must be a nonnegative exact integer, and the content argument must be either a string or a character.

Function: gap-buffer-contains gbuf str :optional gstart gend sstart send

{text.gap-buffer} Search a string str in a gap buffer gbuf. If found, returns the integer index of the beginning of str in gbuf. If not found, returns #f.

The optional arguments gstart and gend restricts the range of gbuf to be searched, by integer indexes. The default is the entire buffer. You can pass #f to indicate to use the default value.

The optional arguments sstart and send restricts the span of str to be searched, by integer indexes. You can pass #f to indicate to use the default value.

Function: gap-buffer-looking-at? gbuf str :optional point

{text.gap-buffer} Returns #t iff the content immeidately following point matches a string str. If point is omitted or #f, the current cursor position is used.

Function: gap-buffer-edit! gbuf edit-command

{text.gap-buffer} This is a convenience procedure to “replay” editing of the gap buffer gbuf. The edit-command argument must be either one of the following:

(i pos string)

Insert string at a position pos.

(d pos length)

Delete length characters from a position pos.

(c pos length string)

Change: Deletes length characters from a position pos, then insert string.

Here, pos must be a nonnegative exact integer specifying the position in the gap buffer.

It returns another edit-command that undo the change.

One of the appliations of this procedure is to handle undo/redo list.

(define buf (string->gap-buffer "Hello, World!"))

(gap-buffer-edit! buf '(d 0 5))
  ⇒ (i 0 "Hello")

(gap-buffer-edit! buf '(i 0 "Konnichiwa"))
  ⇒ (d 0 10)

(gap-buffer->string buf)
  ⇒ "Aloha, World!"

;; Giving the returned values of gap-buffer-edit! in reverse order,
;; you can undo the changes:

(for-each (cut gap-buffer-edit! buf <>) '((d 0 10) (i 0 "Hello")))
(gap-buffer->string buf)
  ⇒ "Hello, World!"


For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT