Helm: More granular helm-grep-do-git-grep

Created on 30 Oct 2015  路  12Comments  路  Source: emacs-helm/helm

Can you change helm-grep-do-git-grep (and helm-grep-git-1 I suppose) so that they can be used to perform a git grep in exactly the directory I want? Now it always passes the value of default-directory to vc-find-root, so I cannot do a grep in a subdirectory of a repository.

I would really like to, since the repository I'm working with is huge (so searching all of it is slow and unnecessary), and there are two top-level directories in it that I frequently call git grep in, for different tasks.

Most helpful comment

@pcompassion give the following a try, C-c g to search whole repo and C-u C-c g to search current directory.

(defun my-helm-grep-do-git-grep (not-all)
  (interactive "P")
  (helm-grep-git-1 default-directory (null not-all)))

(global-set-key (kbd "C-c g") 'my-helm-grep-do-git-grep)

All 12 comments

Hinrik 脰rn Sigur冒sson [email protected] writes:

Can you change helm-grep-do-git-grep (and helm-grep-git-1 I suppose)
so that they can be used to perform a git grep in exactly the
directory I want?

Use helm-find-files to navigate to your directory and start git-grep
from there (M-g g).

NOTE: You could have had this information by using C-h m.

Otherwise you may have also a look at helm-grep-ag, and the git-grep
that comes with helm-ls-git.

Thierry
https://emacs-helm.github.io/helm/

Use helm-find-files to navigate to your directory and start git-grep from there (M-g g).

M-g g still searches the entire repository, because helm-grep-git-1 always passes the supplied directory to vc-find-root first: https://github.com/emacs-helm/helm/blob/master/helm-grep.el#L1301.

M-g a (ag) and M-g s (grep) both do the right thing of course, but they don't have the benefits of git grep.

helm-ls-git only allows marking specific files for searching in, not directories.

The only thing I've found that will do a git grep on a directory of my choosing is (vc-git-grep "someregex" "*" "/some/repo/subdir"), but that's not helm-enabled.

Hinrik 脰rn Sigur冒sson [email protected] writes:

Use helm-find-files to navigate to your directory and start git-grep from there (M-g g).

M-g g still searches the entire repository,

Yes, sorry I misunderstood what you wanted.
So now helm-grep-do-git-grep with a prefix arg grep whole repo and
without grep only current dir.
Same from hff.

I have fixed helm-ls-git also, but it behave differently (as before).

Thierry
https://emacs-helm.github.io/helm/

Thanks!

what if I want the behavior reversed?

helm-grep-do-git-grep without a prefix arg grep whole repo and
with grep only current dir.

Because I most often need to grep from whole repository

I tried looking at the source of helm-grep-do-git-grep but couldn't understand.

pcompassion [email protected] writes:

what if I want the behavior reversed?

helm-grep-do-git-grep without a prefix arg grep whole repo and
with grep only current dir.

Because I most often need to grep from whole repository

I tried looking at the source of helm-grep-do-git-grep but couldn't understand.

You can write your own command calling helm-grep-git-1 with its ALL
argument non--nil:

(helm-grep-git-1 default-directory t)

If you want to be able to grep current-dir only with prefix arg, modify
helm-grep-do-git-grep like this.

(helm-grep-git-1 default-directory (null arg))

Note: I don't want this to be the default, I prefer the actual behavior.

Thierry

Sorry but I don't get how to get

C-g (or any keybinding) to do grep in repository root with (helm-grep-git-1 default-directory t)
and C-u C-g to do grep in current directory with (helm-grep-git-1 default-directory (null arg))

   (defun grep-whole-git ()
     (interactive)
     (helm-do-grep-1 default-directory t))
   (global-set-key (kbd "C-c g") 'grep-whole-git)


   (defun grep-subdirectory ()
     (interactive)
     (helm-grep-git-1 default-directory (null arg)))
   (global-set-key (kbd "C-u C-c g") 'grep-subdirectory)

I get error

Error (use-package): helm :init: Key sequence C-u C-c g starts with non-prefix key C-u

If you want to be able to grep current-dir only with prefix arg, modify
helm-grep-do-git-grep like this. How do I do that? I don't think you mean, modify helm-grep.el file.

I also get Wrong type argument: stringp, 47 when I do C-g

@pcompassion give the following a try, C-c g to search whole repo and C-u C-c g to search current directory.

(defun my-helm-grep-do-git-grep (not-all)
  (interactive "P")
  (helm-grep-git-1 default-directory (null not-all)))

(global-set-key (kbd "C-c g") 'my-helm-grep-do-git-grep)

Actually I managed to solve it, not sure if this is best approach though.

I copied helm-grep-git-1 from helm-grep.el to my init.el and changed if all to if (not all) when calling helm-do-grep-1

(defun helm-grep-git-1 (directory &optional all default input)
(require 'vc)
(let* (helm-grep-default-recurse-command
;; Expand filename of each candidate with the git root dir.
;; The filename will be in the help-echo prop.
(helm-grep-default-directory-fn (lambda ()
(vc-find-root directory ".git")))
(helm-ff-default-directory (funcall helm-grep-default-directory-fn)))
(cl-assert helm-ff-default-directory nil "Not inside a Git repository")
(helm-do-grep-1 (if (not all) '("") `(,(expand-file-name directory)))
nil 'git nil default input)))

Oh. xuchnyang I see that is better way of doing the same thing.

pcompassion [email protected] writes:

Sorry but I don't get how to get

C-g (or any keybinding)

Never (I mean NEVER!) bind something to C-g in emacs.

and C-u C-g

And never use C-u C-g to bind something in emacs.

to do grep in current directory with (helm-grep-git-1
default-directory (null arg))

(defun grep-whole-git ()
(interactive)
(helm-do-grep-1 default-directory t))
(global-set-key (kbd "C-c g") 'grep-whole-git)

This will grep whole directory only.

(defun grep-subdirectory ()
(interactive)
(helm-grep-git-1 default-directory (null arg)))
(global-set-key (kbd "C-u C-c g") 'grep-subdirectory)

Argument ARG is unknown in your function, see how interactive specs
work in elisp manual, what you want is something like this:

(defun grep-subdirectory (arg)
  (interactive "P")
  (helm-grep-git-1 default-directory (null arg)))

Here if you call this command with C-u, ARG will be bound to '(4).
If you don't prefix your command with C-u ARG will be == to nil.

I get error

Error (use-package): helm :init: Key sequence C-u C-c g starts with non-prefix key C-u

Of course, use instead:

(global-set-key (kbd "C-c g") 'grep-subdirectory)

More generally try to see emacs manual about prefix args and how to use
them.

Thierry

pcompassion [email protected] writes:

Actually I managed to solve it, not sure if this is best approach though.

It is not, but I see Chunyang already showed you the best approach to use.

Thierry

@xuchunyang Thank you! This helped me switch away from Projectile. 馃檹

It doesn't have to be a default, but making this a config option (helm-ls-git-search-root?) that's easy to enable would make switching from Projectile more friendly.

I love helm, thanks for the work you all put into it.

Was this page helpful?
0 / 5 - 0 ratings