bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#459: Zero-length overlays, overlay keymaps, and `overlays-at'


From: Lars Ingebrigtsen
Subject: bug#459: Zero-length overlays, overlay keymaps, and `overlays-at'
Date: Tue, 20 Jul 2021 13:28:10 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Eli Zaretskii <eliz@gnu.org> writes:

> No, please don't make that the default behavior.  It makes no sense to
> change the default behavior of such a veteran API for the benefit of a
> rare use case.  The gains are very small, and don't justify the risks.
> An optional argument gets us the best of both worlds, so it's a clear
> winner.

I was just hedging in case somebody came up with a brilliant reason for
including them by default.  :-)

However...  after implementing this, I see that `overlays-in' is
something that exists?  And does include zero-length overlays?  *sigh*
So `(overlays-in 1 1)' is the answer to this bug report.

I've included the patch that won't be applied below for reference.
Instead I'll just mention `overlays-in' in the `overlays-at' doc string.

diff --git a/src/buffer.c b/src/buffer.c
index d3a5ffd149..93f3e3dbb6 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2859,7 +2859,8 @@ DEFUN ("kill-all-local-variables", 
Fkill_all_local_variables,
 ptrdiff_t
 overlays_at (EMACS_INT pos, bool extend, Lisp_Object **vec_ptr,
             ptrdiff_t *len_ptr,
-            ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr, bool change_req)
+            ptrdiff_t *next_ptr, ptrdiff_t *prev_ptr, bool change_req,
+            bool include_zero_length)
 {
   ptrdiff_t idx = 0;
   ptrdiff_t len = *len_ptr;
@@ -2886,7 +2887,8 @@ overlays_at (EMACS_INT pos, bool extend, Lisp_Object 
**vec_ptr,
         so its start counts for PREV_PTR if it's before POS.  */
       if (prev < startpos && startpos < pos)
        prev = startpos;
-      if (endpos == pos)
+      if (endpos == pos
+         && (!include_zero_length || endpos != startpos))
        continue;
       if (startpos <= pos)
        {
@@ -2928,7 +2930,8 @@ overlays_at (EMACS_INT pos, bool extend, Lisp_Object 
**vec_ptr,
          break;
        }
       ptrdiff_t endpos = OVERLAY_POSITION (end);
-      if (pos < endpos)
+      if (pos < endpos
+         || (include_zero_length && pos == endpos && startpos == endpos))
        {
          if (idx == len)
            {
@@ -4220,10 +4223,13 @@ DEFUN ("overlay-properties", Foverlay_properties, 
Soverlay_properties, 1, 1, 0,
 }
 
 
-DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 2, 0,
+DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 3, 0,
        doc: /* Return a list of the overlays that contain the character at POS.
-If SORTED is non-nil, then sort them by decreasing priority.  */)
-  (Lisp_Object pos, Lisp_Object sorted)
+If SORTED is non-nil, then sort them by decreasing priority.
+
+If INCLUDE-ZERO-LENGTH is non-nil, also include zero-length overlays
+at POS.  (These are otherwise excluded.)  */)
+  (Lisp_Object pos, Lisp_Object sorted, Lisp_Object include_zero_length)
 {
   ptrdiff_t len, noverlays;
   Lisp_Object *overlay_vec;
@@ -4241,7 +4247,7 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 2, 0,
   /* Put all the overlays we want in a vector in overlay_vec.
      Store the length in len.  */
   noverlays = overlays_at (XFIXNUM (pos), 1, &overlay_vec, &len,
-                          NULL, NULL, 0);
+                          NULL, NULL, 0, !NILP (include_zero_length));
 
   if (!NILP (sorted))
     noverlays = sort_overlays (overlay_vec, noverlays,
@@ -4317,7 +4323,7 @@ DEFUN ("next-overlay-change", Fnext_overlay_change, 
Snext_overlay_change,
      Store the length in len.
      endpos gets the position where the next overlay starts.  */
   noverlays = overlays_at (XFIXNUM (pos), 1, &overlay_vec, &len,
-                          &endpos, 0, 1);
+                          &endpos, 0, 1, false);
 
   /* If any of these overlays ends before endpos,
      use its ending point instead.  */
@@ -4364,7 +4370,7 @@ DEFUN ("previous-overlay-change", 
Fprevious_overlay_change,
      Store the length in len.
      prevpos gets the position of the previous change.  */
   overlays_at (XFIXNUM (pos), 1, &overlay_vec, &len,
-              0, &prevpos, 1);
+              0, &prevpos, 1, false);
 
   xfree (overlay_vec);
   return make_fixnum (prevpos);
diff --git a/src/buffer.h b/src/buffer.h
index 24e9c3fcbc..daa666248d 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1145,7 +1145,8 @@ #define CHECK_FIXNUM_COERCE_MARKER(x) ((x) = make_fixnum 
(fix_position (x)))
 extern void compact_buffer (struct buffer *);
 extern void evaporate_overlays (ptrdiff_t);
 extern ptrdiff_t overlays_at (EMACS_INT, bool, Lisp_Object **,
-                             ptrdiff_t *, ptrdiff_t *, ptrdiff_t *, bool);
+                             ptrdiff_t *, ptrdiff_t *, ptrdiff_t *, bool,
+                             bool);
 extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *);
 extern void recenter_overlay_lists (struct buffer *, ptrdiff_t);
 extern ptrdiff_t overlay_strings (ptrdiff_t, struct window *, unsigned char 
**);
@@ -1204,13 +1205,13 @@ #define GET_OVERLAYS_AT(posn, overlays, noverlays, 
nextp, chrq)         \
     ptrdiff_t maxlen = 40;                                             \
     SAFE_NALLOCA (overlays, 1, maxlen);                                        
\
     (noverlays) = overlays_at (posn, false, &(overlays), &maxlen,      \
-                              nextp, NULL, chrq);                      \
+                              nextp, NULL, chrq, false);               \
     if ((noverlays) > maxlen)                                          \
       {                                                                        
\
        maxlen = noverlays;                                             \
        SAFE_NALLOCA (overlays, 1, maxlen);                             \
        (noverlays) = overlays_at (posn, false, &(overlays), &maxlen,   \
-                                  nextp, NULL, chrq);                  \
+                                  nextp, NULL, chrq, false);           \
       }                                                                        
\
   } while (false)
 
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 2adffc024a..5e83c0beab 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -1386,4 +1386,17 @@ buffer-tests-inhibit-buffer-hooks-indirect
           (when (buffer-live-p base)
             (kill-buffer base)))))))
 
+(ert-deftest zero-length-overlays-and-not ()
+  (with-temp-buffer
+    (insert "hello")
+    (let ((long-overlay (make-overlay 2 4))
+          (zero-overlay (make-overlay 3 3)))
+      ;; Exclude.
+      (should (= (length (overlays-at 3)) 1))
+      (should (eq (car (overlays-at 3)) long-overlay))
+      ;; Include.
+      (should (= (length (overlays-at 3 nil t)) 2))
+      (should (memq long-overlay (overlays-at 3 nil t)))
+      (should (memq zero-overlay (overlays-at 3 nil t))))))
+
 ;;; buffer-tests.el ends here


-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





reply via email to

[Prev in Thread] Current Thread [Next in Thread]