0

I'm using Projectile with ripgrep.

I can search project lines by some pattern, as an example:

test 42 will match strings like this so, test is not 42 at all

I would like to be able to add additional pattern to the search string which would take all search results and display only those containing pattern in file path, like this:

test 42 | app migrations will match results like this

src/app/lib/migrations/file.txt: so, test is not 42 at all

Example: I want to search word "text" in all project files containing "test_dir" in any place within file path relative to project's root

3
  • The question isn't very clear (to me). Please show what you've tried. Doesn't ripgrep let you pipe directly, the way M-x grep does?
    – Drew
    Jul 17 '21 at 21:01
  • You can pass additional arguments to ripgrep with C-u, where you can define a directory/pattern you want to search in, but there is not way to do fuzzy search in file content and file path relative to project root at the same time Example: I want to search word "text" in all project files containing "test_dir" in any place within file path relative to project's root
    – achempion
    Jul 19 '21 at 6:22
  • Probably, you can create a custom shell command which will parse an argument string and then pipe ripgrep results into the ripgrep again where you can use custom pattern to exclude all results where file path does not match specific pattern
    – achempion
    Jul 19 '21 at 6:27
1

EDIT

A very basic code example to achieve fuzzy search using a single grep would be:

(defun custom-counsel-function (str)
    (or
     (ivy-more-chars)
     (progn
       (let ((str (split-string str)))
         (counsel--async-command
          (format "rg --max-columns 240 --with-filename --no-heading --line-number --color never '%s' | grep %s"
                  (car str) (cadr str))))
         '("" "working..."))))

;;;###autoload
(defun custom-counsel (&optional initial-input)
  "Call the \"locate\" shell command.
INITIAL-INPUT can be given as the initial minibuffer input."
  (interactive)
  (let ((default-directory (read-directory-name "Start search from directory: ")))
    (ivy-read "Ripgrep: " #'custom-counsel-function
              :initial-input initial-input
              :dynamic-collection t
              :history 'counsel-locate-history
              :action (lambda (file)
                        (with-ivy-window
                          (when file
                            (find-file file))))
              :unwind #'counsel-delete-process
              :caller 'counsel-locate)))

The rg and grep patterns can be entered by separating them using a single space. For sure there are nicer ways to achieve this, but it takes some more time to inspect the Ivy (or any other completion framework) API.

END EDIT

From M-x man rg we find that this can be achieved using the -g flag. Now neither projectile-ripgrep nor the ripgrep-regexp command allow you to pass arguments to rg when called interactively (you can look at their definitions to see how they work).

However, counsel-rg of the swiper/Ivy package does allow for passing arguments, and an example of how to use it is given in its docstring (and probably there exist helm and possibly consult alternatives for this also).

For filtering on directory paths, be sure to read well the documentation after -g in rg's man-page. For example, to filter for files that are located in some-path dir-example/file.ext relative from your initial search directory, you could search for the following: ripgrep-pattern -- -g dir*/*

3
  • You can't do fuzzy search with -g option, i.e. no way to tell rg to show only results with file path containing "migrations" word in any place
    – achempion
    Jul 21 '21 at 10:36
  • Also, you can pass -g option to projectile-ripgrep by pressing M-x before the calling projectile-ripgrep command
    – achempion
    Jul 21 '21 at 10:38
  • Okay, I did not get the fuzzy search requirement from your question. Anyway, I think you would have to write some elisp yourself. Fortunately it looks like a nice exercise... I will edit the answer to add a very simple example. Of course, you can process the search results more thoroughly, e.g. to apply the grep only to the path. But it needs some more thinking/research about how to achieve that. Jul 22 '21 at 13:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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