My favorite things about easy motion is that you don't need to move your gaze away from where you want to go. The text decorations seem to break that though since they get placed behind the text and shift everything on the line over. When there are a lot of matches on a given line, it can move the characters significantly.
Is there any way to avoid replacing the text in the buffer like the original easymotion did while also keeping the text in it's original positions?
Yep
https://github.com/asvetliakov/vscode-neovim#vim-easymotion
Sorry if I wasn't clear. My concern is with that fork of the plugin and the way it shifts the text. For example, the screenshot at that link shows how the start of the lines get shifted to the right to make room for the decorations. That's most visible on the import lines that have 2 characters preceding them instead of 1. Although it's minor in that example, it becomes much worse when the motion has a lot of matches on a single line.
I figured it out by lifting some code from the main vim plugin for vscode. Here is the diff that worked for me:
diff --git a/src/controller.ts b/src/controller.ts
index 18d7889..e57aa86 100644
--- a/src/controller.ts
+++ b/src/controller.ts
@@ -1899,15 +1899,26 @@ export class NVIMPluginController implements vscode.Disposable {
for (const [colNum, text] of cols) {
// vim sends column in bytes, need to convert to characters
// const col = colNum - 1;
- const col = Utils.convertByteNumToCharNum(line, colNum - 1);
+ const col = Utils.convertByteNumToCharNum(line, colNum - 1+1);
+ const width = text.length * 8;
const opt: vscode.DecorationOptions = {
range: new vscode.Range(lineNum, col, lineNum, col),
renderOptions: {
- before: {
+ /* before: { */
+ /* ...conf, */
+ /* ...conf.before, */
+ /* contentText: text, */
+ /* }, */
+ after: {
+ margin: `0 0 0 -${width}px`,
+ height: `14px`,
...conf,
...conf.before,
+ // This is a tricky part. Set position and z-index property along with width
+ // to bring markers to front
+ width: `${width}px; position:absoulute; z-index:99;`,
contentText: text,
- },
+ },
},
};
options.push(opt);
I can try adding a setting for this and making a pull request if there's any interest. I've only briefly tested it so hopefully it works in all cases.
I'll try this out for a few days, it seems to be working pretty well under normal use. It is definitely an improvement from before (once you pointed out the shifting I realized it was pretty annoying).
One difference I've noticed between normal (terminal) vim and this fix is that with 2-letter targets, vim aligns the first letter of the target with the jump position, whereas in vscode the last letter is aligned with the jump target. On targets that are in the first column, this means the first letter is hidden by the gutter. This also makes jumping to 2-letter targets cumbersome in general.
After playing around with that patch a bit more, I noticed the 2 letter alignment problem as well. The pull request I just opened fixes that problem and adds an option to toggle between the old and new styles. Let me know if you catch any other problems.
I would love if the VSCode easymotion fork didn't shift the characters. I agree, it's jarring to be looking where you want to jump and have it move when you activate the motion.
Fixed by #358
Most helpful comment
After playing around with that patch a bit more, I noticed the 2 letter alignment problem as well. The pull request I just opened fixes that problem and adds an option to toggle between the old and new styles. Let me know if you catch any other problems.