asciidoctor / atom-asciidoc-preview

⚛ AsciiDoc preview for the Atom editor.
https://atom.io/packages/asciidoc-preview
MIT License
142 stars 42 forks source link

Add option to sync on scroll instead of cursor position #221

Open mojavelinux opened 7 years ago

mojavelinux commented 7 years ago

Description

The current behavior of the sync feature is to align the preview with the position of the cursor in the editor. Some users would like to have the sync be based on the scroll position instead. Add an option to the package that allows the user to control this preference.

Proposed solution

The plugin should watch for the scroll event from the editor, select the nearest block seeking upwards, then scroll the preview to that location.

ferdnyc commented 5 years ago

This would be a great change, as the current sync functionality is disruptive enough to my editing process that I had to disable it. The problem isn't so much the sync-on-cursor, it's the positioning of the sync.

For writing documents, the current sync functionality is great. Because you're working at the very end of the existing source, generally, the preview will be positioned to the bottom of the rendered page, and everything's fine.

But when editing an existing file, you often want to see edits in the context of how they fit into the surrounding content. In those scenarios, the asciidoc-preview sync positioning actively obscures half of that context by positioning the node under the cursor right at the TOP of the preview pane.

To take an extremely real-word example, say that I'm attempting to edit the following block of asciidoc (because I am), in the context of a much longer document (because it is). (Specifically this is lines 86-95 of the total 153 lines in the Fedora Packaging Committee Licensing Guidelines):

=== Multiple Licensing Scenarios

If your package contains files which are under multiple, distinct, and independent licenses, then the spec must reflect this by using "and" as a separator. Fedora maintainers are highly encouraged to avoid this scenario whenever reasonably possible, by dividing files into subpackages (subpackages can each have their own `+License:+` field).

Example:
Package bar-utils contains some files under the Python License, some other files under the GNU Lesser General Public License v2 or later, and one file under the BSD License (no advertising). The package spec must have:

....
License: Python and LGPLv2+ and BSD
....

I might want to try different ways of formatting that section. I'd really want to be viewing at least everything from the heading down, as I'm editing anywhere within the section block. But most of the following are unideal, with sync enabled:

  1. The moment I move my cursor below the heading, it scrolls off the top of the preview.
  2. Moving my cursor to the start of the "Package..." line and inserting a blank line happens to keep "Example:" at the very top of the preview pane, but as soon as I move down to the next line it scrolls away.
  3. Worse, going to the start of the "Package..." line again and deleting the blank line I inserted actually scrolls to the next node (the "License:..." code block), meaning even the line I'm positioned on is off the top of the pane. To get it to reappear I have to move the cursor up a line.
  4. If I move down, then back up to "Packaging", and hit Enter to re-insert that blank line again, this time "Packaging" positions to the very top of the preview, and "Example:" now is off the top of the visible page.

There are two options that I can see for solving this:

  1. Reposition the preview when the cursor moves, but not to the node under the cursor. Rather, scroll the first node that's visible in the source pane to the top of the preview. That'd effectively be sync on scroll, since the positioning would generally only change when the viewport of the source editor moves.

    (It might be an easier implementation than literal sync-on-scroll, though, because it'd automatically account for any possible corner cases around mass-deletion / insertion of text. I assume that any change in the length of the source would register as a scroll event, so it may not be an issue, but it'd be one way to avoid them.)

  2. Scroll the frame based on the cursor position, but scroll that node to the middle of the preview pane, instead of the very top. That's basically, AIUI, what this comment on #82 is asking for.

The immediate problem that comes to mind with the first option is, if your source pane's contents render longer than the source, positioning the preview to the top of the source may not be ideal. Content at the bottom of the source view may not actually fit into the rendered output viewport, in that scenario. But literal sync on scroll can have the same pitfall, depending how it makes its positioning decisions.

The second option would hopefully avoid those issues, and (if possible) may actually be the better approach.