Closed agenbite closed 2 years ago
I'm trying
prescient-forget
and I guess there's something I don't get about the inner workings of prescient.el. For example, if I callfind-file
, I get a nice list of files. Then, if I callconsult-buffer
, I get an even nicer list of buffers and other things However, if I callprescient-forget
on any of the two prompts, I get a list of candidates to forget which mixes up candidates from bothfind-file
andconsult-buffer
. In fact, I get candidates from other prompts as well, which makes it hard to know what's what.
I'm not sure what you mean by "on the prompt". prescient-forget
can be run using M-x prescient-forget
. You don't need to run another command beforehand, if that's what you are referring to.
Prescient works by recording candidates selected by completion UIs like Company or Selectrum. The frequencies of selected candidates are recorded in one table and the recency of selected candidates in another.
These two tables are used for all selected candidates for commands. The candidates are not currently separated by which command produces a list of candidates or in which history variable (those outside of Prescient) a candidate is recorded. This lack of separation means that a candidate's ranking applies across commands. For example, if one reads a candidate's documentation using describe-function
, that candidate will be suggested when completing function names using Company.
prescient-forget
presents the candidates recorded in the tables, so it shows candidates used in all commands. Forgetting a candidate means deleting the ranking from the tables, which applies to all commands.
So, I guess my question is if there's a way to get a contextually relevant list of candidates upon calling
prescient-forget
.
Not at the moment, no. The sorting does not consider context. This was requested in #85, but it hasn't been implemented yet.
On Fri Mar 11, 2022 at 6:15 PM CET, okamsn wrote:
I'm not sure what you mean by "on the prompt".
prescient-forget
can be run usingM-x prescient-forget
. You don't need to run another command beforehand, if that's what you are referring to. Exactly. I was thinking that I could do something like editing the list of candidates "on-the-fly", so to speak, and now I understand that the edition needs not be at the same time. Thanks for your detailed explanation.Not at the moment, no. The sorting does not consider context. This was requested in #85, but it hasn't been implemented yet. Good to know. I'll keep an eye on that.
Thanks again! :)
I'll add here that, apparently, it is not possible to use prescient-forget
to edit the history of candidates that one gets with M-r
in Selectrum (from the docs: "M-r
will invoke an improved version of history search with completion"). I believe it'd be great to have a single coherent way to access and edit the candidate history.
I'll add here that, apparently, it is not possible to use
prescient-forget
to edit the history of candidates that one gets withM-r
in Selectrum (from the docs: "M-r
will invoke an improved version of history search with completion").
Yes, selectrum-select-from-history
is just the normal minibuffer history. The minibuffer history accessed with M-p
and M-n
is a normal Emacs feature that is unaffected by Prescient.
I believe it'd be great to have a single coherent way to access and edit the candidate history.
Try the below for editing the completion history variable. It seems to mostly work for me on Emacs 28.0.92.
consult-completing-read-multiple
seems to work fine with it, but selectrum-completing-read-multiple
is a bit odd when selecting multiple file paths. It can always be changed to normal completing-read
.
(require 'seq)
(require 'selectrum)
(defun selectrum-remove-cands-from-hist ()
"Remove candidates from hist.
Must be run inside command. All instances of candidates are removed."
(interactive)
(let* ((selectrum-should-sort nil)
(hist (symbol-value minibuffer-history-variable))
(cands (completing-read-multiple "Candidates: " hist
nil t nil t)))
(set minibuffer-history-variable (seq-difference hist cands))))
(define-key selectrum-minibuffer-map (kbd "C-c d")
#'selectrum-remove-cands-from-hist)
Oh, thanks, @okamsn!! I've tried your code on Emacs 27.1 and, unfortunately, I get "symbol's function definition is void: t". Might that be related to my Emacs version?
EDIT: I've updated to the last Emacs master and I have the same result. What I'm doing is calling selectrum-remove-cands-from-hist
after doing M-r
in a prompt (for a notmuch tagging operation, if that's relevant).
Try using it after M-x
or C-x C-f
(though note the quirk mentioned above). It won't work for commands that disable their history, like selectrum-select-from-history
. History is disabled by passing t
as the name of the history variable, which I think is the source of the error you see. I'll update the example in a bit.
EDIT:
Please try this version of the example command:
(require 'seq)
(defun selectrum-remove-cands-from-hist ()
"Remove candidates from hist.
Must be run inside a command like `find-file' or
`execute-extended-command'. All instances of candidates are
removed.
This command only edits Emacs's history variables. It does not
affect features like prescient.el. For that, see `prescient-forget'."
(interactive)
(cond
((eq t minibuffer-history-variable)
(user-error "No history for this command"))
((not (boundp minibuffer-history-variable))
(user-error "History variable not bound: `%s'" minibuffer-history-variable))
(t
(let* ((selectrum-should-sort nil)
(hist (symbol-value minibuffer-history-variable))
(cands (completing-read-multiple "Candidates: " hist
nil t nil t)))
(set minibuffer-history-variable (seq-difference hist cands))))))
(define-key selectrum-minibuffer-map (kbd "C-c d")
#'selectrum-remove-cands-from-hist)
Thank you for your patience and your help. It is hard for me to understand how this software works, and I don't want to sound as if I was expecting a solution to be developed for me. With this in mind, what follows is valuable only if it helps others and me to learn more about Prescient and Selectrum.
The solution you proposed does not really work in my case. If I do M-x
and then C-c d
, I can indeed select a candidate for removal. However, when I go back to the M-x
selection list, that candidate is still there (it is not to be found if I call C-c d
again, so it has in fact been removed somehow from somewhere). Surprisingly, if I cancel the selection at that point and hit M-x
again, I get the "removed" candidate on top!
The situation is similar if I try to edit the list of frecently applied tags in notmuch, which I believe uses completing-read-multiple
. Furthermore, in this case, if I try to delete a candidate after having used Selectrum's M-r
functionality to get a list of the multiple tag candidates history, nothing happens.
Is there a way to being able to remove candidates from the very list I'm actually seeing when I call the selectrum-remove-cands-from-hist
function? Would it maybe be possible to use embark to get that list into a buffer which one can edit, for example?
Thanks again! :)
Thank you for your patience and your help. It is hard for me to understand how this software works, and I don't want to sound as if I was expecting a solution to be developed for me. With this in mind, what follows is valuable only if it helps others and me to learn more about Prescient and Selectrum.
There are two things:
M-p
in the minibuffer will suggest the most recently used
previous candidates first.minibuffer-history
).selectrum-select-from-history
.selectrum-remove-cands-from-hist
.
M-p
is
used. That seems to be correct according to a quick check.
TAB
) and
submission (RET
) of candidates in supported completion UIs, such as
Selectrum and Company.Prescient is for sorting lists of candidates (and filtering, of course). It is
a similar but separate feature from the minibuffer history recorded by Emacs.
There are times when one might wish to use a previous candidate via M-r
that
was not used recently or frequently. Having both allows this. For example, I
have prescient-history-length
set to 100 but the normal history-length
set
to 200.
Does this explanation make sense?
The solution you proposed does not really work in my case. If I do
M-x
and thenC-c d
, I can indeed select a candidate for removal. However, when I go back to theM-x
selection list, that candidate is still there (it is not to be found if I callC-c d
again, so it has in fact been removed somehow from somewhere). Surprisingly, if I cancel the selection at that point and hitM-x
again, I get the "removed" candidate on top!
This behavior is the difference between the minibuffer history and Prescient sorting.
The process was this:
M-x
is next used, the command that was removed from Emacs's minibuffer
history is sorted to the top by Prescient, as it was a recently used
candidate in another command (in selectrum-remove-cands-from-hist
).This raises the question of what is meant by "removal". For Emacs's minibuffer history, that means deleting the candidate from the list variable. For Prescient, that can mean removing the candidate from Prescient's records, or, in other words, forgetting about the candidate.
However, Prescient forgetting about a candidate does not remove a
candidate from the candidate list. It only sorts the candidate lower in the
list, treating it like every other unrecognized candidate. Prescient's sorting
method does not add or remove candidates from the candidate list, it only sorts
them. The list of available candidates comes from the command itself, such as
M-x
or find-file
.
For example, if I use a command which allows arbitrary input, that arbitrary
input will be recorded by Prescient as being recently used, but it will never be
sorted near the top of a list of candidates unless it already occurs in that
list. It will, however, be added to the front of the history variable and will
show up when using M-r
with that command.
The situation is similar if I try to edit the list of frecently applied tags in notmuch, which I believe uses
completing-read-multiple
. Furthermore, in this case, if I try to delete a candidate after having used Selectrum'sM-r
functionality to get a list of the multiple tag candidates history, nothing happens.
If you mean that you tried to edit the history within M-r
, that won't work.
Because selectrum-select-from-history
is itself a completing command, it has
its own (disabled) history, which stops selectrum-remove-cands-from-hist
from
knowing which history variable was used by the command from which
selectrum-select-from-history
was called. You saw the effects of this earlier
in the error about t
, which selectrum-select-from-history
passes as the name
of its history variable (disabling history for itself).
Is there a way to being able to remove candidates from the very list I'm actually seeing when I call the
selectrum-remove-cands-from-hist
function?
The candidates that are listed by the example selectrum-remove-cands-from-hist
are the same that are listed by selectrum-select-from-history
. It's just that
the former doesn't work within the latter, due to the reasons described above.
The name of the history variable is reset for each recursive completion command.
Would it maybe be possible to use embark to get that list into a buffer which one can edit, for example?
I've tested it using embark-export
and it does seem to edit the history variable
as expected, though the list of items isn't updated in the Embark buffer. I'm
not familiar with Embark enough to know how to change that.
In summary:
prescient-forget
to sort a candidate lower in the list. This will not
remove candidates from the command's list of candidates.selectrum-remove-cands-from-hist
to remove
candidates from the history variable. This will not remove candidates from
the command's list of candidates, only the list of previous candidates
recorded by Emacs. This does not affect Prescient's records, which are
separate.
M-r
,
but selectrum-remove-cands-from-hist
will not work inside M-r
. This is
because selectrum-select-from-history
itself has its own history settings,
preventing the example command from seeing anything further up.If you're wondering, selectrum-select-from-history
does not use Prescient for
sorting. The candidates are displayed as they exist in the history variable.
Does this answer your questions?
Wow. Thank you so much for such a detailed answer. I'll read it slowly. It is indeed helpful.
After carefully reading your answer, yes, it answers my questions very well. Thanks again! :)
I'm trying
prescient-forget
and I guess there's something I don't get about the inner workings of prescient.el. For example, if I callfind-file
, I get a nice list of files. Then, if I callconsult-buffer
, I get an even nicer list of buffers and other things. However, if I callprescient-forget
on any of the two prompts, I get a list of candidates to forget which mixes up candidates from bothfind-file
andconsult-buffer
. In fact, I get candidates from other prompts as well, which makes it hard to know what's what.So, I guess my question is if there's a way to get a contextually relevant list of candidates upon calling
prescient-forget
.