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

Feature request: Repeat last command #27

Closed
sibbng opened this issue Dec 29, 2020 · 12 comments
Closed

Feature request: Repeat last command #27

sibbng opened this issue Dec 29, 2020 · 12 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@sibbng
Copy link

sibbng commented Dec 29, 2020

Problem

Sometimes commands requires a lot of key strokes. Repeating last command with single key would be great.

<spc> T T

<spc>: Opens Which Key => 1 key
Shift + t: Uppercase t, Opens UI Toggles => 2 key
Shift + t: Uppercase t, Toggles Tabs => 2 key

Total key strokes: 5

Solution

Repeat last command:
<spc> r
Total key strokes: 2

List of last commands:
<spc> R

Repeats last command:
<spc> R 1

Repeats 2nd last command:
<spc> R 2

Repeats 3rd last command:
<spc> R 3

@sibbng sibbng added the enhancement New feature or request label Dec 29, 2020
@stevenguh
Copy link
Member

That's very interesting. I did some digging, apparently this does not exist in any of the which-key implementation (at least I can't find it). There are some feature request on the spacemacs repo.
syl20bnr/spacemacs#1402
syl20bnr/spacemacs#7846
After reading those issues, <spc> . could also be a good candidate to repeat last command.

As far as implementation goes, it doesn't seems to be too hard. I am imagining it would be circular buffer storing the history ox commands. However, commands executed in transient and conditional can be a bit tricky.

For transient binding (e.g. zooming multiple times<spc> z f + +).

  • should we simply store the commands executed
  • should store the non duplicate command
  • not store transient command at all

For conditional binding (e.g. like major mode)

  • should we simply store the commands executed (the command executed by repeat might not work because user changed from a python file to a java file for example)
  • not store conditional command at all

The simplest implementation would be just record all the commands history and "replay" it.

@MarcoIeni
Copy link
Member

That would be a really nice feature!
spc r is already taken, so spc . is perfect for that (talking about VSpaceCode binding).

We might want to use spc R in the future for other bindings..maybe..
Do you like spc > instead of spc R? (it's shift + .). I was thinking about spc r ., too.

For transient binding (e.g. zooming multiple times<spc> z f + +).

  • should we simply store the commands executed
  • should store the non duplicate command
  • not store transient command at all

I would pick option 2. Since sibbng proposed to pick a command from the list, we should avoid storing duplicate commands in my opinion. It's useless to see duplicate commands in the list.

For conditional binding (e.g. like major mode)

  • should we simply store the commands executed (the command executed by repeat might not work because user changed from a python file to a java file for example)
  • not store conditional command at all

Option 1! If the command will not work, no problem :)

basic solution

The simplest implementation would be just record all the commands history and "replay" it.

This, but only add the command to the history if different from the last one.

improvement over basic solution

An improvement might be to recognize if the executed command is present in the list of recent commands. If so move that command to the last position.

I have this behavior in my shell history.
This is what I see when I press ctrl+r:
image

Then, when I pick the command I want (in this case cd ..), it is moved on the first position.

image

I hope I was clear

@stevenguh
Copy link
Member

Both your basic and improvement sound reasonable. It's basically like a LRU cache.

I like the idea for using <spc> . to repeat the last command in executed by which-key
For the other functions like listing last executed commands, and last 1st, 2nd, 3nd, etc: It would be awesome if we can find a place in the <spc> r instead of <spc> R. For example: <spc> r 1, <spc> r 2, and <spc> r .

@sibbng
Copy link
Author

sibbng commented Dec 29, 2020

If these repeat functionality can be exported to a registered command I would prefer assigning it to a vim binding rather than using space <key>.

Example:

  {
    "key": "r",
    "command": "whichkey.repeatLastCommand", // Repeats last command
    "when": "editorFocus && !extension.simpleVim.insertMode" //I'm using my own fork of Simple Vim.
  },
  {
    "key": "R",
    "command": "whichkey.showLastCommands", // Opens Which Keys numbered last command list
    "when": "editorFocus && !extension.simpleVim.insertMode"
  },

@stevenguh
Copy link
Member

Make sense, the function will be exposed as a command so VSpaceCode can bind it in the menu, or people can also bind it anywhere they want :)

@MarcoIeni
Copy link
Member

I like the idea for using <spc> . to repeat the last command in executed by which-key
For the other functions like listing last executed commands, and last 1st, 2nd, 3nd, etc: It would be awesome if we can find a place in the <spc> r instead of <spc> R. For example: <spc> r 1, <spc> r 2, and <spc> r .

Yeah, but when you press spc r the resume menu is loaded:
image

If also 1, 2..9 are there, then the text will be something like "run action 1" or "run action 2". Not the actual name of the action, right? So it is difficult to pick one.

Instead if there is a dedicated shortcut that shows the "actions history" (that could be assigned to spc r . for example), you can see the actual actions names in the list, so it's easier to pick the one you are looking for.

Correct me if I am wrong or tell me if I wasn't clear.

@stevenguh
Copy link
Member

Maybe talking about the API will makes it a little bit clear of what I am thinking. We will have a command to executed the last action by default (with argument it can execute last 2nd, 3rd, etc), a command to open a list of previous actions.

whichkey.repeatPreviousCommand will by default execute the last command and can pass an argument to repeat last 2nd, 3rd, and etc.
whichkey.showPreviousCommands will show a QuickPick menu that a user can pick all the previous commands by clicking 1-9. (brain dump on implementation so I don't forget: we can probably output a collection of bindings from the cache, so we can simply open a which-key menu with the dynamic generated content when a user execute this command)


<spc> . should bind to whichkey.repeatPreviousCommand so a user can repeat last action quickly

Instead if there is a dedicated shortcut that shows the "actions history" (that could be assigned to spc r . for example), you can see the actual actions names in the list, so it's easier to pick the one you are looking for.

This would be the whichkey.showPreviousCommands and it makes sense assigned to <spc> r .

If also 1, 2..9 are there, then the text will be something like "run action 1" or "run action 2". Not the actual name of the action, right? So it is difficult to pick one.

I guess if we have <spc> r . where a user can navigate, there isn't much value to put static bindings like <spc> r 1, <spc> r 2 into our config where we can't change the name of the action (e.g. run last action, or run last 2nd action). With whichkey.repeatPreviousCommand providing positional argument, a user can choose to add an override or in other context like in Vim.

@MarcoIeni
Copy link
Member

Yes, perfect!

@stevenguh
Copy link
Member

I have been thinking a little bit more about transient menu. It seems like it makes more sense to record the action of opening a transient menu instead of the action executed in the transient and the repeat command would only open the transient again.

To achieve this, that prompted me to think about refactoring the transient menu into a standalone command (e.g. calling whichkey.showTransient instead of being one of the types (type transient) in which key menu config.

Concretely, instead of

{
    "key": "J",
    "name": "Move lines down",
    "type": "transient",
    "command": "editor.action.moveLinesDownAction",
    "bindings": [
        {
            "key": "J",
            "name": "Move lines down",
            "type": "command",
            "command": "editor.action.moveLinesDownAction"
        },
        {
            "key": "K",
            "name": "Move lines up",
            "type": "command",
            "command": "editor.action.moveLinesUpAction"
        }
    ]
}

we will simply call the command with the argument to locate the config.

{
    "key": "J",
    "name": "Move lines down",
    "type": "commands",
    "commands": ["editor.action.moveLinesDownAction", "whichkey.showTransient"],
    "args": [null, "linesMovingTransient"]
}

Refactoring this way also solves #13.

Lastly, this also help us implement #12 so it's more like spacemacs. Spacemacs' <spc> ? doesn't show transient keys and it only shows the transient command because it uses hydra for the transient menu.

@MarcoIeni
Copy link
Member

MarcoIeni commented Jan 3, 2021

I have been thinking a little bit more about transient menu. It seems like it makes more sense to record the action of opening a transient menu instead of the action executed in the transient and the repeat command would only open the transient again.

I agree!

I think I also got the rest of your comment, and I agree with that, too :)

@stevenguh
Copy link
Member

The refactoring is going take some more time to think through. This feature probably doesn't need the refactoring, and a preliminary of this feature looks like
image

@stevenguh stevenguh self-assigned this Jan 25, 2021
@stevenguh stevenguh added this to the v0.9.0 milestone May 24, 2021
@stevenguh
Copy link
Member

Released v0.9.0 finally! Closing this :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants