]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow 'make-cursor-line-fully-visible' name a function
authorEli Zaretskii <eliz@gnu.org>
Sun, 30 Sep 2018 11:14:59 +0000 (14:14 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sun, 30 Sep 2018 11:14:59 +0000 (14:14 +0300)
* src/xdisp.c (cursor_row_fully_visible_p): Handle the case of
make-cursor-line-fully-visible being a function.  Accept a 3rd
argument; if non-zero, assume the caller already tested the
conditions for the cursor being fully-visible, and don't
recheck them.  All callers changed.
(try_cursor_movement, try_window_id): Call
cursor_row_fully_visible_p instead of testing the value of
make-cursor-line-fully-visible directly.
(syms_of_xdisp) <make-cursor-line-fully-visible>: Update the
doc string.  Define a symbol Qmake_cursor_line_fully_visible.
(Bug#32848)

* lisp/cus-start.el (standard): Update the Custom form.

* etc/NEWS: Mention the change in possible values of
'make-cursor-line-fully-visible'.

etc/NEWS
lisp/cus-start.el
src/xdisp.c

index 7e7de165ec1eeb0277e8e281ebb4ac2b64175b84..155394ef68f51e9dfa899aa2f55afeec647c1415 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -220,6 +220,12 @@ This triggers to search the program on the remote host as indicated by
 When set to t, no message will be shown when auto-saving (default
 value: nil).
 
+---
+** The value of 'make-cursor-line-fully-visible' can now be a function.
+In addition to nil or non-nil, the value can now be a predicate
+function.  Follow mode uses this to control scrolling of its windows
+when the last screen line in a window is not fully visible.
+
 \f
 * Editing Changes in Emacs 27.1
 
index 88a61753f25527aba092acd81fecbbb69d9d728b..e33fe6e5ecff353d691eeea689621e5ed3b83105 100644 (file)
@@ -547,7 +547,12 @@ since it could result in memory overflow and make Emacs crash."
                      (const :tag "Respect `truncate-lines'" nil)
                      (other :tag "Truncate if not full-width" t))
              "23.1")
-            (make-cursor-line-fully-visible windows boolean)
+            (make-cursor-line-fully-visible
+              windows
+              (choice
+               (const :tag "Make cursor always fully visible" t)
+               (const :tag "Allow cursor to be partially-visible" nil)
+               (function :tag "User-defined function")))
             (mode-line-in-non-selected-windows mode-line boolean "22.1")
             (line-number-display-limit display
                                        (choice integer
index 93cd54a324053588821fb0a0b9cf8d54ccb51ead..d61d421f08a0a0470ba45e761cbf9b7f243c7346 100644 (file)
@@ -842,7 +842,7 @@ static Lisp_Object redisplay_window_1 (Lisp_Object);
 static bool set_cursor_from_row (struct window *, struct glyph_row *,
                                 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
                                 int, int);
-static bool cursor_row_fully_visible_p (struct window *, bool, bool);
+static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
 static bool update_menu_bar (struct frame *, bool, bool);
 static bool try_window_reusing_current_matrix (struct window *);
 static int try_window_id (struct window *);
@@ -14346,7 +14346,7 @@ redisplay_internal (void)
              eassert (this_line_vpos == it.vpos);
              eassert (this_line_y == it.current_y);
              set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-             if (cursor_row_fully_visible_p (w, false, true))
+             if (cursor_row_fully_visible_p (w, false, true, false))
                {
 #ifdef GLYPH_DEBUG
                  *w->desired_matrix->method = 0;
@@ -15628,19 +15628,46 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
    window's current glyph matrix; otherwise use the desired glyph
    matrix.
 
+   If JUST_TEST_USER_PREFERENCE_P, just test what the value of
+   make-cursor-row-fully-visible requires, don't test the actual
+   cursor position.  The assumption is that in that case the caller
+   performs the necessary testing of the cursor position.
+
    A value of false means the caller should do scrolling
    as if point had gone off the screen.  */
 
 static bool
 cursor_row_fully_visible_p (struct window *w, bool force_p,
-                           bool current_matrix_p)
+                           bool current_matrix_p,
+                           bool just_test_user_preference_p)
 {
   struct glyph_matrix *matrix;
   struct glyph_row *row;
   int window_height;
+  Lisp_Object mclfv_p =
+    buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
 
-  if (!make_cursor_line_fully_visible_p)
+  /* If no local binding, use the global value.  */
+  if (EQ (mclfv_p, Qunbound))
+    mclfv_p = Vmake_cursor_line_fully_visible;
+  /* Follow mode sets the variable to a Lisp function in buffers that
+     are under Follow mode.  */
+  if (FUNCTIONP (mclfv_p))
+    {
+      Lisp_Object window;
+      XSETWINDOW (window, w);
+      /* Implementation note: if the function we call here signals an
+        error, we will NOT scroll when the cursor is partially-visible.  */
+      Lisp_Object val = safe_call1 (mclfv_p, window);
+      if (NILP (val))
+       return true;
+      else if (just_test_user_preference_p)
+       return false;
+    }
+  else if (NILP (mclfv_p))
     return true;
+  else if (just_test_user_preference_p)
+    return false;
 
   /* It's not always possible to find the cursor, e.g, when a window
      is full of overlay strings.  Don't do anything in that case.  */
@@ -16002,7 +16029,7 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
       /* If cursor ends up on a partially visible line,
         treat that as being off the bottom of the screen.  */
       if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
-                                       false)
+                                       false, false)
          /* It's possible that the cursor is on the first line of the
             buffer, which is partially obscured due to a vscroll
             (Bug#7537).  In that case, avoid looping forever. */
@@ -16367,7 +16394,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
              /* Make sure this isn't a header line by any chance, since
                 then MATRIX_ROW_PARTIALLY_VISIBLE_P might yield true.  */
              && !row->mode_line_p
-             && make_cursor_line_fully_visible_p)
+             && !cursor_row_fully_visible_p (w, true, true, true))
            {
              if (PT == MATRIX_ROW_END_CHARPOS (row)
                  && !row->ends_at_zv_p
@@ -16385,7 +16412,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
              else
                {
                  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-                 if (!cursor_row_fully_visible_p (w, false, true))
+                 if (!cursor_row_fully_visible_p (w, false, true, false))
                    rc = CURSOR_MOVEMENT_MUST_SCROLL;
                  else
                    rc = CURSOR_MOVEMENT_SUCCESS;
@@ -16964,7 +16991,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
            new_vpos = window_box_height (w) / 2;
        }
 
-      if (!cursor_row_fully_visible_p (w, false, false))
+      if (!cursor_row_fully_visible_p (w, false, false, false))
        {
          /* Point does appear, but on a line partly visible at end of window.
             Move it back to a fully-visible line.  */
@@ -17059,7 +17086,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
                goto need_larger_matrices;
            }
        }
-      if (w->cursor.vpos < 0 || !cursor_row_fully_visible_p (w, false, false))
+      if (w->cursor.vpos < 0
+         || !cursor_row_fully_visible_p (w, false, false, false))
        {
          clear_glyph_matrix (w->desired_matrix);
          goto try_to_scroll;
@@ -17206,7 +17234,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
            /* Forget any recorded base line for line number display.  */
            w->base_line_number = 0;
 
-         if (!cursor_row_fully_visible_p (w, true, false))
+         if (!cursor_row_fully_visible_p (w, true, false, false))
            {
              clear_glyph_matrix (w->desired_matrix);
              last_line_misfit = true;
@@ -17502,7 +17530,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
     }
 
-  if (!cursor_row_fully_visible_p (w, false, false))
+  if (!cursor_row_fully_visible_p (w, false, false, false))
     {
       /* If vscroll is enabled, disable it and try again.  */
       if (w->vscroll)
@@ -19068,9 +19096,10 @@ try_window_id (struct window *w)
         && CHARPOS (start) > BEGV)
        /* Old redisplay didn't take scroll margin into account at the bottom,
           but then global-hl-line-mode doesn't scroll.  KFS 2004-06-14 */
-       || (w->cursor.y + (make_cursor_line_fully_visible_p
-                          ? cursor_height + this_scroll_margin
-                          : 1)) > it.last_visible_y)
+       || (w->cursor.y
+           + (cursor_row_fully_visible_p (w, false, true, true)
+              ? 1
+              : cursor_height + this_scroll_margin)) > it.last_visible_y)
       {
        w->cursor.vpos = -1;
        clear_glyph_matrix (w->desired_matrix);
@@ -32903,9 +32932,15 @@ automatically; to decrease the tool-bar height, use \\[recenter].  */);
     doc: /* Non-nil means raise tool-bar buttons when the mouse moves over them.  */);
   auto_raise_tool_bar_buttons_p = true;
 
-  DEFVAR_BOOL ("make-cursor-line-fully-visible", make_cursor_line_fully_visible_p,
-    doc: /* Non-nil means to scroll (recenter) cursor line if it is not fully visible.  */);
-  make_cursor_line_fully_visible_p = true;
+  DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
+    doc: /* Whether to scroll the window if the cursor line is not fully visible.
+If the value is non-nil, Emacs scrolls or recenters the window to make
+the cursor line fully visible.  The value could also be a function, which
+is called with a single argument, the window to be scrolled, and should
+return non-nil if the partially-visible cursor requires scrolling the
+window, nil if it's okay to leave the cursor partially-visible.  */);
+  Vmake_cursor_line_fully_visible = Qt;
+  DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
 
   DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
     doc: /* Border below tool-bar in pixels.