embark icon indicating copy to clipboard operation
embark copied to clipboard

Action, target finder, target collector and exporter wishlist

Open oantolin opened this issue 4 years ago • 193 comments

I think I might be missing many opportunities for target finders, target collectors and exporters. Let's list some here in this issue:

Target finders

  • in eww buffers, the link at point could be targeted as a url.

Target collectors

  • in eww buffers, all the links could be collected as urls. Or a new type weblink could be introduced which has both a url and a title.

Enhancements to existing collectors:

  • the collect collector, when the region is active could collect only the candidates in the region
  • the dired collector could collect only the marked files
  • similarly, the ibuffer collector could collect only the marked buffers

Exporters

  • ~~bookmark should export to bookmark-bmenu-mode.~~ Done.
  • ~~line should export to occur-mode.~~ line was renamed consult-location and it does export to occur mode now!
  • url or weblink if introduced could export to eww-bookmark-mode, which seems like a reasonable mode for a list of links even if they are not actually bookmarks. (I'm not sure about this.)

Actions

  • url could use a download action (I'm thinking I'd only use this outside of eww buffers).
  • kill-ring could use a "remove from kill-ring" action.

oantolin avatar Jan 08 '21 17:01 oantolin

We should also think about exporters run from non-mini buffers. One that has been suggested is that in an eww buffer, export could make a list of all the links. I'm not so sure about that, probably a consult-link command is better and you can always run embark export from inside that hypothetical consult-link.

But I'm sure there are some good opportunities for export from regular buffers I'm missing. Currently the only ones are kind of boring: dired buffers export their files, ibuffers export their buffers, *Completions* buffers export their completions. Of course, dired and ibuffer are full-featured and you can also act on completions in a *Completions* buffer, so all of these exports are kind of pointless ---although I guess you do gain grid and zebra views in all cases, and the direct action minor mode might be useful for *Completions*.

oantolin avatar Jan 08 '21 17:01 oantolin

Is there also a target finder wishlist? Or is the list already exhautive?

minad avatar Jan 08 '21 18:01 minad

The target finder list is not exhaustive at all! Should I make a separate issue for that or just broaden this one?

oantolin avatar Jan 08 '21 18:01 oantolin

I would use one wishlist as I have in consult. I think this works quite well as some kind of general discussion thread before the details are then discussed in a separate dedicated issue.

minad avatar Jan 08 '21 18:01 minad

Earlier when I mentioned eww links I was really talking about just collecting them and forgot to say what kind of buffer they should export to: maybe an eww-bookmark-mode buffer is reasonable, even though they aren't bookmarks.

oantolin avatar Jan 08 '21 18:01 oantolin

OK, I've broadened this issue on your advice @minad. (I don't want the wishlist to also cover new commands, since in fact, I'm pretty skeptical about adding any new top-level commands to Embark at this point, except possibly the resume functionality, if we think it fits better in Embark.)

oantolin avatar Jan 08 '21 18:01 oantolin

Oh, I just remembered some actions for variables I often miss: set-variable and customize-set-variable, maybe even customize-variable.

oantolin avatar Jan 08 '21 19:01 oantolin

Good news: now consult-line, consult-outline, consult-mark and consult-global-mark export to occur mode buffers and e (for occur-edit-mode) works in them!

oantolin avatar Jan 09 '21 20:01 oantolin

@oantolin This is amazing! I already have it mentioned here: https://github.com/minad/consult#integration-with-embark. Now I can remove the work in progress note :partying_face:

minad avatar Jan 09 '21 21:01 minad

Oh, I just remembered some actions for variables I often miss: set-variable and customize-set-variable, maybe even customize-variable.

I added these for variables, and for commands I added execute-extended-command, global-set-key and local-set-key. 846cfbd7212ba3a3a47a059ba35400d534968815

oantolin avatar Jan 10 '21 03:01 oantolin

I am just sharing this good idea for targeting video links: https://jao.io/blog/2021-01-09-embarking-videos.html. Natural complements are audio files and an action to yt-dl the target (audio could call mpv with the --no-video flag).

Maybe this is something that can be of use.

protesilaos avatar Jan 10 '21 09:01 protesilaos

@oantolin the actions for variables and commands are not available here. I checked that the commit you referenced is applied, value of embark-keymap-alist set accordingly, etc. But when I act on something like (defcustom e|mbark-keymap-alist (point at "|" char) I don't see customize or set variable options, same with commands like embark-act (version 20210111.1408). Can I see which map has been selected somewhere?

[edit: (embark--target) returns (symbol . "name") when invoked from source code. It works in C-h v etc. So an extended classifier for elisp variables/commands would be great]

sheijk avatar Jan 11 '21 20:01 sheijk

org-mode classifiers and actions would also be great. Or would this be better for an external package?

sheijk avatar Jan 11 '21 20:01 sheijk

@sheijk The variable and command specific actions are currently only available from minibuffer commands for those categories. For example you get the command actions for candidates in M-x in recent Emacsen. If you use Marginalia, then you get the command actions in M-x even on older Emacsen. And again, with Marginalia, you get the variable actions from describe-variable, for example, or from customize-variable.

The point is that, as you found, they are not supposed to work on symbols in regular buffers... yet! I've been thinking about refining the type. It would be much better once the multiple-targets stuff is finished #92, but for now I guess I could just pick an order: prefer command over variable if the symbol is both things. If Emacs were extended in Guile we wouldn't have these problems... 😛

oantolin avatar Jan 11 '21 21:01 oantolin

org-mode classifiers and actions would also be great. Or would this be better for an external package?

Possibly a separate package would be better, I'm not sure. I mean Org does come with Emacs. But that can be decided later, the first thing is to decide what kinds of targets and actions would be useful in Org buffers. Did you have any thing in mind? For a target type to be really useful ideally it should have several associated actions.

oantolin avatar Jan 11 '21 21:01 oantolin

Separate package makes sense, or at least a separate elisp file to not require loading org-mode when embark gets used in other buffers. I've recently made a little transient based menu for org, I think most actions offered there would be good embark candidates. Some examples for actions would be:

  • TODO items - toggle next state, set explicit state, remove state
  • Headline - same as TODO, org-update-checkbox-count, move up/down, (de)indent, cut tree
  • Timestap - change date, toggle type, show in calendar
  • Link - open, edit
  • Region - toggle bold/italic/..
  • List items - set to "[ ]", "[x]", "[-]", no checkbox, indent/outdent, org-list-repair, org-list-make-subtree, cycle-style, maybe move up/down
  • Table: evaluate (cell/line/all/all-until-nothing-changes), add/delete/move row/column, edit field, blank field, org-copy-down, set field/column formula

sheijk avatar Jan 11 '21 21:01 sheijk

I think your suggested org targets and actions are very good and that a separate embark-org (or org-embark?, how does that work?) package with them would be reasonable, but, wow, your org-menu package looks fantastic, @sheijk! I'd say your package takes the pressure off Embark to provide similar functionality with a different interface. 😄

oantolin avatar Jan 11 '21 23:01 oantolin

You could create an embark-org.el file similar to consult-flymake.el in order to retain lazy loading but distribute it as part of embark melpa.

minad avatar Jan 11 '21 23:01 minad

@oantolin or maybe start it with the actions I already made. Are you looking for contributions (no promise!)?

sheijk avatar Jan 11 '21 23:01 sheijk

@sheijk I added a transformer to refine symbol to command or variable if possible, for when you act on the symbol at point in a regular buffer. 296ad8077092ff839029c0bdb53c279e921e5354

oantolin avatar Jan 12 '21 00:01 oantolin

I am just sharing this good idea for targeting video links: https://jao.io/blog/2021-01-09-embarking-videos.html. Natural complements are audio files and an action to yt-dl the target (audio could call mpv with the --no-video flag).

Thanks for pointing this out, @protesilaos. I wrote to jao to suggest a slightly different implementation which he wrote about, and I noticed he also wrote an async Spotify client using Consult and Marginalia!

oantolin avatar Jan 12 '21 01:01 oantolin

oantolin: I wrote to jao to suggest a slightly different implementation which he wrote about, and I noticed he also wrote an async Spotify client using Consult and Marginalia!

Yes, I have read them. My plan is to copy and adapt the video targeting part (never used spotify). More generally, I am excited to see what kind of solutions, tips and tricks the community comes up with for those packages.

protesilaos avatar Jan 12 '21 09:01 protesilaos

@oantolin @protesilaos Regarding the spotify client, it is exciting that they implemented a web access using the async api! I have some small experiments in the consult websearch branches as well, but they turned out to be not useful.

minad avatar Jan 12 '21 11:01 minad

I think the way Embark works on a regular buffer is too Elisp-centric. Hopefully most people spend most of their time in Emacs doing other things!

For the purposes of embark-target-symbol-at-point, I would argue that symbol should mean a symbol in the current major mode. So the d action would be bound to xref-find-definitions. It's less clear what to bind to h, since there's no “describe thing at point” in xref (or whatever Emacs component this would fit into). Anyway, I suggest binding the h key to display-local-help. This is mostly useless in itself, but at least the user can remap that command to suitable major-mode specific values (describe-symbol in Elisp, cider-doc in Cider, etc.). Plus, it would work out-of-the-box with Eglot, which does precisely that remapping in its own mode-map.

On the other hand, I'm fine with the eval-region binding in embark-region-map because there's no better option, and, as above, one can use remaps to improvise a generic interface to the “send to repl” action across major modes.

There could still be an embark-target-emacs-lisp-symbol-at-point, but it should probably check if the buffer is in Elisp mode. Then it wouldn't work in random places like help buffers, but at least Embark would not capriciously (not) recognize words in regular text or other programming languages just because they happen to (not) have a meaning in Elisp.

astoff avatar Jan 12 '21 15:01 astoff

@astoff I agree! But I guess thing-at-point is also elisp centric. Unfortunately elisp is somehow more first class in Emacs then the other major modes. But that is natural since you can see it as a whole programmable environment.

minad avatar Jan 12 '21 15:01 minad

@minad thing-at-point uses the syntax table to decide what is a symbol. (So in most prog-modes, but not in lisp-mode, (thing-at-point 'symbol) just after the text x-y returns y.)

astoff avatar Jan 12 '21 15:01 astoff

@astoff Thanks! Good to know!

minad avatar Jan 12 '21 15:01 minad

Another suggestion: support find-file-at-point for embark-become

sheijk avatar Jan 12 '21 15:01 sheijk

Those are all very good points, @astoff. I think the symbol stuff is so Emacs Lisp centric because I used it to develop it 😛

I've been thinking that the symbol target finder shouldn't check to see if the symbol is bound anyway. It uses (thing-at-point 'symbol) so it already takes syntax into account. I'll just remove the check for bindings from the target finder.

As for the actions, I use it all the time to lookup help or definitions for Emacs Lisp symbols in non-Emacs Lisp buffers (mostly help, markdown, org and message buffers) and I'd really, really hate to lose that. I guess I could make the configuration that ships with Embark more "politically correct" along the lines you suggest, and put a proper Emacs Lisp-centric configuration in my personal init.el. 😛

Or maybe I could still bind those Emacs Lisp centric commands, to different keys. I can't be the only one who wants to go to the definition of an Emacs Lisp symbol in a help buffer and is frustrated that xref-find-definitions prompts you for a tags table.

oantolin avatar Jan 12 '21 16:01 oantolin

xref-find-definitions prompts you for a tags table.

You can fix that by disabling the obsolete etags backend.

minad avatar Jan 12 '21 16:01 minad

Another suggestion: support find-file-at-point for embark-become

I don't understand this suggestion, @sheijk. Do you mean you want find-file-at-point bound in the embark-file+buffer-map? I don't think it would be very useful: find-file-at-point is basically the same as find-file, except the default is the file at point. As soon as you type something at the prompt, which embark-become does for you, it becomes just like find-file.

Could you explain what you meant?

oantolin avatar Jan 12 '21 16:01 oantolin

You can fix that by disabling the obsolete etags backend.

I'm confused: disabling that backend makes xref think that help buffer contain Emacs Lisp symbols?

oantolin avatar Jan 12 '21 16:01 oantolin

If I call find-file I can move to other file contexts. But if I call find-file-at-point embark-become doesn't offer any targets to jump to

sheijk avatar Jan 12 '21 16:01 sheijk

From Elisp buffer, does xref work for you, @oantolin? xref-find-definitions has the additional benefit that you can go back to where you were before with xref-pop-marker-stack. Those things also have nice and prominent keybindings anyway, but it would be nice for the sake of consistency if Embark knew about them.

I use it all the time to lookup help or definitions for Emacs Lisp symbols in non-Emacs Lisp buffers

Fair enough. You could recover this behavior in one of two ways: (1) remapping xref-find-definitions and display-local-help in enough modes, or (2) introducing embark-target-emacs-lisp-symbol-at-point, which could or could not be on by default, and could perhaps also check if the major mode derives from one in a customizable list.

astoff avatar Jan 12 '21 16:01 astoff

@sheijk

If I call find-file I can move to other file contexts. But if I call find-file-at-point embark-become doesn't offer any targets to jump to

Gotcha! You don't want it so other commands become it but for it to become other commands. That makes perfect sense, sorry I didn't see that at once. I added it. 9fa6d6adc0086a97d82bf36723d44490bb6c9aa1

oantolin avatar Jan 12 '21 17:01 oantolin

@astoff

From Elisp buffer, does xref work for you, @oantolin

Yes, of course. I use it there instead of Embark actions so I can use xref-pop-marker-stack, as you mentioned. I use the Embark actions on Emacs Lisp symbols in a variety of non-Emacs Lisp buffers.

I use it all the time to lookup help or definitions for Emacs Lisp symbols in non-Emacs Lisp buffers

Fair enough. You could recover this behavior in one of two ways: (1) remapping xref-find-definitions and display-local-help in enough modes, or (2) introducing embark-target-emacs-lisp-symbol-at-point, which could or could not be on by default, and could perhaps also check if the major mode derives from one in a customizable list.

Or (3), having both xref-find-defintions and embark-find-definition bound to different keys in the symbol action map. They do, after all, do different things. And I have wanted both in the same buffer at times.

I wouldn't really want a separate embark-target-emacs-lisp-symbol-at-point, specially one that's not on by default. Does really no-one else want Emacs Lisp symbol actions to be on by default in *Help* buffers? I'd find that very hard to believe.

oantolin avatar Jan 12 '21 17:01 oantolin

Does really no-one else want Emacs Lisp symbol actions to be on by default in Help buffers? I'd find that very hard to believe.

:+1:

Would it make sense to add a possibility to select keymaps based on some predicate? This way you could exchange keymaps depending on the major mode for example.

minad avatar Jan 12 '21 17:01 minad

Would it make sense to add a possibility to select keymaps based on some predicate?

Seems unnecessary, just use a transformer to change the type based on the major mode. Something like:


(defun refine-symbol-type-by-major-mode (target)
  (cons (or (alist-get major-mode '((java-mode . java-symbol)
                                    (cc-mode . c-symbol)))
            'symbol)
        target)

And associate java-symbol, etc. to whatever action map you want.

oantolin avatar Jan 12 '21 17:01 oantolin

Does really no-one else want Emacs Lisp symbol actions to be on by default in Help buffers? I'd find that very hard to believe.

Me too. And maybe this is a bug in xref! But then, as you mentioned, there are other places beyond Help buffers where it's perfectly reasonable to want actions on Elisp symbols. I'm not against special treatment to Elisp, but I'm arguing for staying as generic as possible, given certain limitations of Emacs itself.

Or (3), having both xref-find-defintions and embark-find-definition bound to different keys in the symbol action map.

I wouldn't really want that, I'm afraid... the xref stuff already has nice keybindings. I think the interesting thing here is to make the action context-dependent. So just one key for “show documentation”, and it does what you mean everywhere.

We're discussing the tail of embark-target-finders here, and maybe this is not even a super interesting case, so it shouldn't be overengineered :-). Don't you think a embark-target-emacs-lisp-symbol-at-point, placed as the next-to-last` finder, and of the shape

(when (apply 'derived-mode-p embark-modes-containing-stray-elisp-symbols)
  ...)

would be reasonable? The very last finder would then be the one for symbols as per the major mode, which relies on xref (plus display-local-help on h as long as xref doesn't offer anything suitable).

astoff avatar Jan 12 '21 18:01 astoff

Do you want a separate finder for Emacs Lisp symbols because you want it always recognize Emacs Lisp symbol syntax independent of the major mode syntax for symbols? I've been just using (thing-at-point 'symbol) in all major modes.

The very last finder would then be the one for symbols as per the major mode, which relies on xref (plus display-local-help on h as long as xref doesn't offer anything suitable).

Just to make sure I understand you: you don't literally mean the finder would depend on xref, right? The finder would use (thing-at-point 'symbol), and what you mean is that the actions offered would include xref-find-definitions on d and display-local-help on h?

oantolin avatar Jan 12 '21 18:01 oantolin

Do you want a separate finder for Emacs Lisp symbols because you want it always recognize Emacs Lisp symbol syntax independent of the major mode syntax for symbols?

No, all that I care about is for M-x embark-act RET h to do the right thing on any buffer. It doesn't on a Python buffer. (Even weirder, if you look for help on assoc in a Clojure buffer and believe what you see, you'll be thoroughly confused!) And just to clarify, I can easily fix this for myself, I was just wondering if there's a nice, generic, unsurprising approach that requires no configuration. Seems quite tricky, though.

Just to make sure I understand you: you don't literally mean the finder would depend on xref, right?

Yes, right, maybe I put it a bit confusingly. I was imagining separate keymaps for Elisp symbols and for "symbols according to the major mode". This could be achieved through separate finders, but not only that way, as you pointed out above.

My quibble here is that every major mode agrees on how to choose the syntax highlight colors, but there's no unified interface for something as fundamental as requesting documentation on a symbol.

astoff avatar Jan 12 '21 19:01 astoff

OK, I think I understand and agree now. What actions are appropriate for non-Emacs Lisp symbols besides xref-find-definitions and display-local-help? Should they only get those two (plus the actions in embark-general-map, of course).

oantolin avatar Jan 12 '21 19:01 oantolin

What actions are appropriate for non-Emacs Lisp symbols besides xref-find-definitions and display-local-help?

That's all there is, I think.

astoff avatar Jan 12 '21 19:01 astoff

OK. Got it. Will do. I'll call that new non-Emacs Lisp symbol type identifier, which is the term xref-find-definitions uses.

oantolin avatar Jan 12 '21 19:01 oantolin

Good, now that I think about it, "identifier" is really the standard terminology. Symbols go by the weird name of "string" in most languages these days :rofl:

astoff avatar Jan 12 '21 19:01 astoff

OK, @astoff. I made the change. Now (thing-at-point 'symbol) is always recognized as a valid target and it is classified as either symbol (meaning Emacs Lisp symbol), or as identifier. The ones classified as symbols are those either were found in an Emacs Lisp buffer (whether or not they are bound), or are interned in the Emacs Lisp environment and were found in a buffer whose major mode does not inherit from prog-mode. Does that sound OK? beb5dd604890f4920e39bebefdd5619c81626fdc

oantolin avatar Jan 12 '21 21:01 oantolin

For identifiers the only actions you get are, as you suggested, xref-find-definitions and that lovely function display-local-help which is used to print the message "No local help at point". 😛

oantolin avatar Jan 12 '21 21:01 oantolin

Hello everyone. I'm thinking about adding an action run M-x when I run find-file

With this action I can :

  • Run find-grep/rg with pointed directory
  • Run eshell/shell/ansi-term/vterm under pointed directory
  • Any commands require default-directory

WDYT?

TxGVNN avatar Jan 25 '21 16:01 TxGVNN

Do you mean you want to be able to run find-file, maybe navigate to some directory, and then run embark-act but instead of choosing one of the actions in the file map, use M-x to run whatever command you wan. @TxGVNN? If that's what you mean you can already do it!

If you use the keymap prompter, just type M-x and the command; if you use the completing-read prompter, when it prompts you for a command just type the command you want, it does not need to be one the list, those are just suggestions.

oantolin avatar Jan 25 '21 17:01 oantolin

Thank @oantolin, That is possible, right. I just suggest adding this action to the package if you think it is useful for everyone. I will build it for me.

TxGVNN avatar Jan 25 '21 17:01 TxGVNN

Thank @oantolin, That is possible, right. I just suggest adding this action to the package if you think it is useful for everyone. I will build it for me.

What I am trying to say is that it has already been added to the package and that you do not need to build it, since the functionality already exists, @TxGVNN. Or am I misundertanding what your action would do?

oantolin avatar Jan 25 '21 17:01 oantolin

Oh, maybe I misunderstood you, @TxGVNN! Do you want the action to use the target just to set the default directory and not to pass the target to the command you run? Like this?

(defun embark-in-directory (dir cmd)
  "Run CMD in directory DIR."
  (interactive "DIn directory: \nCRun command: ")
  (let ((default-directory dir))
    (command-execute cmd)))

oantolin avatar Jan 25 '21 18:01 oantolin

Oh, yes! That is my idea.

(defun embark-in-directory (dir cmd)
  "Run CMD in directory DIR."
  (interactive "DIn directory: \nCRun command: ")
  (let ((default-directory (file-name-directory dir)))
    (command-execute cmd)))

(define-key embark-file-map (kbd "M-x") #'embark-in-directory)

TxGVNN avatar Jan 26 '21 03:01 TxGVNN

Ah, good! Sorry for the initial misunderstanding.

By the way, I would not recommend the M-x binding for that, because you'd loose the ability to use M-x to pick an action (unless you happen to have a different key binding for execute-extended-command). Maybe /, because the action is used to pick a directory?

oantolin avatar Jan 26 '21 03:01 oantolin

Yup. I'm binding M-o to embark-act. But if you add this action, I see / is a good default keybinding.

TxGVNN avatar Jan 26 '21 04:01 TxGVNN

@TxGVNN I feel like this is essentially not an Embark-specific matter, unless we're discussing the need of an Embark wrapper for an already existing functionality.

Do you need to be able to select an arbitrary directory? I often want to run commands in an external directory which is fixed, on a per-project basis. So I have a directory-local variable mirror-location and use a command like this:

(defun mirror-command-execute (command)
  "Execute COMMAND with remote `default-directory'.
Interactively, reads a key sequence, so it acts like a keymap."
  (interactive (list (lookup-key (current-active-maps)
                                 (read-key-sequence "On remote: "))))
  (setq this-command command)
  (let ((default-directory mirror-location))
    (command-execute command)))

When called interactively, this reads the command not from a M-x style prompt, but from a key sequence, so it acts like a fake prefix map. Of course you can always type M-x to get a prompt. (The version I actually use computes the remote directory based on the buffer's file name, the local project root, and remote project root, but that's just a detail.)

If you wanted to replace the fixed mirror-location by a completing-reading prompt, then Embark would insert the action subject there. Maybe a macro of the kind (embark-eval-this-without-inserting-the-action-subject FORMS) would be a good solution for this?

astoff avatar Jan 29 '21 08:01 astoff

Thank @astoff, I'm glad with embark-in-directoryaction right now. I love it. I had a same feature with ivy action in past.

If I want to grep something in a other directory, I always find-file then run grep on it. That is my workflow. I have 3 scopes to run a command:

  • current dir scope -> it is default in all commands. Example: consult-grep
  • project scope -> I will run with projectile-* command. Example: consult-projectile-grep (my function)
  • other dir scope -> I use find-file then action with embark-in-directory

TxGVNN avatar Jan 29 '21 11:01 TxGVNN

The embark-in-directory action is a nice idea :) But note that you can configure a project root function in consult, then you get the project root by default and if you press C-u you can chose a directory in consult-grep.

minad avatar Jan 29 '21 11:01 minad

kill-buffer support would be great. Ideally without closing the completion afterwards so multiple buffers can be killed on-the-fly while switching between them

sheijk avatar Jan 30 '21 14:01 sheijk

@sheijk kill-buffer is already part of the buffer actions (bound to k), but it is affected by #117 too, when keeping the completion system open.

minad avatar Jan 30 '21 14:01 minad

kill-buffer support would be great

@sheijk You can run kill-buffer as an action in any command that offers completion of buffer names, such as switch-to-buffer or kill-buffer itself. As @minad said, it is bound to k.

Ideally without closing the completion afterwards so multiple buffers can be killed on-the-fly while switching between them

The embark-act command can be run in two ways: so that it quits the minibuffer after you run or in a way that keeps the minibuffer open. This is controlled by the variable embark-quit-after-action which is t by default, which means embark-act quits the minibuffer and C-u embark-act does not. If you set embark-quit-after-action to nil (which I prefer) it's the other way around, embark-act keeps the minibuffer open and C-u embark-act quits.

I often do exactly what you asked, @sheijk, kill several buffers without quitting a switch-to-buffer command.

@minad said:

but it is affected by #117 too, when keeping the completion system open.

The built-in buffer commands are careful to make sure the buffers in the candidate lists are still live, so for these commands simply refreshing the completion UI is enough. The refresh can be triggered manually (by adding and removing a character) or automatically with the configuration from the wiki.

oantolin avatar Jan 30 '21 15:01 oantolin

@oantolin

The built-in buffer commands are careful to make sure the buffers in the candidate lists are still live, so for these commands simply refreshing the completion UI is enough. The refresh can be triggered manually (by adding and removing a character) or automatically with the configuration from the wiki.

Are you sure? switch-to-buffer+kill does not for me with Selectrum. Since you moved the Selectrum config to embark.el, I am using a barebone Embark configuration without configuring any hooks myself besides the which-key indicator.

minad avatar Jan 30 '21 15:01 minad

Ah, when will I learn to always test with Selectrum? It works with default completion, icomplete and embark collect live or completions. Selectrum is more static, I forget it only gets the list of candidates once. I don't even know why we have a refresh snippet for it on the wiki. Does the snippet actually do anything?

oantolin avatar Jan 30 '21 15:01 oantolin

No idea. I hope the non-functional snippet is not part of embark.el :smile: While the way Selectrum does things is a bit non-standard, I think it is still valid. Selectrum applies some kind of normalization first to get all the candidates. This is perfectly valid given how baroque the completing-read API is. Maybe switch-to-buffer would work if you use selectrum-exhibit to update, since this works with Consult async and ensures that the candidates are reread. However I still think we need #117, since for example consult-buffer would not update without it. And I don't see how I could possibly change consult-buffer/consult--multi to magically pick up changes to the original candidate lists.

minad avatar Jan 30 '21 15:01 minad

The snippet is not in embark.el (which indeed, does not try to automatically refresh completion UIs at all), just on the wiki. And I remember it used to work with switch-to-buffer. It doesn't seem to work now, even if you add a post action hook that calls selectrum-exhibit.

@clemera, is this out of date?

(defun refresh-selectrum ()
  (setq selectrum--previous-input-string nil))

(add-hook 'embark-pre-action-hook #'refresh-selectrum)

I remember that it used to remove buffers I just killed from switch-to-buffer.

oantolin avatar Jan 30 '21 16:01 oantolin

To refresh you should better call selectrum-exhibit now. BTW I just noticed a weird issues which seems to be introduced by e20a1ec093cdf8877a93511277208794fea03ce0. When using embark keymap help and prescient sorting candidates get inserted into other commands afterwards by selectrum-prescient--preprocess :eyes: I don't know what is happening yet.

clemera avatar Jan 30 '21 16:01 clemera

Additionally I get weird display issues when using it multiple times these go away when removing the recent change to highlighting in Selectrum (you get the other display issues back in exchange) but the inserting of embark keymap help candidates into other commands persists.

clemera avatar Jan 30 '21 17:01 clemera

That's really weird, @clemera. embark-completing-read-prompter just calls completing-read as it did before, I don't see why this change would make any difference in prescient.

oantolin avatar Jan 30 '21 17:01 oantolin

It doesn't happen before e20a1ec093cdf8877a93511277208794fea03ce0 but I also don't know what is happening (maybe it also another commit later). I'm currently trying to figure out the issue with regard to the new display issue first.

clemera avatar Jan 30 '21 17:01 clemera

This display issue is really strange, too. The (symbol-name cmd) in embark-completing-read-prompter returns a string which already has the display property applied (in subsequent calls), seems like the string is cached in memory and reused or something like that?

clemera avatar Jan 30 '21 17:01 clemera

Ah, I thought that was always a fresh string. I'll copy it before adding the display attributes.

oantolin avatar Jan 30 '21 17:01 oantolin

Yes, using substring-no-properties on it seems to fix it.

clemera avatar Jan 30 '21 17:01 clemera

Oh, I used concat instead. But I think it should work too? 3ccb9c2721f9bee854fe50be50d9724953bc5556

oantolin avatar Jan 30 '21 17:01 oantolin

I think that should work, too I will check.

clemera avatar Jan 30 '21 17:01 clemera

Yes, that works, thanks!

clemera avatar Jan 30 '21 17:01 clemera

This also fixes the other issue, apparently the cached string with the display property was then also later reused when using M-x which would display embark-insert (or other candidates of the completion help) with the prefix :laughing:

clemera avatar Jan 30 '21 17:01 clemera

I did not notice it without prescient because then they wouldn't be sorted first...

clemera avatar Jan 30 '21 17:01 clemera

This also fixes the other issue, apparently the cached string with the display property was then also later reused when using M-x which would display embark-insert (or other candidates of the completion help) with the prefix 😆

Ah, OK! Great, @clemera!

oantolin avatar Jan 30 '21 17:01 oantolin

Added an exporter for bookmarks. e361607d448243b1a5c6b6eac71627e7636fdabc

oantolin avatar Feb 02 '21 18:02 oantolin

A detector for flyspell errors (face flyspell-incorrect) and an action to call ispell-word (M-$ by default bindings) on it. A detector for flymake/flyspell would also be nice altough users would need to provide actions. Maybe "copy error message" and "copy error location"?

sheijk avatar Feb 09 '21 16:02 sheijk

Over on minad/consult#210, @hmelman suggested a dired-jump action for the file action map.

oantolin avatar Feb 09 '21 17:02 oantolin

I'm not sure there's much advantage in having a flyspell error target, @sheijk, what action other than ispell-word would make sense for it? If that's the only one, it's better to press M-$ directly.

oantolin avatar Feb 09 '21 17:02 oantolin

On Tue, Feb 09 2021, Omar Antolín Camarena wrote:

If that's the only one, it's better to press M-$ directly.

hmm, i'm not sure that's the case. if one uses embark often, it's one less keybinding to memorize (assuming one remembers there's an associated action). of course, M-$ is one keypress less if one has to choose the action, but couldn't embark be configure to just run the action when there's only one? (maybe that's already the case)

jaor avatar Feb 09 '21 21:02 jaor

but couldn't embark be configure to just run the action when there's only one? (maybe that's already the case)

There is never only one possible action, @jaor. You can always run any command you want as an action (just use M-x after embark-act, if you are using the keymap prompter, or type the command name if you are using the completing-read prompter). Of course you probably meant, "if the relevant keymap has only one binding", but since they all inherit from embark-general-map, there always a bunch of actions available, including saving in the kill ring, inserting in the buffer, etc. OK, but maybe Embark could autorun an action if there is only one action bound in the keymap that is not in embark-general-map. Well, that could be done, but I wouldn't want to, since you'd lose the ability to use M-x for actions in that case.

oantolin avatar Feb 09 '21 21:02 oantolin

But your point about learning one fewer keybinding is a good point, @joar, because embark can remind you of the keybinding.

oantolin avatar Feb 09 '21 21:02 oantolin

Yes, having this single entry point context-dependent keybinding is is a big plus of Embark, in particular since the keyboard is already so crowded with Emacs default bindings! It seems you have to promote this embark-act M-x feature more heavily :laughing: I would also not like to have a special casing to save keystrokes if only one a single non-general binding exists.

minad avatar Feb 09 '21 21:02 minad

On Tue, Feb 09 2021, Omar Antolín Camarena wrote:

There is never only one possible action, @jaor.

that's true. what would you think about having the ability of marking an action as default and having an embark-act-default (or some better name) command?

the mark could be added by the embark-define-keymap macro, and maybe use the convention that the first action in the specific keymap is the default, so that nothing new (except the new command) needs to be learned.

jaor avatar Feb 09 '21 22:02 jaor

Can I suggest adding hi-lock-face-symbol-at-point to embark-symbol-map. I don't use it much myself now that I've found symbol-overlay.el but the concept is good.

hmelman avatar Feb 09 '21 22:02 hmelman

@jaor

The current convention is that you bind the "default default action" to RET in your type's keymap. The actual default action is given in order of priority by:

  • looking up the type in embark-default-action-overrides
  • the command that opened the minibuffer, if you are in a minibuffer
  • the command bound to RET in the appropriate action keymap.

I guess <embark-act> RET is still at least two keypresses, maybe it would make sense to define a command that just runs the default action.

oantolin avatar Feb 09 '21 22:02 oantolin

what would you think about having the ability of marking an action as default and having an embark-act-default (or some better name) command?

I did basically this in an old package mouseme.el (which I think is still shipped with ess), it was similar to embark but was a mouse-based menu that figured out thing-at-click and presented a menu of commands. My favorite use case was a regexp that recognized how we typed our homegrown bug database numbers, (e.g, PR12234) and set the default action to do a websearch in our bug system but other actions too like copy the text, etc. At the time I was using emacs for coding and email and reading newsgroups so this worked in any context I saw a bug number and was great.

hmelman avatar Feb 09 '21 22:02 hmelman

That sounds very cool, @hmelman! And it's also exactly the type of thing I hope people start using Embark for. Well, people have started, for example @jaor has some code to recognize video URLs. (Maybe you want to bind jao-play-video-url to RET instead of p, to indicate it's the default, @jaor?)

Also GNU Hyperbole's action key does this kind of thing and it comes preconfigured with a large number of recognizers for things, including, I believe Emacs bug numbers.

oantolin avatar Feb 09 '21 22:02 oantolin

I've looked at hyperbole a few times but can't get passed the documentation and the idea that it seems like a hodgepodge of stuff much of which I'm not interested in. But yes I think the core idea is similar I wish it would take the architecture approach of selectrum/consult/embark/marginalia and keep things independent.

But what I didn't state explicitly is that I do like a default action and like the idea of having another command that could typically be bound to the same key with an additional modifier or could use a universal argument or something quick to act as basically the "I feel lucky" button.

hmelman avatar Feb 09 '21 22:02 hmelman

another command that could typically be bound to the same key with an additional modifier

Think of RET as a postfix modifier. 😛 So if you bind embark-act to, say, C-,, then C-, RET is your "I'm feeling lucky" button.

oantolin avatar Feb 09 '21 22:02 oantolin

Think of RET as a postfix modifier. stuck_out_tongue So if you bind embark-act to, say, C-,, then C-, RET is your "I'm feeling lucky" button.

Note that you could easily write a command which wraps this exact behavior and saves you the two keypresses. So you could really put it onto a single button.

minad avatar Feb 09 '21 22:02 minad

Think of RET as a postfix modifier. stuck_out_tongue So if you bind embark-act to, say, C-,, then C-, RET is your "I'm feeling lucky" button.

Note that you could easily write a command which wraps this exact behavior and saves you the two keypresses. So you could really put it onto a single button.

(defun embark-default-action ()
  (interactive)
  (pcase-let ((`(,type . ,target) (embark--target)))
    (embark--act (embark--default-action type) target)))

oantolin avatar Feb 09 '21 22:02 oantolin

I really have to internalize pcase-let and use it more, the destructing binding is really nice. I do it in python, but haven't adopted it since it's come to elisp.

hmelman avatar Feb 09 '21 22:02 hmelman

I believe pcase was added to Emacs about 8 or 9 years ago, @hmelman. 😛

oantolin avatar Feb 09 '21 22:02 oantolin

I believe pcase was added to Emacs about 8 or 9 years ago, @hmelman. stuck_out_tongue

It is still broken - it does not get dynamic binding right, due to some invalid optimization on Emacs 28. The tendency seems to be to just disallow dynamic bindings, I disagree with that :-P See https://github.com/minad/consult/issues/108.

EDIT: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45619

minad avatar Feb 09 '21 22:02 minad

On Tue, Feb 09 2021, Omar Antolín Camarena wrote:

(defun embark-default-action () (interactive) (pcase-let ((`(,type . ,target) (embark--target))) (embark--act (embark--default-action type) target)))

that's exactly what i was looking for, thanks (fwiw, i think it's a function worth adding to embark proper, or perhaps to its documentation).

jaor avatar Feb 09 '21 23:02 jaor

Well maybe in another 8 or 9 years pcase will work correctly 🤣

hmelman avatar Feb 09 '21 23:02 hmelman