mirror of
https://github.com/SqrtMinusOne/dotfiles.git
synced 2025-12-11 19:45:25 +03:00
feat(exwm): some improvements
This commit is contained in:
parent
a8a2ea0b00
commit
d3f9973d63
2 changed files with 125 additions and 40 deletions
|
|
@ -92,34 +92,72 @@ _=_: Balance "
|
||||||
(defun my/cycle-persp-exwm-buffers (dir)
|
(defun my/cycle-persp-exwm-buffers (dir)
|
||||||
(let* ((current (current-buffer))
|
(let* ((current (current-buffer))
|
||||||
(ignore-rx (persp--make-ignore-buffer-rx))
|
(ignore-rx (persp--make-ignore-buffer-rx))
|
||||||
(exwm-buffers
|
(visible-buffers '())
|
||||||
|
(exwm-data
|
||||||
(cl-loop for buf in (persp-current-buffers)
|
(cl-loop for buf in (persp-current-buffers)
|
||||||
|
for is-another = (and (get-buffer-window buf) (not (eq current buf)))
|
||||||
if (and (buffer-live-p buf)
|
if (and (buffer-live-p buf)
|
||||||
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
|
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
|
||||||
(not (string-match-p ignore-rx (buffer-name buf))))
|
(not (string-match-p ignore-rx (buffer-name buf))))
|
||||||
collect buf))
|
collect buf into all-buffers
|
||||||
(current-pos (or (cl-position current exwm-buffers) -1)))
|
and if (not is-another) collect buf into cycle-buffers
|
||||||
(if (seq-empty-p exwm-buffers)
|
finally (return (list all-buffers cycle-buffers))))
|
||||||
(message "No EXWM buffers!")
|
(all-buffers (nth 0 exwm-data))
|
||||||
(let* ((next-pos (% (+ current-pos (length exwm-buffers)
|
(cycle-buffers (nth 1 exwm-data))
|
||||||
|
(current-pos (or (cl-position current cycle-buffers) -1)))
|
||||||
|
(if (seq-empty-p cycle-buffers)
|
||||||
|
(message "No EXWM buffers to cycle!")
|
||||||
|
(let* ((next-pos (% (+ current-pos (length cycle-buffers)
|
||||||
(if (eq dir 'forward) 1 -1))
|
(if (eq dir 'forward) 1 -1))
|
||||||
(length exwm-buffers)))
|
(length cycle-buffers)))
|
||||||
(next-buffer (nth next-pos exwm-buffers)))
|
(next-buffer (nth next-pos cycle-buffers)))
|
||||||
(switch-to-buffer next-buffer)
|
(switch-to-buffer next-buffer)
|
||||||
(message
|
(message
|
||||||
"%s"
|
"%s"
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (buf)
|
(lambda (buf)
|
||||||
(let ((name (string-replace "EXWM :: " "" (buffer-name buf))))
|
(let ((name (string-replace "EXWM :: " "" (buffer-name buf))))
|
||||||
(if (eq (current-buffer) buf)
|
(cond
|
||||||
(concat
|
((eq (current-buffer) buf)
|
||||||
"["
|
(concat
|
||||||
(propertize name 'face `(foreground-color . ,(doom-color 'yellow)))
|
"["
|
||||||
"]")
|
(propertize name 'face `(foreground-color . ,(doom-color 'yellow)))
|
||||||
(format " %s " name))))
|
"]"))
|
||||||
exwm-buffers
|
((not (member buf cycle-buffers))
|
||||||
|
(concat
|
||||||
|
"["
|
||||||
|
(propertize name 'face `(foreground-color . ,(doom-color 'blue)))
|
||||||
|
"]"))
|
||||||
|
(t (format " %s " name)))))
|
||||||
|
all-buffers
|
||||||
" "))))))
|
" "))))))
|
||||||
|
|
||||||
|
(defun my/add-exwm-buffers-to-current-perspective ()
|
||||||
|
(interactive)
|
||||||
|
(let ((ignore-rx (persp--make-ignore-buffer-rx)))
|
||||||
|
(cl-loop for buf in (buffer-list)
|
||||||
|
if (and (buffer-live-p buf)
|
||||||
|
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
|
||||||
|
(not (string-match-p ignore-rx (buffer-name buf))))
|
||||||
|
do (persp-add-buffer (buffer-name buf)))))
|
||||||
|
|
||||||
|
(defun my/exwm-revive-perspectives ()
|
||||||
|
"Make perspectives in the current frame not killed."
|
||||||
|
(interactive)
|
||||||
|
(let ((to-switch nil))
|
||||||
|
(maphash
|
||||||
|
(lambda (_ v)
|
||||||
|
(setf (persp-killed v) nil)
|
||||||
|
(unless to-switch
|
||||||
|
(setq to-switch v)))
|
||||||
|
(frame-parameter nil 'persp--hash))
|
||||||
|
(when to-switch
|
||||||
|
(persp-switch (persp-name to-switch)))))
|
||||||
|
|
||||||
|
(defun my/exwm-lock ()
|
||||||
|
(interactive)
|
||||||
|
(my/run-in-background "i3lock -f -i /home/pavel/Pictures/lock-wallpaper.png"))
|
||||||
|
|
||||||
(use-package pinentry
|
(use-package pinentry
|
||||||
:straight t
|
:straight t
|
||||||
:after (exwm)
|
:after (exwm)
|
||||||
|
|
|
||||||
97
Desktop.org
97
Desktop.org
|
|
@ -260,13 +260,10 @@ References:
|
||||||
- [[https://github.com/ch11ng/exwm/wiki][EXWM Wiki]]
|
- [[https://github.com/ch11ng/exwm/wiki][EXWM Wiki]]
|
||||||
- [[https://github.com/daviwil/emacs-from-scratch/blob/master/Desktop.org][Emacs From Scratch config]]
|
- [[https://github.com/daviwil/emacs-from-scratch/blob/master/Desktop.org][Emacs From Scratch config]]
|
||||||
|
|
||||||
TODO Look at:
|
|
||||||
- https://github.com/ch11ng/exwm/issues/202
|
|
||||||
|
|
||||||
** Xsession
|
** Xsession
|
||||||
First things first, Emacs has to be launched as a window wanager. On a more conventional system I'd create a .desktop file in some system folder that can be seen by a login manager, but in the case of Guix it's a bit more complicated, because all such folders are not meant to be changed manually.
|
First things first, Emacs has to be launched as a window manager. On a more conventional system, I'd create a .desktop file in some system folder that can be seen by a login manager, but in the case of Guix, it's a bit more complicated, because all such folders are not meant to be changed manually.
|
||||||
|
|
||||||
However, GDM, the login manager that seems to be default on Guix, launches =~/.xsession= on the startup if it's present, which is just fine for my purposes.
|
However, GDM, the login manager that seems to default on Guix, launches =~/.xsession= on the startup if it's present, which is just fine for my purposes.
|
||||||
|
|
||||||
#+begin_src sh :tangle ~/.xsession
|
#+begin_src sh :tangle ~/.xsession
|
||||||
# Source .profile
|
# Source .profile
|
||||||
|
|
@ -304,7 +301,7 @@ I want to launch some apps from EXWM instead of the Xsession file for two purpos
|
||||||
- the app may need to have the entire desktop environment set up
|
- the app may need to have the entire desktop environment set up
|
||||||
- or it may need to be restarted if Emacs is killed.
|
- or it may need to be restarted if Emacs is killed.
|
||||||
|
|
||||||
As of now, these are polybar, feh and shepherd:
|
As of now, these are polybar, feh and, shepherd:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(defun my/exwm-run-polybar ()
|
(defun my/exwm-run-polybar ()
|
||||||
(call-process "~/bin/polybar.sh"))
|
(call-process "~/bin/polybar.sh"))
|
||||||
|
|
@ -331,7 +328,7 @@ A predicate which checks whether there is space in the given direction:
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
And a function to move windows with the following behavior:
|
And a function to move windows with the following behavior:
|
||||||
- if there is space in the required directon, move the Emacs window there;
|
- if there is space in the required direction, move the Emacs window there;
|
||||||
- if there is no space in the required direction, but space in two orthogonal directions, move the Emacs window so that there is no more space in the orthogonal directions;
|
- if there is no space in the required direction, but space in two orthogonal directions, move the Emacs window so that there is no more space in the orthogonal directions;
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(defun my/exwm-move-window (dir)
|
(defun my/exwm-move-window (dir)
|
||||||
|
|
@ -451,41 +448,91 @@ Switch to the opposite monitor.
|
||||||
(exwm-workspace-switch other)))
|
(exwm-workspace-switch other)))
|
||||||
#+end_src
|
#+end_src
|
||||||
** Switching buffers
|
** Switching buffers
|
||||||
A single perspective usually has only a handful of EXWM buffers, so here are functions to cycle them
|
A single perspective usually has only a handful of EXWM buffers, so here is a function to cycle them.
|
||||||
|
|
||||||
|
Those buffers that are visible in another window are highlighted blue and skipped. The current buffer is highlighted yellow.
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(defun my/cycle-persp-exwm-buffers (dir)
|
(defun my/cycle-persp-exwm-buffers (dir)
|
||||||
(let* ((current (current-buffer))
|
(let* ((current (current-buffer))
|
||||||
(ignore-rx (persp--make-ignore-buffer-rx))
|
(ignore-rx (persp--make-ignore-buffer-rx))
|
||||||
(exwm-buffers
|
(visible-buffers '())
|
||||||
|
(exwm-data
|
||||||
(cl-loop for buf in (persp-current-buffers)
|
(cl-loop for buf in (persp-current-buffers)
|
||||||
|
for is-another = (and (get-buffer-window buf) (not (eq current buf)))
|
||||||
if (and (buffer-live-p buf)
|
if (and (buffer-live-p buf)
|
||||||
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
|
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
|
||||||
(not (string-match-p ignore-rx (buffer-name buf))))
|
(not (string-match-p ignore-rx (buffer-name buf))))
|
||||||
collect buf))
|
collect buf into all-buffers
|
||||||
(current-pos (or (cl-position current exwm-buffers) -1)))
|
and if (not is-another) collect buf into cycle-buffers
|
||||||
(if (seq-empty-p exwm-buffers)
|
finally (return (list all-buffers cycle-buffers))))
|
||||||
(message "No EXWM buffers!")
|
(all-buffers (nth 0 exwm-data))
|
||||||
(let* ((next-pos (% (+ current-pos (length exwm-buffers)
|
(cycle-buffers (nth 1 exwm-data))
|
||||||
|
(current-pos (or (cl-position current cycle-buffers) -1)))
|
||||||
|
(if (seq-empty-p cycle-buffers)
|
||||||
|
(message "No EXWM buffers to cycle!")
|
||||||
|
(let* ((next-pos (% (+ current-pos (length cycle-buffers)
|
||||||
(if (eq dir 'forward) 1 -1))
|
(if (eq dir 'forward) 1 -1))
|
||||||
(length exwm-buffers)))
|
(length cycle-buffers)))
|
||||||
(next-buffer (nth next-pos exwm-buffers)))
|
(next-buffer (nth next-pos cycle-buffers)))
|
||||||
(switch-to-buffer next-buffer)
|
(switch-to-buffer next-buffer)
|
||||||
(message
|
(message
|
||||||
"%s"
|
"%s"
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (buf)
|
(lambda (buf)
|
||||||
(let ((name (string-replace "EXWM :: " "" (buffer-name buf))))
|
(let ((name (string-replace "EXWM :: " "" (buffer-name buf))))
|
||||||
(if (eq (current-buffer) buf)
|
(cond
|
||||||
(concat
|
((eq (current-buffer) buf)
|
||||||
"["
|
(concat
|
||||||
(propertize name 'face `(foreground-color . ,(doom-color 'yellow)))
|
"["
|
||||||
"]")
|
(propertize name 'face `(foreground-color . ,(doom-color 'yellow)))
|
||||||
(format " %s " name))))
|
"]"))
|
||||||
exwm-buffers
|
((not (member buf cycle-buffers))
|
||||||
|
(concat
|
||||||
|
"["
|
||||||
|
(propertize name 'face `(foreground-color . ,(doom-color 'blue)))
|
||||||
|
"]"))
|
||||||
|
(t (format " %s " name)))))
|
||||||
|
all-buffers
|
||||||
" "))))))
|
" "))))))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
** Add all EXWM buffers to current perspective
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun my/add-exwm-buffers-to-current-perspective ()
|
||||||
|
(interactive)
|
||||||
|
(let ((ignore-rx (persp--make-ignore-buffer-rx)))
|
||||||
|
(cl-loop for buf in (buffer-list)
|
||||||
|
if (and (buffer-live-p buf)
|
||||||
|
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
|
||||||
|
(not (string-match-p ignore-rx (buffer-name buf))))
|
||||||
|
do (persp-add-buffer (buffer-name buf)))))
|
||||||
|
#+end_src
|
||||||
|
** Revive perspectives
|
||||||
|
Occasionally the current perspective gets screwed up after a popup. This function attempts to fix it.
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun my/exwm-revive-perspectives ()
|
||||||
|
"Make perspectives in the current frame not killed."
|
||||||
|
(interactive)
|
||||||
|
(let ((to-switch nil))
|
||||||
|
(maphash
|
||||||
|
(lambda (_ v)
|
||||||
|
(setf (persp-killed v) nil)
|
||||||
|
(unless to-switch
|
||||||
|
(setq to-switch v)))
|
||||||
|
(frame-parameter nil 'persp--hash))
|
||||||
|
(when to-switch
|
||||||
|
(persp-switch (persp-name to-switch)))))
|
||||||
|
#+end_src
|
||||||
|
** Locking up
|
||||||
|
Run i3lock.
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun my/exwm-lock ()
|
||||||
|
(interactive)
|
||||||
|
(my/run-in-background "i3lock -f -i /home/pavel/Pictures/lock-wallpaper.png"))
|
||||||
|
#+end_src
|
||||||
** Keybindings
|
** Keybindings
|
||||||
Setting keybindings for EXWM. This actually has to be in the =:config= block of the =use-package= form, that is it has to be run after EXWM is loaded, so I use noweb to put this block in a correct place.
|
Setting keybindings for EXWM. This actually has to be in the =:config= block of the =use-package= form, that is it has to be run after EXWM is loaded, so I use noweb to put this block in the correct place.
|
||||||
|
|
||||||
First, some prefixes for keybindings that are always passed to EXWM instead of the X application in =line-mode=:
|
First, some prefixes for keybindings that are always passed to EXWM instead of the X application in =line-mode=:
|
||||||
#+begin_src emacs-lisp :tangle no :noweb-ref exwm-keybindings
|
#+begin_src emacs-lisp :tangle no :noweb-ref exwm-keybindings
|
||||||
|
|
@ -595,7 +642,7 @@ And keybindings that are available in both =char-mode= and =line-mode=:
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Pinentry
|
** Pinentry
|
||||||
The GUI pinentry doesn't work too well with EXWM because of the popup windows, so we will the the built-in Emacs pinentry.
|
The GUI pinentry doesn't work too well with EXWM because of issues with popup windows, so we will use the Emacs one.
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package pinentry
|
(use-package pinentry
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue