Skip to content

Commit

Permalink
Merge 64d7bf0 into 6898409
Browse files Browse the repository at this point in the history
  • Loading branch information
zonotope committed Jan 7, 2018
2 parents 6898409 + 64d7bf0 commit 2c6643b
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 53 deletions.
163 changes: 110 additions & 53 deletions rg.el
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,13 @@ If LITERAL is non nil prompt for literal pattern."
nil default-directory t)))
(list pattern files dir)))

(defun rg-read-files (pattern)
(defun rg-read-files (&optional pattern)
"Read files argument for interactive rg. PATTERN is the search string."
(let ((default-alias (rg-default-alias)))
(let ((default-alias (rg-default-alias))
(pattern-string (if pattern (concat "for \"" pattern "\" ")
"")))
(completing-read
(concat "Search for \"" pattern
"\" in files"
(concat "Search " pattern-string "in files"
(if default-alias
(concat
" (default: [" (car default-alias) "] = "
Expand Down Expand Up @@ -1007,67 +1008,123 @@ prefix is not supplied `rg-keymap-prefix' is used."
(message "Global key bindings for `rg' enabled with prefix: %s"
(edmacro-format-keys prefix))))

(defun rg-set-search-defaults (args)
(if (not (plist-get args :pattern)) (plist-put args :pattern 'regexp)
args))

(defun rg-search-parse-local-bindings (search-cfg)
(let* ((binding-list `((confirm ,(plist-get search-cfg :confirm))))
(pattern-opt (plist-get search-cfg :pattern))
(literal (or (eq pattern-opt 'literal)
(eq pattern-opt 'point)))
(alias-opt (plist-get search-cfg :files))
(dir-opt (plist-get search-cfg :dir)))

;; literal binding
(setq binding-list (append binding-list `((literal ,literal))))

;; pattern binding
(when (not (or (eq pattern-opt 'literal)
(eq pattern-opt 'regexp)))
(let ((pattern (cond ((eq pattern-opt 'point) '(grep-tag-default))
(t pattern-opt))))
(setq binding-list (append binding-list `((pattern ,pattern))))))

;; dir binding
(when dir-opt
(let ((dirs (cond ((eq dir-opt 'project) '(rg-project-root
buffer-file-name))
((eq dir-opt 'current) 'default-directory)
(t dir-opt))))
(setq binding-list (append binding-list `((dir ,dirs))))))

;; file alias binding
(when alias-opt
(let ((files (if (eq alias-opt 'current) '(car (rg-default-alias))
alias-opt)))
(setq binding-list (append binding-list `((files ,files))))))

binding-list))

(defun rg-search-parse-interactive-pattern-arg (search-cfg)
(let* ((opt (plist-get search-cfg :pattern))
(literal (eq opt 'literal)))
(when (not (eq opt 'point))
(cond ((not opt) `((pattern . (rg-read-pattern nil ,literal))))
(t `((pattern . ,opt)))))))

(defun rg-search-parse-interactive-file-alias-arg (search-cfg)
(when (not (plist-get search-cfg :files))
'((files . (rg-read-files)))))

(defun rg-search-parse-interactive-dir-arg (search-cfg)
(when (not (plist-get search-cfg :dir))
'((dir . (read-directory-name
"In directory: " nil default-directory t)))))

(defun rg-search-parse-interactive-args (search-cfg)
(let* ((iargs '()))
(setq iargs
(append iargs (rg-search-parse-interactive-pattern-arg search-cfg)))
(setq iargs
(append iargs (rg-search-parse-interactive-file-alias-arg
search-cfg)))
(setq iargs
(append iargs (rg-search-parse-interactive-dir-arg search-cfg)))

iargs))

;;;###autoload
(defmacro rg-define-search (name &rest args)
(let* ((search-cfg (rg-set-search-defaults args))
(local-bindings (rg-search-parse-local-bindings search-cfg))
(iargs (rg-search-parse-interactive-args search-cfg)))
`(defun ,name ,(mapcar 'car iargs)
(interactive
(list ,(mapcar 'cdr iargs)))
(let* ,local-bindings
(rg-run pattern files dir literal confirm)))))

;;;###autoload
(rg-define-search rg-project
:dir project)

;;;###autoload
(rg-define-search rg-dwim-project-dir
:pattern point
:files current
:dir project)

;;;###autoload
(defun rg-project (regexp files)
"Run ripgrep in current project searching for REGEXP in FILES.
The project root will will be determined by either common project
packages like projectile and `find-file-in-project' or the source
version control system."
(interactive
(progn
(let* ((regexp (rg-read-pattern))
(files (rg-read-files regexp)))
(list regexp files))))
(let ((root (rg-project-root buffer-file-name)))
(if root
(rg-run regexp files root)
(signal 'user-error '("No project root found")))))
(rg-define-search rg-dwim-current-dir
:pattern point
:files current
:dir current)

;;;###autoload
(defun rg-dwim (&optional curdir)
"Run ripgrep without user interaction figuring out the intention by magic(!).
The default magic searches for thing at point in files matching
current file under project root directory.
With \\[universal-argument] prefix (CURDIR), search is done in current dir
instead of project root."
(interactive "P")
(let* ((literal (grep-tag-default))
(files (car (rg-default-alias)))
(dir (or (when curdir default-directory)
(rg-project-root buffer-file-name))))
(rg-run literal files dir 'literal)))

(defun rg-literal (pattern files dir &optional confirm)
"Run ripgrep, searching for literal PATTERN in FILES in directory DIR.
With \\[universal-argument] prefix (CONFIRM), you can edit the
constructed shell command line before it is executed."
(interactive
(progn
(append (rg-read-input 'literal)
(list (equal current-prefix-arg '(4))))))
(rg-run pattern files dir 'literal confirm))
(if curdir
(rg-dwim-current-dir)
(rg-dwim-project-dir)))


;;;###autoload
(rg-define-search rg-dwim-regexp
:files current
:dir project)

;;;###autoload
(rg-define-search rg-literal
:pattern literal)

;;;###autoload
(defun rg (regexp files dir &optional confirm)
"Run ripgrep, searching for REGEXP in FILES in directory DIR.
The search is limited to file names matching shell pattern FILES.
FILES may use abbreviations defined in `rg-custom-type-aliases' or
ripgrep builtin type aliases, e.g. entering `elisp' is equivalent to `*.el'.
REGEXP is a regexp as defined by the ripgrep executable.
With \\[universal-argument] prefix (CONFIRM), you can edit the
constructed shell command line before it is executed.
Collect output in a buffer. While ripgrep runs asynchronously, you
can use \\[next-error] (M-x `next-error'), or \\<grep-mode-map>\\[compile-goto-error] \
in the rg output buffer, to go to the lines where rg found matches."
(interactive
(progn
(append (rg-read-input)
(list (equal current-prefix-arg '(4))))))
(rg-run regexp files dir nil confirm))
(rg-define-search rg)

(provide 'rg)

Expand Down
20 changes: 20 additions & 0 deletions test/rg.el-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,26 @@ and ungrouped otherwise."
(rg-dwim 'curdir)
(should (equal (expand-file-name called-dir) (expand-file-name default-directory)))))

(ert-deftest rg-integration/dwim-regexp-search ()
"Test `rg-dwim-regexp'."
(cl-letf ((called-pattern nil)
(called-files nil)
(called-dir nil)
(called-literal nil)
(project-dir (expand-file-name default-directory))
((symbol-function #'rg-run)
(lambda (pattern files dir &optional literal _)
(setq called-pattern pattern)
(setq called-files files)
(setq called-dir dir)
(setq called-literal literal))))
(find-file "test/data/foo.el")
(rg-dwim-regexp "hello")
(should (equal called-pattern "hello"))
(should (equal called-files "elisp"))
(should (equal (expand-file-name called-dir) project-dir))
(should (eq called-literal nil))))

(ert-deftest rg-integration/project-search ()
"Test `rg-project'."
(cl-letf ((called-pattern nil)
Expand Down

0 comments on commit 2c6643b

Please sign in to comment.