-
Notifications
You must be signed in to change notification settings - Fork 721
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
vim-repeat Extension #110
vim-repeat Extension #110
Conversation
Hi, @dhleong! |
Sure, I'll get on it as soon as I can.
…On Thu, Feb 21, 2019 at 6:25 AM Alex Plate ***@***.***> wrote:
Hi, @dhleong <https://github.com/dhleong>!
Thank you for such a long wait! We will be happy to review the pull
request, but do you have the opportunity to update it in connection with
the latest changes and resolve all conflicts?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#110 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAx0FoQ0-1Se3BE5p1b7Tb5ls_Gj2HTkks5vPoJFgaJpZM4IgTAa>
.
|
e7c2d17
to
20ad816
Compare
Rebased against master— |
I believe so. It's been a while but that sounds right :) |
20ad816
to
53fcb9b
Compare
@AlexPl292 Hey Alex, Thanks for working on this. It's a great feature. Any ETA on when it will get merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HI @dhleong!
I was able to review this pr. Thank you for work!
I have some questions in comments, could you please check them?
Actually, the implementation looks pretty simple. But I still think a bit more about potential drawbacks.
This PR was made quite a long time ago. What are your plans for it? Do you have time/desire to continue it?
I introduce here a global InputQueue (should it rather be per-editor, like the TestInputModel?)
Well, I guess no. Repeat should work in other editors as well.
@Override | ||
public void execute(@NotNull Editor editor, @NotNull DataContext context) { | ||
Project proj = editor.getProject(); | ||
if (proj == null) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this check still necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getProject
seems to be nullable?
public static void executeNormal(@NotNull List<KeyStroke> keys, @NotNull Editor editor) { | ||
enqueue(keys); | ||
|
||
final EditorDataContext context = new EditorDataContext(editor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you want to pass context from VimRepeat
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea was that InputQueue
needn't be exclusively owned by VimRepeat
. We could, however, optionally support providing the data context.
// instance of handleKey, so that any mapping actions | ||
// can appropriately happen "before" the extra strokes. | ||
// NB: Multiple recursive mappings might still break.... | ||
new DrainTask(editor, context).run(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
run()
, not start()
. Everything correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so; it looks like the task enqueues itself if necessary.
|
||
@Override | ||
public void run() { | ||
KeyStroke key = dequeue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just a bit scared about this "recursion". Are you sure that there are no cases when the queue will be populated during this execution? Probably we should add a flag that will "close" the queue while this run()
is running?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's by design that it can get populated during run
. I suppose it would make sense to add some failsafe in case some malfunctioning plugin caused an infinite loop, however.
} | ||
|
||
public static void set(Editor editor, List<KeyStroke> sequence) { | ||
repeatChangeCommand = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that CommandState.getInstance(editor).getLastChangeCommand();
is a proper way. Plugins do execute some other actions during it's execition.
I was able to broke behaviour like this:
- Yank and paste text
- Dot to repeat
- Execute
cs"'
extension - Dot to repeat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or is it what are talking about in
public void run() {
KeyStroke key = dequeue();
if (key != null) {
KeyHandler.getInstance().handleKey(myEditor, key, myContext);
// NB: this doesn't always work; take repeating gcip, for example:
// handling the `c` will trigger `execute(g@)`; the `g` will
// execute first, then this, then the `@`.
final Application application = ApplicationManager.getApplication();
application.invokeLater(this);
}
}
}
?
Waiting for this since 2016 |
Includes support for repeating `ys`, with a test. Required some refactoring of the old, simple `executeNormal` so a string of keys can be processed by the right things, in the right order.
This isn't a great fix, however. Having two different versions of `executeNormal` seems like it's just asking for bugs in the future. It is, however, required for gc(motion)---as mentioned in the comments, the extension's executeNormal calls will get interposed with the characters enqueued for repeating.
Change tag support is incomplete at best
This makes the inputKeyStroke and inputString code not have to know about the InputQueue at all, as it should be
53fcb9b
to
988bb01
Compare
Hi @AlexPl292, sorry for the late response. I've been busy with other projects and this sort of fell off my radar. I'm certainly still interested in the feature, but I'm not certain if this is the best approach. I believe I had in mind that perhaps the
I agree, but I don't think a global queue precludes that. I believe the idea behind the global queue was that queued input can potentially operate across editors. It's been a while so I'll have to look into some of your other comments with regards to breaking things, and some of the code comments. |
Hi! Thank you for your contribution, but we've ended up with another approach of implementing it: 59f4dc8 |
This PR refactors some input handling for Extensions to be able to feed input in a vim-like way, enabling a vim-repeat-style interface for supporting repeat from extension functions. This is another that may not be merged right away, but I'm submitting to open the dialog about how best to go about this.
I introduce here a global
InputQueue
(should it rather be per-editor, like theTestInputModel
?) so we can more closely simulate vim'sexecute
command with input queued up and processed in-order. The queue accessed indirectly forinputKeyStroke
andinputString
(viaModalEntry
andTestInputModel
), so it is transparent to the Extensions.Since we're not actually vim, it may not be necessary to support this sort of input feeding (we could instead save some executable object that performs the repeat) and indeed it does bring up some weirdness in implementation. Specifically, the
VimRepeat
class uses theInputQueue
directly to perform a sort of lazy/delayed run through the input queue, but other plugins need to use the regularVimExtensionFacade#executeNormal
. This interplay seems to work, but it might open the door to potential bugs in the future, if there are particularly complicated extensions.I originally had the Facade call the
InputQueue
always so it would be more symmetrical, but this introduces a weird timing condition when repeatinggcip
, for example. Sincegc
triggers the "lazy" execution ofg@
, thatg
would execute before thei
, and the@
would execute before thep
, causing you to enter insert mode unexpectedly. As it is now, all the Extension's intended executions and execute atomically, with the rest of the enqueued input happening after, as expected. Again, though, it's easy to imagine a situation where this would not be sufficient.Included is repeat support for
surround
and the proposedcommentary
extension from #109, with tests that ensure the repeating cleans up when another change command is executed. Future extensions should probably test their own repeat-ability.Let me know what you think!
(This PR addresses VIM-1118)