Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anzu's counter is case insensitive even if isearch is case sensitive #93

Closed
agreselin opened this issue Aug 29, 2018 · 15 comments · Fixed by #102
Closed

Anzu's counter is case insensitive even if isearch is case sensitive #93

agreselin opened this issue Aug 29, 2018 · 15 comments · Fixed by #102
Labels
bug a feature isn't working

Comments

@agreselin
Copy link
Contributor

Hello. In a buffer containing

Anzu please count right

if I do C-s M-c anzu isearch fails but Anzu counts one match (the counter is (0/1)). I use Anzu 0.62 on Emacs 25.2; my set-up for Anzu is

(require 'anzu)
(global-anzu-mode)
(define-key isearch-mode-map [remap isearch-query-replace]  #'anzu-isearch-query-replace)
(define-key isearch-mode-map [remap isearch-query-replace-regexp] #'anzu-isearch-query-replace-regexp)
@agreselin agreselin changed the title Anzu counter is case insensitive even if isearch is case sensitive Anzu's counter is case insensitive even if isearch is case sensitive Aug 30, 2018
@syohex
Copy link
Contributor

syohex commented Mar 20, 2020

I have sent PR #102

@agreselin
Copy link
Contributor Author

agreselin commented Mar 21, 2020

It's not fixed, at least for me. I had fixed it by replacing the original definition of anzu--case-fold-search with

(defsubst anzu--case-fold-search () ; I don't use the argument.
  (if isearch-mode
      isearch-case-fold-search
    case-fold-search))

and by adding (not (eq last-command 'isearch-toggle-case-fold)) to anzu--use-result-cache-p:

(defun anzu--use-result-cache-p (input)
  (and (eq (anzu--isearch-regexp-function) (car anzu--last-search-state))
       (eq isearch-regexp (cdr anzu--last-search-state))
       (string= input anzu--last-isearch-string)
       (not (eq last-command 'isearch-toggle-case-fold))))

I don't understand the original anzu--case-fold-search:

(defsubst anzu--case-fold-search (input)
  (when isearch-case-fold-search
    (let ((case-fold-search nil))
      (not (string-match-p "[A-Z]" input)))))

As far as I understand, it only returns nil if there are uppercase letters in input, but that means that anzu can't match all-lowercase strings case sensitively (i.e. don't match "Error" when I'm searching for "error").

I've made a pull request (#104) but please bear with me, it's my first pull request and I'm not an experienced Elisp programmer. Notice that my proposed solution still has the problem that the counter is not updated right after typing M-c, but only at the next invocation of C-s or C-r.

@gonewest818 gonewest818 reopened this Mar 22, 2020
@gonewest818
Copy link
Collaborator

Thanks for providing this. I'm reopening to take a closer look why this isn't fixed for you.

@gonewest818 gonewest818 added bug a feature isn't working need repro we can't reproduce this labels Mar 22, 2020
@gonewest818
Copy link
Collaborator

Documenting here the behavior I see in Emacs 25.3 or Emacs 27.0.90. Is this what you see?

With a buffer containing:

Anzu please count right

Tests:

  • perform a isearch-forward for the string "anzu" and the counter is (1/1) as expected.

  • perform isearch-forward for the string "Anzu" and the counter is (1/1) as expected.

  • perform isearch-forward then M-c to make it case sensitive, then enter the search string "anzu" and the counter is (0/0), again as expected.

  • perform isearch-forward then the string "anzu" and finally M-c to toggle case sensitive matching. A message in the mini buffer says "Pending I-search: anzu" with the counter (1/1). The counter updates when you type another character to update the the search string:

    • If you type a space after the M-c so that the search string is "anzu " then the counter will update (0/0).
    • If you hit DEL after the M-c so that the search string is "anz" then the counter remains (1/1) as if the case sensitivity has been discarded.

In summary I would there is some inconsistency in the isearch system but anzu seems to be fumbling the M-c toggle also.

@agreselin
Copy link
Contributor Author

Yes, I see the same behaviour. Anyway, I'm using Emacs 26.3 now.

In particular, with a buffer containing

AB ab AB ab AB ab.

(so as to have many possible matches), perform an isearch-forward for the string "ab": the counter is (1/6) as expected; type M-c to toggle case sensitivity on and the counter is still (1/6); now

  • type a space: the first "ab " is matched, and the counter is updated to (1/2).
  • press backspace: the counter stays at (1/6) and the match doesn't move; hit C-s repeatedly: the "A"'s are matched by Isearch as if the search is case insensitive, and the counter is updated accordingly. (I too think it is somewhat inconsistent.)
  • type C-s: the first "ab" is matched, the counter is (2/6); type C-s again: the second "ab" is matched and the counter jumps to (4/6), skipping (3/6).

After applying #104 all your tests give the same results, as do my first two tests. If you try my last test: C-s ab M-c (at this point the counter is still (1/6), which is not ideal) C-s, the first "ab" is matched and the counter is updated to (1/3); on following invocations of C-s it cycles through (2/3), (3/3) and (1/3), as expected, without skipping numbers.

@gonewest818
Copy link
Collaborator

Same here, except on Emacs 27.0.90 your second bullet (C-s ab DEL) ... after the DEL the match position does move back to the first "AB". And, as you said, it seems to me that typing DEL throws away the case-sensitive toggle during the interactive search.

Have you tested anzu's query-replace functionality with PR #104 applied?

@gonewest818 gonewest818 removed the need repro we can't reproduce this label Mar 23, 2020
@agreselin
Copy link
Contributor Author

agreselin commented Mar 24, 2020

except on Emacs 27.0.90 your second bullet (C-s ab DEL) ... after the DEL the match position does move back to the first "AB".

Did you backspace after having inserted the space? My tests above were meant to be done each after having repeated the first part (C-s ab M-c) from the beginnig. Sorry I wasn't clear. So, if I do C-s ab M-c SPC <backspace>, as I understand you did, I get back to the first match, the counter correctly displaying (1/6); if I do C-s ab M-c <backspace> there happens what I described in my second point above.

Have you tested anzu's query-replace functionality with PR #104 applied?

I just did these tests with the buffer containing AB ab AB ab AB ab.:

With case-fold-search set to t

  • anzu-query-replace "ab" with "cd": offers to replace each "ab" with "cd" and each "AB" with "CD", counts correctly 6 matches. The unpatched Anzu counts 3 instead.
  • anzu-query-replace "AB" with "CD": offers to replace each "AB" with "CD", but counts wrongly 6 matches (bug 1); without Fix issue #93 #104 Anzu counts the total right, but the three matches are numbered (1/3), (3/3), (5/3).

With these two tests, if I repeat the command using the default replacement that Emacs offers (i.e. I do anzu-query-replace RET) the behaviour is the same, but there's another pesky bug (bug 2): start with

Gee AB ab AB ab AB ab.

then do, in sequence,

  1. anzu-query-replace e RET RET -- the counter is (1/2) -- quit and go back at the bol (C-a), then
  2. anzu-query-replace ab RET RET -- the counter is (1/6) -- C-a, then
  3. anzu-query-replace RET (accepting the proposed replacement ab → ); the counter wrongly shows (1/2).

This last bug has proved rather hard to reproduce consistently. If I run all the other tests, including those with case-fold-search set to nil, then set case-fold-search to t again and run this one, at point 3 the counter becomes (1/6) instead of (1/2). If you can't reproduce point 3, do another replacement of "e", quit and do an additional one using the suggested replacement, I get (1/6) instead of (1/2) sometimes. The heart of the matter is that sometimes Anzu appears to use the previous replacement's count when performing another one using the suggested completion. I was able to reproduce this with the unpatched Anzu, using the additional step I just described; in that case Anzu showed the counter (1/3) instead of (1/2) when searching for "e".

With case-fold-search set to nil

  • anzu-query-replace "ab" with "cd": offers to replace each "ab" with "cd" , counts correctly to 3 matches;
  • anzu-query-replace "AB" with "CD": offers to replace each "AB" with "CD", counts correctly to 3 matches, but...

In each of the last two cases, if I repeat the replacement accepting Emacs' suggestion, Anzu counts 6 replacements even thogh there are actually 3 to be done (bug 3). This too doesn't always reproduce, but I got it consistently after having done the previous tests. The unpatched Anzu doesn't seem to suffer from this bug.


In each case anzu-query-replace-regexp behaved the same as anzu-query-replace did.

I tried to keep the descriptions simple but some of these are subtle sneaky bugs. If you need me to clarify something just ask. I'm sorry but I don't have the time to review #104 myself these days.

@gonewest818
Copy link
Collaborator

Ok, thank you. I’ll keep this open until I have a chance to get back to that PR.

gonewest818 added a commit that referenced this issue Mar 28, 2020
fix the displayed counter to follow the case-sensitivity toggle more accurately

Fix issue #93
@gonewest818
Copy link
Collaborator

I've merged this fix. We can document the subtle bugs that remain and handle separately.

gonewest818 added a commit that referenced this issue Mar 28, 2020
gonewest818 added a commit that referenced this issue Mar 28, 2020
@gonewest818
Copy link
Collaborator

I reverted that merge because it broke the build for all Emacs versions > 25.

gonewest818 added a commit that referenced this issue Mar 28, 2020
doing by hand to ensure all the changes apply properly
@gonewest818
Copy link
Collaborator

And now I've reapplied that fix correctly. Sorry about all the back and forth.

@agreselin
Copy link
Contributor Author

agreselin commented Mar 29, 2020

You only left out the (not (eq last-command 'isearch-toggle-case-fold)) at the end of the definition of anzu--use-result-cache-p, right? It's strange if it was breaking Anzu in Emacs v. > 25, because I was running the patch on Emacs 26.3.

For me removing that line cancels the fix for Isearch: if I type C-s ab M-c C-s the counter is left unchanged. I don't know if (not (eq last-command 'isearch-toggle-case-fold)) is the way to go, but I think the result cache is getting in the way and it should be refreshed after issuing M-c.

@gonewest818
Copy link
Collaborator

It was failing in circleci in the bytecompiler, and the error was wrong number of arguments to the inlined function. The whole thing took me by surprise -- I used git to merge the pull request but it presented a merge conflict (in the web ui) and I wasn't careful enough when reviewing that. At any rate it should be correct now.

@agreselin
Copy link
Contributor Author

agreselin commented Mar 31, 2020

Is it fixed for you?

Btw, my version, based on the latest one from MELPA but including (not (eq last-command 'isearch-toggle-case-fold)), byte-compiles without any warning on Emacs 26.3.

@gonewest818
Copy link
Collaborator

Ok - I overlooked that change somehow, so I'll put that line back in as well. Seems unrelated to the bytecompile issue fixed earlier (which was the result of the blown merge). Sorry! let's get this one PR fixed up, and then create new tickets for the new bugs documented in testing above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug a feature isn't working
Development

Successfully merging a pull request may close this issue.

3 participants