abo-abo / swiper

Ivy - a generic completion frontend for Emacs, Swiper - isearch with an overview, and more. Oh, man!
https://oremacs.com/swiper/
2.29k stars 338 forks source link

Ivy-Occur buffer created incorrectly from a restricted search #2721

Open brownts opened 3 years ago

brownts commented 3 years ago

I'm expecting that I can perform the same kind of narrowing when using the git-grep search mechanism via the counsel-git-grep search. The narrowing seems to work fine and I end up with a restricted set of matches, but when I attempt to send the results to an ivy-occur buffer, the contents of the buffer do not match the final search results due to the narrowing.

Steps to reproduce:

  1. Start Emacs via the repository make plain command
  2. Open ivy.el in buffer: C-x C-f ~/git/swiper/ivy.el
  3. Start a git-grep search: C-c j
  4. Search for "swiper", resulting in 1681 candidates
  5. Start a restricted search: S-SPC
  6. Search for "ivy", resulting in 240 candidates
  7. Create an "occur" buffer with candidate results: C-c C-o

The created *ivy-occur* buffer has 4807 candidates (not 240 candidates as was shown in the candidates list). The 4807 candidates is the same number and set of results as if only a git-grep search for "ivy" had been done without the previous narrowing due to the "swiper" search string.

The following screenshots cover steps 4, 6 and 7 as identified above.

Example showing the search results for "swiper" (step 4) git-grep_step4

Example showing the restricted search results for "ivy" (step 6) git-grep_step6

Example showing the occur buffer generated from the restricted search results (step 7) git-grep_step7

brownts commented 3 years ago

This seems to be a more fundamental and systemic problem than I had originally realized, as it appears to affect a number of other counsel commands too. I tried this out with counsel-git, counsel-find-file and counsel-grep and they all behaved in the same incorrect manner. I used the same make plain configuration as above. The following describes scenarios for each of these three commands. I didn't try any additional commands in counsel, but I suspect they would have problems too. It appears the original search criteria is "forgotten" and the results of the occur buffer are only based on the last search criteria. This is further evidenced by the commands placed in the occur buffer for the counsel-git and counsel-find-file for locating the candidates.

counsel-git scenario

  1. Start Emacs via the repository make plain command
  2. Run counsel-git: M-x counsel-git
  3. Search for: .el
    • Results in 17 candidates
  4. Start a restricted search: C-c C-o
  5. Search for: doc
    • Results in 3 candidates
  6. Create an "occur" buffer with candidate results: C-c C-o
    • Results in 10 candidates in the occur buffer
    • Command in occur buffer: git ls-files --full-name -- | perl -ne '/(.*doc.*)/i && print "$1\n";' | xargs ls -alh | sed -e "s/^/ /"

counsel-find-file scenario

  1. Start Emacs via the repository make plain command
  2. Run counsel-find-file: M-x counsel-find-file
  3. Search for: ~/git/swiper/doc/.org
    • Results in 3 candidates
  4. Start a restricted search: C-c C-o
  5. Search for: ~/git/swiper/doc/ivy
    • Results in 2 candidates
  6. Create an "occur" buffer with candidate results: C-c C-o
    • Results in 4 candidates (all files with "ivy" in their name in ~/git/swiper/doc)
    • Command in occur buffer: ls -a | perl -ne '/(.*ivy.*)/i && print "$1\n";' | xargs -d '\n' ls -d --group-directories-first -alh | sed -e "s/^/ /"

counsel-grep scenario

  1. Start Emacs via the repository make plain command
  2. Open counsel.el: C-x C-f ~/git/swiper/counsel.el
  3. Run counsel-grep: M-x counsel-grep
  4. Search for: swiper
    • Results in 43 candidates
  5. Start a restricted search: C-c C-o
  6. Search for: ivy
    • Results in 8 candidates
  7. Create an "occur" buffer with candidate results: C-c C-o
    • Results in 533 candidates in the occur buffer
brownts commented 3 years ago

I just noticed that this is likely a duplicate of #2427.

brownts commented 3 years ago

I performed some additional investigation into this issue today. It appears that the restricted results that are in the minibuffer are not actually used to create the occur buffer. Instead, counsel-grep-like-occur is used (invoked from counsel-git-grep-occur, counsel-ag-occur, etc.) to recreate these results by re-running the corresponding "grep like" command. The restricted results from the minibuffer are passed to the counsel-*-occur functions (via the _cands parameter), but are ignored. Instead counsel-grep-like-occur attempts to re-run the corresponding "grep like" command and populate the occur buffer with these results.

It appears the reason these results are being recreated rather than just passed from the minibuffer directly to the occur buffer, is to support refreshing the occur buffer after changes may have been made to the corresponding buffers (via ivy-occur-revert-buffer), as described in 225eb2f75a544b331d3cd06c2bd70ad97467ef39. Since the minibuffer would not necessarily exist at that point in time, there needs to be a way to recreate the search by running the command again.

However, it appears that counsel-grep-like-occur just isn't designed to support multiple restrictions. It uses only the last search string, specified in ivy-text and thus does not appear to run multiple passes, or save multiple search strings from each restriction in order to accurately recreate the restricted search.