1

I have followed answer for Emacs: Combine iseach-forward and recenter-top-bottom, replacing (recenter-top-bottom) to (recenter).

My goal is to re-center after each isearch-forward or isearch-backward. When I put same two words into the buffer and do isearch-repeat-forward operation (CTLR and hold s for the selected word) screen keep flashes (like keep blinks). This does not happen on default isearch-repeat-* operation.

[Q] Is it possible to prevent flashing on combination of isearch and recenter?


My setup:

(defadvice
  isearch-repeat-forward
  (after isearch-repeat-forward-recenter activate)
  (recenter))

(defadvice
  isearch-repeat-backward
  (after isearch-repeat-backward-recenter activate)
  (recenter))

(ad-activate 'isearch-repeat-forward)
(ad-activate 'isearch-repeat-backward)
2
  • 1
    Without a video, and even with a video, you are likely to receive comments from forum participants such as ... I don't see the problem on my setup. You will probably see questions such as what is your OS and version of Emacs and where did you get it? I know that macOS is prone to screen glitches that began on 09/28/2018 (7946445962372c4255180af45cb7c857f1b0b5fa) to provide compatibility with Mojave, i.e., the NS port no longer does anything useful during update_window except mark dirty rectangles -- the drawing is now done when the OS calls drawRect, which in turn calls expose_frame.
    – lawlist
    Commented Aug 5, 2020 at 1:59
  • Good catch I am on macOS Catalina and it has glitches (even more when I use flux). I thing default search is recenter-bottom which works pretty good. But when I use the code on my questions, blink occurs after each search , this is the only time I observe this kind of behavior on emacs.
    – alper
    Commented Aug 7, 2020 at 23:27

1 Answer 1

2

In a comment underneath the question, the O.P. stated that he/she is using a version of Emacs on macOS Catalina -- presumably the GUI version (although not stated one way or the other).

In the event that Alan Third (the maintainer of the macOS port of Emacs) reads this, I really do appreciate everything that he has done and continues to do to keep the macOS port of Emacs alive. My comments are not meant to be a criticism of anything he has implemented as a means of working around certain problems introduced by Apple ...

For at least as long as I have been using Emacs (i.e., version 24), and probably a lot longer than that, Emacs updated the glass directly during its redisplay cycle when running update_window in dispnew.c. All was well until Apple introduced its Mojave version of the macOS operating system -- effectively doing away with the ability for applications such as Emacs to update the glass directly at any given time during its redisplay cycle. In a nutshell, applications must now wait until the OS calls drawRect to update the glass. It is possible (but not recommended), or at least it was possible the last time I checked, to force the OS to call drawRect out of order in its normal redisplay cycle.

As of 09/28/2018 (7946445962372c4255180af45cb7c857f1b0b5fa), the macOS port of Emacs now only marks dirty rectangles (areas that need updating) during update_window and then Emacs has to wait until the OS calls drawRect to update the areas of the glass that had been marked as dirty -- triggering Emacs to run expose_frame on said areas. That changeover in the way the glass is updated during redisplay causes certain screen glitches (e.g., flickering) in terms of areas that do not update correctly and/or certain additional areas of the screen are redrawn (which was not the case prior to 09/28/2018). I do not have a solution for those issues, sorry.

I would suggest that the O.P. reduce the number of calls to recenter to an absolute bare minimum. My preference would be to run recenter prior to isearch calling isearch-update, because the latter updates the display based upon the lay of the land. I.e., running recenter after isearch runs isearch-update seems unwise (in my opinion). My idea is to call recenter only when the line containing point is not centered. I considered using something like count-screen-lines and recording the line containing point, but I know from experience that vertical-motion can slow things down when called excessively. I also know that posn-at-point can slow things down when called excessively, but I figure it will probably suffice for this use-case to help us record the Y-axis containing point. If the Y-axis containing point has changed, then recenter and record the new Y and the selected-window in a variable -- to be compared against future values. Other than reducing the calls to recenter as in the following example, I cannot think of anything else to reduce screen flickering:

(defvar my-isearch-window-start '(nil 0)
"Record the `selected-window' and the Y-axis coordinate of point each time that
`isearch-update' calls `my-isearch-update-recenter' (via an advice).  The value
of this variable will be a cons cell with the CAR being the `selected-window' and
the CDR being the Y-axis coordinate of point.")

(defun my-isearch-update-recenter ()
  (let* ((win (selected-window))
         (pt (point))
         (y (cdr (nth 2 (posn-at-point pt win))))
         (same-y-p (and y
                        (eq win (car my-isearch-window-start))
                        (= y (cdr my-isearch-window-start)))))
    (when (and y (not same-y-p))
      (recenter)
      (setq my-isearch-window-start (cons win y)))))

(advice-add 'isearch-update :before 'my-isearch-update-recenter)

USAGE:

(1) Open up either a terminal or a GUI version of Emacs 26.3.50, built for the OSX/macOS platform, without any user configuration -- aka /path/to/correct/version/of/Emacs -nw -Q or drop the -nw from the command-line if the GUI version is desired. I have tested the code on both a terminal version of Emacs and also a GUI version of Emacs -- the procedure and result should be the same.

[NOTE that many versions of OSX/macOS came with Emacs 22.1.1 pre-installed at /usr/bin/emacs -- therefore, we want to be sure to launch a current version of Emacs by either using the absolute path to the executable or navigating to its directory and typing ./Emacs .... In my case, the Emacs executable is inside a packaged Emacs.app directory located at /Applications/Emacs.app/Contents/MacOS/Emacs]

(2) Copy the code snippets from the answer above, and then switch to the *scratch* buffer in Emacs and paste the code snippets we just copied, and then type M-x eval-buffer.

(3) Open a lengthy test file by typing M-x find-library RET simple RET, which will open the simple.el library if our version of Emacs was built using the standard defaults that install the Lisp source code.

(4) Type the keyboard shortcut C-s which is bound to isearch-forward by default.

(5) isearch-forward is now active based upon the preceding step. Type the letters: update. Emacs searches forward for the first occurrence of the letters update and automatically recenters the screen.

(6) Now we want to search for the next occurrence of the letters update. To do that, we can either type the keyboard shortcut C-s or s-g (aka Command-g) -- both keyboard shortcuts are bound to isearch-repeat-forward. Emacs searches forward for the next occurrence of the letters update and recenters the screen.

(7) We can continue repeating the preceding step to verify that everything is working as advertised. This concludes our test.

13
  • Sorry to mention: I was using terminal version (no GUI) . Recenter does not take place should I bind my-isearch-update-recenter in to a keybinding?
    – alper
    Commented Aug 8, 2020 at 12:28
  • Thank you for trying out the answer. There is no need to rebind anything. The code works on both a terminal and a GUI version of Emacs 26.3.50. I have updated the answer with a step-by-step method to test the code and verify that it works as advertised. As always, we try it out without any user-configuration to verify that nothing in our personal user-configuration interferes with the answer.
    – lawlist
    Commented Aug 8, 2020 at 16:46
  • Thanks for depth answer, on my end screen blinking on each isearch-forward is still generated. Since recenter is not done , i think the code is note loaded
    – alper
    Commented Aug 8, 2020 at 19:44
  • Perhaps you are unwittingly loading your own user-configuration and/or perhaps you are still using some of the code identified in your question and/or in the link to your question. I would recommend trying steps 1 through 7 to the letter -- ensuring that you bypass any user-configuration by launching with /path/to/correct/version/of/Emacs -nw -Q. Inasmuch as I have tested steps 1 through 7 several times on both the terminal and GUI versions of Emacs 26.3 (built for OSX/macOS), I can assure you that isearch recenters as advertised. If flickering persists though, you may be out of luck.
    – lawlist
    Commented Aug 8, 2020 at 20:29
  • 1
    If you build Emacs using configure flag --enable-checking='yes,glyphs', then when you launch a GUI version of Emacs from the terminal, you can type M-x trace-redisplay and the redisplay cycle generates messages within the terminal from which Emacs was launched. If there is a never-ending loop in the redisplay engine, it will be readily apparent from those messages. If running under gdb, then of course you can break and inspect ... All of that, though, is the type of stuff that is handled with the help of Emacs Devel on the appropriate mailing list or through a formal bug report ...
    – lawlist
    Commented Aug 31, 2021 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.