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'.
The cookie package uses its own terminology. Here are some important definitions.
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.
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.
(collection-create buffer pretty-printer &optional header footer pos)
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)
(collection-length collection)
(collection-list-cookies 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)
(cookie-enter-last collection cookie)
(cookie-enter-after-tin collection tin cookie)
(cookie-enter-before-tin collection tin cookie)
(collection-append-cookies (collection cookie-list))
(tin-cookie collection tin)
There are a couple of different ways to delete cookies from the collection.
(tin-delete collection tin)
(cookie-delete-first collection)
nil
if there are no cookies left in
collection.
(cookie-delete-last collection)
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)
collection-filter-cookies
they will be passed
unmodified to predicate.
(collection-filter-tins collection predicate &rest extra-args)
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)
The functions in this section treat the collection as a doubly linked list.
(tin-nth collection n)
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)
tin-nth
, but the cookie is returned instead of
the tin.
(tin-next collection tin)
nil
or refers to the last cookie in collection.
(tin-previous collection tin)
nil
or refers to the first cookie in
collection.
(cookie-sort collection predicate)
(cookie-first collection)
(cookie-last collection)
(cookie-map map-function collection &rest map-args)
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)
cookie-map
, but map-function will be
applied to the last cookie first.
(collection-collect-tin collection predicate &rest predicate-args)
collection-collect-tin
the remaining arguments will
be passed to predicate.
(collection-collect-cookie collection predicate &rest predicate-args)
collection-collect-tin
, but a list of cookies
is returned.
(collection-buffer collection)
(collection-refresh collection)
tin-invalidate
is more efficient if only
a small number of cookies needs to be refreshed.
(tin-invalidate collection &rest tins)
(collection-set-goal-column collection goal)
(tin-goto-previous collection pos arg)
(tin-goto-next collection pos arg)
tin-goto-previous
, but move towards the end of
the buffer instead.
(tin-goto collection tin)
(tin-locate collection pos &optional guess)
nil
is returned.
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.