mirror of
https://github.com/SqrtMinusOne/dotfiles.git
synced 2025-12-10 11:13:04 +03:00
feat(*): Emacs & i3 integration
This commit is contained in:
parent
a0f25dd23f
commit
20af706fa2
7 changed files with 300 additions and 81 deletions
|
|
@ -42,6 +42,7 @@
|
|||
"curl"
|
||||
"bind:utils"
|
||||
"polybar"
|
||||
"python-i3-balance-workspace"
|
||||
"i3-gaps"
|
||||
"xinput"
|
||||
"xgamma"
|
||||
|
|
|
|||
|
|
@ -27,47 +27,48 @@ bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcu
|
|||
# General settings:1 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Managing windows][Managing windows:1]]
|
||||
bindsym $mod+Shift+q kill
|
||||
bindsym $mod+Shift+q exec emacs-i3-integration kill
|
||||
# Managing windows:1 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Managing windows][Managing windows:2]]
|
||||
bindsym $mod+h focus left
|
||||
bindsym $mod+j focus down
|
||||
bindsym $mod+k focus up
|
||||
bindsym $mod+l focus right
|
||||
bindsym $mod+h exec emacs-i3-integration focus left
|
||||
bindsym $mod+j exec emacs-i3-integration focus down
|
||||
bindsym $mod+k exec emacs-i3-integration focus up
|
||||
bindsym $mod+l exec emacs-i3-integration focus right
|
||||
|
||||
bindsym $mod+Left focus left
|
||||
bindsym $mod+Down focus down
|
||||
bindsym $mod+Up focus up
|
||||
bindsym $mod+Right focus right
|
||||
bindsym $mod+Left exec emacs-i3-integration focus left
|
||||
bindsym $mod+Down exec emacs-i3-integration focus down
|
||||
bindsym $mod+Up exec emacs-i3-integration focus up
|
||||
bindsym $mod+Right exec emacs-i3-integration focus right
|
||||
# Managing windows:2 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Managing windows][Managing windows:3]]
|
||||
bindsym $mod+Shift+h move left
|
||||
bindsym $mod+Shift+j move down
|
||||
bindsym $mod+Shift+k move up
|
||||
bindsym $mod+Shift+l move right
|
||||
bindsym $mod+Shift+h exec emacs-i3-integration move left
|
||||
bindsym $mod+Shift+j exec emacs-i3-integration move down
|
||||
bindsym $mod+Shift+k exec emacs-i3-integration move up
|
||||
bindsym $mod+Shift+l exec emacs-i3-integration move right
|
||||
|
||||
bindsym $mod+Shift+Left move left
|
||||
bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Right move right
|
||||
bindsym $mod+Shift+Left exec emacs-i3-integration move left
|
||||
bindsym $mod+Shift+Down exec emacs-i3-integration move down
|
||||
bindsym $mod+Shift+Up exec emacs-i3-integration move up
|
||||
bindsym $mod+Shift+Right exec emacs-i3-integration move right
|
||||
# Managing windows:3 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Managing windows][Managing windows:4]]
|
||||
bindsym $mod+s split h
|
||||
bindsym $mod+v split v
|
||||
bindsym $mod+s exec emacs-i3-integration split h
|
||||
bindsym $mod+v exec emacs-i3-integration split v
|
||||
# Managing windows:4 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Managing windows][Managing windows:5]]
|
||||
# enter fullscreen mode for the focused container
|
||||
bindsym $mod+f fullscreen toggle
|
||||
bindsym $mod+c fullscreen toggle global
|
||||
# Managing windows:5 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Managing windows][Managing windows:6]]
|
||||
bindsym $mod+w layout stacking
|
||||
bindsym $mod+t layout tabbed
|
||||
bindsym $mod+e layout toggle split
|
||||
bindsym $mod+e exec emacs-i3-integration layout toggle split
|
||||
# Managing windows:6 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Managing windows][Managing windows:7]]
|
||||
|
|
@ -226,31 +227,31 @@ bindsym $mod+g mode "inner gaps"
|
|||
bindsym $mod+Shift+g mode "outer gaps"
|
||||
# Keybindings:1 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Move & resize windows][Move & resize windows:1]]
|
||||
# resize window (you can also use the mouse for that)
|
||||
# [[file:../../Desktop.org::*Move & resize windows][Move & resize windows:2]]
|
||||
mode "resize" {
|
||||
# These bindings trigger as soon as you enter the resize mode
|
||||
|
||||
bindsym h resize shrink width 10 px or 10 ppt
|
||||
bindsym j resize grow height 10 px or 10 ppt
|
||||
bindsym k resize shrink height 10 px or 10 ppt
|
||||
bindsym l resize grow width 10 px or 10 ppt
|
||||
bindsym h exec emacs-i3-integration resize shrink width 10 px or 10 ppt
|
||||
bindsym j exec emacs-i3-integration resize grow height 10 px or 10 ppt
|
||||
bindsym k exec emacs-i3-integration resize shrink height 10 px or 10 ppt
|
||||
bindsym l exec emacs-i3-integration resize grow width 10 px or 10 ppt
|
||||
|
||||
bindsym Shift+h resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+j resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+k resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+l resize grow width 100 px or 100 ppt
|
||||
bindsym Shift+h exec emacs-i3-integration resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+j exec emacs-i3-integration resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+k exec emacs-i3-integration resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+l exec emacs-i3-integration resize grow width 100 px or 100 ppt
|
||||
|
||||
# same bindings, but for the arrow keys
|
||||
bindsym Left resize shrink width 10 px or 10 ppt
|
||||
bindsym Down resize grow height 10 px or 10 ppt
|
||||
bindsym Up resize shrink height 10 px or 10 ppt
|
||||
bindsym Right resize grow width 10 px or 10 ppt
|
||||
bindsym Left exec emacs-i3-integration resize shrink width 10 px or 10 ppt
|
||||
bindsym Down exec emacs-i3-integration resize grow height 10 px or 10 ppt
|
||||
bindsym Up exec emacs-i3-integration resize shrink height 10 px or 10 ppt
|
||||
bindsym Right exec emacs-i3-integration resize grow width 10 px or 10 ppt
|
||||
|
||||
bindsym Shift+Left resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+Down resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+Up resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+Right resize grow width 100 px or 100 ppt
|
||||
bindsym Shift+Left exec emacs-i3-integration resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+Down exec emacs-i3-integration resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+Up exec emacs-i3-integration resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+Right exec emacs-i3-integration resize grow width 100 px or 100 ppt
|
||||
|
||||
bindsym equal exec i3-emacs-balance-windows
|
||||
|
||||
# back to normal: Enter or Escape
|
||||
bindsym Return mode "default"
|
||||
|
|
@ -278,7 +279,7 @@ mode "move" {
|
|||
}
|
||||
|
||||
bindsym $mod+m mode "move" focus floating
|
||||
# Move & resize windows:1 ends here
|
||||
# Move & resize windows:2 ends here
|
||||
|
||||
# [[file:../../Desktop.org::*Integration with rofi][Integration with rofi:1]]
|
||||
bindsym $mod+d exec "rofi -modi 'drun,run' -show drun"
|
||||
|
|
|
|||
|
|
@ -211,7 +211,8 @@
|
|||
comint
|
||||
git-timemachine
|
||||
magit
|
||||
prodigy)))
|
||||
prodigy
|
||||
slime)))
|
||||
|
||||
(defun minibuffer-keyboard-quit ()
|
||||
"Abort recursive edit.
|
||||
|
|
@ -303,6 +304,7 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
|
|||
"h" 'previous-buffer
|
||||
"k" 'kill-buffer
|
||||
"b" 'persp-ivy-switch-buffer
|
||||
"r" 'revert-buffer
|
||||
"u" 'ibuffer)
|
||||
|
||||
(general-nmap
|
||||
|
|
@ -335,6 +337,72 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
|
|||
(global-set-key (kbd "C-+") 'my/zoom-in)
|
||||
(global-set-key (kbd "C-=") 'my/zoom-out)
|
||||
|
||||
(defmacro i3-msg (&rest args)
|
||||
`(start-process "emacs-i3-windmove" nil "i3-msg" ,@args))
|
||||
|
||||
(add-hook 'after-init-hook #'server-start)
|
||||
|
||||
(defun my/emacs-i3-windmove (dir)
|
||||
(let ((other-window (windmove-find-other-window dir)))
|
||||
(if (or (null other-window) (window-minibuffer-p other-window))
|
||||
(i3-msg "focus" (symbol-name dir))
|
||||
(windmove-do-window-select dir))))
|
||||
|
||||
(defun my/emacs-i3-move-window (dir)
|
||||
(let ((other-window (windmove-find-other-window dir)))
|
||||
(if (null other-window)
|
||||
(i3-msg "move" (symbol-name dir))
|
||||
(window-swap-states (selected-window) other-window))))
|
||||
|
||||
(defun my/emacs-i3-resize-direction-exists-p (dir)
|
||||
(some #'windmove-find-other-window
|
||||
(pcase dir
|
||||
('width '(left right))
|
||||
('height '(up down)))))
|
||||
|
||||
(defun my/emacs-i3-resize-window (dir kind value)
|
||||
(if (or (one-window-p)
|
||||
(not (my/emacs-i3-resize-direction-exists-p dir)))
|
||||
(i3-msg "resize" (symbol-name kind) (symbol-name dir)
|
||||
(format "%s px or %s ppt" value value))
|
||||
(setq value (/ value 2))
|
||||
(pcase kind
|
||||
('shrink
|
||||
(pcase dir
|
||||
('width
|
||||
(evil-window-decrease-width value))
|
||||
('height
|
||||
(evil-window-decrease-height value))))
|
||||
('grow
|
||||
(pcase dir
|
||||
('width
|
||||
(evil-window-increase-width value))
|
||||
('height
|
||||
(evil-window-increase-height value)))))))
|
||||
|
||||
(use-package transpose-frame
|
||||
:straight t
|
||||
:commands (transpose-frame))
|
||||
|
||||
(defun my/emacs-i3-integration (command)
|
||||
(pcase command
|
||||
((rx bos "focus")
|
||||
(my/emacs-i3-windmove
|
||||
(intern (elt (split-string command) 1))))
|
||||
((rx bos "move")
|
||||
(my/emacs-i3-move-window
|
||||
(intern (elt (split-string command) 1))))
|
||||
((rx bos "resize")
|
||||
(my/emacs-i3-resize-window
|
||||
(intern (elt (split-string command) 2))
|
||||
(intern (elt (split-string command) 1))
|
||||
(string-to-number (elt (split-string command) 3))))
|
||||
("layout toggle split" (transpose-frame))
|
||||
("split h" (evil-window-split))
|
||||
("split v" (evil-window-vsplit))
|
||||
("kill" (evil-quit))
|
||||
(- (i3-msg command))))
|
||||
|
||||
(use-package visual-fill-column
|
||||
:straight t
|
||||
:config
|
||||
|
|
@ -2851,6 +2919,12 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
|
|||
;; (add-hook 'emacs-lisp-mode-hook #'smartparens-strict-mode)
|
||||
(add-hook 'emacs-lisp-mode-hook #'lispy-mode)
|
||||
|
||||
(use-package slime
|
||||
:straight t
|
||||
:config
|
||||
(setq inferior-lisp-program "sbcl")
|
||||
(add-hook 'slime-repl-mode 'smartparens-mode))
|
||||
|
||||
(add-hook 'lisp-mode-hook #'aggressive-indent-mode)
|
||||
;; (add-hook 'emacs-lisp-mode-hook #'smartparens-strict-mode)
|
||||
(add-hook 'lisp-mode-hook #'lispy-mode)
|
||||
|
|
|
|||
95
Desktop.org
95
Desktop.org
|
|
@ -283,54 +283,57 @@ bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcu
|
|||
** Managing windows
|
||||
Some keybindings for managing windows.
|
||||
|
||||
=emacs-i3-integration= is a script to pass some command to Emacs to get a consistent set of keybindings in both i3 and Emacs. Check out [[file:Emacs.org::i3 integration][the section in Emacs.org]] for details.
|
||||
|
||||
Kill focused windows
|
||||
#+begin_src conf-space
|
||||
bindsym $mod+Shift+q kill
|
||||
bindsym $mod+Shift+q exec emacs-i3-integration kill
|
||||
#+end_src
|
||||
|
||||
Change focus
|
||||
#+begin_src conf-space
|
||||
bindsym $mod+h focus left
|
||||
bindsym $mod+j focus down
|
||||
bindsym $mod+k focus up
|
||||
bindsym $mod+l focus right
|
||||
bindsym $mod+h exec emacs-i3-integration focus left
|
||||
bindsym $mod+j exec emacs-i3-integration focus down
|
||||
bindsym $mod+k exec emacs-i3-integration focus up
|
||||
bindsym $mod+l exec emacs-i3-integration focus right
|
||||
|
||||
bindsym $mod+Left focus left
|
||||
bindsym $mod+Down focus down
|
||||
bindsym $mod+Up focus up
|
||||
bindsym $mod+Right focus right
|
||||
bindsym $mod+Left exec emacs-i3-integration focus left
|
||||
bindsym $mod+Down exec emacs-i3-integration focus down
|
||||
bindsym $mod+Up exec emacs-i3-integration focus up
|
||||
bindsym $mod+Right exec emacs-i3-integration focus right
|
||||
#+end_src
|
||||
|
||||
Move windows around
|
||||
#+begin_src conf-space
|
||||
bindsym $mod+Shift+h move left
|
||||
bindsym $mod+Shift+j move down
|
||||
bindsym $mod+Shift+k move up
|
||||
bindsym $mod+Shift+l move right
|
||||
bindsym $mod+Shift+h exec emacs-i3-integration move left
|
||||
bindsym $mod+Shift+j exec emacs-i3-integration move down
|
||||
bindsym $mod+Shift+k exec emacs-i3-integration move up
|
||||
bindsym $mod+Shift+l exec emacs-i3-integration move right
|
||||
|
||||
bindsym $mod+Shift+Left move left
|
||||
bindsym $mod+Shift+Down move down
|
||||
bindsym $mod+Shift+Up move up
|
||||
bindsym $mod+Shift+Right move right
|
||||
bindsym $mod+Shift+Left exec emacs-i3-integration move left
|
||||
bindsym $mod+Shift+Down exec emacs-i3-integration move down
|
||||
bindsym $mod+Shift+Up exec emacs-i3-integration move up
|
||||
bindsym $mod+Shift+Right exec emacs-i3-integration move right
|
||||
#+end_src
|
||||
|
||||
Split windows
|
||||
#+begin_src conf-space
|
||||
bindsym $mod+s split h
|
||||
bindsym $mod+v split v
|
||||
bindsym $mod+s exec emacs-i3-integration split h
|
||||
bindsym $mod+v exec emacs-i3-integration split v
|
||||
#+end_src
|
||||
|
||||
Enter fullscreen mode
|
||||
#+begin_src conf-space
|
||||
# enter fullscreen mode for the focused container
|
||||
bindsym $mod+f fullscreen toggle
|
||||
bindsym $mod+c fullscreen toggle global
|
||||
#+end_src
|
||||
|
||||
Changing layout
|
||||
#+begin_src conf-space
|
||||
bindsym $mod+w layout stacking
|
||||
bindsym $mod+t layout tabbed
|
||||
bindsym $mod+e layout toggle split
|
||||
bindsym $mod+e exec emacs-i3-integration layout toggle split
|
||||
#+end_src
|
||||
|
||||
Toggle tiling/floating, switch between tiled and floating windows
|
||||
|
|
@ -518,34 +521,46 @@ bindsym $mod+g mode "inner gaps"
|
|||
bindsym $mod+Shift+g mode "outer gaps"
|
||||
#+end_src
|
||||
** Move & resize windows
|
||||
A more or less standard set of keybindings to move & resize floating windows.
|
||||
| Guix dependency |
|
||||
|-----------------------------|
|
||||
| python-i3-balance-workspace |
|
||||
|
||||
A more or less standard set of keybindings to move & resize floating windows. Just be careful to always make a way to return from these new modes, otherwise you'd end up in a rather precarious situation.
|
||||
|
||||
[[https://github.com/atreyasha/i3-balance-workspace][i3-balance-workspace]] is a small Python package to balance the i3 windows, but for the Emacs integration I also want this button to balance the Emacs windows, so here is a small script to do just that.
|
||||
|
||||
#+begin_src bash :tangle ~/bin/scripts/i3-emacs-balance-windows
|
||||
if [[ $(xdotool getactivewindow getwindowname) =~ ^emacs(:.*)?@.* ]]; then
|
||||
emacsclient -e "(balance-windows)" &
|
||||
fi
|
||||
i3_balance_workspace
|
||||
#+end_src
|
||||
|
||||
Just be careful to always make a way to return from these new modes, otherwise you'd end up in a rather precarious situation.
|
||||
#+begin_src conf-space
|
||||
# resize window (you can also use the mouse for that)
|
||||
mode "resize" {
|
||||
# These bindings trigger as soon as you enter the resize mode
|
||||
|
||||
bindsym h resize shrink width 10 px or 10 ppt
|
||||
bindsym j resize grow height 10 px or 10 ppt
|
||||
bindsym k resize shrink height 10 px or 10 ppt
|
||||
bindsym l resize grow width 10 px or 10 ppt
|
||||
bindsym h exec emacs-i3-integration resize shrink width 10 px or 10 ppt
|
||||
bindsym j exec emacs-i3-integration resize grow height 10 px or 10 ppt
|
||||
bindsym k exec emacs-i3-integration resize shrink height 10 px or 10 ppt
|
||||
bindsym l exec emacs-i3-integration resize grow width 10 px or 10 ppt
|
||||
|
||||
bindsym Shift+h resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+j resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+k resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+l resize grow width 100 px or 100 ppt
|
||||
bindsym Shift+h exec emacs-i3-integration resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+j exec emacs-i3-integration resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+k exec emacs-i3-integration resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+l exec emacs-i3-integration resize grow width 100 px or 100 ppt
|
||||
|
||||
# same bindings, but for the arrow keys
|
||||
bindsym Left resize shrink width 10 px or 10 ppt
|
||||
bindsym Down resize grow height 10 px or 10 ppt
|
||||
bindsym Up resize shrink height 10 px or 10 ppt
|
||||
bindsym Right resize grow width 10 px or 10 ppt
|
||||
bindsym Left exec emacs-i3-integration resize shrink width 10 px or 10 ppt
|
||||
bindsym Down exec emacs-i3-integration resize grow height 10 px or 10 ppt
|
||||
bindsym Up exec emacs-i3-integration resize shrink height 10 px or 10 ppt
|
||||
bindsym Right exec emacs-i3-integration resize grow width 10 px or 10 ppt
|
||||
|
||||
bindsym Shift+Left resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+Down resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+Up resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+Right resize grow width 100 px or 100 ppt
|
||||
bindsym Shift+Left exec emacs-i3-integration resize shrink width 100 px or 100 ppt
|
||||
bindsym Shift+Down exec emacs-i3-integration resize grow height 100 px or 100 ppt
|
||||
bindsym Shift+Up exec emacs-i3-integration resize shrink height 100 px or 100 ppt
|
||||
bindsym Shift+Right exec emacs-i3-integration resize grow width 100 px or 100 ppt
|
||||
|
||||
bindsym equal exec i3-emacs-balance-windows
|
||||
|
||||
# back to normal: Enter or Escape
|
||||
bindsym Return mode "default"
|
||||
|
|
|
|||
112
Emacs.org
112
Emacs.org
|
|
@ -817,6 +817,118 @@ Evil does a pretty good job of uniting these two in the set of vim-like keybindi
|
|||
(global-set-key (kbd "C-+") 'my/zoom-in)
|
||||
(global-set-key (kbd "C-=") 'my/zoom-out)
|
||||
#+end_src
|
||||
** i3 integration
|
||||
I'm a bit jealous of EXWM having a consistent set of keybindings to manage both Emacs windows and X windows, so I figured I could try to implement something like this with i3.
|
||||
|
||||
The basic idea is to launch a normal i3 command with =i3-msg= in case the current window is not Emacs, otherwise pass that command to Emacs with =emacsclient=. In Emacs, execute the command if possible, otherwise pass the command back to i3.
|
||||
|
||||
I actually tried to use EXWM but returned back to i3 because EXWM wasn't snappy enough. While this integration adds some overhead, I can't detect it even in the worst case (i3 -> Emacs -> i3), so the integration feels seamless.
|
||||
|
||||
At any rate, we need a script to do the i3 -> Emacs part:
|
||||
#+begin_src bash :tangle ~/bin/scripts/emacs-i3-integration
|
||||
if [[ $(xdotool getactivewindow getwindowname) =~ ^emacs(:.*)?@.* ]]; then
|
||||
command="(my/emacs-i3-integration \"$@\")"
|
||||
emacsclient -e "$command"
|
||||
else
|
||||
i3-msg $@
|
||||
fi
|
||||
#+end_src
|
||||
|
||||
This script is being run from the [[file:Desktop.org::*i3wm][i3 configuration]].
|
||||
|
||||
For the second part, we need to call i3 from emacs. Here is a simple macro to do just that:
|
||||
#+begin_src emacs-lisp
|
||||
(defmacro i3-msg (&rest args)
|
||||
`(start-process "emacs-i3-windmove" nil "i3-msg" ,@args))
|
||||
#+end_src
|
||||
|
||||
Also, we have to make sure that Emacs starts a server, so here is a hook to do just that:
|
||||
#+begin_src emacs-lisp
|
||||
(add-hook 'after-init-hook #'server-start)
|
||||
#+end_src
|
||||
|
||||
Then we have to handle the required i3 commands. First, for the =focus= command I want to move to the Emacs window in the given direction if there is one, otherwise move to the X window in the same direction. Fortunately, i3 and windmove have the same names for directions, so the function is rather straightforward.
|
||||
|
||||
Also, one caveat here is that the minibuffer is always below, so it is necessary to check for that as well.
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/emacs-i3-windmove (dir)
|
||||
(let ((other-window (windmove-find-other-window dir)))
|
||||
(if (or (null other-window) (window-minibuffer-p other-window))
|
||||
(i3-msg "focus" (symbol-name dir))
|
||||
(windmove-do-window-select dir))))
|
||||
#+end_src
|
||||
|
||||
For the =move= command I want to move the Emacs window in the required direction if there is space in there, otherwise move an X window, which will be the Emacs frame.
|
||||
|
||||
I tried to use =evil-move-window= here, but it doesn't behave quite like i3, for instance, =(evil-move-window 'right)= in a tree-column split would move the window from the far left side to the far right side (bypassing center). =window-swap-states= with a window in the given direction does better.
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/emacs-i3-move-window (dir)
|
||||
(let ((other-window (windmove-find-other-window dir)))
|
||||
(if (null other-window)
|
||||
(i3-msg "move" (symbol-name dir))
|
||||
(window-swap-states (selected-window) other-window))))
|
||||
#+end_src
|
||||
|
||||
Next, =resize grow= and =resize shrink=. To avoid running resize when there is no place to resize to, here is a simple predicate which checks whether there is space in the given direction.
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/emacs-i3-resize-direction-exists-p (dir)
|
||||
(some #'windmove-find-other-window
|
||||
(pcase dir
|
||||
('width '(left right))
|
||||
('height '(up down)))))
|
||||
#+end_src
|
||||
|
||||
Now we can use that to perform the actual resizing. =evil-window-= functions do that nicely.
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/emacs-i3-resize-window (dir kind value)
|
||||
(if (or (one-window-p)
|
||||
(not (my/emacs-i3-resize-direction-exists-p dir)))
|
||||
(i3-msg "resize" (symbol-name kind) (symbol-name dir)
|
||||
(format "%s px or %s ppt" value value))
|
||||
(setq value (/ value 2))
|
||||
(pcase kind
|
||||
('shrink
|
||||
(pcase dir
|
||||
('width
|
||||
(evil-window-decrease-width value))
|
||||
('height
|
||||
(evil-window-decrease-height value))))
|
||||
('grow
|
||||
(pcase dir
|
||||
('width
|
||||
(evil-window-increase-width value))
|
||||
('height
|
||||
(evil-window-increase-height value)))))))
|
||||
#+end_src
|
||||
|
||||
[[https://github.com/emacsorphanage/transpose-frame][transpose-frame]] is a package to "transpose" the current frame layout, which behaves someone similar to the =layout toggle split= command in i3.
|
||||
#+begin_src emacs-lisp
|
||||
(use-package transpose-frame
|
||||
:straight t
|
||||
:commands (transpose-frame))
|
||||
#+end_src
|
||||
|
||||
Finally, an entrypoint for the Emacs integration. In addition to the commands defined above, it processes =split= and =kill= commands and passes every other command back to i3.
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/emacs-i3-integration (command)
|
||||
(pcase command
|
||||
((rx bos "focus")
|
||||
(my/emacs-i3-windmove
|
||||
(intern (elt (split-string command) 1))))
|
||||
((rx bos "move")
|
||||
(my/emacs-i3-move-window
|
||||
(intern (elt (split-string command) 1))))
|
||||
((rx bos "resize")
|
||||
(my/emacs-i3-resize-window
|
||||
(intern (elt (split-string command) 2))
|
||||
(intern (elt (split-string command) 1))
|
||||
(string-to-number (elt (split-string command) 3))))
|
||||
("layout toggle split" (transpose-frame))
|
||||
("split h" (evil-window-split))
|
||||
("split v" (evil-window-vsplit))
|
||||
("kill" (evil-quit))
|
||||
(- (i3-msg command))))
|
||||
#+end_src
|
||||
** Editing helpers
|
||||
*** Visual fill column mode
|
||||
#+begin_src emacs-lisp
|
||||
|
|
|
|||
9
bin/scripts/emacs-i3-integration
Executable file
9
bin/scripts/emacs-i3-integration
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
# [[file:../../Emacs.org::*i3 integration][i3 integration:1]]
|
||||
if [[ $(xdotool getactivewindow getwindowname) =~ ^emacs(:.*)?@.* ]]; then
|
||||
command="(my/emacs-i3-integration \"$@\")"
|
||||
emacsclient -e "$command"
|
||||
else
|
||||
i3-msg $@
|
||||
fi
|
||||
# i3 integration:1 ends here
|
||||
7
bin/scripts/i3-emacs-balance-windows
Executable file
7
bin/scripts/i3-emacs-balance-windows
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
# [[file:../../Desktop.org::*Move & resize windows][Move & resize windows:1]]
|
||||
if [[ $(xdotool getactivewindow getwindowname) =~ ^emacs(:.*)?@.* ]]; then
|
||||
emacsclient -e "(balance-windows)" &
|
||||
fi
|
||||
i3_balance_workspace
|
||||
# Move & resize windows:1 ends here
|
||||
Loading…
Add table
Reference in a new issue