annotate.el icon indicating copy to clipboard operation
annotate.el copied to clipboard

Working with visual-line-mode

Open oatmealm opened this issue 3 years ago • 10 comments

Hi, thanks for a wonderful mode!

Wanted to ask if annotate-mode is designed to work with visual-line-mode for example in org-mode buffer?

I have it set to 'margin, but the effect is new line, with text aligne to the left.

gnome-shell-screenshot-VWP0Q0

oatmealm avatar Sep 15 '20 11:09 oatmealm

On Tue, Sep 15, 2020 at 04:24:21AM -0700, oatmealm wrote:

Hi, thanks for a wonderful mode!

Hi!

Always happy if this library is useful for other people! :)

Wanted to ask if annotate-mode is designed to work with visual-line-mode for example in org-mode buffer?

I have it set to 'margin, but the effect is new line, with text aligne to the left.

To be honest i do not think there was something preventing annotate-mode to works fine with visual-line-mode. I can see two problem here: the wrong text flushing in the annotation (but i wonder if is possible to mix two language with different line flushing in the same buffer, actually i have no idea but if emacs could) and the newline.

Please can you share a little org file thah shown the problem? Because i tried to reproduce the second bug (newline) with no luck. Also in the image you provided how much is the width of the window containing the buffer? Have you tried to enlarge it 8if possible of course) and see what happens?

The problem with text flushing is simple to reproduce but i do not know how much this package can do to prevent that (any hint is welcome!).

Bye! C.

cage2 avatar Sep 15 '20 16:09 cage2

Hi @cage2 ! Thanks for taking the time to have a look. Attaching and org file with the annotations. demo.zip

Notes:

  1. The buffer in the screenshot has writteroom-mode, visual-line-mode and variable-pitch mode enabled.
  2. The variable bidi-parapgraph-direction is set to 'nil, so flushing/alignment of English/Arabic/Hebrew is automatic.

I don't know what controls the comment's appearance... is it affected by any of the modes enabled in the buffer?

The comment in English seems to be flashed to the left, but the rest of the text is wrong.

The second screenshot is with writeroom-mode disabled.

gnome-shell-screenshot-KS35Q0

gnome-shell-screenshot-KZHCR0

oatmealm avatar Sep 15 '20 18:09 oatmealm

Hi!

Thank you for your file, was useful! Now my best guess is that the issue arises because annotate-mode does not play well with variable-width font. For annotate the unit of measure to align stuff is the column (the width of a character); but this value is variable for non monospaced fonts (the same could be true for any character that does not fit in a single column: emoji, for example). I tried to use a monospaced font with the file you provided and seems to me that the text align nicely, can you please confirm? FWIW I installed and used Miriam Mono. from a package called culmus (https://packages.debian.org/buster/culmus). Anyway, hopefully any mono fonts should works.

If confirmed i could "improve" (actually: add a workaround to ;-)) the heuristic to switch policy for annotation placement and force a :new-line policy if appears that a variable switch font line fonts is annotated.

Of course any suggestion, better solution or even actual code is welcome! :-)

Looking forward for your opinion! Bye! C.

cage2 avatar Sep 16 '20 13:09 cage2

Hi, @cage2 I looked again and I can see that flushing is correct--ish (aligned to the right) in with monospace font and w/o visual-line-mode.

I guess indeed that working variable pitch is maybe not possible when you don't have predictable margins?

gnome-shell-screenshot-QUY7Q0

oatmealm avatar Sep 18 '20 08:09 oatmealm

BTW, are you aware of this?

Functions for annotating text with faces and help bubbles https://github.com/agda/agda/blob/aa5e3a127bf17a8c80d947f3c286758a36dadc36/src/data/emacs-mode/annotation.el

It's part of the agda mode and I didn't see it in action, but sounds interesting ...

oatmealm avatar Sep 18 '20 08:09 oatmealm

I guess indeed that working variable pitch is maybe not possible when you don't have predictable margins?

It is possible, there are Emacs functions for measuring the pixel size of a piece of text. But it is not currently implemented.

bastibe avatar Sep 18 '20 10:09 bastibe

Hi, @cage2

Hi everyone!

I looked again and I can see that flushing is correct--ish (aligned to the right) in with monospace font and w/o visual-line-mode.

So it does not works with visual-mode on?

I guess indeed that working variable pitch is maybe not possible when you don't have predictable margins?

Yes! And like @bastibe already wrote Emacs provides functions to calculate the width of a line in pixels. But there is a problem with this approach and i was not able to find a solution so far.

The important concept behind this package is the concept of text properties, In Emacs a property is some little information (in the form of a set of key value pairs) attached to a portion of text in a buffer. So, for example, (display "x") means: instead of this piece of text print the string "x".

An annotation is, a text that is assigned to the 'display' property of the newline of the line (or last line when the text annotated contains multiple lines) that contains annotated text. So instead of the newline the annotation is displayed.

Said annotations contains a bunch of consecutive spaces to align the actual annotation text like that:

this is the newline
that holds the
display property ('*' is actually a space)
              |
              V
text text text***** first annotation line
******************* second annotation line

Emacs provides also a way to add space using pixel as unit of measures using the same 'display property) like that: (propertize "h" 'display '(space :width (40)))

In this case 40 pixel of space is printed instead of 'h'

So i was thinking to switch to using this property to align the annotation text this means that i could use an annotation text like:

text text text padding-pixel-based  first annotation line

This translated to pseudo-elisp means something like:

((" " 'display '(space :width (40))) ("annotation" text 'face 'annotate-annotation))

this string will became the display property of the newline above.

The problem with this approach is that a string with a display property set to a non-null value (the space above) will be included in the display property of the newline. And, unfortunately, display property does not nest, if a display property is found inside a display property the latter is ignored (according to the documentation).

I would like to make this package supports non monospaced fonts but this limitation is insurmountable for me and i can not figure out a solution that does not involve radically changing the way this package works (and even if i would try to rewrite all i have no guarantee that i would be able to find another way to get code with the same functionality).

I would love to have some hint by elisp hackers how (and if) is possible to reach this goal (align nicely with non monospaced font in the context of this package).

I hope i did not annoyed you with this (imprecise and confusing) explanation! :)

Bye! C.

cage2 avatar Sep 18 '20 13:09 cage2

BTW, are you aware of this?

Functions for annotating text with faces and help bubbles https://github.com/agda/agda/blob/aa5e3a127bf17a8c80d947f3c286758a36dadc36/src/data/emacs-mode/annotation.el

It's part of the agda mode and I didn't see it in action, but sounds interesting ...

Skimming the source seems that they use a "tooltip" approach for annotation, the annotation is shown when the mouse is over the annotated text. Should be not impossible to add this feature to this package (maybe switching the "popup" approach using a customizable variable), do you think this could be a useful feature to add?

Of course i have to discuss this feature with @bastibe too.

Bye! C.

cage2 avatar Sep 18 '20 13:09 cage2

Sounds interesting, and probably not too hard to implement. And it would provide a nice workaround for cases where our current approach does not work so well (like highly formatted modes, mixed faces, or variable-width faces).

Regarding the problem of nested display properties, we could use regular spaces instead of a (space :width (pixls)), and resort to U+0x2009 (thin space) and U+0x200A (hair space) for almost pixel-perfect positioning (see the madness of https://en.wikipedia.org/wiki/Whitespace_character for more information).

bastibe avatar Sep 19 '20 16:09 bastibe

On Sat, Sep 19, 2020 at 09:50:21AM -0700, Bastian Bechtold wrote:

Hi Bastian!

Sounds interesting, and probably not too hard to implement. And it would provide a nice workaround for cases where our current approach does not work so> well (like highly formatted modes, mixed faces, or variable-width faces).

OK, I also think could be an useful feature and I would like to try implement that! :)

According to the documentation here:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Overlay-Properties.html

if an overlay has a property 'help-echo' the value of that property (the annotation's text in this case) will be print in the "echo-area" (a popup in some graphical environment). So i think we have all the scaffolding if we decide to go on on that way.

What do you think?

Moreover i think that if an user choose to use this kind of notification the other method based on fontification (the one we are using right now) should be disabled and i think that preventing the call to font-lock-add-keyword

https://github.com/bastibe/annotate.el/blob/master/annotate.el#L384

should suffice.

Seems too simple to me, though! :-D

Regarding the problem of nested display properties, we could use regular spaces instead of a (space :width (pixls)), and resort to U+0x2009 (thin space) and U+0x200A (hair space) for almost pixel-perfect positioning (see the madness of https://en.wikipedia.org/wiki/Whitespace_character for more information).

This is definitely something i would explore but i have some doubts about the results as i can not see how can we be sure that things will align nicely because the small spaces are measured in physical units (fraction of 'em' or 'en' character, right?) and the function Emacs provides are in pixel units.

Anyway, we should check the final results anyway! :)

Bye! C.

cage2 avatar Sep 20 '20 10:09 cage2