emacs-format-all-the-code icon indicating copy to clipboard operation
emacs-format-all-the-code copied to clipboard

Cursor jumping up and down after formatting

Open ztlevi opened this issue 7 years ago • 13 comments
trafficstars

Sometimes I get my cursor jumping around after formatting and I do suffer from other emacs formater packages too. For example, yapfify breaks up when I have split window.

The ideal behavior should be like the cursor stays the same line number after formatting while sometimes it brokes up.

I didn't test quite a lot across different modes but I peek at the code we have here and seems like we don't have any cursor navigation functionality built.

My suggestion is we might need to record down the line position by (line-number-at-position) and set it back after formatting the buffer.

ztlevi avatar Jun 28 '18 22:06 ztlevi

Currently it moves the cursor to the first change made by the formatter. The idea is that you may want to check what the formatter did, because sometimes it does unexpected things or reveals a bug in your code by indenting the code differently than you expected. (I always want to check for things like this, but I realize that not everyone does).

Keeping the line number intact works very well some of the time, but can be very confusing if the formatter makes big changes (e.g. changing an array literal from single-line to multiline). I believe it would be hard to detect things like this so the behavior is pleasing in most cases.

lassik avatar Jun 29 '18 18:06 lassik

This is also somewhat about different ways of working. I tend to run the formatter repeatedly while editing, like once every 5 minutes or even more often - I don't bother to use Emacs own indent-region much anymore because most formatters are fast and do much more thorough job than indent-region would.

If you run the formatter all the time, then it usually makes very small changes, so the cursor doesn't jump very far at all. I realize that this is just my style of working, but I took it up because it works very well in practice.

lassik avatar Jun 29 '18 18:06 lassik

Yep. But small changes might spread across the whole file or at least half page or so. Then, in this case, it's better to just jump back to the line the cursor was at.

ztlevi avatar Jul 01 '18 22:07 ztlevi

They often do (especially when first formatting a file there can be changes everywhere).

Do you have some example of a formatter (in any editor/IDE) that you think already solves this problem well, so that it feels intuitive? I expect it would be more complicated than simply "jump back to the same line number". Perhaps something akin to what diff does when matching chunks to the file even when line numbers have changed. In fact, some of the formatters can output their changes in diff format. I imagine the ideal solution would be based on diffs somehow.

lassik avatar Jul 02 '18 08:07 lassik

I don't think it works for long lines or minified files. Only if the formatter has the full understanding of the language, when the file is formatted, it can jump right back to the specific definition or references. Otherwise, I can't really imagine a perfect way.

ztlevi avatar Jul 03 '18 02:07 ztlevi

I tried implementing your suggestion. After using it for some time with format-all-mode I think it works pretty well, so I added it in. It's now always enabled. Sorry about the delay and enjoy :)

lassik avatar Sep 30 '18 11:09 lassik

After reading how this is, it kind of make sense, but when having auto-save-visited-mode and format-all-mode. You can sometimes get thrown off when the cursor jumps to a different line because the formatting resulted in fewer or more lines above. Do you think it would be possible to have the cursor in the same position? And also let the scroll position change which I see occurs sometimes.

I know that ws-butler feels very non-intrusive, perhaps they have some tricks up their sleeve: https://github.com/lewang/ws-butler/blob/master/ws-butler.el

If it is possible to fix perhaps it could be a customize-able variable that could be triggered if someone prefers to keep same line/column position instead of actual document position.

terlar avatar Nov 28 '18 15:11 terlar

The most likely approach to work well is to generate a diff from the formatter results and then apply that using some diff/patch package that comes with Emacs. Some Emacs packages for specific formatters do approximately that. If ws-butler works well, their approach is worth studying. I think Doom Emacs also added something like this to their adaptation of format-all. I don't know whether that work is finished.

I don't have quite enough energy to work on this myself, but if someone else does a PR, I will be happy to merge it in. Preserving the line number was always a hack to handle the most common case since the patch approach seemed quite complex. If you can figure it out and get it to work then that's great.

I think the starting point should be that the formatter returns the formatted code and format-all makes a patch out of it. Some formatters can also output a patch directly, but not all of them by any means. Maybe we can use formatters' own patch output later, maybe it's an unnecessary complication altogether.

lassik avatar Nov 28 '18 17:11 lassik

If keeping the exact position works well, I can't image that anyone would want to keep just the line number. At least to me this sounds like the kind of thing that should "just work", and how it does it is an implementation detail that users will be happy to ignore. So IMHO this should replace the line number approach altogether once it is working :)

lassik avatar Nov 28 '18 17:11 lassik

It would be great if the point movement behavior were configurable. I'm used to the ALE in Vim, where the cursor is not moved after fixing. I really want to use format-all, but I find the point movement distracting and frustrating.

danielcnorris avatar Mar 29 '19 18:03 danielcnorris

Thanks for the interest :) Unfortunately the situation is still the same as above, i.e. I don't have the bandwidth to fix it myself so I'm waiting for somebody else to send a pull request.

lassik avatar Mar 29 '19 18:03 lassik

An alternative implementation could be something like I mentioned in https://github.com/ubolonton/emacs-tree-sitter/issues/28.

danlamanna avatar Mar 11 '20 17:03 danlamanna

I noticed this problem too, it occurs to me when I open two windows with one single buffer side by side since I need to check different parts of the file at the same time, whenever I modify and save the buffer, the cursor in the other window will be placed into the beginning of the buffer.

There is a workaround, use clone-indirect-buffer-other-window on the current buffer to open current buffer in new window(side by side).

c02y avatar May 20 '21 18:05 c02y