branch: master
commit fe95f52772c6e25c54085fcaca189296bb0c8aad
Author: nathan moreau <[email protected]>
Commit: Oleh Krehel <[email protected]>
Unify the different ways to check for git.
Merge both variables counsel--git-dir and counsel--git-grep-dir.
---
counsel.el | 179 ++++++++++++++++++++++++++++---------------------------------
1 file changed, 81 insertions(+), 98 deletions(-)
diff --git a/counsel.el b/counsel.el
index 37c1928..536dee9 100644
--- a/counsel.el
+++ b/counsel.el
@@ -1006,27 +1006,29 @@ BUFFER defaults to the current one."
("x" counsel-find-file-extern "open externally")))
;;;###autoload
+(defun counsel-locate-git-root ()
+ "Locate the root of the git repository containing the current buffer."
+ (setq counsel--git-dir (locate-dominating-file default-directory ".git"))
+ (and (null counsel--git-dir) (error "Not in a git repository"))
+ counsel--git-dir)
+
(defun counsel-git (&optional initial-input)
"Find file in the current Git repository.
INITIAL-INPUT can be given as the initial minibuffer input."
(interactive)
(counsel-require-program (car (split-string counsel-git-cmd)))
- (setq counsel--git-dir (locate-dominating-file
- default-directory ".git"))
+ (counsel-locate-git-root)
(ivy-set-prompt 'counsel-git counsel-prompt-function)
- (if (null counsel--git-dir)
- (error "Not in a git repository")
- (setq counsel--git-dir (expand-file-name
- counsel--git-dir))
- (let* ((default-directory counsel--git-dir)
- (cands (split-string
- (shell-command-to-string counsel-git-cmd)
- "\n"
- t)))
- (ivy-read "Find file" cands
- :initial-input initial-input
- :action #'counsel-git-action
- :caller 'counsel-git))))
+ (setq counsel--git-dir (expand-file-name counsel--git-dir))
+ (let* ((default-directory counsel--git-dir)
+ (cands (split-string
+ (shell-command-to-string counsel-git-cmd)
+ "\n"
+ t)))
+ (ivy-read "Find file" cands
+ :initial-input initial-input
+ :action #'counsel-git-action
+ :caller 'counsel-git)))
(defun counsel-git-action (x)
"Find file X in current Git repository."
@@ -1051,9 +1053,6 @@ INITIAL-INPUT can be given as the initial minibuffer
input."
(defvar counsel-git-grep-cmd nil
"Store the command for `counsel-git-grep'.")
-(defvar counsel--git-grep-dir nil
- "Store the base git directory.")
-
(defvar counsel--git-grep-count nil
"Store the line count in current repository.")
@@ -1073,7 +1072,7 @@ Typical value: '(recenter)."
(defun counsel-prompt-function-dir ()
"Return prompt appended with the parent directory."
(ivy-add-prompt-count
- (let ((directory counsel--git-grep-dir))
+ (let ((directory counsel--git-dir))
(format "%s [%s]: "
(ivy-state-prompt ivy-last)
(let ((dir-list (eshell-split-path directory)))
@@ -1093,7 +1092,7 @@ Typical value: '(recenter)."
(if (and (or counsel-git-grep-skip-counting-lines (> counsel--git-grep-count
20000))
(< (length string) 3))
(counsel-more-chars 3)
- (let* ((default-directory counsel--git-grep-dir)
+ (let* ((default-directory counsel--git-dir)
(cmd (format counsel-git-grep-cmd
(setq ivy--old-re (ivy--regex string t)))))
(if (and (not counsel-git-grep-skip-counting-lines) (<=
counsel--git-grep-count 20000))
@@ -1107,7 +1106,7 @@ Typical value: '(recenter)."
(with-ivy-window
(let ((file-name (match-string-no-properties 1 x))
(line-number (match-string-no-properties 2 x)))
- (find-file (expand-file-name file-name counsel--git-grep-dir))
+ (find-file (expand-file-name file-name counsel--git-dir))
(goto-char (point-min))
(forward-line (1- (string-to-number line-number)))
(re-search-forward (ivy--regex ivy-text t) (line-end-position) t)
@@ -1195,37 +1194,32 @@ INITIAL-INPUT can be given as the initial minibuffer
input."
(setq proj (car proj-and-cmd))
(setq counsel-git-grep-cmd (cdr proj-and-cmd))
(counsel-require-program (car (split-string counsel-git-grep-cmd)))
- (setq counsel--git-grep-dir
- (if proj
- (car proj)
- (locate-dominating-file default-directory ".git")))
- (if (null counsel--git-grep-dir)
- (error "Not in a git repository")
- (unless (or proj counsel-git-grep-skip-counting-lines)
- (setq counsel--git-grep-count
- (if (eq system-type 'windows-nt)
- 0
- (counsel--gg-count "" t))))
- (let ((collection-function
- (if proj
- #'counsel-git-grep-proj-function
- #'counsel-git-grep-function))
- (unwind-function
- (if proj
- (lambda ()
- (counsel-delete-process)
- (swiper--cleanup))
+ (counsel-locate-git-root)
+ (unless (or proj counsel-git-grep-skip-counting-lines)
+ (setq counsel--git-grep-count
+ (if (eq system-type 'windows-nt)
+ 0
+ (counsel--gg-count "" t))))
+ (let ((collection-function
+ (if proj
+ #'counsel-git-grep-proj-function
+ #'counsel-git-grep-function))
+ (unwind-function
+ (if proj
(lambda ()
- (swiper--cleanup)))))
- (ivy-read "git grep" collection-function
- :initial-input initial-input
- :matcher #'counsel-git-grep-matcher
- :dynamic-collection (or proj
counsel-git-grep-skip-counting-lines (> counsel--git-grep-count 20000))
- :keymap counsel-git-grep-map
- :action #'counsel-git-grep-action
- :unwind unwind-function
- :history 'counsel-git-grep-history
- :caller 'counsel-git-grep)))))
+ (counsel-delete-process)
+ (swiper--cleanup))
+ (lambda ()
+ (swiper--cleanup)))))
+ (ivy-read "git grep" collection-function
+ :initial-input initial-input
+ :matcher #'counsel-git-grep-matcher
+ :dynamic-collection (or proj
counsel-git-grep-skip-counting-lines (> counsel--git-grep-count 20000))
+ :keymap counsel-git-grep-map
+ :action #'counsel-git-grep-action
+ :unwind unwind-function
+ :history 'counsel-git-grep-history
+ :caller 'counsel-git-grep))))
(defun counsel-git-grep-proj-function (str)
"Grep for STR in the current git repository."
@@ -1255,7 +1249,7 @@ INITIAL-INPUT can be given as the initial minibuffer
input."
"Return git grep candidates for REGEX."
(setq counsel-gg-state -2)
(counsel--gg-count regex)
- (let* ((default-directory counsel--git-grep-dir)
+ (let* ((default-directory counsel--git-dir)
(counsel-gg-process " *counsel-gg*")
(proc (get-process counsel-gg-process))
(buff (get-buffer counsel-gg-process)))
@@ -1296,7 +1290,7 @@ EVENT is a string describing the change."
"Count the number of results matching REGEX in `counsel-git-grep'.
The command to count the matches is called asynchronously.
If NO-ASYNC is non-nil, do it synchronously instead."
- (let ((default-directory counsel--git-grep-dir)
+ (let ((default-directory counsel--git-dir)
(cmd
(concat
(format
@@ -1335,7 +1329,7 @@ If NO-ASYNC is non-nil, do it synchronously instead."
When REVERT is non-nil, regenerate the current *ivy-occur* buffer."
(unless (eq major-mode 'ivy-occur-grep-mode)
(ivy-occur-grep-mode)
- (setq default-directory counsel--git-grep-dir))
+ (setq default-directory counsel--git-dir))
(setq ivy-text
(and (string-match "\"\\(.*\\)\"" (buffer-name))
(match-string 1 (buffer-name))))
@@ -1370,7 +1364,7 @@ When REVERT is non-nil, regenerate the current
*ivy-occur* buffer."
(when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" cand)
(with-ivy-window
(let ((file-name (match-string-no-properties 1 cand)))
- (setq file-name (expand-file-name file-name
counsel--git-grep-dir))
+ (setq file-name (expand-file-name file-name
counsel--git-dir))
(unless (member file-name done-buffers)
(push file-name done-buffers)
(find-file file-name)
@@ -1388,17 +1382,15 @@ The git command applies the stash entry where candidate
X was found in."
(defun counsel-git-stash ()
"Search through all available git stashes."
(interactive)
- (let ((dir (locate-dominating-file default-directory ".git")))
- (if (null dir)
- (error "Not in a git repository")
- (let ((cands (split-string (shell-command-to-string
- "IFS=$'\n'
+ (counsel-locate-git-root)
+ (let ((cands (split-string (shell-command-to-string
+ "IFS=$'\n'
for i in `git stash list --format=\"%gd\"`; do
git stash show -p $i | grep -H --label=\"$i\" \"$1\"
done") "\n" t)))
- (ivy-read "git stash: " cands
- :action 'counsel-git-stash-kill-action
- :caller 'counsel-git-stash)))))
+ (ivy-read "git stash: " cands
+ :action 'counsel-git-stash-kill-action
+ :caller 'counsel-git-stash)))
;;** `counsel-git-log'
(defvar counsel-git-log-cmd "GIT_PAGER=cat git log --grep '%s'"
"Command used for \"git log\".")
@@ -1442,31 +1434,23 @@ TREE is the selected candidate."
(defun counsel-git-worktree-list ()
"List worktrees in the git repository containing the current buffer."
+ (counsel-locate-git-root)
(let ((cmd-output (shell-command-to-string "git worktree list")))
- (and (string-match "fatal: Not a git repository" cmd-output)
- (error "Not in a git repository!"))
(delete "" (split-string (string-trim-right cmd-output) "\n"))))
(defun counsel-git-worktree-parse-root (tree)
"Return worktree from candidate TREE."
(substring tree 0 (string-match " " tree)))
-(defun counsel-git-toplevel ()
- "Return the base directory of the current git repository."
- (let ((out (string-trim-right (shell-command-to-string "git rev-parse
--show-toplevel"))))
- (unless (string-match-p "Not a git repository" out) out)))
-
(defun counsel-git-close-worktree-files-action (root-dir)
"Close all buffers from the worktree located at ROOT-DIR."
(setq root-dir (counsel-git-worktree-parse-root root-dir))
(save-excursion
(dolist (buf (buffer-list))
(set-buffer buf)
- (let (top)
- (and buffer-file-name
- (setq top (counsel-git-toplevel))
- (string= "." (file-relative-name root-dir top))
- (kill-buffer buf))))))
+ (and buffer-file-name
+ (string= "." (file-relative-name root-dir
(counsel-locate-git-root)))
+ (kill-buffer buf)))))
(ivy-set-actions
'counsel-git-change-worktree
@@ -1476,14 +1460,14 @@ TREE is the selected candidate."
(defun counsel-git-change-worktree ()
"Find the file corresponding to the current buffer on a different worktree."
(interactive)
- (let ((git-root-dir (counsel-git-toplevel)))
- (ivy-read "Select worktree: "
- (or (cl-delete git-root-dir (counsel-git-worktree-list)
- :key #'counsel-git-worktree-parse-root :test
#'string=)
- (error "No other worktrees!"))
- :action (lambda (tree) (counsel-git-change-worktree-action
git-root-dir tree))
- :require-match t
- :caller 'counsel-git-change-worktree)))
+ (counsel-locate-git-root)
+ (ivy-read "Select worktree: "
+ (or (cl-delete counsel--git-dir (counsel-git-worktree-list)
+ :key #'counsel-git-worktree-parse-root :test
#'string=)
+ (error "No other worktrees!"))
+ :action (lambda (tree) (counsel-git-change-worktree-action
counsel--git-dir tree))
+ :require-match t
+ :caller 'counsel-git-change-worktree))
;;** `counsel-git-checkout'
(defun counsel-git-checkout-action (branch)
@@ -1498,9 +1482,8 @@ BRANCH is a string whose first word designates the
command argument."
"List branches in the git repository containing the current buffer.
Does not list the currently checked out one."
+ (counsel-locate-git-root)
(let ((cmd-output (shell-command-to-string "git branch -vv --all")))
- (and (string-match "fatal: Not a git repository" cmd-output)
- (error "Not in a git repository!"))
(cl-mapcan
(lambda (str) (when (string-prefix-p " " str)
(list (substring str (string-match (rx (not (any blank)))
str)))))
@@ -1920,7 +1903,7 @@ INITIAL-DIRECTORY, if non-nil, is used as the root
directory for search."
;;* Grep
(defun counsel--grep-mode-occur (git-grep-dir-is-file)
"Generate a custom occur buffer for grep like commands.
-If GIT-GREP-DIR-IS-FILE is t, then `counsel--git-grep-dir' is treated as a full
+If GIT-GREP-DIR-IS-FILE is t, then `counsel--git-dir' is treated as a full
path to a file rather than a directory (e.g. for `counsel-grep-occur').
This function expects that the candidates have already been filtered.
@@ -1929,11 +1912,11 @@ It applies no filtering to ivy--all-candidates."
(ivy-occur-grep-mode))
(let* ((directory
(if git-grep-dir-is-file
- (file-name-directory counsel--git-grep-dir)
- counsel--git-grep-dir))
+ (file-name-directory counsel--git-dir)
+ counsel--git-dir))
(prepend
(if git-grep-dir-is-file
- (concat (file-name-nondirectory counsel--git-grep-dir) ":")
+ (concat (file-name-nondirectory counsel--git-dir) ":")
"")))
(setq default-directory directory)
;; Need precise number of header lines for `wgrep' to work.
@@ -1967,7 +1950,7 @@ If non-nil, append EXTRA-AG-ARGS to BASE-CMD."
(setq extra-ag-args ""))
(if (< (length string) 3)
(counsel-more-chars 3)
- (let ((default-directory counsel--git-grep-dir)
+ (let ((default-directory counsel--git-dir)
(regex (counsel-unquote-regex-parens
(setq ivy--old-re
(ivy--regex string)))))
@@ -2011,7 +1994,7 @@ AG-PROMPT, if non-nil, is passed as `ivy-read' prompt
argument."
"%s" "" (substring-no-properties
counsel-ag-base-command pos))))
(read-string (format "(%s) args:" command) ag-args)))))
(ivy-set-prompt 'counsel-ag counsel-prompt-function)
- (setq counsel--git-grep-dir (or initial-directory default-directory))
+ (setq counsel--git-dir (or initial-directory default-directory))
(ivy-read (or ag-prompt (car (split-string counsel-ag-base-command)))
(lambda (string)
(counsel-ag-function string counsel-ag-base-command
extra-ag-args))
@@ -2091,9 +2074,9 @@ RG-PROMPT, if non-nil, is passed as `ivy-read' prompt
argument."
" in directory: ")))))
(counsel-require-program (car (split-string counsel-rg-base-command)))
(ivy-set-prompt 'counsel-rg counsel-prompt-function)
- (setq counsel--git-grep-dir (or initial-directory
- (locate-dominating-file default-directory
".git")
- default-directory))
+ (setq counsel--git-dir (or initial-directory
+ (locate-dominating-file default-directory ".git")
+ default-directory))
(ivy-read (or rg-prompt (car (split-string counsel-rg-base-command)))
(lambda (string)
(counsel-ag-function string counsel-rg-base-command
extra-rg-args))
@@ -2126,17 +2109,17 @@ RG-PROMPT, if non-nil, is passed as `ivy-read' prompt
argument."
(ivy--regex string)))))
(counsel--async-command
(format counsel-grep-base-command regex
- (shell-quote-argument counsel--git-grep-dir)))
+ (shell-quote-argument counsel--git-dir)))
nil)))
(defun counsel-grep-action (x)
"Go to candidate X."
(with-ivy-window
(swiper--cleanup)
- (let ((default-directory (file-name-directory counsel--git-grep-dir))
+ (let ((default-directory (file-name-directory counsel--git-dir))
file-name line-number)
(when (cond ((string-match "\\`\\([0-9]+\\):\\(.*\\)\\'" x)
- (setq file-name counsel--git-grep-dir)
+ (setq file-name counsel--git-dir)
(setq line-number (match-string-no-properties 1 x)))
((string-match "\\`\\([^:]+\\):\\([0-9]+\\):\\(.*\\)\\'" x)
(setq file-name (match-string-no-properties 1 x))
@@ -2177,7 +2160,7 @@ RG-PROMPT, if non-nil, is passed as `ivy-read' prompt
argument."
(interactive)
(counsel-require-program (car (split-string counsel-grep-base-command)))
(setq counsel-grep-last-line nil)
- (setq counsel--git-grep-dir (buffer-file-name))
+ (setq counsel--git-dir (buffer-file-name))
(let ((init-point (point))
res)
(unwind-protect