How about this:
(defun ace-command-other-window (cmd &optional one-win-cmd)
"Execute CMD in another window.
If provided, call ONE-WIN-CMD instead when there is only one window."
(interactive "CM-x (other window) ")
(catch 'done
(when (and one-win-cmd
(not (window-parent)))
(call-interactively one-win-cmd)
(throw 'done t))
(let ((start-window (selected-window)))
(unwind-protect
(progn
(aw-switch-to-window
(aw-select " Ace - Command "))
(call-interactively cmd))
(aw-switch-to-window start-window)))))
(defun ace-find-file ()
"Find a file in another window."
(interactive)
(ace-command-other-window #'ido-find-file
#'ido-find-file-other-window))
(defun ace-switch-buffer ()
"Switch buffers in another window."
(interactive)
(ace-command-other-window #'ido-switch-buffer
#'ido-switch-buffer-other-window))
When you have only one window, these call the normal ido commands to split the window and switch to the specified file or buffer. If you have two windows, they will switch file/buffer in the other window but keep the current window active. With three or more windows, you'll be prompted to choose a target window using ace.
Suggested bindings: C-x 4 M-x
for ace-command-other-window
, and then rebind C-x 4 f
and C-x 4 b
for the other two.
Update
My original approach was to use ace to switch to an arbitrary window and then call the desired command. This doesn't behave as you might expect. For example, if you call ace-find-file you end up starting in the default directory of the target window rather than the currently active one.
Here is an alternative implementation that flips things around to choose the target file/buffer first, then displays it in an ace-selected window.
(defun ace-switch-buffer ()
"Switch to another buffer in another window."
(interactive)
(if (not (window-parent))
(ido-switch-buffer-other-window)
(let ((start-win (selected-window))
(buf (ido-read-buffer "Buffer: "))
(win (aw-select " Ace Buffer: ")))
(unwind-protect
(progn
(aw-switch-to-window win)
(switch-to-buffer buf))
(aw-switch-to-window start-win)))))
(defun ace-find-file ()
"Find a file and display it in another window."
(interactive)
(if (not (window-parent))
(ido-find-file-other-window)
(let ((start-win (selected-window))
(buf (find-file-noselect (ido-read-file-name "File: ")))
(win (aw-select " Ace File: ")))
(unwind-protect
(progn
(aw-switch-to-window win)
(switch-to-buffer buf))
(aw-switch-to-window start-win)))))