Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's the deal with "useful" and "useless" buffers? #6683

Closed
bmag opened this issue Jul 26, 2016 · 11 comments
Closed

What's the deal with "useful" and "useless" buffers? #6683

bmag opened this issue Jul 26, 2016 · 11 comments
Labels
- Mailling list - Buffers stale marked as a stale issue/pr (usually by a bot)

Comments

@bmag
Copy link
Collaborator

bmag commented Jul 26, 2016

Spacemacs has a concept of "useful" and "useless" buffers. The rules for usefuleness are defined and implemented by variables spacemacs-useful-buffers-regexp, spacemacs-useless-buffers-regexp and functions spacemacs/useful-buffer-p, spacemacs/useless-buffer-p. I'm trying to understand what is the rule-of-thumb to decide whether a buffer is useful.

I thought the rule-of-thumb is "if it's normal for the user to want to see this buffer, then it's useful". According to this logic, I plugged spacemacs/useful-buffer-p into buffer-predicate in commit fe60d0f, so functions like next-buffer, other-buffer, etc. skip useless buffers. The commit caused two unexpected issues (#6678, #6681), so the question is: am I wrong, and spacemacs/useful-buffer-p shouldn't be plugged into buffer-predicate? or am I right and it's the current imlpementation just doesn't implement the rules we want?

Usefulness rules, according to current implementation:

  • comint-derived buffers are useful (read: all REPLs and shells, except those
    that don't derive from comint-mode)
  • buffers whose name start with *cider-repl, *ansi-term, *eshell,
    *terminal and end with * (REPLs/shells that might not derive from comint-mode)
  • the scratch buffer
  • buffers whose name doesn't contain *

In short, currently useful buffers are files, directories, REPLs, shells and the scratch buffer. This excludes also buffers that the user interacts with, like notmuch buffers (see #6681), *IBuffer* and magit buffers.

For context, in the previous situation, useful/useless buffer distinction was only used by SPC b n and SPC b p which where bound to are own implementations of next-buffer and previous-buffer. My commit was discussed in #6574 and fixes #6159.

@a13ph
Copy link

a13ph commented Jul 26, 2016

@bmag FYI this distinction is (at least originally) from vanilla Emacs and its packages. E,g. code for managing buffers which should [not] be garbage collected. So it's not Spacemacs initiated term.
That's just my understanding/memory, EmacsWiki might have more about that
No comment on the substance of this issue yet (too tired even to read it, so pardon if my msg is irrelevant).

@TheBB
Copy link
Collaborator

TheBB commented Jul 27, 2016

Presumably the useless buffer regexp is too permissive. It should perhaps be "^\\*.*\\*$"?

Does anyone know what the default buffer-predicate is?

@bmag
Copy link
Collaborator Author

bmag commented Jul 27, 2016

By default there's no buffer-predicate, so no filtering. Package persp-mode from layer spacemacs-layouts uses buffer-predicate, presumably to filter buffers from current layout.

It should perhaps be "^\\*.*\\*$"?

I thought so too, at first, but then I remembered buffers can start with space or end with <number>, e.g. " *Echo Area*" and "*some-name*<2>". We can use "^ ?\\*.*\\*\\(<[0-9]+>\\)?$".
It probably catches the same buffers as the simpler "*.+", because it's rare for buffer names to have * not at the beginning or the end. I think maybe we should replace it with specific rules (e.g. for helm buffers, *Messages*) so we allow Occur buffers (for example), but I'm not too sure about it.

@syl20bnr
Copy link
Owner

Sorry if what I'm writing sounds trivial but I try to catch up on this issue.

Two possibilities:

  • We define a base regexp that's restrictive enough to not catch unwanted buffers and then update the filters at the layer level to fine tune them, for example this should be added in the notmuch layer (well we don't have one, this is just for illustration).
  • Or we can go the other way around by defining a base regexp very permissive and fine tune the filters to exclude additional buffers.

The current implementation may fit better the first possibility but the less intrusive solution is the second one. Maybe reversing the filter priority may allow to go with the second possibility which makes more sense: we allow a lot of buffers by default until one (or a family) becomes annoying and we filter it out.

@bmag
Copy link
Collaborator Author

bmag commented Aug 26, 2016

Having a blacklist and an overriding whitelist (the first option) implies that all buffers are white by default, unless matched by the blacklist. The first option is equivalent to a base regexp that is very permissive (it just matches everything), so I think the two possibilities are: (am I'm just rephrasing what you meant?)

  • use spacemacs-useless-buffers-regexp (which is actually a list of regexps) to match a lot of buffers by default, then use spacemacs-useful-buffers-regexp (which is also a list) heavily to allow some kinds of buffers (notmuch, magit, ibuffer, ...)
  • use spacemacs-useless-buffers-regexp to match specific buffers (or families), then use spacemacs-useful-buffers-regexp to allow specific buffers from blacklisted families

@rgrinberg
Copy link
Contributor

What about moving away from just using regexps to specify this useful/useless distinction?

I have some use cases where I want to mark some asterisk buffers as useful but there's really no regex that can catch all these buffers (the concrete use case is notmuch buffers if you're wondering). It would be a lot easier if I could just set usefulness based on the major mode instead (since all notmuch buffers inherit from 1 mode).

What about upgrading this list of regexps to a list of predicates that take a buffer perhaps? It would still support all the old regexp patterns, but would allow to determine usefulness based on other properties.

@syl20bnr
Copy link
Owner

syl20bnr commented Feb 9, 2017

@rgrinberg indeed it would be better to do this.

I think we should make this useful/unuseful buffer feature an explicit feature, I mean we should have dedicated key bindings to use these lists, or we could use the universal prefix argument to use these lists. For instance SPC b n does not filter the buffers but SPC b N or C-u SPC b n does. The transient states adapts atomatically to the chosen version.

@mkaito
Copy link
Contributor

mkaito commented Feb 16, 2017

I've run into an issue where I would like to define dired buffers as generally not useful, in the context of switching between buffers. There is no way to catch these with a regexp, since the buffer name is simply the visited folder's name, but a predicate could probably catch these easily.

I figured out a way to achieve this using advice-add:

(defun my-buffer-file-name (oldfun buffer)
  "Advise spacemacs/useful-buffer-p to exclude dired buffers"
  (if (funcall oldfun buffer)
      (not (with-current-buffer buffer
          (derived-mode-p 'dired-mode)))))
(advice-add 'spacemacs/useful-buffer-p :around #'my-buffer-file-name)

Took me forever to figure out that I had to use funcall instead of apply when using named args instead of a &rest args splat. Emacs could really point one at the line of code that produces a certain warning/error instead of just saying something like error: list-p <buffer>. But I digress.

How about adding a hook in spacemacs/useful-buffer-p to allow a user to add some predicates to the chain?

@Stebalien
Copy link
Contributor

Alternatively, we could use a buffer-local variable. You could then use (add-hook 'dired-mode-hook (lambda () (setq-local spacemacs-buffer-is-useless t))). On the other hand, a hook might allow a more context dependent definition of uselessness, i.e. "buffer is relevant", but that sounds more like the job of purpose/layouts.

Note: the problem with the current heuristic is that the * in *Buffer Name... is just a convention to mean that the buffer doesn't correspond to a real file on disk.

@braham-snyder
Copy link
Contributor

braham-snyder commented Mar 18, 2017

I've recently changed to using only:

(setq spacemacs-useless-buffers-regexp '("^ "))

since I'd rather see, e.g., a *Customize* buffer, skipping it when needed, than add a rule for *Messages*, *Colors*, *Faces*, every shell I use, etc. This seems to work fairly well, since -- as noted in this comment, and at https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffer-Names.html -- many of the buffers we truly don't want to switch to with, e.g., previous-buffer, have buffer names starting with a space.

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please let us know if this issue is still valid!

@github-actions github-actions bot added the stale marked as a stale issue/pr (usually by a bot) label Feb 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
- Mailling list - Buffers stale marked as a stale issue/pr (usually by a bot)
Projects
Mailing list
  
Acknowledged
Development

No branches or pull requests

8 participants