-
Notifications
You must be signed in to change notification settings - Fork 0
Uses Vim's timer instead of CursorHold trigger #374
Conversation
ktonga
left a comment
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.
First of all thank you so much for taking the time to open this PR, it's really good stuff what you're doing here.
I've left a few inline comments but there is also one more general thing that we should consider, currently there is a big outgoing refactor (#367) which touches everywhere including the very same places you're modifying. So I think we should hold on this change until the refactor lands and then you should rebase your PR.
I have already added a comment about this, but I want to emphasize that we should keep the old implementation to support older versions of Vim and Neovim which don't count with this new feature.
Cheers,
Gaston.
autoload/ensime.vim
Outdated
| @@ -43,14 +43,6 @@ function! ensime#au_buf_leave(filename) abort | |||
| return s:call_plugin('au_buf_leave', [a:filename]) | |||
| endfunction | |||
|
|
|||
| function! ensime#au_cursor_hold(filename) abort | |||
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 we shouldn't discard this implementation totally, we should use timers when +timers is present and fallback to this implementation otherwise.
Maybe we can encapsulate the scheduling implementation details inside Editor class as much as possible.
ensime_shared/client.py
Outdated
| @@ -602,7 +603,7 @@ def unqueue_and_display(self, filename): | |||
| self.editor.lazy_display_error(filename) | |||
| self.unqueue() | |||
|
|
|||
| def on_cursor_hold(self, filename): | |||
| def refresh(self, filename): | |||
| """Handler for event CursorHold.""" | |||
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.
This comment should be changed accordingly
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.
tick might be an apt name for this?
ensime_shared/editor.py
Outdated
| # http://vim.wikia.com/wiki/Timer_to_execute_commands_periodically | ||
| self._vim.command(r'call feedkeys("f\e")') | ||
| self._vim.eval("timer_start({}, 'EnRefreshMessages', {{'repeat': -1}})" | ||
| .format(500)) |
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.
Why the half of the time than before? Have you tried different values and this is the most suitable?
Also why the time as parameter and everything else inline?
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.
It's based on nothing, I'll revert back. And the parameter is a left over from the updatetime config variable.
ensime_shared/ensime.py
Outdated
| client.on_cursor_move(filename) | ||
| def refresh_messages(self, client): | ||
| filename = client.editor.path() | ||
| if filename.endswith(".scala"): |
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.
We also support java files
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.
There are a few lines of code in fun_en_complete_func that could be factored out into a function for checking "is the buffer one that ensime-vim supports?". It uses Vim's notion of filetype, which I think is a better way to go than file extension.
rplugin/python/ensime.py
Outdated
| @neovim.autocmd('CursorMoved', **autocmd_params) | ||
| def au_cursor_moved(self, *args, **kwargs): | ||
| super(NeovimEnsime, self).au_cursor_moved(*args, **kwargs) | ||
| @neovim.function('EnRefreshMessages', sync=True) |
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.
This is only for Neovime, you should also define this function for Vim in plugin/ensime.vim
ensime_shared/client.py
Outdated
| @@ -170,6 +170,7 @@ def lazy_initialize_ensime(): | |||
|
|
|||
| try: | |||
| self.ensime = self.launcher.launch() | |||
| self.editor.start_timer() | |||
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 can't see this method implemented in Editor I think you just kept the old name cursorhold. Also I think that this method could use a more descriptive name, something like start_refresh_timer
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.
Some uncommited modifications, my bad.
ensime_shared/editor.py
Outdated
| # Keys with no effect, just retrigger CursorHold | ||
| # http://vim.wikia.com/wiki/Timer_to_execute_commands_periodically | ||
| self._vim.command(r'call feedkeys("f\e")') | ||
| self._vim.eval("timer_start({}, 'EnRefreshMessages', {{'repeat': -1}})" |
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.
You should keep a reference to the timer id returned by timer_start so it can be stopped when the plugin is disabled
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.
This makes me think that each Editor instance shouldn't maintain its own timer as state. There could be a single timer reference as an attribute of Ensime. That's kind of the spirit of the todo comment just above this diff.
There can be more than one live instance of Editor—currently one is created for each EnsimeClient instance, meaning if you edit two ENSIME-enabled projects in one Vim session you'd end up with two timers. That could be changed (in fact #367 changes it, though I didn't think about that much), but I feel leery of having one Editor that needs to be treated as a singleton. As an abstraction it might make perfect sense that there is one editor, but practically speaking singletons get ugly. Running with the extensions idea of #366, it'd be nice if third-party code can simply do editor = Editor(vim) for UI conveniences, instead of there being some global. It currently has virtually no significant state.
Ensime is already effectively a singleton, so it's nice to keep stuff of this nature there as long as it feels like a reasonable design and not overloaded, I think. Thoughts?
|
I haven't reviewed the changes closely yet, but just wanted to say that if this PR gets to a state that everyone is happy with quickly, then I can rebase #367 to include it. It's my fault that big PR has been open for so long so I'd rather deal with conflicts than ask @Kazy to do so. Generally I love the idea of being able to use a proper timer instead of the hacky |
|
Thanks all for the comments. As explained in the issue, that was more a proof of concept than a proper PR. I'll implement your remarks in the next few days to get this PR in an acceptable state. |
|
I've put the logic about the periodic function into I've let the cursor hold and cursor move handler for now, so they trigger the A solution would be to define those purely in Vim, including starting the timer. |
ensime_shared/ensime.py
Outdated
|
|
||
| @execute_with_client() | ||
| def fun_en_complete_func(self, client, findstart_and_base, base=None): | ||
| """Invokable function from vim and neovim to perform completion.""" | ||
| current_filetype = self._vim.eval('&filetype') | ||
| if current_filetype not in ['scala', 'java']: | ||
| if not is_buffer_ensime_compatible(self._vim): |
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 this is a good time to achieve what this TODO says and get rid of this unnecessary check
ensime_shared/util.py
Outdated
| @@ -41,6 +41,11 @@ def extract_package_name(lines): | |||
| break | |||
| return package | |||
|
|
|||
| def is_buffer_ensime_compatible(_vim): | |||
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.
Please move this method to Editor, we are trying to reduce the dependency on the Vim object to only the editor module. This is the best for many reasons, but mostly for making the testing easier.
|
Hey @Kazy are you still keen/able to wrap this PR up? If you rebase it on latest master we maybe could ask the folks in the gitter channel to try the branch for a few days, I can test it on neovim myself. Cheers. |
|
Yes sure, sorry for the delay. I should be able to do that in the next few days. |
ktonga
left a comment
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.
Nice work, I've been using it and seems to be working, but in my case that's only for neovim (0.2.0-dev).
Let's sit on it for a while just in case the rest of the guys have something to add.
plugin/ensime.vim
Outdated
| autocmd BufLeave *.java,*.scala call ensime#au_buf_leave(expand("<afile>")) | ||
| autocmd CursorHold *.java,*.scala call ensime#au_cursor_hold(expand("<afile>")) | ||
| autocmd CursorMoved *.java,*.scala call ensime#au_cursor_moved(expand("<afile>")) | ||
| if !has('timers'): |
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.
You haven't done the same for neovim, is that on purpose?
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 didn't find a way to conditionally define autocmd using Neovim's library. More precisely, neovim.autocmd decorator is used when the class (NeovimEnsime here) is loaded. You can't call it after the fact to define an autocmd.
A possibility would be to declare the CursorHold and CursorMoved autocmd in ensime.vim for Neovim and not in Python.
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.
Ok @Kazy, I've been asking to the nvim guys what to do about it (start of chat) and we should be ok not defining auto commands when in nvim since timers have been around for an year now and people already switched to nvim like new stuff that's for sure :)
So let's remove cursorhold and friends from nvim as it is not acceptable to have both mechanisms running at the same time.
What you reckon? I can test it for a while after you change it.
Cheers.
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.
Thanks for getting info on that ! It's been implemented. I had to create an autocmd on BufEnter that does nothing to trigger the creation of a client and to start the trigger.
|
@Kazy I think it would be useful if you add a few logging (debug) lines, we could use a bit of info about what's going on, this kind of things tend to be difficult to troubleshot :) |
With the removal of CursorHold and CursorMove autocmd, this is needed to start the connection to the Ensime server without having to execute a command manually.
|
Thanks a lot @Kazy it's looking great. I'll give it a go for a couple of days. Since it's not a trivial change I could use at least a second pair of eyes :) @ches @jvican anything to add? If you are using anything else other than Neovim it would be nice guys if you could try this branch for a while. Let's sit on it for a few days and if everything goes fine we are ready to merge it. Cheers. |
|
@Kazy bad news, for me in neovim the server is never starting but the plugin is activated tho, as in when I trigger a plugin action it tries to send the request but obviously nothing is happening as there is no server to handle it. Nothing on the logs that can give me a clue. |
|
Sorry 'bout the false alarm, it was an unrelated problem. |
|
Hey @Kazy I'm cool with this for Neovim, how was it going for you on Vim? If it went ok we could merge it. |
|
One of my last commit fixed the support for vim. I haven't used it extensively though, just tried a few commands. |
|
Are you keen to fix any bug that could come up? I'm keen to merge it already. |
|
@ktonga Let's just merge it. If a bug comes up, we can fix it later down the road. This PR has been for too long in the queue 😄. |
|
Thank you so much @Kazy for this valuable contribution! |
|
Yes I'm available if bugs come up. Ping me if you see one that might be related ! |
|
Thanks @Kazy, this turned out really nicely. |
Related issue: #373