branch: externals/urgrep
commit 026c54d11ea2ef260f8b3e4e412ac40c4fc37842
Author: Jim Porter <jporterb...@gmail.com>
Commit: Jim Porter <jporterb...@gmail.com>

    Add support for setting context
---
 urgrep-test.el |  33 ++++++++++++-----
 urgrep.el      | 109 ++++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 101 insertions(+), 41 deletions(-)

diff --git a/urgrep-test.el b/urgrep-test.el
index 7f0dd5e4bf..27fcb4c86a 100644
--- a/urgrep-test.el
+++ b/urgrep-test.el
@@ -27,24 +27,39 @@
 (require 'ert)
 
 (ert-deftest urgrep-test-command-ag ()
-  (let ((tool (assoc "ag" urgrep-tools)))
+  (let ((tool (assoc "ag" urgrep-tools))
+        (common-args "ag --color-path 35 --color-match 1\\;31 "))
     (should (equal (urgrep-command "foo" :tool tool)
-                   "ag --color-path 35 --color-match 1\\;31 -Q --group foo"))
+                   (concat common-args "-Q --group foo")))
     (should (equal (urgrep-command "foo" :tool tool :group nil)
-                   "ag --color-path 35 --color-match 1\\;31 -Q --nogroup 
foo"))))
+                   (concat common-args "-Q --nogroup foo")))
+    (should (equal (urgrep-command "foo" :tool tool :regexp t)
+                   (concat common-args "--group foo")))
+    (should (equal (urgrep-command "foo" :tool tool :context 3)
+                   (concat common-args "-C3 -Q --group foo")))))
 
 (ert-deftest urgrep-test-command-git-grep ()
-  (let ((tool (assoc "git-grep" urgrep-tools)))
+  (let ((tool (assoc "git-grep" urgrep-tools))
+        (common-args "git -c color.grep.filename\\=magenta grep -n 
--recurse-submodules --color "))
     (should (equal (urgrep-command "foo" :tool tool)
-                   "git -c color.grep.filename\\=magenta grep -n 
--recurse-submodules --color -F --heading --break foo"))
+                   (concat common-args "-F --heading --break foo")))
     (should (equal (urgrep-command "foo" :tool tool :group nil)
-                   "git -c color.grep.filename\\=magenta grep -n 
--recurse-submodules --color -F foo"))))
+                   (concat common-args "-F foo")))
+    (should (equal (urgrep-command "foo" :tool tool :regexp t)
+                   (concat common-args "--heading --break foo")))
+    (should (equal (urgrep-command "foo" :tool tool :context 3)
+                   (concat common-args "-C3 -F --heading --break foo")))))
 
 (ert-deftest urgrep-test-command-grep ()
   (let ((tool (assoc "grep" urgrep-tools)))
-    (should (string-match "^find \\." (urgrep-command "foo" :tool tool)))
-    (should (string-match "^find \\." (urgrep-command "foo" :tool tool
-                                                      :group nil)))))
+    (should (string-match "^find \\."
+                          (urgrep-command "foo" :tool tool)))
+    (should (string-match "^find \\."
+                          (urgrep-command "foo" :tool tool :group nil)))
+    (should (string-match "^find \\."
+                          (urgrep-command "foo" :tool tool :regexp t)))
+    (should (string-match "^find \\."
+                          (urgrep-command "foo" :tool tool :context 3)))))
 
 (defun urgrep-test--check-match-at-point ()
   (let* ((line (string-to-number (current-word)))
diff --git a/urgrep.el b/urgrep.el
index b69448f899..0536a7372a 100644
--- a/urgrep.el
+++ b/urgrep.el
@@ -49,6 +49,11 @@
   :type 'boolean
   :group 'urgrep)
 
+(defcustom urgrep-context-lines 0
+  "Number of lines of context to show."
+  :type 'integer
+  :group 'urgrep)
+
 (defface urgrep-hit '((t :inherit compilation-info))
   "Face for matching files."
   :group 'urgrep)
@@ -61,11 +66,15 @@
   "Face for matching text."
   :group 'urgrep)
 
+(defface urgrep-context '((t :inherit shadow))
+  "Face for context lines."
+  :group 'urgrep)
+
 
 ;; Urgrep tools
 
 (cl-defun urgrep-rgrep--command (query &key &allow-other-keys)
-  ;; XXX: Support literal/regexp setting.
+  ;; XXX: Support literal/regexp and context settings.
   (grep-compute-defaults)
   (rgrep-default-command query "*" nil))
 
@@ -75,14 +84,16 @@
      (always-arguments ("--color-path" "35" "--color-match" "1;31"))
      (group-arguments ((t   ("--group"))
                        (nil ("--nogroup"))))
-     (regexp-arguments ((nil ("-Q")))))
+     (regexp-arguments ((nil ("-Q"))))
+     (context-arguments "-C%d"))
     ("git-grep"
      (executable-name "git")
      (vc-backend "Git")
      (always-arguments ("-c" "color.grep.filename=magenta" "grep" "-n"
                         "--recurse-submodules" "--color"))
      (group-arguments ((t ("--heading" "--break"))))
-     (regexp-arguments ((nil ("-F")))))
+     (regexp-arguments ((nil ("-F"))))
+     (context-arguments "-C%d"))
     ("grep"
      (executable-name "grep")
      (command-function ,#'urgrep-rgrep--command)))
@@ -115,7 +126,8 @@
                        (string= vc-backend-name tool-vc-backend)))
           (cl-return tool))))))
 
-(cl-defun urgrep-command (query &rest rest &key tool (group t) regexp)
+(cl-defun urgrep-command (query &rest rest &key tool (group t) regexp
+                                (context 0))
   (let* ((tool (or tool (urgrep-get-tool)))
          (cmd-fun (urgrep-get-property tool 'command-function)))
     (if cmd-fun
@@ -131,6 +143,11 @@
         (when-let ((x (urgrep-get-property-assoc tool 'regexp-arguments
                                                  regexp)))
           (setq arguments (append x arguments)))
+        ;; Fill in context arguments.
+        (when-let (((> context 0))
+                   (prop (urgrep-get-property tool 'context-arguments))
+                   (context-arg (format prop context)))
+          (setq arguments (append (list context-arg) arguments)))
         ;; FIXME: Inside compile and dired buffers, `shell-quote-argument'
         ;; doesn't handle TRAMP right...
         (mapconcat #'shell-quote-argument
@@ -196,20 +213,26 @@
     "]"))
 
 (defvar urgrep-mode-font-lock-keywords
-   '(("^Urgrep started.*"
-      (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t))
-     ("^Urgrep finished with \\(?:\\(\\(?:[0-9]+ \\)?match\\(?:es\\)? 
found\\)\\|\\(no matches found\\)\\).*"
-      (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
-      (1 'urgrep-match-count nil t)
-      (2 'compilation-warning nil t))
-     ("^Urgrep \\(exited 
abnormally\\|interrupt\\|killed\\|terminated\\)\\(?:.*with code 
\\([0-9]+\\)\\)?.*"
-      (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
-      (1 'compilation-error)
-      (2 'compilation-error nil t))
-     ;; Hide excessive part of rgrep command
-     ("^find \\(\\. -type d .*\\(?:\\\\)\\|\")\"\\)\\)"
-      (1 (if grep-find-abbreviate grep-find-abbreviate-properties
-           '(face nil abbreviated-command t))))))
+  '(("^Urgrep started.*"
+     (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t))
+    ("^Urgrep finished with \\(?:\\(\\(?:[0-9]+ \\)?match\\(?:es\\)? 
found\\)\\|\\(no matches found\\)\\).*"
+     (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
+     (1 'urgrep-match-count nil t)
+     (2 'compilation-warning nil t))
+    ("^Urgrep \\(exited 
abnormally\\|interrupt\\|killed\\|terminated\\)\\(?:.*with code 
\\([0-9]+\\)\\)?.*"
+     (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
+     (1 'compilation-error)
+     (2 'compilation-error nil t))
+    ;; Highlight context lines of various flavors.
+    ("^\\(?:.+?\\([:-=\0]\\)\\)?[1-9][0-9]*\\([-=]\\).*\n"
+     (0 'urgrep-context)
+     (1 (if (eq (char-after (match-beginning 1)) ?\0)
+            `(face nil display ,(match-string 2)))
+        nil t))
+    ;; Hide excessive part of rgrep command.
+    ("^find \\(\\. -type d .*\\(?:\\\\)\\|\")\"\\)\\)"
+     (1 (if grep-find-abbreviate grep-find-abbreviate-properties
+          '(face nil abbreviated-command t))))))
 
 (defun urgrep--column-begin ()
   "Look forwards for the match highlight to compute the beginning column."
@@ -246,18 +269,14 @@
        "\\|"
        ;; Fallback if we can't use null terminators after the filename.
        ;; Use [1-9][0-9]* rather than [0-9]+ to allow ":034:" in file names.
-       "\\(?1:"
-       "\\(?:[a-zA-Z]:\\)?" ; Allow "C:..." for w32.
-       "[^\n:]+?[^\n/:]"
-       "\\)"
-       ":[\t ]*\\(?2:[1-9][0-9]*\\)[\t ]*:"
+       "\\(?1:[^\n:]+?[^\n/:]\\):[\t ]*\\(?2:[1-9][0-9]*\\)[\t ]*:"
        "\\)")
      1 2 (,#'urgrep--column-begin . ,#'urgrep--column-end)
      nil nil
      (3 '(face nil display ":")))
 
     ;; Grouped matches
-    ("^\\([[:digit:]]+\\):"
+    ("^\\([1-9][0-9]*\\):"
      ,#'urgrep--grouped-filename 1
      (,#'urgrep--column-begin . ,#'urgrep--column-end)))
   "Regexp used to match results.
@@ -337,6 +356,8 @@ This function is called from `compilation-filter-hook'."
 This depends on the current values of various urgrep options."
   (concat "Search "
           (if urgrep-search-regexp "regexp" "string")
+          (when (> urgrep-context-lines 0)
+            (format " -C%d" urgrep-context-lines))
           ": "))
 
 (defun urgrep--update-search-prompt ()
@@ -356,26 +377,47 @@ This depends on the current values of various urgrep 
options."
   (if (< (point) (minibuffer-prompt-end)) (goto-char (minibuffer-prompt-end))))
 
 (defun urgrep-toggle-regexp ()
-  "Toggle whether or not to use regexps for the current search."
+  "Toggle whether or not to use regexps for the search query.
+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)
   (setq urgrep-search-regexp (not urgrep-search-regexp))
   (when (window-minibuffer-p) (urgrep--update-search-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: ")))))
+  (setq urgrep-context-lines 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)
     map))
 
-(cl-defun urgrep--read-query (&key (regexp urgrep-search-regexp))
+(cl-defun urgrep--read-query (&key (regexp urgrep-search-regexp)
+                                   (context urgrep-context-lines))
   "Prompt the user for a search query.
 Return a list that can be passed to `urgrep-command' to turn into a shell
 command."
   (let* ((urgrep-search-regexp regexp)
+         (urgrep-context-lines context)
          (query (read-from-minibuffer (urgrep--search-prompt) nil
                                       urgrep-minibuffer-map nil
                                       'urgrep-search-history)))
-    (list query :group urgrep-group-matches :regexp urgrep-search-regexp)))
+    (list query :group urgrep-group-matches :regexp urgrep-search-regexp
+          :context urgrep-context-lines)))
 
 
 ;; User-facing functions (and supporting helpers)
@@ -392,14 +434,17 @@ command."
   "Recursively search in DIRECTORY for a given QUERY.
 
 When called interactively, search in the project's root directory, or
-the current directory if there is no current project. With 
\\[universal-argument] prefix,
-search in the current directory. With two \\[universal-argument] prefixes, 
prompt for a
+the current directory if there is no current project.  With 
\\[universal-argument] prefix,
+search in the current directory.  With two \\[universal-argument] prefixes, 
prompt for a
 directory to search in.
 \\<urgrep-minibuffer-map>
-The following keys are bound in `urgrep-minibuffer-map', active
-when entering the search query:
+The following keys are bound in `urgrep-minibuffer-map', active when
+entering the search query:
 
-Type \\[urgrep-toggle-regexp] to toggle regular-expression mode."
+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."
   (interactive
    (list
     ;; Wrap the command in a list so that we can tell it's a real command, not

Reply via email to