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)

Drew
  • 77,472
  • 10
  • 114
  • 243
alper
  • 1,370
  • 1
  • 13
  • 35
  • 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 Aug 05 '20 at 01: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 Aug 07 '20 at 23:27

1 Answers1

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.

lawlist
  • 19,106
  • 5
  • 38
  • 120
  • 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 Aug 08 '20 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 Aug 08 '20 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 Aug 08 '20 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 Aug 08 '20 at 20:29
  • In mac when I use iTerm2 I am experiencing flickering once in a 3 or 4 search in a row, which does not accout in Terminal. I had (setq scroll-conservatively 100), which was also affecting your functions , I removed it and everything works perfect – alper Aug 27 '20 at 19:26
  • When I do magt-log-buffer-file , select one of the log a magit-revision window is opened. On that window, when I seach a word; in each search emacs flashes all the time. I was wondering do you experience this as well ? – alper Oct 25 '20 at 01:12
  • I do not use magit, sorry. – lawlist Oct 25 '20 at 16:12
  • My emacs 28.0 freezes once in a while due to redisplay I believe when I dig in into debug. The debug results: https://gist.github.com/avatar-lavventura/e9b1dda204ce006c8f23c7a6257ef069 . I am not sure the main reason of it just thought could it be related to isearch? – alper Aug 30 '21 at 10:53
  • @alper -- In general, debugging an experimental / developmental version of Emacs not yet released to the general public is something that is handled by the developers on the appropriate mailing list. – lawlist Aug 30 '21 at 13:27
  • lsp-python recommended me to use GccEmacs, when I compilete it Emacs 28.0.50 is build. But I was having same problem in version 27 as well, abnormally emacs get frozen :-( – alper Aug 31 '21 at 07:30
  • @alper -- in order to assist you further, a minimal working example would be needed to reliably reproduce the problem you are experiencing. From your description, it is unclear whether redisplay (internals) is caught in some sort of a never ending loop, or whether this is a Lisp issue that C-g can break out of, or whether Emacs actually locks up entirely. You may need to run Emacs under gdb to catch the problem exactly when it happens. This is most likely an issue that would require a bug report to the Emacs developers once you have a reliable recipe to reproduce the problem. – lawlist Aug 31 '21 at 14:53
  • Thanks I will try with gdp. It is a very nast bug where everything freezes and does not accept any characters and happend so rarely. Due to its freeze, I cannot pull out any information. After restarting emacs, all the characters I entered during its freeze duration printed in the console. It may be related to zsh – alper Aug 31 '21 at 16:19
  • 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 Aug 31 '21 at 17:25