summaryrefslogtreecommitdiffstats
path: root/.emacs.d/lisp/bandali-exwm.el
diff options
context:
space:
mode:
authorAmin Bandali <bandali@kelar.org>2025-01-30 22:55:32 -0500
committerAmin Bandali <bandali@kelar.org>2025-01-30 22:55:32 -0500
commitc7b47e03e0ac16d6db84d59d8cff58291b22fbaa (patch)
tree64997f5e10d25897966d496d905aa6ff835f5f94 /.emacs.d/lisp/bandali-exwm.el
parent563fb78037f21c6503c6489758e8f0d86173bb7e (diff)
downloadconfigs-c7b47e03e0ac16d6db84d59d8cff58291b22fbaa.tar.gz
configs-c7b47e03e0ac16d6db84d59d8cff58291b22fbaa.tar.xz
configs-c7b47e03e0ac16d6db84d59d8cff58291b22fbaa.zip
Break out .emacs.d/init.el into .emacs.d/lisp/bandali-*.el again
Having used the monolithic init.el approach, I found it somewhat unwieldy, especially as the file grows larger and larger.
Diffstat (limited to '.emacs.d/lisp/bandali-exwm.el')
-rw-r--r--.emacs.d/lisp/bandali-exwm.el301
1 files changed, 301 insertions, 0 deletions
diff --git a/.emacs.d/lisp/bandali-exwm.el b/.emacs.d/lisp/bandali-exwm.el
new file mode 100644
index 0000000..d8e285a
--- /dev/null
+++ b/.emacs.d/lisp/bandali-exwm.el
@@ -0,0 +1,301 @@
+;;; bandali-exwm.el --- bandali's EXWM configuration -*- lexical-binding: t; -*-
+
+;; Copyright (c) 2018-2024 Amin Bandali <bandali@gnu.org>
+
+;; Author: Amin Bandali <bandali@gnu.org>
+;; Keywords: tools
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; My EXWM setup. Makes good use of its simulation keys.
+
+;;; Code:
+
+(when (and
+ (display-graphic-p)
+ ;; we're not running in another WM/DE
+ (not (or
+ (getenv "XDG_CURRENT_DESKTOP")
+ (getenv "WAYLAND_DISPLAY")))
+ (member (system-name) '("adelita")))
+ (add-to-list 'load-path (b/emacs.d "lisp/xelb"))
+ (add-to-list 'load-path (b/emacs.d "lisp/exwm"))
+ (require 'exwm)
+
+ (global-set-key (kbd "C-x b") #'exwm-workspace-switch-to-buffer)
+
+ (menu-bar-mode -1)
+ (tool-bar-mode -1)
+
+ (defun b/exwm-rename-buffer ()
+ "Make class name the buffer name, truncating beyond 60 characters."
+ (interactive)
+ (exwm-workspace-rename-buffer
+ (concat exwm-class-name ":"
+ (if (<= (length exwm-title) 60) exwm-title
+ (concat (substring exwm-title 0 59) "...")))))
+
+ (defvar b/shifted-ws-names
+ '(0 \) 1 \! 2 \@ 3 \# 4 \$
+ 5 \% 6 \^ 7 \& 8 \* 9 \()
+ "Mapping of shifted numbers on my keyboard.")
+
+ (setq
+ ;; Initial number of workspaces
+ exwm-workspace-number 4
+ ;; Global keybindings
+ exwm-input-global-keys
+ `(([?\s-r] . exwm-reset) ; Reset (to line-mode)
+ ([?\s-/] . exwm-workspace-switch)
+ ([?\s-\s] . (lambda (command)
+ (interactive (list (read-shell-command "$ ")))
+ (start-process-shell-command command nil command)))
+ ([?\s-\\] . (lambda ()
+ (interactive)
+ (start-process-shell-command
+ "passmenu" nil "passmenu --type")))
+ ([s-return] . (lambda ()
+ (interactive)
+ (start-process "" nil "xterm")))
+ ([S-s-return] . (lambda ()
+ (interactive)
+ (start-process "" nil "xterm"
+ "-name" "floating")))
+ ([?\s-h] . windmove-left)
+ ([?\s-j] . windmove-down)
+ ([?\s-k] . windmove-up)
+ ([?\s-l] . windmove-right)
+ ([?\s-H] . windmove-swap-states-left)
+ ([?\s-J] . windmove-swap-states-down)
+ ([?\s-K] . windmove-swap-states-up)
+ ([?\s-L] . windmove-swap-states-right)
+ ([?\M-\s-h] . shrink-window-horizontally)
+ ([?\M-\s-l] . enlarge-window-horizontally)
+ ([?\M-\s-k] . shrink-window)
+ ([?\M-\s-j] . enlarge-window)
+ ([mode-line mouse-4] . b/exwm-ws-prev) ; up
+ ([mode-line mouse-5] . b/exwm-ws-next) ; down
+ ([mode-line mouse-6] . b/exwm-ws-prev) ; left
+ ([mode-line mouse-7] . b/exwm-ws-next) ; right
+ ([?\s-\[] . b/exwm-ws-prev)
+ ([?\s-\]] . b/exwm-ws-next)
+ ([?\s-{] . (lambda ()
+ (interactive)
+ (exwm-workspace-move-window
+ (b/exwm-ws-prev-index))))
+ ([?\s-}] . (lambda ()
+ (interactive)
+ (exwm-workspace-move-window
+ (b/exwm-ws-next-index))))
+ ,@(mapcar (lambda (i)
+ `(,(kbd (format "s-%d" i)) .
+ (lambda ()
+ (interactive)
+ (exwm-workspace-switch-create ,i))))
+ (number-sequence 0 (1- exwm-workspace-number)))
+ ,@(mapcar
+ (lambda (i)
+ `(,(kbd (format "s-%s"
+ (plist-get b/shifted-ws-names i)))
+ .
+ (lambda ()
+ (interactive)
+ (exwm-workspace-move-window ,i))))
+ (number-sequence 0 (1- exwm-workspace-number)))
+ ([?\s-.] . exwm-floating-toggle-floating)
+ ([?\s-f] . exwm-layout-toggle-fullscreen)
+ ([?\s-W] . (lambda ()
+ (interactive)
+ (kill-buffer (current-buffer))))
+ ([?\s-Q] . (lambda ()
+ (interactive)
+ (exwm-manage--kill-client)))
+ ([?\s-\'] . (lambda ()
+ (interactive)
+ (start-process-shell-command
+ "dmneu-light" nil "dmenu-light")))
+ ([\s-XF86Back] . previous-buffer)
+ ([\s-XF86Forward] . next-buffer))
+ ;; Line-editing shortcuts
+ exwm-input-simulation-keys
+ '(;; movement
+ ([?\C-b] . [left])
+ ([?\M-b] . [C-left])
+ ([?\C-f] . [right])
+ ([?\M-f] . [C-right])
+ ([?\C-p] . [up])
+ ([?\C-n] . [down])
+ ([?\C-a] . [home])
+ ([?\C-e] . [end])
+ ([?\M-v] . [prior])
+ ([?\C-v] . [next])
+ ([?\C-d] . [delete])
+ ([?\C-k] . [S-end delete])
+ ([?\M-<] . C-home)
+ ([?\M->] . C-end)
+ ;; cut/copy/paste
+ ([?\C-w] . [?\C-x])
+ ([?\M-w] . [?\C-c])
+ ([?\C-y] . [?\C-v])
+ ([?\M-d] . [C-S-right ?\C-x])
+ ([?\M-\d] . [C-S-left ?\C-x])
+ ;; closing/quite
+ ([?\s-w] . [?\C-w])
+ ([?\s-q] . [?\C-q])
+ ;; misc
+ ([?\C-s] . [?\C-f])
+ ([?\s-g] . [?\C-g])
+ ([?\s-s] . [?\C-s])
+ ([?\C-g] . [escape])
+ ([?\C-/] . [?\C-z])))
+
+ (with-eval-after-load 'exwm-manage
+ (setq
+ exwm-manage-configurations
+ '(((equal exwm-instance-name "floating")
+ floating t
+ floating-mode-line nil)))
+ (add-hook
+ 'exwm-manage-finish-hook
+ (lambda ()
+ (when exwm-class-name
+ (cond
+ ((member exwm-class-name '("Abrowser" "IceCat" "Firefox-esr"))
+ (exwm-input-set-local-simulation-keys
+ `(,@exwm-input-simulation-keys
+ ([?\C-\S-d] . [?\C-d]))))
+ ((member exwm-class-name '("XTerm" "Mate-terminal"))
+ (exwm-input-set-local-simulation-keys
+ '(([?\C-c ?\C-c] . [?\C-c])
+ ([?\C-c ?\C-u] . [?\C-u]))))
+ ((string= exwm-class-name "Zathura")
+ (exwm-input-set-local-simulation-keys
+ '(([?\C-p] . [C-up])
+ ([?\C-n] . [C-down])))))))))
+
+ ;; Enable EXWM
+ (exwm-enable)
+ (add-hook 'exwm-update-class-hook #'b/exwm-rename-buffer)
+ (add-hook 'exwm-update-title-hook #'b/exwm-rename-buffer)
+
+ (defun b/fix-ido-buffer-window-other-frame ()
+ "Fix `ido-buffer-window-other-frame'."
+ (defalias 'b/ido-buffer-window-other-frame-orig
+ (symbol-function 'ido-buffer-window-other-frame))
+ (defun ido-buffer-window-other-frame (buffer)
+ "This is a version redefined for EXWM.
+
+The original one is at `b/ido-buffer-window-other-frame-orig'."
+ (with-current-buffer (window-buffer (selected-window))
+ (if (and (derived-mode-p 'exwm-mode)
+ exwm--floating-frame)
+ ;; Switch from a floating frame.
+ (with-current-buffer buffer
+ (if (and (derived-mode-p 'exwm-mode)
+ exwm--floating-frame
+ (eq exwm--frame exwm-workspace--current))
+ ;; Switch to another floating frame.
+ (frame-root-window exwm--floating-frame)
+ ;; Do not switch if the buffer is not on the current workspace.
+ (or (get-buffer-window buffer exwm-workspace--current)
+ (selected-window))))
+ (with-current-buffer buffer
+ (when (derived-mode-p 'exwm-mode)
+ (if (eq exwm--frame exwm-workspace--current)
+ (when exwm--floating-frame
+ ;; Switch to a floating frame on the current workspace.
+ (frame-selected-window exwm--floating-frame))
+ ;; Do not switch to exwm-mode buffers on other workspace (which
+ ;; won't work unless `exwm-layout-show-all-buffers' is set)
+ (unless exwm-layout-show-all-buffers
+ (selected-window)))))))))
+ (add-hook 'exwm-init-hook #'b/fix-ido-buffer-window-other-frame)
+
+ (require 'exwm-input)
+ (defun b/exwm-ws-prev-index ()
+ "Return the index for the previous EXWM workspace, wrapping
+around if needed."
+ (if (= exwm-workspace-current-index 0)
+ (1- exwm-workspace-number)
+ (1- exwm-workspace-current-index)))
+
+ (defun b/exwm-ws-next-index ()
+ "Return the index for the next EXWM workspace, wrapping
+around if needed."
+ (if (= exwm-workspace-current-index
+ (1- exwm-workspace-number))
+ 0
+ (1+ exwm-workspace-current-index)))
+
+ (defun b/exwm-ws-prev ()
+ "Switch to previous EXWM workspace, wrapping around if needed."
+ (interactive)
+ (exwm-workspace-switch-create
+ (b/exwm-ws-prev-index)))
+
+ (defun b/exwm-ws-next ()
+ "Switch to next EXWM workspace, wrapping around if needed."
+ (interactive)
+ (exwm-workspace-switch-create
+ (b/exwm-ws-next-index)))
+
+ ;; Shorten 'C-c C-q' to 'C-q'
+ (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
+
+ ;; Scroll up/down/left/right on the echo area
+ (define-key minibuffer-inactive-mode-map [mouse-4] #'b/exwm-ws-prev)
+ (define-key minibuffer-inactive-mode-map [mouse-5] #'b/exwm-ws-next)
+ (define-key minibuffer-inactive-mode-map [mouse-6] #'b/exwm-ws-prev)
+ (define-key minibuffer-inactive-mode-map [mouse-7] #'b/exwm-ws-next)
+
+ ;; (require 'exwm-randr)
+ ;; (setq
+ ;; exwm-randr-workspace-monitor-plist
+ ;; '(0 "eDP-1"
+ ;; 1 "eDP-1" 2 "eDP-1" 3 "eDP-1"
+ ;; 4 "eDP-1" 5 "eDP-1" 6 "eDP-1"
+ ;; 7 "HDMI-1" 8 "HDMI-1" 9 "HDMI-1"))
+ ;; ;; (add-hook
+ ;; ;; 'exwm-randr-screen-change-hook
+ ;; ;; (lambda ()
+ ;; ;; (start-process-shell-command
+ ;; ;; "xrandr" nil
+ ;; ;; "xrandr --output HDMI-1 --mode 1280x720 --above eDP-1 --auto")))
+ ;; (exwm-randr-enable)
+
+ (require 'exwm-systemtray)
+ (exwm-systemtray-enable)
+
+ ;; (add-to-list 'load-path (b/lisp "exwm-edit"))
+ ;; (require 'exwm-edit)
+
+ (with-eval-after-load 'exwm-workspace
+ (setq exwm-workspace-show-all-buffers t)
+ ;; Display current EXWM workspace in mode-line
+ (setq-default
+ mode-line-format
+ (append
+ mode-line-format
+ '((:eval
+ (format
+ " [%s]" (number-to-string
+ exwm-workspace-current-index)))))))
+
+ (with-eval-after-load 'exwm-layout
+ (setq exwm-layout-show-all-buffers t)))
+
+(provide 'bandali-exwm)
+;;; bandali-exwm.el ends here