unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* bmenu for recentf (or abstracting-away bmenu)
@ 2023-11-16  3:13 Lockywolf
  2023-11-16  7:03 ` Yuri Khan
  2023-11-16 16:46 ` [External] : " Drew Adams
  0 siblings, 2 replies; 3+ messages in thread
From: Lockywolf @ 2023-11-16  3:13 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org

Dear Emacs Developers/Users

I want to have a buffer-menu for recent files, in a way similar to
bookmarks.

In fact, the bmenu code in bookmarks.el is just about 700 lines, not
very huge, so I considered writing it myself. However, later I thought
that this would mean effectively duplicating a lot of code which might
happen to be useful in other packages too.

Are there some plans on creating a common bmenu library for Emacs?
Perhaps it could also integrate with the menu-bar mode somehow (which
would be less surprising for the users used to the Windows way of
self-discovery). Or maybe such a library already exists?

-- 
Your sincerely,
Vladimir Nikishkin (MiEr, lockywolf)
(Laptop)



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: bmenu for recentf (or abstracting-away bmenu)
  2023-11-16  3:13 bmenu for recentf (or abstracting-away bmenu) Lockywolf
@ 2023-11-16  7:03 ` Yuri Khan
  2023-11-16 16:46 ` [External] : " Drew Adams
  1 sibling, 0 replies; 3+ messages in thread
From: Yuri Khan @ 2023-11-16  7:03 UTC (permalink / raw)
  To: Lockywolf; +Cc: help-gnu-emacs@gnu.org

On Thu, 16 Nov 2023 at 12:54, Lockywolf
<for_help-gnu-emacs_at_gnu_org_2023-11-16@lockywolf.net> wrote:

> I want to have a buffer-menu for recent files, in a way similar to
> bookmarks.
>
> In fact, the bmenu code in bookmarks.el is just about 700 lines, not
> very huge, so I considered writing it myself. However, later I thought
> that this would mean effectively duplicating a lot of code which might
> happen to be useful in other packages too.
>
> Are there some plans on creating a common bmenu library for Emacs?
> Perhaps it could also integrate with the menu-bar mode somehow (which
> would be less surprising for the users used to the Windows way of
> self-discovery). Or maybe such a library already exists?

The abstraction behind bmenu is called tabulated-list-mode. Here’s a
simplified extract from my config implementing a recent files
navigator. The core functionality is just about 50 lines of code and
all of it is domain-specific (cannot be abstracted).

You start with a top-level command to conjure a buffer and put it into
a major mode derived from ‘tabulated-list-mode’:

    (defun yk-recentf-show ()
      "Show a list of recently opened files."
      (interactive)
      (with-current-buffer (get-buffer-create " *Recentf*")
        (yk-recentf-show-mode)              ;; see below
        (tabulated-list-revert)
        (pop-to-buffer (current-buffer))))

That mode needs to set a few buffer-local variables to teach the base
mode how to display entries and how to revert itself on ‘g’:

    (define-derived-mode yk-recentf-show-mode
      tabulated-list-mode
      "Recentf"
      "Major mode for `yk-recentf-show' buffers."
      (setq tabulated-list-format [("M" 1 nil)
                                   ("Filename" 20 nil)
                                   ("Directory" -1 nil)])
      (setq-local tabulated-list-revert-hook 'yk-recentf-show--revert)
 ;; see below
      (tabulated-list-init-header))

Your revert hook needs to populate the buffer-local
‘tabulated-list-entries’ with a list whose each element is a list of
an ID and a vector of cell values:

    (defun yk-recentf-show--revert ()
      "Re-populate the buffer listing recently opened files."
      (setq tabulated-list-entries
            (mapcar (lambda (filename)
                      `(,filename [""
                                   ,(file-name-nondirectory filename)
                                   ,(file-name-directory filename)]))
                    recentf-list)))

That’s basically all you need for the displaying part. Now for the
acting part. You define a keymap for the derived mode (named by
‘*-map’ convention so the mode uses it automatically):

    (defvar yk-recentf-show-mode-map
      (let ((map (make-sparse-keymap)))
        (define-key map (kbd "RET") 'yk-recentf-show-find-file)
        (define-key map (kbd "o") 'yk-recentf-show-find-file-other-window)
        map))

The handlers are simple wrappers that get the ID of the entry at point
and pass it to whatever command:

    (defun yk-recentf-show-find-file ()
      "Visit the file at point."
      (interactive)
      (find-file (tabulated-list-get-id)))

    (defun yk-recentf-show-find-file-other-window ()
      "Visit the file at point in other window."
      (interactive)
      (find-file-other-window (tabulated-list-get-id)))

All that is left now is to bind the top-level command to some easy
key. I use Alt+F11 in memory of a certain blue-and-cyan text mode file
manager on a popular non-free platform.

    (global-set-key (kbd "M-<f11>") 'yk-recentf-show)


One thing I found lacking in the base tabulated-list-mode is generic
support for marks and deletion. Like, in Dired, Bmenu, and Ibuffer you
can type ‘D’ to delete an entry at point immediately (possibly after
confirmation), ‘d’ to mark an entry for deletion, ‘x’ to delete all
entries marked thus, ‘m’ to mark for other operations, and ‘u’ to
unmark. With tabulated-list-mode, you have to program all that for
every derived mode. It could be abstracted by defining a buffer-local
variable that would point to a mode-specific deletion function (taking
an ID); all the marking mechanics could be implemented generically.

As for menu bar integration, I’m not interested. Emacs tends to
accumulate buffers, bookmarks, and recent files in numbers that are
unwieldy in a pull-down menu but work just well in a tabulated-list
buffer.



^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [External] : bmenu for recentf (or abstracting-away bmenu)
  2023-11-16  3:13 bmenu for recentf (or abstracting-away bmenu) Lockywolf
  2023-11-16  7:03 ` Yuri Khan
@ 2023-11-16 16:46 ` Drew Adams
  1 sibling, 0 replies; 3+ messages in thread
From: Drew Adams @ 2023-11-16 16:46 UTC (permalink / raw)
  To: Lockywolf, help-gnu-emacs@gnu.org

> I want to have a buffer-menu for recent files,
> in a way similar to bookmarks.

Not sure just what you mean by a buffer menu for
recent files, similar to bookmarks.

But if you use Dired+ then you have these commands,
which give you Dired listings of recent files and
directories: `diredp-dired-recent-files' and
`diredp-dired-recent-dirs'.

You can optionally add other files/dirs to such a
listing, and optionally exclude files/dirs from it.
___

  C-x D R runs the command diredp-dired-recent-files,
  which is an interactive compiled Lisp function in
  'dired+.el'.

  It is bound to menu-bar subdir diredp-dired-recent-files, C-x D R.

  (diredp-dired-recent-files BUFFER &optional ARG)

  Open Dired in BUFFER, showing recently visited files and directories.
  You are prompted for BUFFER (default: `Recently Visited Files').

  With a numeric prefix arg you can enter names of recent files to
  include or exclude.

  No prefix arg or a plain prefix arg (`C-u', `C-u C-u', etc.) means
  list all of the recently used files.

  With a prefix arg:
  * If 0, `-', or plain (`C-u') then you are prompted for the `ls'
    switches to use.
  * If not plain (`C-u') then:
    * If >= 0 then the files to include are read, one by one.
    * If  < 0 then the files to exclude are read, one by one.

  When entering files to include or exclude, use `C-g' to end.

  The file listing is sorted by option
  `diredp-default-sort-arbitrary-function', if non-nil.  If nil (the
  default) then the listing is in reverse chronological order of opening
  or writing files you access.

  Use `g' to revert the buffer, as usual.  If you use it without a
  prefix arg then the same files are relisted.  A prefix arg is handled
  as for `C-x D R itself.

  When called from Lisp, ARG corresponds to the raw prefix arg.
___

  C-x D r runs the command diredp-dired-recent-dirs,
  which is an interactive compiled Lisp function in
  'dired+.el'.

  It is bound to menu-bar subdir diredp-dired-recent-dirs, C-x D r.

  (diredp-dired-recent-dirs BUFFER &optional ARG)

  Open Dired in BUFFER, showing recently visited directories.
  Like `diredp-dired-recent-files', but limited to recent directories.
  A directory is recent if any of its files is recent.
___

You can sort such a listing in various ways, but you
need to use `C-M-L' (aka `C-M-S-l') to do so - you can't
use the ordinary Dired sort commands, such as `s'.

You're prompted for the sort order for such buffers:

* Last-access order, most recent first (default)
* Last-access order, least recent first
* A-Z (alphabetical), by last part of file/dir name
* A-Z, by full file/dir name
* Z-A, by last part of name
* Z-A, by full name

The default sort order is determined by option
`diredp-default-sort-arbitrary-function'.  It
defaults to most recent first.
___

https://www.emacswiki.org/emacs/DiredPlus

https://www.emacswiki.org/emacs/download/dired%2b.el




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-11-16 16:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-16  3:13 bmenu for recentf (or abstracting-away bmenu) Lockywolf
2023-11-16  7:03 ` Yuri Khan
2023-11-16 16:46 ` [External] : " Drew Adams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).