branch: master
commit 01e305ce5bbaf9b2756d1ee3cd16d3d75a9177ba
Author: Brendan Cully <[email protected]>
Commit: Oleh Krehel <[email protected]>
Add counsel-url-expand helper for ivy-ffap-url-functions
counsel-url-expand makes it easy to add keyword to URL expansions for
ivy-ffap, simply by adding a (REGEXP . FORMAT) pair to
counsel-url-expansions.
Fixes #1164
---
counsel.el | 44 ++++++++++++++++++++++++++++++++++++++++++++
ivy-test.el | 29 +++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
diff --git a/counsel.el b/counsel.el
index e07fc97..e7a6984 100644
--- a/counsel.el
+++ b/counsel.el
@@ -1537,6 +1537,7 @@ Does not list the currently checked out one."
(add-to-list 'ivy-ffap-url-functions 'counsel-github-url-p)
(add-to-list 'ivy-ffap-url-functions 'counsel-emacs-url-p)
+(add-to-list 'ivy-ffap-url-functions 'counsel-url-expand)
(defun counsel-find-file-cd-bookmark-action (_)
"Reset `counsel-find-file' from selected directory."
(ivy-read "cd: "
@@ -1699,6 +1700,49 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer
during completion."
(format "http://debbugs.gnu.org/cgi/bugreport.cgi?bug=%s"
(substring url 1)))))))
+(defvar counsel-url-expansions nil
+ "Map of regular expressions to expansions.
+
+This variable should take the form of a list of (REGEXP . FORMAT)
+pairs.
+
+`counsel-url-expand' will expand the word at point according to
+FORMAT for the first matching REGEXP. FORMAT can be either a
+string or a function. If it is a string, it will be used as the
+format string for the `format' function, with the word at point
+as the next argument. If it is a function, it will be called
+with the word at point as the sole argument.
+
+For example, a pair of the form:
+ '(\"\\`BSERV-[[:digit:]]+\\'\" . \"https://jira.atlassian.com/browse/%s\")
+will expand to URL `https://jira.atlassian.com/browse/BSERV-100'
+when the word at point is BSERV-100.
+
+If the format element is a function, more powerful
+transformations are possible. As an example,
+ '(\"\\`issue\\([[:digit:]]+\\)\\'\" .
+ (lambda (word)
+ (concat \"http://debbugs.gnu.org/cgi/bugreport.cgi?bug=\"
+ (match-string 1 word))))
+trims the \"issue\" prefix from the word at point before creating the URL.")
+
+(defun counsel-url-expand ()
+ "Expand word at point using `counsel-url-expansions'.
+The first pair in the list whose regexp matches the word at point
+will be expanded according to its format. This function is
+intended to be used in `ivy-ffap-url-functions' to browse the
+result as a URL."
+ (let ((word-at-point (current-word)))
+ (cl-some
+ (lambda (pair)
+ (let ((regexp (car pair))
+ (formatter (cdr pair)))
+ (when (string-match regexp word-at-point)
+ (if (functionp formatter)
+ (funcall formatter word-at-point)
+ (format formatter word-at-point)))))
+ counsel-url-expansions)))
+
;;** `counsel-recentf'
(defvar recentf-list)
(declare-function recentf-mode "recentf")
diff --git a/ivy-test.el b/ivy-test.el
index ea30f13..7ac9326 100644
--- a/ivy-test.el
+++ b/ivy-test.el
@@ -249,6 +249,35 @@ will bring the behavior in line with the newer Emacsen."
(ivy--regex "(foo bar"))
"(\\(foo).*?(bar)")))
+(defmacro ivy--string-buffer (text &rest body)
+ "Test helper that wraps TEXT in a temp buffer while running BODY."
+ `(with-temp-buffer
+ (insert ,text)
+ ,@body))
+
+(ert-deftest counsel-url-expand ()
+ "Test ffap expansion using counsel-url-expansions."
+ ;; no expansions defined
+ (let (counsel-url-expansions)
+ (should (eq (counsel-url-expand) nil)))
+ (let ((counsel-url-expansions
+ `(("^foo$" . "https://foo.com/%s")
+ ("^issue\\([0-9]+\\)" . ,(lambda (word)
+ (concat "https://foo.com/issues/"
+ (match-string 1 word)))))))
+ ;; no match
+ (ivy--string-buffer
+ "foobar"
+ (should (equal (counsel-url-expand) nil)))
+ ;; string expansion
+ (ivy--string-buffer
+ "foo"
+ (should (equal (counsel-url-expand) "https://foo.com/foo")))
+ ;; function expansion
+ (ivy--string-buffer
+ "issue123"
+ (should (equal (counsel-url-expand) "https://foo.com/issues/123")))))
+
(ert-deftest colir-color-parse ()
(should (equal (colir-color-parse "#ab1234")
;; (color-name-to-rgb "#ab1234")