emacsorphanage / helm-ag

The silver searcher with helm interface
493 stars 76 forks source link

Pre-defined input for helm-do-ag #301

Open blaenk opened 7 years ago

blaenk commented 7 years ago

I love helm-ag and I was thinking about creating my own commands which would do helm-ag with a pre-defined query, for example one that would search the project for "TODO" to find all of my TODO markers. This is something that, for example, helm-swoop supports.

Unfortunately I didn't see a way to do this. Perhaps if helm-do-ag took another optional parameter specifying this? I would even be content with hacking around this by creating a local let-binding around the call to helm-do-ag, but there's no variable that's being read for me to do that.

I do notice that helm-do-ag--helm specifies an :input, but there's no obvious way I can see to hack that to make it pick up my own query.

I don't know if this is the best way to do this, but I made these changes on my end:

--- /home/blaenk/.dots/emacs/.emacs.d/elpa/helm-ag-20170209.745/helm-ag.el
+++ #<buffer helm-ag.el>
@@ -1109,7 +1109,7 @@
 (defsubst helm-do-ag--target-one-directory-p (targets)
   (and (listp targets) (= (length targets) 1) (file-directory-p (car targets))))

-(defun helm-do-ag--helm ()
+(defun helm-do-ag--helm (&optional query)
   (let ((search-dir (if (not (helm-ag--windows-p))
                         helm-ag--default-directory
                       (if (helm-do-ag--target-one-directory-p helm-ag--default-target)
@@ -1118,7 +1118,8 @@
     (helm-attrset 'name (helm-ag--helm-header search-dir)
                   helm-source-do-ag)
     (helm :sources '(helm-source-do-ag) :buffer "*helm-ag*" :keymap helm-do-ag-map
-          :input (or (helm-ag--marked-input t)
+          :input (or query
+                     (helm-ag--marked-input t)
                      (helm-ag--insert-thing-at-point helm-ag-insert-at-point))
           :history 'helm-ag--helm-history)))

@@ -1130,7 +1131,7 @@
     (error "Error: This buffer is not visited file.")))

 ;;;###autoload
-(defun helm-do-ag (&optional basedir targets)
+(defun helm-do-ag (&optional basedir targets query)
   (interactive)
   (require 'helm-mode)
   (helm-ag--init-state)
@@ -1156,11 +1157,11 @@
                        (car helm-ag--default-target))
                   helm-source-do-ag)
     (if (or (helm-ag--windows-p) (not one-directory-p)) ;; Path argument must be specified on Windows
-        (helm-do-ag--helm)
+        (helm-do-ag--helm query)
       (let* ((helm-ag--default-directory
               (file-name-as-directory (car helm-ag--default-target)))
              (helm-ag--default-target nil))
-        (helm-do-ag--helm)))))
+        (helm-do-ag--helm query)))))

 (defun helm-ag--project-root ()
   (cl-loop for dir in '(".git/" ".hg/" ".svn/" ".git")

Would you be open to facilitating this?

With this, I was able to implement this command which launches a helm-ag session to search for various markers like TODO, FIXME, etc. If there's a better way to do this I'd love to know:

(defun my-search-todo ()
    "Search for any TODO markers as specified in hl-todo-keyword-faces.

Note that this uses the word boundary \\b to avoid matching these
within other words, but this means that non-word keywords such as
???, which is in the list by default, will not be matched."
    (interactive)
    (require 'projectile)

    (let* ((grouped (funcall #'regexp-opt (--map (car it) hl-todo-keyword-faces)))
           (unescaped (s-replace-all '(("\\(" . "(") ("\\)" . ")") ("\\|" . "|"))
                                     grouped))
           (bounded (concat "\\b" unescaped "\\b"))
           (helm-follow-mode-persistent t))
      (helm-do-ag (projectile-project-root) nil bounded)))
cibinmathew commented 7 years ago

@syohex its a good feature to have a default input