[vim] click places the cursor in illegal position #1084
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
When using http://codemirror.net/demo/vim.html, moving around with direction keys doesn't allow the fat cursor to go past the last column. However, clicking to the far right of a line will place the cursor just after the last column. Instead, it should place it on the last column.
As an aside, you might want to have the vim mode use
defineOptionto add avimModeoption which, when turned on, sets the keymap to vim and does a few other things, such as registering cursoractivity handlers that force the cursor back when it is placed in an invalid position.mentioned in merge request !8420
I've been looking into this suggestion recently and thought I should share my progress at some point so
@mightyguavacan look at it and make a few suggestions. In metatheos/CodeMirror@318c66d8ba I madevim.jsregister the optionvimlike. It sets the keymap, creates the vim-state and registers forbeforeSelectionChange-events.The large amount of red in the commit might be surprising. Actually it was reasonably easy to get the basic functionality of handling cursor-changes and turning visual mode on/off based on mouse input. The most difficult point was to deal with vertical movement since I need to set the two column-variables whenever there is an external change to the cursor.
To solve this I've ended up managing a local
vim.headso I can (mostly) tell where a change is coming from. To make sure the head is updated in every local operation, those operations now usesetCursor(cm,vim,pos,force)which sets the cursor and also updatesvim.head. Theforce-parameter is intended for all those cases where the head is allowed to be placed after the last character of a line.There are a few additional changes covered in the commit:
dandD(adapted tests as well)I didn't make a pull request yet, since with all that shotgun-surgery there might be issues no test caught. Additionally I'm thinking of getting rid of all the passing around of
vim, since with the vim-state being created during the option-change I can expectcm.vimStateto be valid. I might also improve the handling during linewise visual mode by managin a localanchor.The above all sounds very good to me, more or less the direction I hoped the mode would go in. (I didn't look at the code yet, and of course,
@mightyguavahas the last word what happens in this file)Took a pass through the code. Overall I really like it. Here's some initial comments (I'm quite nitpicky :)
selChange()mostly looks good. I'm in agreement with your approach. Will take a deeper look when you make the actual pull request. One suggestion I have is that the logic may read better and be more compact if you switch the order of the conditionals, i.e. make the outer conditionalif (!cursorEqual(sel.head, sel.anchor).headis. I would prefer not to change this unless you find a way to highlight head. Maybe by setting a textmarker with a CSS class that followsvim.selHeadand pretends to be a cursor?vim.headandvim.selHead? Minor enough though.bis pretty broken in visual mode, andgeis a little buggy too. Didn't look into the cause but might be a bug whenheadcrosses overanchor? I'm sorry to say that there are practically no tests for visual mode so a lot of regressions won't be caught, and the negligence is now coming back to bite. It would be great if you could add tests. I think with a bit of thought, it would be possible to make most of the existing motion tests double as visual mode tests.vimseparate fromcmnot because it was not guaranteed to be created (getVimState()is called first thing inhandleKey, the real entrypoint tovim.js), but that I wanted to abstract hide thatvimis a property ofcm. The passing around ofvimis so that if someday I got around to adding a way to define custom actions/motions/operators they would have access to it. I am open to changes on this if you have better suggestions that would not detract from the above, but let that be in a separate change and focus on visual mode here.dandDand text object manipulation into a separate branch? It should be straightforward withgit add -p.You're right I'll really need to look over all the code for the pull request, reorder things and look for obsolete code. This is just the state after I finally got it to mostly behave right.
I had mostly two issues from the user-standpoint:
dtext selected through visual mode, the result is different from right click and cut.Showing a fake cursor to the user would indeed be a solid alternative to moving the actual
sel.head,sel.fromandsel.toaround independently. Unfortunately I don't have any idea if there is a clean way to do this.@marijnhmaybe you can think of something to show a cursor at a custom location without invasive changes to CodeMirror itself?Might very well be true, I have a branch in my personal setup where I could try merging back a few of the issues I've fixed later on. There I've tried allowing to pass my own
sel.fromandsel.toin thebeforeSelectionChange-callback and didn't need this separation.I'll look into that and add tests, thanks for trying it out. I've touched way too much code to find all issues fast myself I fear.
How about having
vim.cmstore a pointer to the parent object and pass aroundviminstead ofcm?Sure, I'll add that to my cleanup
As for
dandDthis would be difficult, since it fell into place by itself and I had to make tests check for the correct behavior, I've actually changedcandCto avoid clipping there. The changes to text object manipulation on the other hand should be filtered out, I included them by accident since they were lingering around from before the other changes. I wanteddiw,caWand anything similar to behave better, but tripped on whitespace-handling around eol.I didn't notice those inconsistences before. Thanks for pointing them out.
I don't think using
cm.markText()is an invasive change. I was thinking that you would maintain a TextMarker object (separate from the vim marks) that followsselHead, update it inselChange, and add a small CSS class (or use the fat cursor's) for the mark incodemirror.css. While not ideal, it would be ok if the cursor didn't blink in visual mode.That does sound good, but would that create a circular reference, which may cause garbage collection problems trying to dispose of
cm? I am not experienced with Javascript memory.@marijnhdo you have any suggestions on a good way to have an abstraction betweenvimandcmstate yet link one to the other? I thought about maintaining a map ofcm => viminvim.jsbut wasn't sure if that would end up causing garbage collection issues als well.Sounds good, leave it in. It's just a nit.
What is wrong with just storing it as a property of the CM instance?
Using
markTextfor the cursor should work. It's not as efficient as the default overlay cursor (requires redraws on the lines themselves), but that's only problematic for very long lines.Nothing wrong with storing it that way. I don't want it to be directly accessed that way since it's a private property. Rethinking it though, it's fine to let the client just break if they play around with the state. So
@metatheosfeel free to get rid ofvimpassing, preferably in a separate branch.mentioned in merge request !8788
Closed by 70a267a