bastibe/annotate.el

Working with visual-line-mode

Opened this issue · 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

cage2 commented

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

cage2 commented

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.

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

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 ...

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.

cage2 commented

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 commented

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.

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).

cage2 commented