branch: master commit 80d40e4fb5e7da0f20bac05333ae068597a76863 Author: CeleritasCelery <t.mac...@gmail.com> Commit: Oleh Krehel <ohwoeo...@gmail.com>
Dynamically handle grep tool look-arounds Fixes #1935 --- counsel.el | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/counsel.el b/counsel.el index 81b0402..a1e43f6 100644 --- a/counsel.el +++ b/counsel.el @@ -54,7 +54,7 @@ (define-obsolete-function-alias 'counsel-more-chars 'ivy-more-chars "0.10.0") -(defun counsel--elisp-to-pcre (regex) +(defun counsel--elisp-to-pcre (regex &optional look-around) "Convert REGEX from Elisp format to PCRE format, on best-effort basis. REGEX may be of any format returned by an Ivy regex function, namely a string or a list. The return value is always a string. @@ -62,14 +62,23 @@ namely a string or a list. The return value is always a string. Note that incorrect results may be returned for sufficiently complex regexes." (if (consp regex) - (mapconcat - (lambda (pair) - (let ((subexp (counsel--elisp-to-pcre (car pair)))) - (if (string-match-p "|" subexp) - (format "(?:%s)" subexp) - subexp))) - (cl-remove-if-not #'cdr regex) - ".*") + (if look-around + (mapconcat + (lambda (pair) + (let ((subexp (counsel--elisp-to-pcre (car pair)))) + (format "(?%c.*%s)" + (if (cdr pair) ?= ?!) + subexp))) + regex + "") + (mapconcat + (lambda (pair) + (let ((subexp (counsel--elisp-to-pcre (car pair)))) + (if (string-match-p "|" subexp) + (format "(?:%s)" subexp) + subexp))) + (cl-remove-if-not #'cdr regex) + ".*")) (replace-regexp-in-string "\\\\[(){}|]\\|[()]" (lambda (s) @@ -2534,6 +2543,10 @@ regex string." (defvar counsel-ag-command nil) +(defvar counsel--grep-tool-look-around t) + +(defvar counsel--regex-look-around nil) + (counsel-set-async-exit-code 'counsel-ag 1 "No matches found") (ivy-set-occur 'counsel-ag 'counsel-ag-occur) (ivy-set-display-transformer 'counsel-ag 'counsel-git-grep-transformer) @@ -2565,7 +2578,8 @@ NEEDLE is the search string." (defun counsel--grep-regex (str) (counsel--elisp-to-pcre (setq ivy--old-re - (funcall ivy--regex-function str)))) + (funcall ivy--regex-function str)) + counsel--regex-look-around)) (defun counsel-ag-function (string) "Grep in the current directory for STRING." @@ -2577,6 +2591,9 @@ NEEDLE is the search string." (ivy-more-chars)) (let ((default-directory (ivy-state-directory ivy-last)) (regex (counsel--grep-regex search-term))) + (if (and (stringp counsel--regex-look-around) + (string-match-p "\\`(\\?[=!]" regex)) ;; using look-arounds + (setq switches (concat switches " " counsel--regex-look-around))) (counsel--async-command (counsel--format-ag-command switches (shell-quote-argument regex))) @@ -2591,6 +2608,7 @@ EXTRA-AG-ARGS string, if non-nil, is appended to `counsel-ag-base-command'. AG-PROMPT, if non-nil, is passed as `ivy-read' prompt argument." (interactive) (setq counsel-ag-command counsel-ag-base-command) + (setq counsel--regex-look-around counsel--grep-tool-look-around) (counsel-require-program counsel-ag-command) (when current-prefix-arg (setq initial-directory @@ -2663,7 +2681,8 @@ INITIAL-INPUT can be given as the initial minibuffer input. This uses `counsel-ag' with `counsel-pt-base-command' instead of `counsel-ag-base-command'." (interactive) - (let ((counsel-ag-base-command counsel-pt-base-command)) + (let ((counsel-ag-base-command counsel-pt-base-command) + (counsel--grep-tool-look-around nil)) (counsel-ag initial-input))) (cl-pushnew 'counsel-pt ivy-highlight-grep-commands) @@ -2683,7 +2702,8 @@ INITIAL-INPUT can be given as the initial minibuffer input. This uses `counsel-ag' with `counsel-ack-base-command' replacing `counsel-ag-base-command'." (interactive) - (let ((counsel-ag-base-command counsel-ack-base-command)) + (let ((counsel-ag-base-command counsel-ack-base-command) + (counsel--grep-tool-look-around t)) (counsel-ag initial-input))) @@ -2706,7 +2726,12 @@ INITIAL-DIRECTORY, if non-nil, is used as the root directory for search. EXTRA-RG-ARGS string, if non-nil, is appended to `counsel-rg-base-command'. RG-PROMPT, if non-nil, is passed as `ivy-read' prompt argument." (interactive) - (let ((counsel-ag-base-command counsel-rg-base-command)) + (let ((counsel-ag-base-command counsel-rg-base-command) + (counsel--grep-tool-look-around + (let ((rg (car (split-string counsel-rg-base-command))) + (switch "--pcre2")) + (and (eq 0 (call-process rg nil nil nil switch "--version")) + switch)))) (counsel-ag initial-input initial-directory extra-rg-args rg-prompt))) (cl-pushnew 'counsel-rg ivy-highlight-grep-commands)