This is the documentation for Lister
version 0.9.6
Lister= is a library for creating interactive lists of any kind. In
contrast to similar packages like hierarchy.el
or tablist.el
, it aims
at not simply mapping a data structure to a navigatable list. Rather,
it treats the list buffer like Emacs treats text buffers: It is an
empty space to which you successively add stuff. So Lister
should
actually be called Listed
.
One advantage of this approach is that you don’t have to know in
advance the structure of your data. You just “insert” a new slice on
the fly when you need it. Another advantage is that you do not need to
keep a separate copy of the list and worry about syncing: The buffer
is the whole source of truth. Thus Lister
recommends itself in all
cases where it makes sense to collect, modify, thin out, graft, sort
or otherwise edit lists from various sources.
- Project status
- Feature overview
- Example
- Design principle
- API
- Setting up the buffer
- The mapper function
- Lister Mode (minor mode)
- Inserting, adding, deleting or replacing single items
- Inserting, adding, deleting or replacing lists of items
- Getting the list data
- Normalizing boundaries
- Basic sublist handling
- Marking
- Sorting
- Filter
- Outline
- Finding nodes
- Looping
- Interactive editing
- Modified flag
- Miscellaneous
- Changelog
Current release is 0.9.6
This is an overview of features done or planned. A feature is
considered stable
if it is used and tested by the auther. If it is
rarely used, but seems to work, it just works
.
Feature | State | Automated tests? |
---|---|---|
build simple or large lists | stable | yes |
build nested lists | stable | yes |
retrieve data, with hierarchies | stable | yes |
loop over the list | stable | yes |
marking or unmarking items | stable | yes |
filter items | stable | yes |
hide and show sublists outline-style | partially buggy | not enough |
move items and sublists | works | yes |
navigate within the hierarchy | works | yes |
This piece of code creates a new buffer which displays lists of strings.
(let ((ewoc (lister-setup "BUFFERNAME" #'list)))
;; insert 4 items:
(lister-set-list ewoc '("ITEM1" "ITEM2" "ITEM3" "ITEM4"))
;; add further items:
(lister-add-list ewoc '("ITEM5" "ITEM6"))
;; add sublist:
(lister-insert-sublist-below ewoc :first '("SUBITEM1" "SUBITEM2"))
;; move point:
(lister-goto ewoc :first)
(lister-goto ewoc :next)
;; get item data:
(lister-get-data-at ewoc :point) ;; => "SUBITEM1"
;; get sublist at point:
(lister-get-sublist-at ewoc :point) ;; => ("SUBITEM1" "SUBITEM2")
;; prepend "X" to each item:
(lister-dolist (ewoc data :first :last node)
(lister-replace-at ewoc node (concat "X" data)))
;; alternative, more functional way:
(lister-update-list ewoc (lambda (data) (concat "X" data)))
;; filter every item containing the digit 1:
(let ((filter (apply-partially #'string-match "1")))
(lister-set-filter ewoc filter))
;; only get visible items:
(lister-get-visible-list ewoc)
;; => (("XXSUBITEM2") "XXITEM2" "XXITEM3" "XXITEM4" "XXITEM5" "XXITEM6")
;; remove filter:
(lister-set-filter ewoc nil)
;; collect the list values as a flat list:
(lister-collect-list ewoc)
;; => ("XXITEM1" "XXSUBITEM1" "XXSUBITEM2" "XXITEM2"....)
;; get the data as a nested list:
(lister-get-list ewoc)) ;; => ("XXITEM1" ("XXSUBITEM1" "XXSUBITEM2") "XXITEM2" ....)
Lister
is based on the internal library Ewoc.el
. Have a look at its
info pages. The core idea is that we keep a double linked list which
is “viewed” in the buffer, so that each change in the list will be
reflected in the buffer using a function which pretty prints the data
(model-view-controller pattern). Lister
provides convenience functions
on top of this core principle of Ewoc.el
(and also corrects some of
its bugs). A list item thus is basically a data item which is turned
into a printable representation with a mapper function.
- Structured API to add, insert, delete or replace lists or list
items. All positions can be indicated by passing either the
containing
Ewoc
node, a zero-counting index position, or one of the symbols:first
,:last
,:next
,:prev
,:point
. - Functions to return the next list item matching a predicate.
- Macros to loop over the lists, or a part of it, and to deal safely
with parts of the list (“regions”). The looping macros mimic the
cl-dolist
syntax; e.g. you can use(lister-dolist (data :first :last) ..BODY..)
to loop over the whole list. - Functions to collect data which matches a predicate; and functions which can be used to do something with items (“updating” them).
- Sublist handling: Recognize, insert, delete, replace, reverse or sort a sublist.
- Visually filter items according to a predicate; offer some of the functionality above limited to visible items only.
- Built-in functionality to mark items.
- Mapper function: A buffer local function which turns a data item (a non-list lisp object) into a list of strings which will then be inserted in the buffer as its representation.
- Hierarchy by indentation: Nested list hierarchies are built by visually indenting list items. Each item with the same indentation level belongs to the same nesting level. A sublist is thus defined by having an item with an indentation level greater than the one of its predecessor.
- Data items cannot be lists: Since nested lists are recognized by
simply being lists (
consp
), it is not possible to store lists as data items! If you need to store more complex data, use a vector or adefstruct
instead. - No major mode: To use a buffer with lister, call
lister-setup
first. It prepares the buffer by setting some variables and erasing its content. It does not, however, set a specific major mode. - Keep common navigation keys: Each item is printed with the text
property
intangible
set so that the user can only move point to the very first character of the printed item. You can thus use all basic navigation commands without any further ado, includingisearch
. You do not need to define any navigation commands. - Data, items and nodes: What is visually presented as a list item
has three levels of structure: The
Ewoc
node, theLister
specificlister--item
and the actual list data. This might cause some confusion, so here’s a short explanation: First, each visual list item corresponds to anEwoc
node. This node becomes relevant for all generic list functions, such as “looping over the list” or “deleting a specific region”. Secondly, each node contains a structure calledlister--item
. That structure keeps track of list specific information such as the indentation level or whether the item is visible. Finally, there is the actual data which is mapped and printed. This data is also a part of thatLister
item structure which is stored in each node, but is treated distinctly since accessing it is the purpose of the whole library. To avoid semantic confusion, all functions applying to the node have a “node” somewhere in their function name. All other public functions usually refer to the data. To access thelister--item
, you can use(ewoc-data node)
.
Lister
operations become slower when the list grows above a thousand items. I would love to optimize it more for bigger lists once this becomes a real need.
There is a minor mode shipped with the package which provides some basic keybindings. Here’s the keymap:
Key | Function |
---|---|
m | Mark item at point, or active region, or sublist if prefixed |
u | Unmark item at point, or active region, or sublist if prefixed |
U | Unmark all items in the buffer |
M-up, M-down | Move item at point one up, or down (prefix lifts level restriction) |
M-left, M-right | Indent or unindent the item at point (prefix lifts level restriction) |
S-M-up, S-M-down | Move sublist at point one up, down |
S-M-right, S-M-left | Indent or unindent sublist at point |
<TAB> | Cycle outline visibility of sublist below point |
C-c C-b / C-c C-f | Move forward or backward to next node with same level |
C-c C-u | Move to the next parent node |
M-< / M-> | Move to the beginning or end of the current sublist or list. |
C-c <C-up> | Move up to the next child node |
C-c <C-down> | Move down to the next child node |
The commands to mark and unmark also recognize the region. So you can
mark the whole list by pressing C-x h m
.
All navigation commands push point on mark if they jump more than one step.
If the keys M-<
and M->
are pressed repeatedly, move out of the
sublist to the next outer level list and finally to the top or bottom
item.
(lister-setup buf-or-name mapper &optional header footer)
You have to initialize a buffer in order to use it with Lister
. The
function lister-setup
will either create a buffer with the given name,
or erase the contents of an existing buffer. It then prepares the
buffer by adding some text properties and setting some buffer local
variables.
In addition to defining the buffer and the mapper function, you can
optionally define a header
or a footer
. That can be either a string,
or a list of strings, or a zero-argument function which, called in the
Ewoc buffer, returns a string or a list of strings. The strings will
be inserted before or after the actual list.
Use lister-set-{header/footer}
to change the header or the footer.
Pass the value nil
to delete them. If the header or footer is defined
by a function, use lister-refresh-header-footer
to force a redisplay.
To access the currently installed header
or footer
, use the Ewoc
function ewoc-get-hf
.
Lister-setup
returns an ewoc object, which is then used as the basic
reference for all Lister
operations. The ewoc object is also stored in
the buffer local variable lister-local-ewoc
, which can be retreived
with lister-get-ewoc
.
The buffer local variable can be used to access the ewoc in an interactive function, like this:
(defun do-something (ewoc pos)
"Do something at point."
(interactive (list lister-local-ewoc :point))
(when-let ((node (lister-get-node-at ewoc pos)))
(message "You want to do something with %s."
(lister-node-get-data node))))
See also lister-mode.el
for some exemplary interactive functions and
for a macro which helps to define them.
The mapper function is called for each item. It must return a list of strings representing the item.
Per default, the strings are inserted with the property intangible
. If
you want to insert special fields which can also do something, e.g.
editable fields, you can set the field
property to t
. The region
marked by this continuous property will not be intangible, that is,
the cursor can move to it. Since one very likely use case of that
feature is to insert buttons
, the same rule applies to all characters
which are marked with the property button
.
Example:
(defun my-get-button (label &rest properties)
"Make a button LABEL in a temporary buffer and return it as a string.
Pass PROPERTIES to `insert-text-button', which creates the
button."
(with-temp-buffer
(apply #'insert-text-button label properties)
(buffer-string)))
(defun my-action (_)
(message "I have been clicked!"))
(let ((ewoc (lister-setup "NEW "#'list)))
(lister-set-list ewoc (list "Intangible item"
"Intangible item"
(my-get-button "Click me!"
'action 'my-action)))
(switch-to-buffer (ewoc-buffer ewoc)))
;; Insert a single item at POS:
(lister-insert-at ewoc pos data &optional level insert-after)
;; Add to the end of the list:
(lister-add ewoc data &optional level)
;; Replace the item at POS:
(lister-replace-at ewoc pos data)
;; Delete the item at POS:
(lister-delete-at ewoc pos)
Per default, all insert
operations insert at the position indicated,
moving the previous content down. This might result in unintuitive
results, e.g. (lister-insert-at ewoc :last data)
adds the item at the
second last position. Set insert-after
to a non-nil value to insert
after the position indicated (or use lister-add
).
The same principle applies to interactive function which insert lists.
If the cursor is at the bottom of the list, the intended meaning of
“insert at point” is actually “add to the end of list”. The end of
list can be recognized with the function (lister-eolp)
, so that the
following code works:
(defun insert-something-at-point ()
(interactive)
(lister-insert-at lister-local-ewoc
:point
some-data
nil
;; t means: add, don't insert!
(lister-eolp)))
Argument POS
can be either an Ewoc
node, an integer position, or one
of the symbols :first
, :last
, :next
, :prev
, or :point
.
The integer argument level
determines the indentation level and can be
used to begin a new sublist. Note that Lister
automatically corrects
too big values in order to ensure that every new level is just one
level away from the item at POS
. Thus you can safely use
(lister-insert-at ewoc pos data 999)
in order to begin a new sublist.
;; Erase all previous content and set a new list:
(lister-set-list ewoc data-list)
;; Insert a list at POS:
(lister-insert-list ewoc pos data-list &optional level insert-after)
;; Add a list to the end of the EWOC:
(lister-add-list ewoc data-list &optional level)
;; Replace the items from BEG to END with a new (possibly longer or shorter) list:
(lister-replace-list ewoc data-list beg end &optional level)
;; Delete all items from BEG to END:
(lister-delete-list ewoc beg end)
(lister-delete-all ewoc)
Argument POS
can be either an Ewoc
node, an integer position, or one
of the symbols :first
, :last
, :next
, :prev
, or :point
.
The integer argument level
determines the indentation level and can be
used to begin a new sublist. Note that Lister
automatically corrects
too big values in order to ensure that every new level is just one
level away from the item at POS
. Thus you can safely use
(lister-insert-list ewoc pos data-list 999)
in order to insert a whole
sublist.
;; Return the data of a single item:
(lister-get-data-at ewoc pos)
;; Return the data as a list (with sublists as nested lists):
(lister-get-list ewoc &optional beg end start-level pred)
;; Get the sublist at or below POS:
(lister-get-sublist-at ewoc pos)
(lister-get-sublist-below ewoc pos)
;; Map the data of a list (as a tree):
;; Node that PRED-FN and FN applies to the item data
(lister-map ewoc fn &optional pred-fn beg end start-level))
All functions (except lister-get-data
, of course) return a list of
data. Per default, they return the whole list. If there is a sublist
in the specified region, return it as a nested list, e.g. ("A" ("SUB1"
"SUB2") "B"))
. Multiple levels of indentation lead to multiply nested
lists: ("A" (("SUBSUB1" "SUBSUB2")) "B")
.
Arguments POS
, BEG
and END
can be either an Ewoc
node, an integer
position, or one of the symbols :first
, :last
, :next
, :prev
, or
:point
.
All of these functions ignore any active filter.
Since it is often necessary to operate on a sublist or the whole list, we have a macro to normalize these boundaries:
(lister-with-boundaries ewoc beg-var end-var
...BODY..)
This macro binds BEG-VAR and END-VAR according to the following scheme:
If the variables are already bound, use its value to determine the
position. Then these variables are interpreted as a normal position.
Allowed values are an Ewoc
node, an integer position, or one of the
symbols :first
, :last
, :point
, :next
or :prev
. If the variables are
undefined, bind them to the first and the last node of the list,
respectively.
In short, if you use this macro in a function with the arguments BEG
and END
, and you can profit from automatic parsing these arguments and
also be sure that while in BODY
, BEG
and END
always have a valid
value:
(defun a-function (ewoc beg end)
"Do something within BEG and END. Both arguments can be a node,
an integer position, or one of the symbols `:point', `:first',
`:last', `:next' or `:prev'."
(lister-with-boundaries ewoc beg end
(do-something-with-node beg)))
All looping macros also normalize the region in the same way (see below).
;; Doing something with a sublist below POS:
(lister-insert-sublist-below ewoc pos l)
(lister-delete-sublist-below ewoc pos l)
(lister-replace-sublist-below ewoc pos l)
;; Doing something with the sublist at POS:
(lister-delete-sublist-at ewoc pos l)
(lister-replace-sublist-at ewoc pos l)
;; Check if there is a sublist:
(lister-sublist-below-p ewoc pos)
(lister-sublist-at-p ewoc pos)
;;; Helpful macros:
;;
;; Execute BODY with the symbols BEG-SYM and END-SYM bound to the
;; boundaries of the sublist at POS. Do nothing if there is no
;; sublist.
(lister-with-sublist-at ewoc pos beg-sym end-sym
....BODY...)
;; same as above, but looking for a sublist below POS:
(lister-with-sublist-below ewoc pos beg-sym end-sym
....BODY...)
Argument POS
can be either an Ewoc
node, an integer position, or one
of the symbols :first
, :last
, :next
, :prev
, or :point
.
;; All marked items are highlighted by addding the value of that variable:
lister-mark-face-or-property
;; Check if there are marked items:
(lister-marked-at-p ewoc pos)
(lister-items-marked-p ewoc &optional beg end)
(lister-count-marked-items ewoc &optional beg end)
;; Mark or unmark the item at POS:
(lister-mark-unmark-at ewoc pos state)
;; Set a limiting predicate:
(lister-set-marking-predicate ewoc pred)
;; Mark or unmark a whole list:
(lister-mark-unmark-list ewoc beg end state)
(lister-mark-unmark-sublist-at ewoc pos state)
(lister-mark-unmark-sublist-below ewoc pos state)
;; Get data of only the marked items:
(lister-get-marked-list ewoc &optional beg end pred-fn flatten?)
;; Do something with all marked nodes or items:
(lister-walk-marked-nodes ewoc action-fn &optional beg end marker-pred-fn)
(lister-walk-marked-list ewoc action-fn &optional beg end marker-pred-fn)
If STATE
is nil, mark the item or the specified list items; else
unmark them. Optionally set a buffer-local marking predicate using
lister-set-marking-predicate
. If this predicate is set, only mark
items which satisfy it. Setting a new predicate will unmark alreay
marked items which will not match it.
Note that in the case of walking nodes, ACTION-FN
requires two
arguments: the ewoc object and the node. The reason behind this is
that if you choose do to something with the node rather with the data,
it is very likely you will need the ewoc object.
Arguments POS
, BEG
and END
can be either an Ewoc
node, an integer
position, or one of the symbols :first
, :last
, :next
, :prev
, or
:point
.
;; Reverse the list items between BEG and END, or the whole list:
(lister-reverse-list ewoc &optional beg end)
;; Sort the list according to sorting predicate PRED:
(lister-sort-list ewoc pred &optional beg end)
;; Sort the list according to mulitple predicates in a row:
(lister-sort-list ewoc (list #'comp1 #'comp2) &optional beg end)
;; The same with sublists:
(lister-sort-sublist-at ewoc pos pred)
(lister-sort-sublist-below ewoc pos pred)
;; Reorder sublists using any kind of predicate:
(lister-reorder-sublist-at ewoc pos)
(lister-reorder-sublist-below ewoc pos)
;; Note that "reordering" uses a more complicate predicate function
;; than simple sorting. See the documentation of
;; `lister--reorder-wrapped-list' for a more detailed explanation.
Sorting or reversing a list keeps the individual mark state. Arguments
POS
, BEG
and END
can be either an Ewoc
node, an integer position, or
one of the symbols :first
, :last
, :next
, :prev
, or :point
.
You can either pass a single comparator to the sorting function (such
as string>
or a list of comparators, which then will be applied
successively (reduction). This is useful for sorting according to
multiple criteria (e.g. first the name, then within the same name,
ranking by the income, etc.).
A comparator function has direct access to the list data. So if you use a more complex data structure, do not forget to operate on the actual criteria and not on the containing object. E.g.:
(defstruct list-data name income)
(defun sort-it (ewoc)
(cl-labels ((name> (a b) (string> (list-data-name a)
(list-data-name b)))
(income> (a b) (> (list-data-income a)
(list-data-income b))))
(lister-sort-list ewoc (list #'name> #'income>))))
;; if you use the library dash.el:
(defun sort-it (ewoc)
(lister-sort-list ewoc (list (-on #'string> #'list-data-name)
(-on #'> #'list-data-income))))
;; Set and activate a filter predicate:
(lister-set-filter ewoc pred)
;; Check if filter is active:
(lister-filter-active-p ewoc)
;; Predicates:
(lister-node-visible-p)
(lister-node-marked-and-visible-p)
;; Return the filtered ('visible') list:
(lister-get-visible-list ewoc &optional beg end start-level)
;; Find 'visible' nodes matching a predicate:
(lister-next-visible-matching ewoc pos pred)
(lister-prev-visible-matching ewoc pos pred)
;; Return only data currently visible:
(lister-get-visible-list ewoc &optional beg end start-level)
The filter predicate PRED
is a function which receives the list item’s
data as its sole argument. The item is hidden if PRED
returns a
non-nil value (if it “matches” PRED
).
Arguments POS
, BEG
and END
can be either an Ewoc
node, an integer
position, or one of the symbols :first
, :last
, :next
, :prev
, or
:point
.
You can hide or show sublists as an outline:
;; Hide the sublist below POS as an outline:
(lister-outline-hide-sublist-below ewoc pos)
;; Show it:
(lister-outline-show-sublist-below ewoc pos)
;; Cycle it:
(lister-outline-cycle-sublist-below ewoc pos)
;; Show all hidden outlines:
(lister-outline-show-all ewoc)
Arguments POS
, BEG
and END
can be either an Ewoc
node, an integer
position, or one of the symbols :first
, :last
, :next
, :prev
, or
:point
.
;; From POS, find the next or prev node where the data matches PRED:
(lister-next-matching ewoc pos pred &optional limit)
(lister-prev-matching ewoc pos pred &optional limit)
;; same as above, but only consider visible items:
(lister-next-visible-matching pos pred &optional limit)
(lister-prev-visible-matching pos pred &optional limit)
;; Find the first or last node of the sublist around POS:
(lister-top-sublist-node ewoc pos)
(lister-bottom-sublist-node ewoc pos)
;; Find the parent of the sublist around POS:
(lister-parent-node ewoc pos)
;; Find the first sublist node looking in DIRECTION from POS:
(lister-first-sublist-node ewoc pos direction)
Argument POS
can be either an Ewoc
node, an integer position, or one
of the symbols :first
, :last
, :next
, :prev
, or :point
.
Argument limit
is a position (a node, an index value or one of the
symbols :first
, :last
, :point
, :next
or :prev
, which limits the search. The
search stops when reaching the limit and returns nil, even if the node
at limit
matches pred-fn
.
Note that the generic searching functions (which require a predicate function) ignore visibility status, whereas the sublist functions listed in this section don’t return invisible items. Other sublist functions, however, might not check for visibility.
Most generally, you can access nodes or data items within the body of
a looping macro or using a function. Most looping facilities come in
two flavors, marked by the last word of the function name. Functions
ending with -list
loop over the item data (that which is printed);
functions ending with -nodes
loop over the item node (the lister--item
structure in which the data is stored). As a rule of thumb, you should
use -list
functions if you are just concerned with the data, and
-nodes
functions if you need to explicitly know if a node is marked or
invisible.
Basic macros, imperative style:
;; Basic macro to loop over NODES (not items!)
(lister-dolist-nodes (ewoc var-name &optional beg end))
;; same with items:
(lister-dolist (ewoc var-name &optional beg end node-var-name))
;;; Examples:
;; Delete the whole list:
(lister-dolist-nodes (ewoc node :first :last)
(lister-delete-at ewoc node))
;; Return t if one list item matches X:
(lister-dolist (ewoc data)
(when (equal data x)
(cl-return t)))
The body of the loop macros are all wrappend in an implicit cl-block
.
To quit the loop immediately, use (cl-return)
.
More specific functions, more functional style:
;; Collect and maybe map all items between BEG and END:
(lister-collect-list ewoc &optional beg end pred-fn map-fn)
;; same with nodes:
(lister-collect-nodes ewoc &optional beg end pred-fn map-fn)
;; Modifiy the data and redisplay it:
(lister-update-list ewoc action-fn &optional beg end pred-fn)
;; Do something with each node (not item):
(lister-walk-nodes ewoc action-fn &optional beg end pred-fn)
;; see also (documented somewhere else in that file):
;; - lister-walk-marked-{list/nodes} for looping over all marked items
;; - lister-map for mapping
All functions operate on the items specified by BEG
and END
or on the
whole list. Optionally operation can be restricted to those items
matching PRED-FN
.
Note that in the case of lister-collect-list
and lister-update-list
,
PRED-FN
is called with the item’s data (that which is printed), while
lister-collect-nodes
and lister-walk-nodes
operate on the complete
node. In the latter case, PRED-FN
is called with the complete
lister--item
object, the printed data being only one slot of that
encompassing structure.
When collecting stuff, map-fn
can be used to further transform the
data item.
When updating a list, action-fn
receives a data object. If it returns
nil
, it leaves the corresponding item unchanged, else it updates its
value with the new value and redisplays the node.
Note that in the case of walking nodes, ACTION-FN
requires two
arguments: the ewoc object and the node. The reason behind this is
that if you choose do to something with the node rather with the data,
it is very likely you will need the ewoc object.
Arguments BEG
and END
can be either an Ewoc
node, an integer position,
or one of the symbols :first
, :last
, :next
, :prev
, or :point
.
;; Move items vertically. Per default, only move to
;; items with the same indentation level:
(lister-move-item-up ewoc pos &optional ignore-level)
(lister-move-item-down ewoc pos &optional ignore-level)
;; Move items horizontally:
(lister-move-item-right ewoc pos)
(lister-move-item-left ewoc pos)
;; Move sublists:
(lister-move-sublist-up ewoc pos)
(lister-move-sublist-down ewoc pos)
Argument POS
can be either an Ewoc
node, an integer position, or one
of the symbols :first
, :last
, :next
, :prev
, or :point
.
Since Lister
is intended to offer editing facilities, there’s also a
modified flag. It is stored in the buffer local variable
lister-local-modified
.
The modified flag will be set to t
each time an item is deleted,
inserted, or its content is changed. Since moving also internally
works with deleting and inserting, it will also trigger the modified
flag.
;; Buffer local modified flag
lister-local-modified
;; Get the value of the modified flag
(lister-modified-p ewoc)
;; Set the value
(lister-set-modified-p ewoc &optional flag)
It is recommended to add a variable watcher to display the modified flag (e.g. in the header of the list or in the modeline).
;; Check if the list is empty:
(lister-empty-p ewoc)
;; Check if a node is part of the list from beg to end:
(lister-node-in-region-p node beg end)
;; Move point:
(lister-goto ewoc pos)
;; Manually re-set the level of an item:
(lister-set-level-at ewoc pos)
(lister-get-level-at ewoc pos)
;; Redisplay an item (e.g. if its data has changed):
(lister-refresh-at ewoc pos)
(lister-refresh-list ewoc beg end)
;; Retain position when updating display: Execute BODY, then return
;; to the node at point before BODY. Useful when updating the
;; display, and the items change (because this moves the cursor)
(lister-save-current-node BODY)
Arguments POS
, BEG
and END
can be either an Ewoc
node, an integer
position, or one of the symbols :first
, :last
, :next
, :prev
, or
:point
.
Padding and indentation of the levels is regulated by the following variables:
;; integer: add so many whitespaces in front of each item
lister-local-left-margin
;; string: add this string in front of each item according to the item's level
;; level 0 means no padding; level 1 means one time; 2 means 2 time, etc.
lister-local-padding-string
Current visibility cycling uses the invisibility-spec
and is not
recognized internally by the lister
commands. So while hiding an item
using the filter function is mostly taken care of, hiding items using
invisibility-spec
might lead to inconsistent behavior when jumping
around the list, or when adding or removing items.
- Fix bug in lister–outline-invisible-p
lister-mode
: Silently exitview-mode
on enteringlister-mode
, if necessary.- Add option “LIMIT” to
lister-next-matching
andlister-next-visible-matching
- Add hierarchical navigation keys to
lister-mode
(move to parent, move forward or backward same level, move to beginning or end of the sublist), fixing Issue #3
- Add option “LIMIT” to
- Add sorting with multiple predicates / criteria.
- Add “modified” flag.
- Add
lister-save-current-node
- Add marking predicate (thanks to Nathanael kinfe)
- Add function to get the buffer local ewoc (thanks to Nathanael kinfe)
- Add convenience functions to ‘reorder’ sublists (thanks to Nathanael kinfe)
- Add mapping function
- New feature: header or footer can now also be a function.
- New feature: item strings with fields
button
orfield
set will not be intangible and can be reached with normal cursor motion, while the rest of the item remains inaccessible. - Add new public functions
lister-items-marked-p
,lister-eolp
. - Bugfixes, internal refactoring.
- Some bugfixes; add more tests.
- Added minor-mode.
- Added functions to move items and sublists.
- Added outline style hiding of sublists.
- Rewrite the whole package basing it now on
Ewoc
.