feat(windows): Integrate windmove with tmux

When Emacs is launched within Tmux, and a windmove command fails (due to
it reaching the left/right/top/bottom edge of frame, instead trigger a
Tmux pane switch in that direction.

This allows a nearly seamless window/pane switching experience between
Emacs and Tmux.

It does require the following configuration in Tmux to work properly:

    # Enable smart pane switching that's Emacs aware.
    is_emacs='echo "#{pane_current_command}" | grep -iqE "(^|\/)emacs$"'

    # Use Alt-[i/k/j/l] keys without prefix key to switch panes if current pane is
    # not running Emacs. If the pane is running Emacs, let Emacs receive the
    # keybindings instead.
    bind -n M-i if-shell "$is_emacs" "send-keys M-i" "select-pane -U"
    bind -n M-k if-shell "$is_emacs" "send-keys M-k" "select-pane -D"
    bind -n M-j if-shell "$is_emacs" "send-keys M-j" "select-pane -L"
    bind -n M-l if-shell "$is_emacs" "send-keys M-l" "select-pane -R"
    bind -T copy-mode M-i if-shell "$is_emacs" "send-keys M-i" "select-pane -U"
    bind -T copy-mode M-k if-shell "$is_emacs" "send-keys M-k" "select-pane -D"
    bind -T copy-mode M-j if-shell "$is_emacs" "send-keys M-j" "select-pane -L"
    bind -T copy-mode M-l if-shell "$is_emacs" "send-keys M-l" "select-pane -R"
    bind -T copy-mode-vi M-i if-shell "$is_emacs" "send-keys M-i" "select-pane -U"
    bind -T copy-mode-vi M-k if-shell "$is_emacs" "send-keys M-k" "select-pane -D"
    bind -T copy-mode-vi M-j if-shell "$is_emacs" "send-keys M-j" "select-pane -L"
    bind -T copy-mode-vi M-l if-shell "$is_emacs" "send-keys M-l" "select-pane -R"
This commit is contained in:
2020-05-30 17:01:21 +01:00
parent e6ff06ea2c
commit 0810857131

View File

@@ -8,11 +8,40 @@
(use-package windmove
:straight (:type built-in)
:config
(global-set-key (kbd "M-k") (siren-ignore-error-wrapper 'windmove-down))
(global-set-key (kbd "M-i") (siren-ignore-error-wrapper 'windmove-up))
(global-set-key (kbd "M-j") (siren-ignore-error-wrapper 'windmove-left))
(global-set-key (kbd "M-l") (siren-ignore-error-wrapper 'windmove-right)))
:bind
("M-i" . siren-windmove-up)
("M-k" . siren-windmove-down)
("M-j" . siren-windmove-left)
("M-l" . siren-windmove-right)
:custom
(siren-windmove-tmux-fallback (if (getenv "TMUX") t nil))
:init
(defun siren-windmove-up ()
(interactive)
(if (and (not (ignore-errors (windmove-up)))
siren-windmove-tmux-fallback)
(shell-command "tmux select-pane -U")))
(defun siren-windmove-down ()
(interactive)
(if (and (not (ignore-errors (windmove-down)))
siren-windmove-tmux-fallback)
(shell-command "tmux select-pane -D")))
(defun siren-windmove-left ()
(interactive)
(if (and (not (ignore-errors (windmove-left)))
siren-windmove-tmux-fallback)
(shell-command "tmux select-pane -L")))
(defun siren-windmove-right ()
(interactive)
(if (and (not (ignore-errors (windmove-right)))
siren-windmove-tmux-fallback)
(shell-command "tmux select-pane -R"))))
(provide 'siren-windmove)
;;; siren-windmove.el ends here