branch: master commit e3e1f51eecbe78d06528d06e35fae3ea0459eb3d Author: Oleh Krehel <ohwoeo...@gmail.com> Commit: Oleh Krehel <ohwoeo...@gmail.com>
ivy.el (ivy-ffap-url-functions): Customize "C-x C-f M-n" * ivy.el (ivy-ffap-url-functions): New defvar. (ivy--cd-maybe): When calling a function in `ivy-ffap-url-functions' results in a string, stop completion and open that string with `ffap-url-fetcher'. * counsel.el (counsel-github-url-p): New defun. (ivy-ffap-url-functions): Add `counsel-github-url-p' to the list. This feature allows to quickly visit Github issues from either `magit-commit-mode' or from a version-controlled file. The point has to be at the "#" char in e.g. "#123", that represents an issue. It's possible to customize `ivy-ffap-url-functions' to do a similar thing for places other than Github. The "C-x C-f M-n" key binding will work better with `counsel-find-file', for plain `find-file' it will open a `dired' buffer in addition to opening the URL. --- counsel.el | 23 +++++++++++++++++++++++ ivy.el | 11 ++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/counsel.el b/counsel.el index b6ac36a..6c5a283 100644 --- a/counsel.el +++ b/counsel.el @@ -492,6 +492,29 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer during completion." :history 'file-name-history :keymap counsel-find-file-map)) +(defun counsel-github-url-p () + "Return a Github issue URL at point." + (when (and (looking-at "#[0-9]+") + (or + (eq (vc-backend (buffer-file-name)) 'Git) + (memq major-mode '(magit-commit-mode)))) + (let ((url (match-string-no-properties 0)) + (origin (shell-command-to-string + "git remote get-url origin")) + user repo) + (cond ((string-match "\\`g...@github.com:\\([^/]+\\)/\\(.*\\)\\.git$" + origin) + (setq user (match-string 1 origin)) + (setq repo (match-string 2 origin))) + ((string-match "\\`https://github.com/\\([^/]+\\)/\\(.*\\)$" + origin) + (setq user (match-string 1 origin)) + (setq repo (match-string 2 origin)))) + (when user + (setq url (format "https://github.com/%s/%s/issues/%s" + user repo (substring url 1))))))) +(add-to-list 'ivy-ffap-url-functions 'counsel-github-url-p) + (defcustom counsel-find-file-ignore-regexp nil "A regexp of files to ignore while in `counsel-find-file'. These files are un-ignored if `ivy-text' matches them. diff --git a/ivy.el b/ivy.el index 2240e9e..fb251d1 100644 --- a/ivy.el +++ b/ivy.el @@ -791,13 +791,22 @@ Call the permanent action if possible." (move-end-of-line 1) (ivy--maybe-scroll-history)) +(defvar ivy-ffap-url-functions nil + "List of functions that check if the point is on a URL.") + (defun ivy--cd-maybe () "Check if the current input points to a different directory. If so, move to that directory, while keeping only the file name." (when ivy--directory (let ((input (ivy--input)) url) - (if (setq url (ffap-url-p input)) + (if (setq url (or (ffap-url-p input) + (with-ivy-window + (cl-reduce + (lambda (a b) + (or a (funcall b))) + ivy-ffap-url-functions + :initial-value nil)))) (ivy-exit-with-action (lambda (_) (funcall ffap-url-fetcher url)))