unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: dalanicolai <dalanicolai@gmail.com>
To: Emacs Devel <emacs-devel@gnu.org>
Subject: Two questions about overlays
Date: Tue, 21 Feb 2023 13:46:56 +0100	[thread overview]
Message-ID: <CACJP=3mDp-QNO_oNVLEa_d7VoAM+6UqeyYdwCDmwfF5tzTyvxg@mail.gmail.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 3268 bytes --]

I have two short questions about overlays. To clarify, let me start
with a short motivation.

I have been working on some alternative 'display engine' (I hope I am
using a somewhat correct term here).  Of course, I would prefer to
make functions reusable if possible (currently, image-dired, doc-view,
pdf-tools, and dvju all 'implemented their own' display engines). A
demonstration can be found in the animated gif for the 'universal
document reader' here <https://github.com/dalanicolai/doc-tools> (I would
prefer to reuse/contribute to
doc-view/tools, but it turns out to be much easier to start from
scratch and, if possible, port things over. That simultaneously cleans
up that code).

The 'essence' of that document reader is a very simple 'overlay grid',
which I like to provide as a 'reusable function' (the idea is very
simple and an example is provided in the following file . To try it,
you can simply load the code and show images from a directory by doing
M-x scrap-dir-images. I am not trying to replace image-dired. The
function is just an easy way to implement an example. Also the name
scrap comes from 'scrapbook', but I guess I could simply call it
overlay-grid. Let me know if you have some idea about the naming).

I have been using the overlay grid already in image-roll
<https://github.com/dalanicolai/image-roll.el>, but later I
'discovered' a much simpler way to implement the logic for
'dynamically updating' of visible overlays (i.e. pages, for 'normal
page sizes' we can not display all images of a document at
simultaneously), by simply using the 'overlays-in' function in a
'clever' (or actually quite straightforward) way (instead of
reimplementing that same functionality in lisp).

So now here are the questions:

- when displaying multiple pages in columns, I would like to use the
overlays-in function to determine which overlays should display
images.  So I am creating a full 'book roll' by giving the overlays a
size via the 'space' display property
<https://www.gnu.org/software/emacs/manual/html_node/elisp/Specified-Space.html>,
after which I use overlays-in
to determine which overlays are actually visible. However, after it
takes some time for the 'space' display property to take effect, so I
am manuall adding a 'sit-for' with some reasonable delay
time. However, I would like to ask if there is someone has an idea for
a 'better' mechanism to wait until/detect if the 'overlay expansion'
has finished.

If the explanation is not clear then please load the following file
and do 'M-x scrap-dir-images' on a directory that contains enough
images to not fit all on a single screen. It will print the number of
overlays found via 'overlays-in' directly after 'displaying the
images' (here by assigning the image as display property instead of
space). You will find it prints all overlays in the buffer (instead of
only the ones on screen). To find what I expect it to print now
(again) do 'M-: (overlays-in (window-start) (window-end))'.

My second question is about the function 'overlay-recenter' I don't
really understand its docstring. What kind of 'overlay lookup' would
go faster? What is 'overlay-lookup' anyway?

I hope that some experts here could clear things up in a few words (as
usually is the case :)

Thanks!

[-- Attachment #1.2: Type: text/html, Size: 3714 bytes --]

[-- Attachment #2: scrap-mode.el --]
[-- Type: text/x-emacs-lisp, Size: 3931 bytes --]

;;; image-scroll-mode.el --- Image and document display engine  -*- lexical-binding: t; -*-

;; Copyright (C) 2023  Daniel Nicolai

;; Author: Daniel Nicolai <dalanicolai@gmail.com>
;; Keywords: tools

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;;

;;; Code:
(defvar scrap-incompatible-modes '(visual-line-mode
                                   global-hl-line-mode))

(defvar-local scrap-overlays nil)
(defvar-local scrap-columns nil)
(defvar-local scrap-next-function #'scrap-next)

(defsubst scrap-current-overlay ()
  (car (overlays-at (point))))

(defsubst scrap-get-overlay-n ()
  (overlay-get (scrap-current-overlay) 'n))

(defun scrap-dir-images (dir)
  (interactive
   (list (read-file-name "Select document: " nil nil t nil #'file-directory-p)))
  (pop-to-buffer (get-buffer-create dir))
  (setq buffer-file-name dir)
  (let ((images (seq-filter #'image-supported-file-p (directory-files dir)))
	(max-w (window-text-width nil t))
	;; (max-h 200)
	)
    (scrap-create-overlays (length images) 1)
    (seq-do-indexed (lambda (im n)
		      (overlay-put (nth n scrap-overlays)
				   'display (create-image (concat (file-name-as-directory dir) im) nil nil
							  :max-width max-w)))
		    images))
  (print (length (overlays-in (window-start) (window-end)))))


(defun scrap-create-overlays (number
                              &optional columns hspace vspace
                              &rest overlay-props)
  (dolist (m scrap-incompatible-modes)
    (funcall m -1))
  (toggle-truncate-lines 1) ; also disables visual-mode
  (setq scrap-columns columns)
  (let (overlays)
    (dotimes (i number)
      (let* ((n (1+ i))
             (o (make-overlay
                 (point)
                 (progn (insert " ") (point))
                 (unless (= (% columns 3) 0)
		   (insert (make-string (or hspace 1) (string-to-char " ")))))))
        (when (and (= (% n (or columns 1)) 0)
                   (not (= n number)))
          (insert "\n")
          (insert (make-string (or vspace 1) (string-to-char "\n"))))
        (overlay-put o 'n n)
        (dotimes (j (/ (length overlay-props) 2))
          (let ((m (* j 2)))
            (overlay-put o (nth m overlay-props) (nth (+ m 1) overlay-props))))
        (push o overlays)))
    (goto-char (point-min))
    (setq scrap-overlays (nreverse overlays))
    (scrap-mode)))

(defun scrap-next (n &optional previous)
  (let* ((current (1- (scrap-get-overlay-n)))
         (next (nth (+ current (if previous (- n) n)) scrap-overlays)))
    (goto-char (overlay-start next))
    (overlay-recenter (point))))

(defun scrap-scroll-next (n)
  (interactive "p")
  (funcall scrap-next-function n))

(defun scrap-scroll-previous (n)
  (interactive "p")
  (funcall scrap-next-function n t))

(defun scrap-scroll-next-line (n)
  (interactive "p")
  (funcall scrap-next-function (* n scrap-columns)))

(defun scrap-scroll-previous-line (n)
  (interactive "p")
  (funcall scrap-next-function (* n scrap-columns) t))

(define-minor-mode scrap-mode "Display images in a grid."
  :lighter "Scrap"
  :keymap `((,(kbd "C-n") . scrap-scroll-next)
            (,(kbd "C-p") . scrap-scroll-previous)
            (,(kbd "C-f") . scrap-scroll-next-line)
            (,(kbd "C-b") . scrap-scroll-previous-line)))

(provide 'image-scroll-mode)
;;; image-scroll-mode.el ends here

             reply	other threads:[~2023-02-21 12:46 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-21 12:46 dalanicolai [this message]
2023-02-21 13:21 ` Two questions about overlays Eli Zaretskii
2023-02-21 13:39   ` dalanicolai
2023-02-21 13:50     ` dalanicolai
2023-02-21 13:57       ` dalanicolai
2023-02-21 14:16         ` dalanicolai
2023-02-21 14:52         ` dalanicolai
2023-02-21 15:03     ` Eli Zaretskii
2023-02-21 15:17       ` dalanicolai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CACJP=3mDp-QNO_oNVLEa_d7VoAM+6UqeyYdwCDmwfF5tzTyvxg@mail.gmail.com' \
    --to=dalanicolai@gmail.com \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).