branch: externals/urgrep commit bf24dac2ac35e7f2926394bb80b87c04b3c4614b Author: Jim Porter <jporterb...@gmail.com> Commit: Jim Porter <jporterb...@gmail.com>
Allow for separate before/after contexts --- urgrep-tests.el | 18 ++++++++++++--- urgrep.el | 70 ++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/urgrep-tests.el b/urgrep-tests.el index 6184f9743a..ca2c8031ac 100644 --- a/urgrep-tests.el +++ b/urgrep-tests.el @@ -42,7 +42,11 @@ (should (equal (urgrep-command "(foo)" :tool tool :regexp-syntax 'pcre) (concat common-args "--heading -- \\(foo\\)"))) (should (equal (urgrep-command "foo" :tool tool :context 3) - (concat common-args "-C3 -F --heading -- foo"))))) + (concat common-args "-C3 -F --heading -- foo"))) + (should (equal (urgrep-command "foo" :tool tool :context '(3 . 3)) + (concat common-args "-C3 -F --heading -- foo"))) + (should (equal (urgrep-command "foo" :tool tool :context '(2 . 4)) + (concat common-args "-B2 -A4 -F --heading -- foo"))))) (ert-deftest urgrep-tests-command-ag () (let ((tool (assoc "ag" urgrep-tools)) @@ -58,7 +62,11 @@ (should (equal (urgrep-command "(foo)" :tool tool :regexp-syntax 'pcre) (concat common-args "--group -- \\(foo\\)"))) (should (equal (urgrep-command "foo" :tool tool :context 3) - (concat common-args "-C3 -Q --group -- foo"))))) + (concat common-args "-C3 -Q --group -- foo"))) + (should (equal (urgrep-command "foo" :tool tool :context '(3 . 3)) + (concat common-args "-C3 -Q --group -- foo"))) + (should (equal (urgrep-command "foo" :tool tool :context '(2 . 4)) + (concat common-args "-B2 -A4 -Q --group -- foo"))))) (ert-deftest urgrep-tests-command-ack () (let ((tool (assoc "ack" urgrep-tools)) @@ -74,7 +82,11 @@ (should (equal (urgrep-command "(foo)" :tool tool :regexp-syntax 'pcre) (concat common-args "--group -- \\(foo\\)"))) (should (equal (urgrep-command "foo" :tool tool :context 3) - (concat common-args "-C3 -Q --group -- foo"))))) + (concat common-args "-C3 -Q --group -- foo"))) + (should (equal (urgrep-command "foo" :tool tool :context '(3 . 3)) + (concat common-args "-C3 -Q --group -- foo"))) + (should (equal (urgrep-command "foo" :tool tool :context '(2 . 4)) + (concat common-args "-B2 -A4 -Q --group -- foo"))))) (ert-deftest urgrep-tests-command-git-grep () (let ((tool (assoc "git-grep" urgrep-tools)) diff --git a/urgrep.el b/urgrep.el index 5cf59e4dd4..83eb7dec60 100644 --- a/urgrep.el +++ b/urgrep.el @@ -57,8 +57,10 @@ :group 'urgrep) (defcustom urgrep-context-lines 0 - "Number of lines of context to show." - :type 'integer + "Number of lines of context to show. +If this is an integer, show that many lines of context on either side. +If a cons, show CAR and CDR lines before and after, respectively." + :type '(choice integer (cons integer integer)) :group 'urgrep) (defface urgrep-hit '((t :inherit compilation-info)) @@ -87,8 +89,11 @@ (rgrep-default-command query "*" nil)) (defconst urgrep--context-arguments - '(((and (pred integerp) n (guard (> n 0))) - (list (format "-C%d" n))))) + '(((or '(0 . 0) 0) nil) + (`(,b . 0) (list (format "-B%d" b))) + (`(0 . ,a) (list (format "-A%d" a))) + ((or `(,c . ,c) (and c (pred numberp))) (list (format "-C%d" c))) + (`(,b . ,a) (list (format "-B%d" b) (format "-A%d" a))))) (defvar urgrep-tools `(("ripgrep" @@ -528,8 +533,9 @@ This depends on the current values of various urgrep options. DEFAULT indicates the default query, if any." (concat "Search " (if urgrep-search-regexp "regexp" "string") - (when (> urgrep-context-lines 0) - (format " -C%d" urgrep-context-lines)) + (let ((block (append `(,#'pcase ',urgrep-context-lines) + urgrep--context-arguments))) + (mapconcat (lambda (i) (concat " " i)) (eval block t) "")) (when default (format " (default %s)" default)) ": ")) @@ -560,25 +566,55 @@ future searches." (setq urgrep-search-regexp (not urgrep-search-regexp)) (when (window-minibuffer-p) (urgrep--update-search-prompt))) +(defun urgrep--read-context (prompt) + "Read the number of lines of context, prompting with PROMPT. +If called with a prefix argument, use its numeric value instead of +prompting." + (if current-prefix-arg + (prefix-numeric-value current-prefix-arg) + (let ((enable-recursive-minibuffers t)) + (read-number prompt)))) + (defun urgrep-set-context (lines) "Set the number of LINES of context to show in the search results. Within the `urgrep' search prompt, this sets the value only for the current search. Outside the prompt, this sets the value for all future searches." - (interactive - (list - (if current-prefix-arg - (prefix-numeric-value current-prefix-arg) - (let ((enable-recursive-minibuffers t)) - (read-number "Context: "))))) + (interactive (list (urgrep--read-context "Context: "))) (setq urgrep-context-lines lines) (when (window-minibuffer-p) (urgrep--update-search-prompt))) +(defun urgrep-set-before-context (before-lines) + "Set the number of BEFORE-LINES of context to show in the search results. +Within the `urgrep' search prompt, this sets the value only for the +current search. Outside the prompt, this sets the value for all +future searches." + (interactive (list (urgrep--read-context "Context before: "))) + (let ((after-lines (if (consp urgrep-context-lines) + (cdr urgrep-context-lines) + urgrep-context-lines))) + (setq urgrep-context-lines (cons before-lines after-lines))) + (when (window-minibuffer-p) (urgrep--update-search-prompt))) + +(defun urgrep-set-after-context (after-lines) + "Set the number of AFTER-LINES of context to show in the search results. +Within the `urgrep' search prompt, this sets the value only for the +current search. Outside the prompt, this sets the value for all +future searches." + (interactive (list (urgrep--read-context "Context after: "))) + (let ((before-lines (if (consp urgrep-context-lines) + (car urgrep-context-lines) + urgrep-context-lines))) + (setq urgrep-context-lines (cons before-lines after-lines))) + (when (window-minibuffer-p) (urgrep--update-search-prompt))) + (defvar urgrep-minibuffer-map (let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) (define-key map "\C-c\C-r" #'urgrep-toggle-regexp) (define-key map "\C-c\C-c" #'urgrep-set-context) + (define-key map "\C-c\C-b" #'urgrep-set-before-context) + (define-key map "\C-c\C-a" #'urgrep-set-after-context) map)) (cl-defun urgrep--read-query (initial &key (regexp urgrep-search-regexp) @@ -599,12 +635,14 @@ command." :context urgrep-context-lines))) (defun urgrep--read-command (command) + "Read a shell command to use for searching, with initial value COMMAND." (read-shell-command "Search command: " command (if (equal (car urgrep-command-history) command) '(urgrep-command-history . 1) 'urgrep-command-history))) (cl-defun urgrep--to-command (query &key regexp context) + "Convert the result of `urgrep--read-query' to a shell command." (urgrep-command query :group urgrep-group-matches :regexp-syntax (and regexp urgrep-regexp-syntax) :context context)) @@ -613,6 +651,10 @@ command." ;; User-facing functions (and supporting helpers) (defun urgrep--read-directory (arg) + "Get the directory to search in. +If ARG is nil, return the project's root directory. If ARG's numeric +value is 4, return the current directory. Otherwise, prompt for the +directory." (cond ((not arg) (let ((proj (project-current))) (if proj (project-root proj) default-directory))) @@ -634,7 +676,9 @@ entering the search query: Type \\[urgrep-toggle-regexp] to toggle regular-expression mode. Type \\[urgrep-set-context] to set the number of context lines. With a numeric prefix argument, set the context to that many - lines. Without a prefix, prompt for the number." + lines. Without a prefix, prompt for the number. +Type \\[urgrep-set-before-context] to set the number of before context lines. +Type \\[urgrep-set-after-context] to set the number of after context lines." (interactive (list ;; Wrap the command in a list so that we can tell it's a real command, not