Go to the first, previous, next, last section, table of contents.

The Cookie package--nodal data in a buffer

If you want to have structured nodal data in a buffer, the cookie package can be a help to you.

Cookie is a package that implements a connection between a dll (a doubly linked list) and the contents of a buffer. Possible uses are dired (have all files in a list, and show them), buffer-list, kom-prioritize (in the LysKOM elisp client) and others. `pcl-cvs.el' uses `cookie.el'.

Introduction to cookie terminology

The cookie package uses its own terminology. Here are some important definitions.

cookie
A cookie can be any lisp object. When you use the cookie package you specify a pretty-printer, a function that inserts a printable representation of the cookie in the buffer.
collection
A collection consists of a doubly linked list of cookies, a header, a footer and a pretty-printer. It is displayed at a certain point in a certain buffer. (The buffer and point are selected when the collection is created). The header and the footer are constant strings. They appear before and after the cookies. (Currently, once set, they can not be changed).
tin
A tin is an object that contains one cookie. There are functions in this package that given a tin extracts the cookie, or gives the next or previous tin. (All tins are linked together in a doubly linked list. The previous tin is the one that appears before the other in the buffer.) You should not do anything with a tin except pass it to the functions in this package.

Cookie does not affect the mode of the buffer in any way. It merely makes it easy to connect an underlying data representation to the buffer contents.

A collection is a very dynamic thing. You can easily add or delete cookies. You can sort all cookies in a collection (you have to supply a function that compares two cookies). You can apply a function to all cookies in a collection, et c, et c.

Remember that a cookie can be anything. Your imagination is the limit! It is even possible to have another collection as a cookie. In that way some kind of tree hierarchy can be created.

Coding conventions used in the cookie package

All functions that are intended for external use begin with one of the prefixes `cookie-', `collection-' or `tin-'. The prefix `icookie-' is currently used for internal functions and macros. Currently, no global or buffer-local variables are used.

Many functions operate on tins instead of cookies. For most functions, the prefix used should help tell which kind of object the function uses.

Most doc-strings contains an "Args:" line that lists the arguments.

Manipulating the entire collection

(collection-create buffer pretty-printer &optional header footer pos)
Create a collection that is displayed in buffer. buffer may be a buffer or a buffer name. It is created if it does not exist. pretty-printer should be a function that takes one argument, a cookie, and inserts a string representing it in the buffer (at point). The string pretty-printer inserts may be empty or span several lines. A trailing newline will always be inserted automatically. The pretty-printer should use insert, and not insert-before-markers. Optional third argument header is a string that will always be present at the top of the collection. header should end with a newline. Optionaly fourth argument footer is similar, and will always be inserted at the bottom of the collection. Optional fifth argument pos is a buffer position, specifying where the collection will be inserted. It defaults to the begining of the buffer. pos will probably default to the current value of (point) in future releases of Elib, so you should not depend on this default in cases where it matters.
(collection-empty collection)
Return true if there are no cookies in collection.
(collection-length collection)
Return the number of cookies in collection.
(collection-list-cookies collection)
Return a list of all cookies in collection.

Inserting cookies in the collection

These functions can be used to insert one or more cookies into a collection. The printed representation will immediately and automatically be updated by the cookie package. (It will call the pretty-printer that was specified to collection-create).

(cookie-enter-first collection cookie)
Enter cookie first in the cookie collection collection.
(cookie-enter-last collection cookie)
Enter cookie last in the cookie collection collection.
(cookie-enter-after-tin collection tin cookie)
Enter cookie into collection, immediately after tin.
(cookie-enter-before-tin collection tin cookie)
Enter cookie into collection, immediately before tin.
(collection-append-cookies (collection cookie-list))
Insert all cookies in the list cookie-list last in collection.

Tins and cookies

(tin-cookie collection tin)
This function can be used to extract a cookie from tin. The collection that tin is present in must also be specified as collection.

Deleting cookies

There are a couple of different ways to delete cookies from the collection.

(tin-delete collection tin)
Delete tin from collection. The cookie that is stored in tin is returned.
(cookie-delete-first collection)
Delete first cookie in collection and return it. Returns nil if there are no cookies left in collection.
(cookie-delete-last collection)
Delete last cookie in collection and return it. Returns nil if there are no cookies left in collection.

The following two functions can be used to delete several cookies that fulfills certain criteria.

(collection-filter-cookies collection predicate &rest extra-args)
Remove all cookies in collection for which predicate returns nil. Note that the buffer for collection will be current-buffer when predicate is called. predicate must restore the current buffer before it returns if it changes it. The predicate is called with cookie as its first argument. If any extra-args are given to collection-filter-cookies they will be passed unmodified to predicate.
(collection-filter-tins collection predicate &rest extra-args)
This is like collection-filter-cookies, but predicate is called with a tin instead of a cookie.

And finally, a way to delete all cookies in one swift function call:

(collection-clear collection)
Remove all cookies in collection.

Collection as a Doubly linked list

The functions in this section treat the collection as a doubly linked list.

(tin-nth collection n)
Return the nth tin. n counts from zero. nil is returned if there is less than n cookies. If n is negative, return the -(n+1)th last element. Thus, (tin-nth dll 0) returns the first node, and (tin-nth dll -1) returns the last node. Use tin-cookie to extract the cookie from the tin (or use cookie-nth instead).
(cookie-nth collection n)
Like tin-nth, but the cookie is returned instead of the tin.
(tin-next collection tin)
Get the next tin. Returns nil if tin is nil or refers to the last cookie in collection.
(tin-previous collection tin)
Get the previous tin. Returns nil if tin is nil or refers to the first cookie in collection.
(cookie-sort collection predicate)
Sort the cookies in collection, stably, comparing elements using predicate. predicate is called with two cookies, and should return `t' if the first cookie is less than the second. All cookies will be refreshed when the sort is complete.
(cookie-first collection)
Return the first cookie in collection. The cookie is not removed.
(cookie-last collection)
Return the last cookie in collection. The cookie is not removed.

Scanning the list

(cookie-map map-function collection &rest map-args)
Apply map-function to all cookies in collection. map-function is applied to the first element first. If map-function returns non-nil the cookie will be refreshed (its pretty-printer will be called once again). Note that the buffer for collection will be current buffer when map-function is called. map-function must restore the current buffer to buffer before it returns, if it changes it. If more than two arguments are given to cookie-map, remaining arguments will be passed to map-function.
(cookie-map-reverse map-function collection &rest map-args)
Like cookie-map, but map-function will be applied to the last cookie first.
(collection-collect-tin collection predicate &rest predicate-args)
Select cookies from collection using predicate. Return a list of all selected tins. predicate is a function that takes a cookie as its first argument. The tins on the returned list will appear in the same order as in the buffer. You should not rely on in which order predicate is called. Note that the buffer the collection is displayed in is current-buffer when predicate is called. predicate must restore current-buffer if it changes it. If more than two arguments are given to collection-collect-tin the remaining arguments will be passed to predicate.
(collection-collect-cookie collection predicate &rest predicate-args)
Like collection-collect-tin, but a list of cookies is returned.

Operations that affect the buffer

(collection-buffer collection)
Return the buffer that collection is displayed in.
(collection-refresh collection)
Refresh all cookies in collection. The pretty-printer that was specified when the collection was created will be called for all cookies in collection. Note that tin-invalidate is more efficient if only a small number of cookies needs to be refreshed.
(tin-invalidate collection &rest tins)
Refresh some cookies. The pretty-printer for collection will be called for all tins.
(collection-set-goal-column collection goal)
Set goal-column for collection. goal-column is made buffer-local. This function will be obsoleted in the next release of Elib. Instead, there is going to be a function that given a cookie will return a position where the cursor should be stored. The details are not yet decided.
(tin-goto-previous collection pos arg)
Move point to the argth previous cookie. Don't move if we are at the first cookie, or if collection is empty. Returns the tin we move to.
(tin-goto-next collection pos arg)
Like tin-goto-previous, but move towards the end of the buffer instead.
(tin-goto collection tin)
Move point to tin.
(tin-locate collection pos &optional guess)
Return the tin that pos (a buffer position) is within. pos may be a marker or an integer. guess should be a tin that it is likely that pos is near. If pos points before the first cookie, the first cookie is returned. If pos points after the last cookie, the last cookie is returned. If collection is empty, nil is returned.

Debugging cookie applications

Since the cookie package uses dll, cookie applications can be hard to debug. Fortunately, the same technique can be used here--just load dll-debug prior to loading cookie. See section Debugging dll applications.

Warning! Don't load a byte-compiled `cookie.elc' that was compiled using dll (as opposed to dll-debug) when you have dll-debug in memory. Your Emacs will be seriously confused.


Go to the first, previous, next, last section, table of contents.