minad / consult

:mag: consult.el - Consulting completing-read
GNU General Public License v3.0
1.22k stars 102 forks source link

[Question] consult-grep , consult-ripgrep to specifiled files #407

Closed yamatakau08 closed 2 years ago

yamatakau08 commented 3 years ago

I want to execute consult-grep or consult-ripgrep to specified files, not directory. How do I archive that?

tam17aki commented 3 years ago

Hi,

I wrote the following snippet. Maybe it works.

(defun consult-grep-one-file ()
  "Call `consult-grep' for the current buffer (a single file)."
  (interactive)
  (let ((consult-grep-args
         (concat "grep "
                 "--line-buffered "
                 "--color=never "
                 "--line-number "
                 "-I "
                 "-e ARG OPTS "
                 (shell-quote-argument buffer-file-name))))
    (consult-grep)))
yamatakau08 commented 3 years ago

tam17aki san

Thank you for supporting. Your sample code works fine on Mac and very helpful for me.

Unfortunately, the sample code doesn't work well on Windows Emacs 28.0 and MSYS2. consult-grep itself works fine, but after setting consult-grep-args, consult-grep doesn't.

If you have any tips on Windows environment, I'm waiting for you support.

The attach is the movie gif, I executed the consult-grep and your sample code. Could you check it. consult-grep-one-file-fail

tam17aki commented 3 years ago

HI,

Unfortunately, I will not use Emacs on Windows. My main machine is MacOS, Big Sur and I'm using Emacs 27.2.

Anyway, I have revised the funcion consult-grep-one-file and have written new function for ripgrep.

(defun consult-grep-one-file ()
  "Call `consult-grep' for the current buffer (a single file)."
  (interactive)
  (let ((consult-grep-args
         (concat "grep "
                 "--line-buffered "
                 "--color=never "
                 "--line-number "
                 "--with-filename "
                 (shell-quote-argument buffer-file-name))))
    (consult-grep)))

(defun consult-ripgrep-single-file ()
    "Call `consult-ripgrep' for the current buffer (a single file)."
    (interactive)
    (let ((consult-project-function (lambda (x) nil))
          (consult-ripgrep-args
           (concat "rg "
                   "--null "
                   "--line-buffered "
                   "--color=never "
                   "--line-number "
                   "--smart-case "
                   "--no-heading "
                   "--max-columns=1000 "
                   "--max-columns-preview "
                   "--with-filename "
                   (shell-quote-argument buffer-file-name))))
      (consult-ripgrep)))

Best regards, Akira

yamatakau08 commented 3 years ago

Akira san. Thank you for supporting.

I executed the new consult-grep-one-file sample code you provided, unfortunately it doesn't work on Windows Environment. consult-ripgrep-one-file too.

I checked the follwing in scratch buffer.

(shell-command-to-string "grep --version")
"grep (GNU grep) 3.0
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
"

I put (message "%s" consult-grep-args) in consult-grep-one-file. It puts out the following in Message buffer.

grep --line-buffered --color=never --line-number --with-filename c\:/Temp/Log/log1

Then check if the target file exists in scratch buffer.

(file-exists-p "c\:/Temp/Log/log1")
 t
 (shell-command-to-string "ls c\:/Temp/Log/log1")
 "-rw-r--r-- 1 yama Domain Users 12 Aug 25 22:50 c:/Temp/Log/log1
 "

Then I executed the grep command which made by consult-grep-one-file with the search word "foo". It greps "foo" lines without no problem.

(shell-command-to-string "grep foo --line-buffered --color=never --line-number --with-filename c\:/Temp/Log/log1")
 "c:/Temp/Log/log1:1:foo
 "

I susspect the root cause in consult? Do you have any suggestion?

yamatakau08 commented 3 years ago

I suspect the root cause in consult?

I download consult tag 0.9. Then restart Emacs and execute consult-grep-one-file. It works fine.

So I believe that consult-grep in consult tag >= 0.1 via own code on Windows Emacs is something wrong.

yamatakau08 commented 3 years ago

Futhrermore, I’m digging into the cause.

yama@JPC20165182 ~ (master)> uname -a
MINGW32_NT-6.3-9600 JPC20165182 3.2.0-340.x86_64 2021-04-02 09:40 UTC x86_64 Msys

yama@JPC20165182 ~ (master)> cat /tmp/log1
foo
bar
baz

yama@JPC20165182 ~ (master)> cat /tmp/log2
aaa
bbb
baz

“baz” is in both /tmp/log1 and /tmp/log2.

I defined the following the function as test.

(defun consult-grep-specified-files ()
  (interactive)
  (let ((consult-grep-args
     (concat "grep --line-buffered --color=never --ignore-case --exclude-dir=.git --line-number -I " ; removed "-r ." by from original
         (mapconcat #'shell-quote-argument '("/tmp/log1" "/tmp/log2") " ") ; pass
               ;;(mapconcat #'shell-quote-argument '("c:/msys64/tmp/log1" "c:/msys64/tmp/log2") " ") ; fail
         )))
    (consult-grep nil “baz”)))

When provide the file “/tmp/log1” “/tmp/log2” of grep's argument, it works fine. but provide the file “c:/msys64/tmp/log1”, “c:/msys64/tmp/log2”, it doesn’t work.

When the files path of grep’s argument is under the msys64, it works. But file path as “c:/..” style, it doesn’t work.

Is there any hint to work when provide the file path “c:/…” ?

minad commented 3 years ago

You can look at the hidden *consult-async-log* buffer to debug the issue.

minad commented 3 years ago

But file path as “c:/..” style, it doesn’t work.

The issue could be #419.

failable commented 2 years ago

@tam17aki Can I use consult-ripgrep-one-file to search a buffer that is not associated with a file?

hmelman commented 2 years ago

@tam17aki Can I use consult-ripgrep-one-file to search a buffer that is not associated with a file?

No because there is no file for ripgrep to search. Instead use consult-line and then if you want an occur-like results buffers use embark-collect.

failable commented 2 years ago

@hmelman consult-line is quite slow when working with large file. My use case is searching in a large file buffer inside a Zip file, which does not have an associated file. Besides consult-line, even the built-in isearch and occur is super slow in this situation. rg is super fast (IMHO the best) on the unzip file (2Gb).

hmelman commented 2 years ago

My use case is searching in a large file buffer inside a Zip file, which does not have an associated file.

If you're opening large.txt.gz and it fills a buffer in text mode (for example, the mode is unimportant) then the buffer does have an associated file (large.txt.gz) and consult-ripgrep-one-file will work (provided ripgrep is configured to search compressed files). If there are multiple files in the zip then I'm not sure what to do.

I'm a little surprised isearch or occur is slow. It's probably fontification or other text properties. Try turning font-lock off, or using so-long-mode or if it's an org file, expanding everything. Are you searching for a text literal or a regular expression? If a regexp, perhaps it's doing some backtracking and it's inefficient in that case?

failable commented 2 years ago
(defun consult-ripgrep-one-file ()
    "Call `consult-ripgrep' for the current buffer (a single file)."
    (interactive)
    (let ((consult-project-root-function (lambda nil nil))
          (consult-ripgrep-args
           (concat "rg "
                   "--null "
                   "--line-buffered "
                   "--color=never "
                   "--line-number "
                   "--smart-case "
                   "--no-heading "
                   "--max-columns=1000 "
                   "--max-columns-preview "
                   "--search-zip "
                   "--with-filename "
                   (shell-quote-argument buffer-file-name))))
      (consult-ripgrep)))

When I open a single JSON file inside a archive, the value of (buffer-file-name) is ~/damd-multiwoz/data/multi-woz/data.json.tar.gz!./data.json. The --search-zip does not help, though simply rg pattern --search-zip does work on the command line.

Turning off font-lock does help, but occur is still very slow even in fundamental-mode within an emacs -q session, especially when matched count is not too small.

failable commented 2 years ago

Now I find that consult-ripgrep-one-file works fine on *.gz archive with single compressed file, but not *.zip and *.tar.gz.

minad commented 2 years ago

Now I find that |consult-ripgrep-one-file| works fine on |.gz| archive with single compressed file, but not |.zip| and |*.tar.gz|.

This is not unexpected if you consider how these file formats work. A gzipped file is a single compressed file, which can be decompressed transparently by ripgrep. In contrast, zips and tars are archives which contain more than a single file. I would be astonished if ripgrep handles archives transparently.

minad commented 2 years ago

Closing due to inactivity. It seems the question has been answered?

failable commented 1 year ago

It seems the solution suggested by @tam17aki has been pretty much deprecated. How to search specific (single/multiple) files using the latest version of consult?

cheerio-pixel commented 9 months ago

It seems the solution suggested by @tam17aki has been pretty much deprecated. How to search specific (single/multiple) files using the latest version of consult?

(defun consult-ripgrep-single-file ()
    "Call `consult-ripgrep' for the current buffer (a single file)."
    (interactive)
    (let ((consult-project-function (lambda (x) nil)))
      (consult-ripgrep (list (shell-quote-argument buffer-file-name)))))
(defun consult-grep-one-file ()
    "Call `consult-grep' for the current buffer (a single file)."
    (interactive)
    (consult-grep (list (shell-quote-argument buffer-file-name))))

As you can see, you can extend this to an abtrary number of files.