[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [External] : [emacs bookmark.el] Sorting by last set

From: Drew Adams
Subject: RE: [External] : [emacs bookmark.el] Sorting by last set
Date: Sat, 4 Jun 2022 16:25:45 +0000

If you decide to consider renaming and redesigning
bookmark sorting to some extent, then I invite you
to consider how Bookmark+ handles it, as food for

This doc section describes its approach to sorting:


(I've also put a plain-text version of that text at
the end of this message.)

I suggest you read that _first_, as it gives an
overall view of sorting from a user point of view.
But below are two doc strings that may also help.

And finally, here is a page that describes the
"apples & oranges" approach to combining sort
predicates that Bookmark+ uses:



Doc of macro `bmkp-define-sort-command'.  It
defines commands to sort the displayed bookmark
list (buffer `*Bookmark List*').

bmkp-define-sort-command is a Lisp macro in 'bookmark+-mac.el'.

(bmkp-define-sort-command SORT-ORDER COMPARER DOC-STRING)

Define a command to sort bookmarks in the bookmark list by SORT-ORDER.
SORT-ORDER is a short string or symbol describing the sorting method.
Examples: "by last access time", "by bookmark name".

The new command is named by replacing any spaces in SORT-ORDER with
hyphens (`-') and then adding the prefix `bmkp-bmenu-sort-'.  Example:
`bmkp-bmenu-sort-by-bookmark-name', for SORT-ORDER `by bookmark name'.

COMPARER compares two bookmarks, returning non-nil if and only if the
first bookmark sorts before the second.  It must be acceptable as a
value of `bmkp-sort-comparer'.  That is, it is either nil, a
predicate, or a list ((PRED...) FINAL-PRED).  See the doc for

DOC-STRING is the doc string of the new command.


Doc of user option `bmkp-sort-comparer'.  It
holds the default value of the predicate(s)
that do the sorting. 

bmkp-sort-comparer is a variable defined in `bookmark+-bmu.el'.

Its value is 
((bmkp-info-node-name-cp bmkp-gnus-cp bmkp-url-cp
 bmkp-local-file-type-cp) bmkp-alpha-p)


Predicate or predicates for sorting (comparing) bookmarks.
This defines the default sort for bookmarks in the bookmark list.

Various sorting commands, such as `s v', change the value of this
option dynamically (but they do not save the changed value).

The value must be one of the following:

* nil, meaning do not sort
* a predicate that takes two bookmarks as args
* a list of the form ((PRED...) FINAL-PRED), where each PRED and
  FINAL-PRED are predicates that take two bookmarks as args

If the value is a list of predicates, then each PRED is tried in turn
until one returns a non-nil value.  In that case, the result is the
car of that value.  If no non-nil value is returned by any PRED, then
FINAL-PRED is used and its value is the result.

Each PRED should return `(t)' for true, `(nil)' for false, or nil for
undecided.  A nil value means that the next PRED decides (or
FINAL-PRED, if there is no next PRED).

Thus, a PRED is a special kind of predicate that indicates either a
boolean value (as a singleton list) or "I cannot decide - let the
next guy else decide".  (Essentially, each PRED is a hook function
that is run using `run-hook-with-args-until-success'.)


 nil           - No sorting.
 string-lessp  - Single predicate that returns nil or non-nil.
 ((p1 p2))     - Two predicates `p1' and `p2', which each return
                 (t) for true, (nil) for false, or nil for undecided.
 ((p1 p2) string-lessp)
               - Same as previous, except if both `p1' and `p2' return
                 nil, then the return value of `string-lessp' is used.

Note that these two values are generally equivalent, in terms of their
effect (*):

 ((p1 p2))
 ((p1) p2-plain) where p2-plain is (bmkp-make-plain-predicate p2)

Likewise, these three values generally act equivalently (*):

 (() p1-plain)
 p1-plain        where p1-plain is (bmkp-make-plain-predicate p1)

The PRED form lets you easily combine predicates: use `p1' unless it
cannot decide, in which case try `p2', and so on.  The value ((p2 p1))
tries the predicates in the opposite order: first `p2', then `p1' if
`p2' returns nil.

Using a single predicate or FINAL-PRED makes it easy to reuse an
existing predicate that returns nil or non-nil.

You can also convert a PRED-type predicate (which returns (t), (nil),
or nil) into an ordinary predicate, by using function
`bmkp-make-plain-predicate'.  That lets you reuse elsewhere, as
ordinary predicates, any PRED-type predicates you define.

For example, this defines a plain predicate to compare by URL:
 (defalias 'bmkp-url-p (bmkp-make-plain-predicate 'bmkp-url-cp))

Note: As a convention, predefined Bookmark+ PRED-type predicate names
have the suffix `-cp' (for "component predicate") instead of `-p'.

* If you use `s C-r', then there is a difference in behavior between

   (a) using a plain predicate as FINAL-PRED and
   (b) using the analogous PRED-type predicate (and no FINAL-PRED).

  In the latter case, `s C-r' affects when the predicate is tried and
  its return value.  See `bmkp-reverse-multi-sort-order'.


Plain-text version of doc section about sorting:

(@* "Sorting Bookmarks")
 *** Sorting Bookmarks ***

Filtering hides certain kinds of bookmarks.  Sometimes,
you want to see bookmarks of various kinds, but you
want them to be grouped or sorted in different ways,
for easy recognition, comparison, and access.

Bookmarks shown in the bookmark list are sorted using
the current value of option `bmkp-sort-comparer'.  (If
that is `nil', they are unsorted, which means they
appear in reverse chronological order of their

You can use `s s'... (repeat hitting the `s' key) to
cycle among the various sort orders possible, updating
the display accordingly.  By default, you cycle among
all available sort orders, but you can shorten the
cycling list by customizing option

You can also change directly to one of the main sort
orders (without cycling) using `s >', `s n', `s f n',
etc.  There are many such predefined sort orders bound
to keys with the prefix `s' - use `C-h m' or `?'  for
more info.

`s >'   - Sort marked (`>') before unmarked
`s *'   - Sort modified (`*') before unmodified
`s 0'   - Sort by bookmark creation date/time
`s b'   - Sort by last buffer or file access
`s a'   - Sort annotated (`a') before unannotated
`s d'   - Sort by last bookmark access date/time
`s D'   - Sort flagged (`D') before unflagged
`s f d' - Sort by last local file access date/time
`s f k' - Sort by local file kind: file, symlink, dir
`s f n' - Sort by file name
`s f s' - Sort by local file size
`s f u' - Sort by last local file update (edit) date/time
`s g'   - Sort by Gnus thread: group, article, message.
`s i'   - Sort by Info manual, node, position
`s k'   - Sort by bookmark type (kind)
`s n'   - Sort by bookmark name
`s t'   - Sort tagged (`t') before untagged
`s v'   - Sort by visit frequency

You can reverse the current sort direction
(ascending/descending) using `s r'.  Also, repeating
any of the main sort-order commands (e.g. `s n') cycles
among that order, the reverse, and unsorted.

For a complex sort, which involves composing several
sorting conditions, you can also use `s C-r' to reverse
the order of bookmark sorting groups or the order
within each group (depending on whether `s r' is also
used).  Try it, for example, together with sorting by
bookmark kind (`s k').

Be aware that `s C-r' can be a bit unintuitive.  If it
does not do what you expect or want, or if it confuses
you, then don't use it ;-).  (`s C-r' has no noticeable
effect on simple sorting.)

Remember that you can combine sorting with filtering
different sets of bookmarks - bookmarks of different
kinds (e.g. Info) or bookmarks that are marked or

Finally, you can easily define your own sorting
commands and sort orders.  See macro
`bmkp-define-sort-command' and the documentation for
option `bmkp-sort-comparer'.  (Bookmark+ uses option
`bmkp-sort-comparer'; it *ignores* vanilla Emacs option

Of particular note is that you can interactively define
commands that sort by a given list of tags - you use
keys `T s' (command `bmkp-define-tags-sort-command') to
do that.  You are prompted for the tags to sort by.
Bookmarks are sorted first according to whether they
are tagged with the first tag, then the second tag, and
so on.  Otherwise, sorting is by bookmark name.

The tags you specify are used, in order, in the name of
the new command.  For example, if you enter tags
`alpha', `beta', and `gamma', in that order, then the
sorting command created is
`bmkp-bmenu-sort-alpha-beta-gamma'.  The new command is
saved in your bookmark commands file

Note that because you can add a new tag to all
bookmarks that have some given set of tags, you can use
that single (new) tag to represent the entire tag set.
Sorting by that tag is then the same as sorting by the
tag set.  You can of course use overlapping sets in the
composite sort command.  You can, for example, sort
first according to tag `tag1', which represents the set
of tags `alpha', `beta', `gamma', `delta', and then
sort according to tag `tag2', which represents the set
of tags `beta', `delta'.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]