spacepaste

  1.  
  2. ;;; EXWM
  3. ;;; REVIEW: Athena+Xaw3d confuses xcape when binding Caps-lock to both L_Ctrl
  4. ;;; escape, in which case it will procude <C-escape> in Emacs. In practice, it
  5. ;;; means that `C-` keys will works but `<escape>` will need a fast double tap
  6. ;;; on Caps Lock.
  7. ;;;
  8. ;;; See https://github.com/ch11ng/exwm/issues/285
  9. ;;; and https://gitlab.com/interception/linux/plugins/caps2esc/issues/2.
  10. ;;; Rename buffer to window title.
  11. (defun exwm-rename-buffer-to-title () (exwm-workspace-rename-buffer exwm-title))
  12. (add-hook 'exwm-update-title-hook 'exwm-rename-buffer-to-title)
  13. (add-hook 'exwm-floating-setup-hook 'exwm-layout-hide-mode-line)
  14. (add-hook 'exwm-floating-exit-hook 'exwm-layout-show-mode-line)
  15. ;;; Allow non-floating resizing with mouse.
  16. (setq window-divider-default-bottom-width 2
  17. window-divider-default-right-width 2)
  18. (window-divider-mode)
  19. ;;; send all keypresses to emacs in line mode
  20. (setq exwm-input-line-mode-passthrough t)
  21. ;;; make exwm windows default to char instead of line mode
  22. (add-hook 'exwm-manage-finish-hook
  23. (lambda () (call-interactively #'exwm-input-release-keyboard)
  24. (exwm-layout-hide-mode-line)))
  25. (defun exwm-input-line-mode ()
  26. "Set exwm window to line-mode and show mode line"
  27. (call-interactively #'exwm-input-grab-keyboard)
  28. (exwm-layout-show-mode-line))
  29. (defun exwm-input-char-mode ()
  30. "Set exwm window to char-mode and hide mode line"
  31. (call-interactively #'exwm-input-release-keyboard)
  32. (exwm-layout-hide-mode-line))
  33. (require 'cl)
  34. (defun exwm-input-toggle-mode ()
  35. "Toggle between line- and char-mode"
  36. (with-current-buffer (window-buffer)
  37. (when (eq major-mode 'exwm-mode)
  38. (if (equal (second (second mode-line-process)) "line")
  39. (exwm-input-char-mode)
  40. (exwm-input-line-mode)))))
  41. (exwm-input-set-key (kbd "s-i")
  42. (lambda () (interactive)
  43. (exwm-input-toggle-mode)))
  44. ;;; System tray
  45. (require 'exwm-systemtray)
  46. (exwm-systemtray-enable)
  47. (setq exwm-systemtray-height 16)
  48. ;;; Those cannot be set globally: if Emacs would be run in another WM, the "s-"
  49. ;;; prefix will conflict with the WM bindings.
  50. (exwm-input-set-key (kbd "s-R") #'exwm-reset)
  51. (exwm-input-set-key (kbd "s-x") #'exwm-input-toggle-keyboard)
  52. (exwm-input-set-key (kbd "s-h") #'windmove-left)
  53. (exwm-input-set-key (kbd "s-j") #'windmove-down)
  54. (exwm-input-set-key (kbd "s-k") #'windmove-up)
  55. (exwm-input-set-key (kbd "s-l") #'windmove-right)
  56. (exwm-input-set-key (kbd "s-d") #'delete-window)
  57. (exwm-input-set-key (kbd "s-D") #'kill-this-buffer)
  58. (exwm-input-set-key (kbd "s-b") #'ivy-switch-buffer)
  59. (exwm-input-set-key (kbd "s-f") #'find-file)
  60. (exwm-input-set-key (kbd "s-M") #'exwm-floating-toggle-floating)
  61. (exwm-input-set-key (kbd "s-C") #'ivy-resume)
  62. (exwm-input-set-key (kbd "s-f") #'counsel-find-file)
  63. (exwm-input-set-key (kbd "s-g") #'counsel-ag)
  64. (exwm-input-set-key (kbd "s-c") #'counsel-grep-or-swiper)
  65. (defun exwm-layout-toggle-fullscreen-or-single-window ()
  66. (interactive)
  67. (if (eq major-mode 'exwm-mode)
  68. (call-interactively 'exwm-layout-toggle-fullscreen)
  69. (require 'functions)
  70. (toggle-single-window)))
  71. (exwm-input-set-key (kbd "s-O") #'exwm-layout-toggle-fullscreen-or-single-window)
  72. (defvar single-window--last-configuration nil "Last window configuration before calling `delete-other-windows'.")
  73. (defun toggle-single-window ()
  74. "Un-maximize current window.
  75. If multiple windows are active, save window configuration and
  76. delete other windows. If only one window is active and a window
  77. configuration was previously save, restore that configuration."
  78. (interactive)
  79. (if (= (count-windows) 1)
  80. (when single-window--last-configuration
  81. (set-window-configuration single-window--last-configuration))
  82. (setq single-window--last-configuration (current-window-configuration))
  83. (delete-other-windows)))
  84. ;; 's-SPC': Launch application
  85. (exwm-input-set-key (kbd "s-SPC")
  86. (lambda (command)
  87. (interactive (list (read-shell-command "$ ")))
  88. (start-process-shell-command command nil command)))
  89. ;; split windows
  90. (defun toggle-window-split ()
  91. "Switch between vertical and horizontal split.
  92. It only works for frames with exactly two windows."
  93. (interactive)
  94. (if (= (count-windows) 2)
  95. (let* ((this-win-buffer (window-buffer))
  96. (next-win-buffer (window-buffer (next-window)))
  97. (this-win-edges (window-edges (selected-window)))
  98. (next-win-edges (window-edges (next-window)))
  99. (this-win-2nd (not (and (<= (car this-win-edges)
  100. (car next-win-edges))
  101. (<= (cadr this-win-edges)
  102. (cadr next-win-edges)))))
  103. (splitter
  104. (if (= (car this-win-edges)
  105. (car (window-edges (next-window))))
  106. 'split-window-horizontally
  107. 'split-window-vertically)))
  108. (delete-other-windows)
  109. (let ((first-win (selected-window)))
  110. (funcall splitter)
  111. (if this-win-2nd (other-window 1))
  112. (set-window-buffer (selected-window) this-win-buffer)
  113. (set-window-buffer (next-window) next-win-buffer)
  114. (select-window first-win)
  115. (if this-win-2nd (other-window 1))))))
  116. (exwm-input-set-key (kbd "s-\\") #'toggle-window-split)
  117. (defun switch-to-last-buffer ()
  118. "Switch to last open buffer in current window."
  119. (interactive)
  120. (switch-to-buffer (other-buffer (current-buffer) 1)))
  121. (exwm-input-set-key (kbd "s-<tab>") #'switch-to-last-buffer)
  122. ;;; Emacs mode shortcuts.
  123. (exwm-input-set-key (kbd "s-t") #'org-find-first-agenda)
  124. ;;; TODO: (exwm-input-set-key (kbd "s-<return>") #'eshell-or-new-session)
  125. (exwm-input-set-key (kbd "s-<return>") #'eshell)
  126. (when (fboundp 'magit-status)
  127. (exwm-input-set-key (kbd "s-v") #'magit-status))
  128. (when (fboundp 'emms-all)
  129. (exwm-input-set-key (kbd "s-a") #'emms-smart-browse)
  130. (exwm-input-set-key (kbd "s-A") #'emms))
  131. (when (delq nil (mapcar (lambda (path) (string-match "/mu4e/\\|/mu4e$" path)) load-path))
  132. (exwm-input-set-key (kbd "s-m") #'mu4e-headers))
  133. (defvar exwm-lock-program "slock" "Shell command used to lock the screen.")
  134. (defun exwm-start-lock () (interactive) (start-process-shell-command exwm-lock-program nil exwm-lock-program))
  135. (exwm-input-set-key (kbd "s-z") #'exwm-start-lock)
  136. (defun exwm-start-screenshot () (interactive) (start-process-shell-command "scrot" nil "scrot ~/temp/screen-%F-%T.png"))
  137. (exwm-input-set-key (kbd "<print>") #'exwm-start-screenshot)
  138. ;;; TODO: Check out the 'volume' package.
  139. (defun exwm-volume (&optional up-or-down)
  140. (let ((controllers '(("amixer" . ((control . "set Master") (down . "5%-") (up . "5%+") (toggle . "toggle")))
  141. ("mixer" . ((control . "vol") (down . "-5") (up . "+5") (toggle . "^"))))))
  142. (while (not (executable-find (caar controllers)))
  143. (setq controllers (cdr controllers)))
  144. (when controllers
  145. (start-process-shell-command
  146. "volume control" nil (format "%s %s %s >/dev/null"
  147. (caar controllers)
  148. (alist-get 'control (cdar controllers))
  149. (alist-get up-or-down (cdar controllers) (alist-get 'toggle (cdar controllers) )))))))
  150. (defun exwm-start-volume-down () (interactive) (exwm-volume 'down))
  151. (defun exwm-start-volume-up () (interactive) (exwm-volume 'up))
  152. (defun exwm-start-volume-toggle () (interactive) (exwm-volume))
  153. (exwm-input-set-key (kbd "s-<kp-subtract>") #'exwm-start-volume-down)
  154. (exwm-input-set-key (kbd "s-<kp-add>") #'exwm-start-volume-up)
  155. (exwm-input-set-key (kbd "s-<kp-enter>") #'exwm-start-volume-toggle)
  156. (provide 'init-exwm)
  157. (exwm-enable)
  158.