oantolin / embark

Emacs Mini-Buffer Actions Rooted in Keymaps
GNU General Public License v3.0
930 stars 56 forks source link

Generalize embark-mark and embark-unmark #253

Closed minad closed 1 year ago

minad commented 3 years ago

Very much related to #166, feel free to merge these feature requests.

This gives us convenient actions on multiple candidates.

minad commented 3 years ago

See these relevant comments and the discussion in #256.

jdtsmith commented 3 years ago

A related even simpler but still powerful idea: allow mini-buffer embark to act on all the displayed candidates (instead of the first or single selected). I find my self often selecting buffers using consult+orderless (10x faster than any other way), then exporting to an ibuffer, then selecting all (t), then killing (D) or running multi-occur (O) on them. An embark "act on all" would save the side trip to ibuffer (where I will be selecting all 99% of the time anyway).

minad commented 3 years ago

Yes, indeed. My idea is to have two features:

  1. A collection function which allows to collect candidates one by one and results in a collect buffer
  2. An act function to act on everything in the current context (collect buffer, minibuffer)

Then one can only use (2) to act on a candidate subset obtained by plain filtering using orderless. But one can also do one by one manual collection (1) if that is desired.

oantolin commented 3 years ago

Since this functionality isn't implemented I can't be sure, but I feel like the ability to run the same action on all current candidates would probably be enough for me. I'm not sure I'd miss the ability to collect candidates haphazardly.

minad commented 3 years ago

I'm not sure I'd miss the ability to collect candidates haphazardly.

I have another idea - it would be slightly UI specific: I could add some command to Vertico/Selectrum which allows you to select candidates. And then I write a separate Embark collector which collects just the selected candidates and which will be registered right before the all-candidates-collector. Then we need commands embark-act-all and embark-dwim-all, which should act on all candidates returned from the candidates collector. Problem solved?

bdarcus commented 3 years ago

Not sure where best to put this, but maybe here.

FYI, I had a long back-and-forth in the past couple of weeks trying to get the author of this project to use completing-read everywhere.

https://github.com/jkitchin/org-ref-cite

I mostly succeeded, save for one piece. He explains why he stayed with ivy as:

Ivy is required for this, as it allows single, multiple, and sequential actions on the selected candidates.

minad commented 3 years ago

It seems this package is mostly decoupled? Is there a problem to write multiple frontends, one for ivy, one for helm one only completing-read+embark? Also it seems to be that there is overlap with your bibtex-actions package.

bdarcus commented 3 years ago

It seems this package is mostly decoupled?

Definitely.

Is there a problem to write multiple frontends, one for ivy, one for helm one only completing-read+embark?

Not at all. I just thought it could be valuable to hear what an ivy-focused developer values there.

Also it seems to be that there is overlap with your bibtex-actions package.

Yeah, they're different ways to use the same bibtex-completion backend.

But that's cool. It is all modular, so we can easily mix-and-match components. I, for example, can use his hydra with my CR front-end, and he can in theory use my embark-act at-point integration with his ivy front-end.

bdarcus commented 3 years ago

I'm not sure I'd miss the ability to collect candidates haphazardly.

I have another idea - it would be slightly UI specific: I could add some command to Vertico/Selectrum which allows you to select candidates. And then I write a separate Embark collector which collects just the selected candidates and which will be registered right before the all-candidates-collector. Then we need commands embark-act-all and embark-dwim-all, which should act on all candidates returned from the candidates collector. Problem solved?

Coming back to this "another idea", WDYT?

How it would interact with ideas previously discussed in #166 WRT to embark-collect? You use the "collect" verb here, but I can't tell if you mean that generically, or if this a way to populate the collect buffer?

bdarcus commented 3 years ago

Since this functionality isn't implemented I can't be sure, but I feel like the ability to run the same action on all current candidates would probably be enough for me. I'm not sure I'd miss the ability to collect candidates haphazardly.

Perhaps this would be the correct first step, and if we find this hypothesis is off, can always add the more fine-grained control later?

I was thinking about this feature again when thinking about using consult--multi to select and open multiple files of different categories.

oantolin commented 2 years ago

I added an embark-act-all command (91e6db4dc029cc87ff3315f88552468de7344e30) to act on all current candidates (its mostly useful in the minibuffer, but I guess I could see using it for something in dired buffers, for example: you could mark some files and then use embark-act-all to run consult-file-externally on all of them). Please test!

minad commented 2 years ago

This is great! Thank you. I will give it a test.

oantolin commented 2 years ago

Apparently I only ever used ibuffer when I want to kill a bunch of similarly named buffers: from consult-buffer I'd export the buffers I wanted to kill to ibuffer, toggle the selection, kill them all. Now with embark-act-all it feels like I may never use ibuffer again. 😛

Similarly, I do most of my file management tasks with file actions from find-file, and it seems that about half of the remaining uses of dired were to delete a bunch of similarly named files. I guess I may eventually get to the point where I only use dired for wdired-mode, which actually seems perfectly reasonable.

Elilif commented 1 year ago

I have another idea - it would be slightly UI specific: I could add some command to Vertico/Selectrum which allows you to select candidates. And then I write a separate Embark collector which collects just the selected candidates and which will be registered right before the all-candidates-collector. Then we need commands embark-act-all and embark-dwim-all, which should act on all candidates returned from the candidates collector. Problem solved?

@minad @bdarcus @oantolin
I recently did something similar, but I didn’t use embark-collect because implementing similar functionality with it was a bit cumbersome.

Here is my code:

(defvar eli/vertico-marked-list nil
  "List of marked candidates in minibuffer.")

(defun eli/vertico-mark ()
  "Mark candidates in minibuffer"
  (interactive)
  (let*
      ((selected (embark--vertico-selected))
       (target (cdr selected)))
    (if (member target eli/vertico-marked-list)
        (setq eli/vertico-marked-list (delete target eli/vertico-marked-list))
      (push target eli/vertico-marked-list))))

(defun eli/vertico-marked-p (candidate)
  "Return t if CANDIDATE is in `eli/vertico-marked-list'."
  (member (concat vertico--base candidate) eli/vertico-marked-list))

(defun eli/vertico--format-candidate-hl-marked (args)
  "Highlight marked vertico items."
  (let* ((cand (car args)))
    (if (eli/vertico-marked-p cand)
        (add-face-text-property 0 (length cand) 'embark-collect-marked nil cand)
      (vertico--remove-face 0 (length cand) 'embark-collect-marked cand))
    args))

(advice-add #'vertico--format-candidate :filter-args #'eli/vertico--format-candidate-hl-marked)

(defun eli/vertico-marked-list-clean ()
  "Initialize `eli/vertico-marked-list' and `eli/vertico-mark-type'."
  (setq eli/vertico-marked-list nil))

(add-hook 'minibuffer-setup-hook #'eli/vertico-marked-list-clean)

(defun eli/embark-vertico-marked-list ()
  (when eli/vertico-marked-list
    (cons (car (embark--vertico-selected)) (reverse eli/vertico-marked-list))))

(add-hook 'embark-candidate-collectors #'eli/embark-vertico-marked-list -100)
(setq embark-confirm-act-all nil)
(keymap-set vertico-map "C-SPC" #'eli/vertico-mark)
(keymap-set vertico-map "C-," #'embark-act-all)

Now you can use eli/vertico-mark in minibuffer to mark candidates, then call embark-act-all to do something.

For instance:

  1. insert candidates

  2. kill selected buffers

I think it is easier to operate than embark-collect, and more flexible than embark-act-all.

oantolin commented 1 year ago

That looks quite nice, @Elilif! Maybe it's worth making a tiny package that depends on Embark and on Vertico for this? Or at least documenting it here on the Embark wiki.

I haven't tried your code yet, but if I'm reading it correctly, you can continue typing in the minibuffer to narrow further and this does not forget which candidates of the wider list were marked; that's great!

The one thing I don't like about this type of interface is that it is pretty hard to see all marked candidates at once, although I guess Embark can help with that: just insert them somewhere. If I understand the code correctly, they stay marked so you can act on them again.

bdarcus commented 1 year ago

The one thing I don't like about this type of interface is that it is pretty hard to see all marked candidates at once ...

I guess this is related to previous discussion that resulted in the now defunct consult-completing-read-multiple; that ideally there'd be some sort of grouping of the marked candidates?

minad commented 1 year ago

The snippet made by @Elilif would be quite a simple addition. Unfortunately it breaks down as soon as you want "more", like showing all the marked candidates and also interacting nicely with filtering. But maybe remembering the candidates is just good enough, since you can also show them by collecting them? Anyway, these limitations are the reason why we didn't proceed with this feature in the past.

If we want this, we would also need additional integration code for other UIs. One possibility would be to generalize embark-collect-mark and embark-collect-unmark to arbitrary buffers. The mark/unmark commands would obtain the current candidate via the embark-target-finders hook and add them so some buffer-local (?) list. Marking and unmarking themselves would just become simple actions themselves. The marked list can then be returned by a hook added to embark-candidate-collectors. Furthermore we'd need to hook into UIs like Vertico to show the marked candidates (vertico--format-candidate). I see some elegance in making marking/unmarking plain actions. Maybe @oantolin agrees and we could try this out.

Elilif commented 1 year ago

But maybe remembering the candidates is just good enough, since you can also show them by collecting them?

Yeah, my intention is to have a method that could be between embark-collect and embark-act-all, because when I only need to select a smaller subset of candidates (such as killing some buffers or opening some files), the operation of embark-collect is too complex, while embark-act-all cannot meet my needs.

oantolin commented 1 year ago

@minad: That does sound worth trying.

@Elilif: I haven't actually missed the ability to mark candidates in the minibuffer, and I'm not completely sure why I haven't. I think the main reason is that if I want to do the same thing to a bunch of candidates there is almost always a clear pattern to their names: I want to kill all vc buffers and their names start with *vc; or I want to kill all buffers whose names start with * except *scratch*; or I want to delete all files whose name is foo with any extension; or to delete all files with extension .log; etc.

So the vast majority of the time embark-act-all is good enough for me. If there are one or two exceptions to a pattern I just exclude them using orderless-without-literal. I don't seem to get myself into situations where I want to run the same action on some weird patternless collection of candidates; I don't actually use embark-collect or even dired and ibuffer that often, because embark-act-all seems to be good enough 95% of the time. Why do you want this ability to mark candidates in the minibuffer? I do think it is a good idea to have it, even if I don't personally need it, but I am curious to know why people want it.

minad commented 1 year ago

@oantolin

I don't seem to get myself into situations where I want to run the same action on some weird patternless collection of candidates;

From my experience this mostly happens with killing buffers, deleting files etc, while not having to think about patterns. Oh I want to delete this one, mark, this one, mark, oh and that one over there too, down down down mark.

If we can make this work with reasonable effort, I am in favor of trying this. For me the convincing reason is that it is a generalization of the existing Embark collect marking infrastructure. I can try to implement it for default completion, Embark collect and Vertico. But no guarantee that it will work out nicely. I'd like to avoid adding serious complications to the integration code if possible, since this is a recipe for unstability in the long term.

oantolin commented 1 year ago

I too am in favor of trying this, I was just trying to see more of the appeal. For me, if there is a clear pattern to the candidate I want to act on, I reach for embark-act-all; if not, if I'm going to have to scroll down to each candidate anyway, I just run the action on each one. If it's really complicated, I collect or export. I do like the idea of marking in the minibuffer (maybe even if it only has visual feedback on Vertico!), but I don't see a need for it, and was trying to get a feeling for why other people want this feature.

Marking, unmarking and making embark-act-all work is easy. The only tricky part is getting some visual feedback on what is currenty marked. That requires UI-specific code. For Vertico I think advising vertico--format-candidate is the best option. Maybe for default completion similarly advising completion--insert-strings is a good option. It would be nice to unify the approach to visual feedback in various UIs, but I don't see how to do that yet.

minad commented 1 year ago

I do like the idea of marking in the minibuffer (maybe even if it only has visual feedback on Vertico!), but I don't see a need for it, and was trying to get a feeling for why other people want this feature.

I think one additional motiviation is that completion is restarted for some commands when acting. This means the method of scrolling and acting on each candidate individually is inconvenient. For example Consult narrowing is lost, the selected candidate is lost, etc. I've also recently learned that Helm aborts completion altogether after acting (at least by default), which avoids the kind of restarting ugliness in the first place.

For Vertico I think advising vertico--format-candidate is the best option.

For Vertico one can use a cl-defmethod, which is a cleaner approach than an advice.

Maybe for default completion similarly advising completion--insert-strings is a good option.

No, for default completion, Embark collect and all other normal buffers, Embark should simply install an overlay over the target. This is why I think the generalization is elegant. The target finders should return boundaries in these cases, right? We could simply demand that the target finders must return boundaries for this to work. Only Vertico, Ivy, Icomplete should require special casing.

bdarcus commented 1 year ago

I think one additional motiviation is that completion is restarted for some commands when acting.

Yes, I was wondering about this example.

https://github.com/emacs-citar/citar/issues/714

Edit: The original mastodon thread, with some discussion of the limitation of the embark-collect workaround.

https://mastodon.social/@gmoretti/109460454739376441

Though in that case we're using our custom multi-select UI.

minad commented 1 year ago

@bdarcus embark--restart preserves the input, but not most of the other minibuffer state.

oantolin commented 1 year ago

I've started working on this and hope to have a testable branch soon. I think it'll be cool to be able to select multiple candidates in general buffers, cool but not terribly useful. It'll mainly be useful in Embark Collect buffers and in the minibuffer. :)

I was thinking that there should be one command to select a target that you must run as an action (so that it knows which of the targets at point you meant to select); plus a standalone command that selects the first target at point (embark-dwim style), in case people want to bind that directly to key and not have to go through embark-act.

One silly thing that's going to be difficult is choosing a key binding for the select action...

minad commented 1 year ago

I think it'll be cool to be able to select multiple candidates in general buffers, cool but not terribly useful.

I am sure we can come up with interesting use cases! But my expectation was somehow that we need the functionality anyway for collect and default completions, so we get it in normal buffers for free.

I was thinking that there should be one command to select a target that you must run as an action (so that it knows which of the targets at point you meant to select); plus a standalone command that selects the first target at point (embark-dwim style).

Hmm, without having thought much about this - I would not add such a command. You can always define a keyboard macro. In collect buffers you can also act directly, right?

oantolin commented 1 year ago

Hmm, without having thought much about this - I would not add such a command.

Sure, let's wait to see if people want it. (I'm pretty sure they will want it in the minibuffer, but let's see.) People seem to dislike binding keyboard macros to keys. 😛

oantolin commented 1 year ago

There's an initial implementation in the selections branch (see c5a916732053db0c70a5151e0b5dd03f4b5c4978). So far it only works in regular buffers, not in the minibuffer and not in Embark Collect buffers. There is an action to select or deselect a target which I bound to y (that's a placeholder until I figure out a decent binding) and an action to deselect all targets, bound to Y (also a placeholder).

I already found one cute usage of this: say you want to move 3 defuns to the bottom of a file, then you can select each of the three with C-. y, go to the end of the file, insert at point new copies of all 3 defuns with C-. A i, then delete the originals with C-. A DEL.

The reason the current implementation does not work in the minibuffer nor in Collect buffers is that for those the target buffer is not the buffer from which you run the action. I need to think a bit about how best to handle this.

I already removed the mark/unmark mechanism in Collect buffers, since it will eventually be replaced by this. That mechanism had separate commands to mark and unmark, but I think I prefer this new approach with a single command that toggles selection of the target.

oantolin commented 1 year ago

Mmh, if you select a bunch of targets and then collect them, the collect buffer has no default action. The default action should probably be to take you to where the target was found originally.

oantolin commented 1 year ago

Oh, I shouldn't inherit from the dired-marked face since it is not loaded until you use dired...

minad commented 1 year ago

@oantolin Great! I added a few comments.

oantolin commented 1 year ago

It now works in embark collect buffers too. Minibuffer is next. Actually, it should work now but just not have any visual feedback. I'm confused about why it's actually not working in the minibuffer at this point.

Elilif commented 1 year ago

@oantolin what do you think about setting a global function for embark-toggle-select rather than calling it through embark-act? Because the current solution requires pressing the key twice every time (C-. y) to mark one candidate.

oantolin commented 1 year ago
  1. This Emacs! No-one can force you to ever press more keys than you want to: just use a keyboard macro: (global-set-key (kbd "C-,") (kbd "C-. y")). If anyone ever starts a sentence with "Emacs requires you to press ..." they are almost certainly wrong. ;)

  2. You can't really make a global function that does exactly the same thing as embark-toggle-select, since that function adds the current target to the selection, and if there are several targets at point that you are cycling among a global function has no way of knowing which target in the cycle you are looking at! What you can do is make a global function that adds, for example, the first target at point to the selection. That is basically the same as the keyboard macro above, but if making a kmacro seems too easy you can make life harder for yourself and write a function. 😛

oantolin commented 1 year ago

If you scroll up you'll see I predicted people would want a standalone function even if it is less powerful than the action and always adds the first target at point to the selection (rather than letting you pick which target you want to add). I'll think about it some more, but am not against adding the function.

oantolin commented 1 year ago

I'm an idiot: the reason this didn't work in the minibuffer was just that the Vertico candidate collector had higher priority than the selection collector. 🤣 I've fixed that now. There's still no visual feedback in Vertico. For that I think I'll just use @Elilif's trick and change it if @minad suggests a better way for Vertico.

oantolin commented 1 year ago

OK, I've added @Elilif's strategy for visually indicating the selection in Vertico. And I think that's it: we now have a reasonable first draft of this functionality and all that is needed now is a bit of testing, polish, and documentation.

Things left to decide:

minad commented 1 year ago

@oantolin Nice. I will take a look at the Vertico functionality.

Should I also add a standalone function to select the first target at point?

I argue against that, since you can just as easily bind a keyboard macro as you can bind a command and in order to make marking available with a single key press you have to bind it.

Should I implement a command to toggle the selected status of every candidate in a collect buffer (we had one before)? (If not, I should definitely remove the stub that's still there.)

No, since it doesn't generalize to other buffers.

minad commented 1 year ago

@oantolin I found one problem. Selection doesn't work for consult-line due to the tofu stripping/target transformation. Maybe we should use the original targets for selection? Alternatively instead of member one could look for the original target in the embark--selection list (assuming that the information is still there, e.g., in the text properties).

Please use this better approach for Vertico highlighting using cl-defmethod:

From 6ac9350e3d70de5f7f08ed400803151e5869e937 Mon Sep 17 00:00:00 2001
From: Daniel Mendler <mail@daniel-mendler.de>
Date: Sun, 16 Apr 2023 11:27:04 +0200
Subject: [PATCH] Better method to highlight marked candidates in Vertico

---
 embark.el | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/embark.el b/embark.el
index ee2bea1..e411073 100644
--- a/embark.el
+++ b/embark.el
@@ -3277,7 +3277,6 @@ You can act on all selected targets at once with `embark-act-all'.")

 (declare-function vertico--candidate "ext:vertico")
 (declare-function vertico--update "ext:vertico")
-(declare-function vertico--remove-face "ext:vertico")
 (defvar vertico--input)
 (defvar vertico--candidates)
 (defvar vertico--base)
@@ -3310,22 +3309,18 @@ Return the category metadatum as the type of the candidates."
                         (cons '(vertico-current . embark-target) fr)
                       fr))))))

-(defun embark--vertico-highlight-selected (cand _prefix _suffix _index _start)
-  "Highlight Vertico itmes in the current Embark selection.
-This is meant to be used as advice for `vertico--format-candidate'."
-  (if (member (concat vertico--base cand) embark--selection)
-      (add-face-text-property 0 (length cand) 'embark-selected nil cand)
-    (vertico--remove-face 0 (length cand) 'embark-selected cand)))
-
 (with-eval-after-load 'vertico
+  (cl-defmethod vertico--format-candidate :around (cand prefix suffix index start &context (embark--selection cons))
+    (when (member (concat vertico--base (nth index vertico--candidates)) embark--selection)
+      (setq cand (copy-sequence cand))
+      (add-face-text-property 0 (length cand) 'embark-selected t cand))
+    (cl-call-next-method cand prefix suffix index start))
   (add-hook 'embark-indicators #'embark--vertico-indicator)
   (add-hook 'embark-target-finders #'embark--vertico-selected)
   (add-hook 'embark-candidate-collectors #'embark--vertico-candidates)
   (setq embark-candidate-collectors
-        (cons 'embark-selected-candidates ; ensure highest priority
-              (delq 'embark-selected-candidates embark-candidate-collectors)))
-  (advice-add 'vertico--format-candidate
-              :before 'embark--vertico-highlight-selected))
+        (cons #'embark-selected-candidates ; ensure highest priority
+              (delq #'embark-selected-candidates embark-candidate-collectors))))

 ;; ivy

-- 
2.30.2
oantolin commented 1 year ago

Thanks @minad! I'll update the code in a little while. I'd never looked into how Vertico does formatting and I'm slightly surprised you are using generic functions, but I guess with all the variations of the different extensions that makes sense. I'm also a little surprised you make a copy of the candidate in the code above, I would have assumed a copy was already made.

As for consult-line, you are right that I should have been comparing original candidates instead, I'll fix that.

minad commented 1 year ago

I'll update the code in a little while. I'd never looked into how Vertico does formatting and I'm slightly surprised you are using generic functions, but I guess with all the variations of the different extensions that makes sense.

Yes, cl-defgeneric is pretty nice for all the extensions. Before that I used advices to implement the extensions.

I'm also a little surprised you make a copy of the candidate in the code above, I would have assumed a copy was already made.

Probably, but this is not necessarily guaranteed. For example a completion style which does not apply highlighting does not result in a copy of the candidate string.

I just saw that there is a small additional complication: vertico--format-candidate doesn't guaranteed that the candidate hasn't been changed before, e.g., for multiline candidates as in the kill ring. This means we cannot use the CAND argument for the selection check. Instead use the INDEX argument and lookup the actual candidate again in vertico--candidates. (EDIT: I updated the patch above.)

hmelman commented 1 year ago

IIRC this is similar functionality that helm has. I used helm for a bit but never really used this feature. It seemed mostly useful for buffers and if I wanted this I just used ibuffer. But it may be useful to look at help for examples. It uses C-SPC to toggle marks and M-a to mark-all. The other place I think of with similar functionality is dired and I use marking there often. It uses m to mark u to unmark, U to unmark-all and t toggle marks. I think I prefer the helm approach here, resusing the std binding to set mark which otherwise wouldn't have much use here. But following either of these would make it easier to remember. FWIW on macOS the system standard command-a marks everything and I bind s-a in emacs to do that (e.g., mark-whole-buffer) and would want to be able to do so here as well (in my own config, I'm not suggesting you include this binding in the package).

I think both helm and dired take the approach that if things are marked, an action command that would normally act on the thing under point, instead acts on all the marked items (without some special "act on everything marked" command). I like this approach in dired and would like it here too.

minad commented 1 year ago

On 4/16/23 18:10, Howard Melman wrote:

I think both |helm| and |dired| take the approach that if things are marked, an action command that would normally act on the thing under point, instead acts on all the marked items (without some special "act on everything marked" command). I like this approach in |dired| and would like it here too.

Iirc this has been discussed already, when we added marking to collect buffers. I think it is better to keep embark-act and embark-act-all distinct commands. But if you want this, you can easily write your own command which checks embark--selection and either calls embark-act-all or embark-act.

oantolin commented 1 year ago

@minad I've updated the Vertico integration and fixed the problem you pointed out with consult-line by comparing original targets. Thanks @minad!

Thanks for chiming in, @hmelman! I don't expect I'll use this feature in minibuffers that much either, since I have a lot of practice using orderless to match exactly what I want, meaning I can directly use embark-act-all without selecting candidates. But, maybe selecting candidates when you only want 2 or 3 requires less thought than matching them exactly? I guess time will tell. And anyway, I think it might be pretty fun to use target selections in regular buffers! I could have definitely used this feature in the development of this feature, for example: I wanted to move a bunch of functions definition together in embark.el. Next time I want to do that I'll select them, embark-insert them somewhere and then delete them from their original locations with delete-region. I'm very likely to pull this maneuver with prose paragraphs too.

I've always appreciated your advice on key bindings and this time is no exception. I think C-SPC in the minibuffer makes a lot of sense, I'll suggest in the documentation that people bind it to a keyboard macro which selects the current target. What I'm not so sure about is if C-SPC would be a good binding for the action too, that is, would C-. C-SPC be a comfortable way to toggle whether a candidate is selected? So far I've tried pretty hard to avoid modifiers (other than shift) in the key bindings in the default embark keymaps (I think the only one we have is C-s for isearch). On the other hand if selecting is not that common an operation, maybe that keybinding is short enough.

One other keybinding I've considered for the action is SPC, but then I'd need a new keybinding for marking a target (to turn it into an active region).

minad commented 1 year ago

@oantolin Before having read your comment, I had also considered to either use SPC or C-SPC for selection toggling. These bindings seem natural. Given that C-SPC is used to set a mark why not use that for regions instead?

oantolin commented 1 year ago

Yeah, that seems sensible. SPC is also used in embark-region-map for whitespace-cleanup-region, I guess that could also be moved to C-SPC (both w and W are taken).

oantolin commented 1 year ago

Oh, I probably should also have visual feedback on the selection for icomplete.

minad commented 1 year ago

whitespace-cleanup-region seems like a pretty rare action. Maybe it should be put on an entirely different binding.

oantolin commented 1 year ago

Any thoughts on a key binding for deselecting all? Maybe the commands could be merged? With a prefix argument it deselects all? That would save us the trouble of picking a key binding. 😛 (This is decision-avoidance driven development.)

oantolin commented 1 year ago

whitespace-cleanup-region seems like a pretty rare action. Maybe it should be put on an entirely different binding.

I'd like that, but can't think of a good one. It did feel weird putting it on the SPC prime real estate.