2

I want to insert an overlay at the beginning of every 40th or so visual/screen, to generate a WYSIWYG looking page-break overlay like so: enter image description here

At the moment this is done by font-locking the line-feed character (with overlays), which works but it edits the text and makes the overlay too concrete. Ideally I would have a minor-mode running which inserts overlays at the start of every nth visual line to prevent this.

While I found how to move x number of screen lines or get x number of screen lines in a certain region, https://www.gnu.org/software/emacs/manual/html_node/elisp/Screen-Lines.html, I have not been able to figure out how get that position so that I can use it in the declaration of the overlay. Maybe this is doable with some complicated compute-motion, but I am not exactly sure how that would work.

Any ideas?

This is a partial copy of Obtain points at beginning/ending of visual line without using vertical-motion, but that question specifically concerns obtaining the beginning/end of the current line, not any line. While I could iterate over the entire file and obtain those coordinates, that is obviously not very feasible.

tefkah
  • 101
  • 6
  • I haven't used `follow-mode`, but perhaps that would be something that you might be interested in -- essentially there are two (2) windows and the divider between those windows could serve as a page break .... – lawlist Jun 14 '21 at 15:43
  • I have used follow mode extensively and I like the concept, but it is not quite what I want because a) I want the text of the "page" to be somewhat window-size independent, to make it easier to semantically distinguish content (I find it very hard to keep track of things in large buffers) and b) follow-mode is **extremely** slow for me. This might be because I use a 4K display and have a lot of font-locking going on, but I do not really want to give either of those up. – tefkah Jun 14 '21 at 15:48
  • Another idea might be to have a look at `centered-cursor-mode` and see what makes it tick. Instead of centering the cursor, you could place your overlays to achieve the desired visual effect. There may already be an adjustment built-in to that minor-mode to select a screen position other than dead center ... – lawlist Jun 14 '21 at 20:26

1 Answers1

1

I've figured it out! You can use save-excursion to get the position of the n-th visual line

(defun get-visual-line-start (n)
  "Get the character position of the 'nth' visual line, serving as the visual line number."
  (save-excursion
    (goto-line 1)
    (vertical-motion n)
   ; (end-of-visual-line) ; for the end of the line instead 
    (point)))

Then do something like

(let ((n 40))    
  (dotimes (line (round (/ (count-screen-lines) n))
    (let* ((line-pos get-visual-line-start (* n (1+ line)))  
          (ov (make-overlay line-pos line-pos)))
    ;;; do something with the overlay
)))

Tada

tefkah
  • 101
  • 6