From 4107af662ecaa9058d2b679a103f36198c92a54d Mon Sep 17 00:00:00 2001 From: christopher floess Date: Thu, 25 Apr 2024 18:21:20 -0400 Subject: [PATCH 1/9] Add support for opening git-grep in other window --- counsel.el | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/counsel.el b/counsel.el index 9ed9b631..0d304d87 100644 --- a/counsel.el +++ b/counsel.el @@ -1438,22 +1438,42 @@ This function should set `ivy--old-re'." (defun counsel-git-grep-action (x) "Go to occurrence X in current Git repository." - (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) + (when (string-match (counsel-git-grep-match-regex) x) (let ((file-name (match-string-no-properties 1 x)) (line-number (match-string-no-properties 2 x))) (find-file (expand-file-name file-name (ivy-state-directory ivy-last))) - (goto-char (point-min)) - (forward-line (1- (string-to-number line-number))) - (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) - (when swiper-goto-start-of-match - (goto-char (match-beginning 0)))) - (swiper--ensure-visible) - (run-hooks 'counsel-grep-post-action-hook) - (unless (eq ivy-exit 'done) - (swiper--cleanup) - (swiper--add-overlays (ivy--regex ivy-text)))))) + (counsel-git-grep-go-to-location line-number)))) + +(defun counsel-git-grep-match-regex () + "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'") + +(defun counsel-git-grep-action-other-window (x) + "Go to occurrence X in current Git repository, other window." + (when (string-match (counsel-git-grep-match-regex) x) + (let ((file-name (match-string-no-properties 1 x)) + (line-number (match-string-no-properties 2 x))) + (find-file-other-window (expand-file-name + file-name + (ivy-state-directory ivy-last))) + (counsel-git-grep-go-to-location line-number)))) + +(defun counsel-git-grep-go-to-location (line-number) + (goto-char (point-min)) + (forward-line (1- (string-to-number line-number))) + (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) + (when swiper-goto-start-of-match + (goto-char (match-beginning 0)))) + (swiper--ensure-visible) + (run-hooks 'counsel-grep-post-action-hook) + (unless (eq ivy-exit 'done) + (swiper--cleanup) + (swiper--add-overlays (ivy--regex ivy-text)))) + +(ivy-set-actions + 'counsel-git-grep + '(("j" counsel-git-grep-action-other-window "other window"))) (defun counsel-git-grep-transformer (str) "Highlight file and line number in STR." From 88d5cd2c1d024f9c8d750a5ac1bc77642cf5e6a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Fl=C3=B6=C3=9F?= Date: Sat, 27 Apr 2024 17:06:36 -0400 Subject: [PATCH 2/9] Move logic for git-grep regex --- counsel.el | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/counsel.el b/counsel.el index 0d304d87..acf8b8e2 100644 --- a/counsel.el +++ b/counsel.el @@ -1438,26 +1438,25 @@ This function should set `ivy--old-re'." (defun counsel-git-grep-action (x) "Go to occurrence X in current Git repository." - (when (string-match (counsel-git-grep-match-regex) x) - (let ((file-name (match-string-no-properties 1 x)) - (line-number (match-string-no-properties 2 x))) + (let ((file-and-line-number (counsel-git-grep-file-and-line-number x))) + (when file-and-line-number (find-file (expand-file-name - file-name + (car file-and-line-number) (ivy-state-directory ivy-last))) - (counsel-git-grep-go-to-location line-number)))) + (counsel-git-grep-go-to-location (cdr file-and-line-number))))) -(defun counsel-git-grep-match-regex () - "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'") +(defun counsel-git-grep-file-and-line-number (x) + (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) + (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) (defun counsel-git-grep-action-other-window (x) "Go to occurrence X in current Git repository, other window." - (when (string-match (counsel-git-grep-match-regex) x) - (let ((file-name (match-string-no-properties 1 x)) - (line-number (match-string-no-properties 2 x))) + (let ((file-and-line-number (counsel-git-grep-file-and-line-number x))) + (when file-and-line-number (find-file-other-window (expand-file-name - file-name - (ivy-state-directory ivy-last))) - (counsel-git-grep-go-to-location line-number)))) + (car file-and-line-number) + (ivy-state-directory ivy-last))) + (counsel-git-grep-go-to-location (cdr file-and-line-number))))) (defun counsel-git-grep-go-to-location (line-number) (goto-char (point-min)) From 21a3b119f87903db6b9a7391d54fd57d41a666da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Fl=C3=B6=C3=9F?= Date: Sat, 27 Apr 2024 17:12:13 -0400 Subject: [PATCH 3/9] Clean up naming and documentation --- counsel.el | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/counsel.el b/counsel.el index acf8b8e2..a94a8286 100644 --- a/counsel.el +++ b/counsel.el @@ -1438,27 +1438,29 @@ This function should set `ivy--old-re'." (defun counsel-git-grep-action (x) "Go to occurrence X in current Git repository." - (let ((file-and-line-number (counsel-git-grep-file-and-line-number x))) + (let ((file-and-line-number (counsel--git-grep-file-and-line-number x))) (when file-and-line-number (find-file (expand-file-name (car file-and-line-number) (ivy-state-directory ivy-last))) - (counsel-git-grep-go-to-location (cdr file-and-line-number))))) + (counsel--git-grep-go-to-location (cdr file-and-line-number))))) -(defun counsel-git-grep-file-and-line-number (x) +(defun counsel--git-grep-file-and-line-number (x) + "Returns a cons cell of file-name and line number" (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) (defun counsel-git-grep-action-other-window (x) - "Go to occurrence X in current Git repository, other window." - (let ((file-and-line-number (counsel-git-grep-file-and-line-number x))) + "Go to occurrence X in current Git repository in another window." + (let ((file-and-line-number (counsel--git-grep-file-and-line-number x))) (when file-and-line-number (find-file-other-window (expand-file-name (car file-and-line-number) (ivy-state-directory ivy-last))) - (counsel-git-grep-go-to-location (cdr file-and-line-number))))) + (counsel--git-grep-go-to-location (cdr file-and-line-number))))) -(defun counsel-git-grep-go-to-location (line-number) +(defun counsel--git-grep-go-to-location (line-number) + "Go to line-number within current buffer" (goto-char (point-min)) (forward-line (1- (string-to-number line-number))) (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) From b9878b48d628ee7612b254f77433c899d75d0774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Fl=C3=B6=C3=9F?= Date: Sat, 27 Apr 2024 17:13:20 -0400 Subject: [PATCH 4/9] Group similar functions --- counsel.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/counsel.el b/counsel.el index a94a8286..dc76b0b7 100644 --- a/counsel.el +++ b/counsel.el @@ -1445,11 +1445,6 @@ This function should set `ivy--old-re'." (ivy-state-directory ivy-last))) (counsel--git-grep-go-to-location (cdr file-and-line-number))))) -(defun counsel--git-grep-file-and-line-number (x) - "Returns a cons cell of file-name and line number" - (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) - (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) - (defun counsel-git-grep-action-other-window (x) "Go to occurrence X in current Git repository in another window." (let ((file-and-line-number (counsel--git-grep-file-and-line-number x))) @@ -1459,6 +1454,11 @@ This function should set `ivy--old-re'." (ivy-state-directory ivy-last))) (counsel--git-grep-go-to-location (cdr file-and-line-number))))) +(defun counsel--git-grep-file-and-line-number (x) + "Returns a cons cell of file-name and line number" + (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) + (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) + (defun counsel--git-grep-go-to-location (line-number) "Go to line-number within current buffer" (goto-char (point-min)) From 2019a92016ff152ee19d611f2bba8a527d8ac79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Fl=C3=B6=C3=9F?= Date: Mon, 29 Apr 2024 17:02:41 -0400 Subject: [PATCH 5/9] Use rx for regular expressions New regex:"\\`\\(.*\\):\\([[:digit:]]+\\):\\(.*\\)\\'" Old regex: "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" --- counsel.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/counsel.el b/counsel.el index dc76b0b7..9d92e754 100644 --- a/counsel.el +++ b/counsel.el @@ -1454,9 +1454,14 @@ This function should set `ivy--old-re'." (ivy-state-directory ivy-last))) (counsel--git-grep-go-to-location (cdr file-and-line-number))))) +(rx-define grouped-regex-matches + (seq string-start (group (zero-or-more any)) + ":" (group (+ digit)) ":" + (group (* any)) string-end)) + (defun counsel--git-grep-file-and-line-number (x) "Returns a cons cell of file-name and line number" - (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) + (when (string-match (rx grouped-regex-matches) x) (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) (defun counsel--git-grep-go-to-location (line-number) From 11809a445970cae919af320a4dd02efbcca8126e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Fl=C3=B6=C3=9F?= Date: Wed, 1 May 2024 20:15:41 -0400 Subject: [PATCH 6/9] Don't use rx --- counsel.el | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/counsel.el b/counsel.el index 9d92e754..dc76b0b7 100644 --- a/counsel.el +++ b/counsel.el @@ -1454,14 +1454,9 @@ This function should set `ivy--old-re'." (ivy-state-directory ivy-last))) (counsel--git-grep-go-to-location (cdr file-and-line-number))))) -(rx-define grouped-regex-matches - (seq string-start (group (zero-or-more any)) - ":" (group (+ digit)) ":" - (group (* any)) string-end)) - (defun counsel--git-grep-file-and-line-number (x) "Returns a cons cell of file-name and line number" - (when (string-match (rx grouped-regex-matches) x) + (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) (defun counsel--git-grep-go-to-location (line-number) From 29f1ba8b0084374153d61fc39b48a6df2ea2d558 Mon Sep 17 00:00:00 2001 From: christopher floess Date: Fri, 3 May 2024 07:33:07 -0400 Subject: [PATCH 7/9] Clean up doc strings. --- counsel.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/counsel.el b/counsel.el index dc76b0b7..8ee7207a 100644 --- a/counsel.el +++ b/counsel.el @@ -1455,12 +1455,13 @@ This function should set `ivy--old-re'." (counsel--git-grep-go-to-location (cdr file-and-line-number))))) (defun counsel--git-grep-file-and-line-number (x) - "Returns a cons cell of file-name and line number" + "Extract file name and line number from `counsel-git-grep' line X. +Return a pair (FILE . LINE) on success; nil otherwise." (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) (defun counsel--git-grep-go-to-location (line-number) - "Go to line-number within current buffer" + "Go to LINE-NUMBER within current buffer." (goto-char (point-min)) (forward-line (1- (string-to-number line-number))) (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) From b316b8daefea3724a18910de719519a9ea6b03c9 Mon Sep 17 00:00:00 2001 From: christopher floess Date: Fri, 3 May 2024 07:37:14 -0400 Subject: [PATCH 8/9] Move number parsing --- counsel.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/counsel.el b/counsel.el index 8ee7207a..de8b9654 100644 --- a/counsel.el +++ b/counsel.el @@ -1458,12 +1458,12 @@ This function should set `ivy--old-re'." "Extract file name and line number from `counsel-git-grep' line X. Return a pair (FILE . LINE) on success; nil otherwise." (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) - (cons (match-string-no-properties 1 x) (match-string-no-properties 2 x)))) + (cons (match-string-no-properties 1 x) (string-to-number (match-string-no-properties 2 x))))) (defun counsel--git-grep-go-to-location (line-number) "Go to LINE-NUMBER within current buffer." (goto-char (point-min)) - (forward-line (1- (string-to-number line-number))) + (forward-line (1- line-number)) (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) (when swiper-goto-start-of-match (goto-char (match-beginning 0)))) From 058cb3a36c4ef446565a7933a3c13ec79bbed908 Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Sun, 5 May 2024 18:33:08 +0200 Subject: [PATCH 9/9] Minor counsel-git-grep cleanup * counsel.el (counsel-git-grep-function): Simplify. (counsel--git-grep-file-and-line-number): Rename... (counsel--git-grep-file-and-line): ...to this, splitting long lines. (counsel--git-grep-go-to-location): Rename... (counsel--git-grep-visit): ...to this, incorporating more DRY. (counsel-git-grep-action, counsel-git-grep-action-other-window): Adapt accordingly (#3044). --- counsel.el | 65 +++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/counsel.el b/counsel.el index de8b9654..239f9969 100644 --- a/counsel.el +++ b/counsel.el @@ -1429,49 +1429,44 @@ This function should set `ivy--old-re'." "Grep in the current Git repository for STRING." (or (ivy-more-chars) - (progn - (counsel--async-command - (concat - (funcall counsel-git-grep-cmd-function string) - (if (ivy--case-fold-p string) " -i" ""))) - nil))) + (ignore + (counsel--async-command + (concat + (funcall counsel-git-grep-cmd-function string) + (and (ivy--case-fold-p string) " -i")))))) (defun counsel-git-grep-action (x) "Go to occurrence X in current Git repository." - (let ((file-and-line-number (counsel--git-grep-file-and-line-number x))) - (when file-and-line-number - (find-file (expand-file-name - (car file-and-line-number) - (ivy-state-directory ivy-last))) - (counsel--git-grep-go-to-location (cdr file-and-line-number))))) + (counsel--git-grep-visit x)) (defun counsel-git-grep-action-other-window (x) "Go to occurrence X in current Git repository in another window." - (let ((file-and-line-number (counsel--git-grep-file-and-line-number x))) - (when file-and-line-number - (find-file-other-window (expand-file-name - (car file-and-line-number) - (ivy-state-directory ivy-last))) - (counsel--git-grep-go-to-location (cdr file-and-line-number))))) - -(defun counsel--git-grep-file-and-line-number (x) + (counsel--git-grep-visit x t)) + +(defun counsel--git-grep-file-and-line (x) "Extract file name and line number from `counsel-git-grep' line X. Return a pair (FILE . LINE) on success; nil otherwise." - (when (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) - (cons (match-string-no-properties 1 x) (string-to-number (match-string-no-properties 2 x))))) - -(defun counsel--git-grep-go-to-location (line-number) - "Go to LINE-NUMBER within current buffer." - (goto-char (point-min)) - (forward-line (1- line-number)) - (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) - (when swiper-goto-start-of-match - (goto-char (match-beginning 0)))) - (swiper--ensure-visible) - (run-hooks 'counsel-grep-post-action-hook) - (unless (eq ivy-exit 'done) - (swiper--cleanup) - (swiper--add-overlays (ivy--regex ivy-text)))) + (and (string-match "\\`\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" x) + (cons (match-string-no-properties 1 x) + (string-to-number (match-string-no-properties 2 x))))) + +(defun counsel--git-grep-visit (cand &optional other-window) + "Visit `counsel-git-grep' CAND, optionally in OTHER-WINDOW." + (let ((file-and-line (counsel--git-grep-file-and-line cand))) + (when file-and-line + (funcall (if other-window #'find-file-other-window #'find-file) + (expand-file-name (car file-and-line) + (ivy-state-directory ivy-last))) + (goto-char (point-min)) + (forward-line (1- (cdr file-and-line))) + (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) + (when swiper-goto-start-of-match + (goto-char (match-beginning 0)))) + (swiper--ensure-visible) + (run-hooks 'counsel-grep-post-action-hook) + (unless (eq ivy-exit 'done) + (swiper--cleanup) + (swiper--add-overlays (ivy--regex ivy-text)))))) (ivy-set-actions 'counsel-git-grep