Skip to content

Commit

Permalink
Allow truncating search pattern item in header
Browse files Browse the repository at this point in the history
This adds new variable `rg-header-max-search-string-length`.

If the variable is set to a number and the search pattern exceeds that
threshold the header item of the result buffer is truncated. Function
`truncate-string-to-width` is used.

The help echo of the item now displays the full search pattern if
truncation was applied.
  • Loading branch information
Walheimat committed Oct 1, 2024
1 parent 8c7bdce commit 71df25a
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 2 deletions.
38 changes: 36 additions & 2 deletions rg-header.el
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@
;;; Code:

(require 'mouse)

(declare-function rg-cur-search-pattern "rg-result.el")


;; Customization
(defcustom rg-header-max-search-string-length nil
"The max line length of header line search string item."
:type '(choice (const :tag "Don't truncate" nil)
(number :tag "The max width"))
:group 'rg)


;; Faces
(defface rg-toggle-on-face
Expand Down Expand Up @@ -97,6 +108,29 @@ items that the map will be applied to."
help-echo ,help
keymap ,map)))

(defun rg-header-truncate-search-pattern (search)
"Truncate SEARCH if it exceeds `rg-header-max-search-string-length'."
(if (rg-header-truncates-p search)
(truncate-string-to-width search
rg-header-max-search-string-length
0
nil
t)
search))

(defun rg-header-truncates-p (search)
"Verify that SEARCH would be truncated."
(and (numberp rg-header-max-search-string-length)
(< rg-header-max-search-string-length (length search))))

(defun rg-header-search-help ()
"Get the search help for the current buffer."
(let ((pattern (rg-cur-search-pattern)))

(if (rg-header-truncates-p pattern)
(concat "Change search string: " pattern)
"Change search string")))

;; Use full-command here to avoid dependency on rg-search
;; struct. Should be properly fixed.
(defun rg-create-header-line (search full-command)
Expand All @@ -113,8 +147,8 @@ If FULL-COMMAND specifies if the full command line search was done."
("literal" rg-literal-face)
("regexp" rg-regexp-face))))
(rg-header-mouse-action
'rg-rerun-change-query "Change search string"
`(:eval (rg-search-pattern ,search)))
'rg-rerun-change-query (rg-header-search-help)
`(:eval (rg-header-truncate-search-pattern (rg-search-pattern ,search))))
itemspace
(rg-header-render-label "files")
(rg-header-mouse-action
Expand Down
4 changes: 4 additions & 0 deletions rg-result.el
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,10 @@ previous file with grouped matches."
(push (cons filepath nextfile) elements))
(nreverse elements))))))

(defun rg-cur-search-pattern ()
"Get the current search pattern."
(rg-search-pattern rg-cur-search))

(provide 'rg-result)

;; Local Variables:
Expand Down
99 changes: 99 additions & 0 deletions test/rg-header.el-test.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
(require 'cl-lib)
(require 'mule-util)

(defvar rg-unit/long-search-pattern "everything everywhere all at once")

;;; Mocks.

(cl-defmacro rg-unit/mock-truncation-predicate ((&key max predicate) &rest body)
"Execute BODY with truncation predicate mocked by PREDICATE.
MAX is the value `rg-header-max-search-string-length' will be set to."
(declare (indent defun))
`(cl-letf* ((rg-header-max-search-string-length ,max)
((symbol-function 'rg-header-truncates-p) #',predicate))
,@body))

(cl-defmacro rg-unit/mock-rg-cur-search-pattern ((&key do-return) &rest body)
"Execute BODY with `rg-cur-search-pattern' mocked.
Instead DO-RETURN will be returned when the function is called."
(declare (indent defun))

`(cl-letf* (((symbol-function 'rg-cur-search-pattern) (lambda (&rest _) ,do-return)))
,@body))

;;; Tests.

(ert-deftest rg-unit/header-truncation-predicate ()
"Test `rg-header-truncates-p'."

;; Not set.
(let ((rg-header-max-search-string-length nil))

(should-not (rg-header-truncates-p rg-unit/long-search-pattern)))

;; Erroneous value.
(let ((rg-header-max-search-string-length 'none))

(should-not (rg-header-truncates-p rg-unit/long-search-pattern)))

;; The length of the string passed.
(let ((rg-header-max-search-string-length (length rg-unit/long-search-pattern)))

(should-not (rg-header-truncates-p rg-unit/long-search-pattern)))

;; One below string length.
(let ((rg-header-max-search-string-length (1- (length rg-unit/long-search-pattern))))

(should (rg-header-truncates-p rg-unit/long-search-pattern)))

;; At 0.
(let ((rg-header-max-search-string-length 0))

(should (rg-header-truncates-p rg-unit/long-search-pattern)))

;; Below 0.
(let ((rg-header-max-search-string-length -1))

(should (rg-header-truncates-p rg-unit/long-search-pattern))))


(ert-deftest rg-unit/search-pattern-truncation-in-header ()
"Tests `rg-header-truncate-search-pattern'."
;; When predicate is true.
(rg-unit/mock-truncation-predicate (:max 11 :predicate always)
(should (string=
(concat "everything" (truncate-string-ellipsis))
(rg-header-truncate-search-pattern rg-unit/long-search-pattern))))

(rg-unit/mock-truncation-predicate (:max 5 :predicate always)
(should (string=
"ever…"
(rg-header-truncate-search-pattern rg-unit/long-search-pattern))))

(rg-unit/mock-truncation-predicate (:max (length rg-unit/long-search-pattern) :predicate always)
(should (string=
"everything everywhere all at once"
(rg-header-truncate-search-pattern rg-unit/long-search-pattern))))

;; When predicate is false.
(rg-unit/mock-truncation-predicate (:max 11 :predicate ignore)
(should (string=
"everything everywhere all at once"
(rg-header-truncate-search-pattern rg-unit/long-search-pattern))))

(rg-unit/mock-truncation-predicate (:predicate ignore)
(should (string=
"everything everywhere all at once"
(rg-header-truncate-search-pattern rg-unit/long-search-pattern)))))

(ert-deftest rg-unit/search-help-for-header ()
"Tests `rg-header-search-help'."
(rg-unit/mock-rg-cur-search-pattern (:do-return "this is the full string")

(rg-unit/mock-truncation-predicate (:predicate always)
(should (string= "Change search string: this is the full string" (rg-header-search-help))))

(rg-unit/mock-truncation-predicate (:predicate ignore)
(should (string= "Change search string" (rg-header-search-help))))))

0 comments on commit 71df25a

Please sign in to comment.