From 054c7a0d1c90c18d64f65c338deabdb45b2b9b89 Mon Sep 17 00:00:00 2001 From: Hugo Heagren Date: Wed, 22 Sep 2021 16:16:18 +0100 Subject: [PATCH 1/2] Add "other tab" actions to some commands * ivy.el (ivy--switch-buffer-other-tab-action): New action function. (ivy-switch-buffer): * counsel.el (counsel-find-file, counsel-recentf) (counsel-buffer-or-recentf, counsel-bookmark) (counsel-switch-buffer): New action function (counsel--bookmark-jump-other-tab). Add "other tab" actions, but only on the condition that the relevant features are available (because Ivy supports Emacsen before they were introduced) (#2915). --- counsel.el | 22 ++++++++++++++++++---- ivy.el | 17 ++++++++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/counsel.el b/counsel.el index 8c1f3810..139e48c3 100644 --- a/counsel.el +++ b/counsel.el @@ -1935,8 +1935,10 @@ choose between `yes-or-no-p' and `y-or-n-p'; otherwise default to (ivy-set-actions 'counsel-find-file - '(("j" find-file-other-window "other window") + `(("j" find-file-other-window "other window") ("f" find-file-other-frame "other frame") + ,@(and (fboundp 'find-file-other-tab) + '(("t" find-file-other-tab "other tab"))) ("b" counsel-find-file-cd-bookmark-action "cd bookmark") ("x" counsel-find-file-extern "open externally") ("r" counsel-find-file-as-root "open as root") @@ -2331,6 +2333,8 @@ https://www.freedesktop.org/wiki/Specifications/desktop-bookmark-spec")) 'counsel-recentf `(("j" find-file-other-window "other window") ("f" find-file-other-frame "other frame") + ,@(and (fboundp 'find-file-other-tab) + '(("t" find-file-other-tab "other tab"))) ("x" counsel-find-file-extern "open externally") ("d" ,(lambda (file) (setq recentf-list (delete file recentf-list))) "delete from recentf"))) @@ -2439,8 +2443,10 @@ This function uses the `dom' library from Emacs 25.1 or later." (ivy-set-actions 'counsel-buffer-or-recentf - '(("j" find-file-other-window "other window") + `(("j" find-file-other-window "other window") ("f" find-file-other-frame "other frame") + ,@(and (fboundp 'find-file-other-tab) + '(("t" find-file-other-tab "other tab"))) ("x" counsel-find-file-extern "open externally"))) (defun counsel-buffer-or-recentf-transformer (var) @@ -2488,9 +2494,15 @@ By default `counsel-bookmark' opens a dired buffer for directories." (lambda (bookmark) (funcall fn (bookmark-location bookmark)))) +(defun counsel--bookmark-jump-other-tab (bookmark) + "Jump to BOOKMARK in another tab." + (bookmark-jump bookmark 'switch-to-buffer-other-tab)) + (ivy-set-actions 'counsel-bookmark `(("j" bookmark-jump-other-window "other window") + ,@(and (fboundp 'switch-to-buffer-other-tab) + `(("t" counsel--bookmark-jump-other-tab "other tab"))) ("d" bookmark-delete "delete") ("e" bookmark-rename "edit") ("s" bookmark-set "overwrite") @@ -6346,8 +6358,10 @@ in the current window." (ivy-set-actions 'counsel-switch-buffer - '(("x" counsel-open-buffer-file-externally "open externally") - ("j" ivy--switch-buffer-other-window-action "other window"))) + `(("x" counsel-open-buffer-file-externally "open externally") + ("j" ivy--switch-buffer-other-window-action "other window") + ,@(and (fboundp 'find-file-other-tab) + '(("t" ivy--switch-buffer-other-tab-action "other tab"))))) ;;** `counsel-compile' (defvar counsel-compile-history nil diff --git a/ivy.el b/ivy.el index 33cf95d2..23b550b9 100644 --- a/ivy.el +++ b/ivy.el @@ -4441,6 +4441,17 @@ BUFFER may be a string or nil." (find-file-other-window (cdr virtual)) (switch-to-buffer-other-window buffer))))) +(defun ivy--switch-buffer-other-tab-action (buffer) + "Switch to BUFFER in other tab. +BUFFER may be a string or nil." + (if (zerop (length buffer)) + (switch-to-buffer-other-tab ivy-text) + (let ((virtual (assoc buffer ivy--virtual-buffers))) + (if (and virtual + (not (get-buffer buffer))) + (find-file-other-tab (cdr virtual)) + (switch-to-buffer-other-tab buffer))))) + (defun ivy--rename-buffer-action (buffer) "Rename BUFFER." (let ((new-name (read-string "Rename buffer (to new name): "))) @@ -4505,12 +4516,16 @@ Otherwise, forward to `ivy-kill-line'." (ivy-set-actions 'ivy-switch-buffer - '(("f" + `(("f" ivy--find-file-action "find file") ("j" ivy--switch-buffer-other-window-action "other window") + ,@(and (fboundp 'find-file-other-tab) + '(("t" + ivy--switch-buffer-other-tab-action + "other tab"))) ("k" ivy--kill-buffer-action "kill") From 0616715bb65c51f87ae6a3077bd814e4d478b702 Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Thu, 30 Sep 2021 15:17:14 +0100 Subject: [PATCH 2/2] Reduce ivy-switch-buffer action duplication * ivy.el (ivy--switch-buffer-elsewhere): New subroutine generalized from ivy--switch-buffer-other-window-action. (ivy--switch-buffer-other-window-action): Use it. Expand docstring. (ivy--switch-buffer-other-tab-action): Ditto. Define function only in Emacs 27+. (ivy-switch-buffer): * counsel.el (counsel-switch-buffer): Make "other tab" feature detection explicit. Re: #2915. --- counsel.el | 2 +- ivy.el | 57 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/counsel.el b/counsel.el index 139e48c3..358d1745 100644 --- a/counsel.el +++ b/counsel.el @@ -6360,7 +6360,7 @@ in the current window." 'counsel-switch-buffer `(("x" counsel-open-buffer-file-externally "open externally") ("j" ivy--switch-buffer-other-window-action "other window") - ,@(and (fboundp 'find-file-other-tab) + ,@(and (fboundp 'ivy--switch-buffer-other-tab-action) '(("t" ivy--switch-buffer-other-tab-action "other tab"))))) ;;** `counsel-compile' diff --git a/ivy.el b/ivy.el index 23b550b9..a8152936 100644 --- a/ivy.el +++ b/ivy.el @@ -4430,27 +4430,38 @@ BUFFER may be a string or nil." (switch-to-buffer buffer nil 'force-same-window)))))) +(defun ivy--switch-buffer-elsewhere (bufname switch visit) + "Switch to BUFNAME in other window/frame/tab/etc. +If BUFNAME is nil or empty use `ivy-text' in its place. +SWITCH and VISIT are the desired buffer-switching and +file-visiting functions to use, respectively. Which one is used +depends on whether BUFNAME corresponds to a virtual buffer." + (let* ((empty (zerop (length bufname))) + (virtual (and (not empty) + (assoc bufname ivy--virtual-buffers)))) + (if (and virtual (not (get-buffer bufname))) + (funcall visit (cdr virtual)) + (funcall switch (if empty ivy-text bufname))))) + (defun ivy--switch-buffer-other-window-action (buffer) - "Switch to BUFFER in other window. -BUFFER may be a string or nil." - (if (zerop (length buffer)) - (switch-to-buffer-other-window ivy-text) - (let ((virtual (assoc buffer ivy--virtual-buffers))) - (if (and virtual - (not (get-buffer buffer))) - (find-file-other-window (cdr virtual)) - (switch-to-buffer-other-window buffer))))) - -(defun ivy--switch-buffer-other-tab-action (buffer) - "Switch to BUFFER in other tab. -BUFFER may be a string or nil." - (if (zerop (length buffer)) - (switch-to-buffer-other-tab ivy-text) - (let ((virtual (assoc buffer ivy--virtual-buffers))) - (if (and virtual - (not (get-buffer buffer))) - (find-file-other-tab (cdr virtual)) - (switch-to-buffer-other-tab buffer))))) + "Switch to BUFFER (a string or nil) in other window. +If BUFFER is nil or empty use `ivy-text' in its place. +This function also handles the case where BUFFER is virtual; +see `ivy-use-virtual-buffers'." + (ivy--switch-buffer-elsewhere buffer + #'switch-to-buffer-other-window + #'find-file-other-window)) + +(when (and (fboundp 'switch-to-buffer-other-tab) + (fboundp 'find-file-other-tab)) + (defun ivy--switch-buffer-other-tab-action (buffer) + "Switch to BUFFER (a string or nil) in other tab. +If BUFFER is nil or empty use `ivy-text' in its place. +This function also handles the case where BUFFER is virtual; +see `ivy-use-virtual-buffers'." + (ivy--switch-buffer-elsewhere buffer + #'switch-to-buffer-other-tab + #'find-file-other-tab))) (defun ivy--rename-buffer-action (buffer) "Rename BUFFER." @@ -4522,10 +4533,8 @@ Otherwise, forward to `ivy-kill-line'." ("j" ivy--switch-buffer-other-window-action "other window") - ,@(and (fboundp 'find-file-other-tab) - '(("t" - ivy--switch-buffer-other-tab-action - "other tab"))) + ,@(and (fboundp 'ivy--switch-buffer-other-tab-action) + '(("t" ivy--switch-buffer-other-tab-action "other tab"))) ("k" ivy--kill-buffer-action "kill")