dkellner-exwm.el 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. ;;; dkellner-exwm.el --- EXWM configuration
  2. (defun dkellner/run (command)
  3. "Run COMMAND."
  4. (interactive (list (read-shell-command "$ ")))
  5. (start-process-shell-command command nil command))
  6. ;; from https://github.com/dakra/dmacs
  7. (defun dkellner/exwm-bind-keys (&rest bindings)
  8. "Like exwm-input-set-key but syntax similar to bind-keys.
  9. Define keybindings that work in exwm and non-exwm buffers.
  10. Only works *before* exwm in initialized."
  11. (pcase-dolist (`(,key . ,fun) bindings)
  12. (add-to-list 'exwm-input-global-keys `(,(kbd key) . ,fun))))
  13. (use-package exwm
  14. :demand t
  15. :bind (:map exwm-mode-map
  16. ("C-q" . #'exwm-input-send-next-key)
  17. ("s-i" . #'exwm-input-toggle-keyboard)
  18. ("s-SPC" . #'exwm-layout-toggle-fullscreen)
  19. ("s-F" . #'exwm-floating-toggle-fullscreen)
  20. ("M-y" . #'dkellner/exwm-counsel-yank-pop))
  21. :config
  22. ;; Workspaces
  23. (setq exwm-workspace-number 10
  24. exwm-workspace-show-all-buffers t
  25. exwm-layout-show-all-buffers t)
  26. (dotimes (i 10)
  27. (exwm-input-set-key (kbd (format "s-%d" i))
  28. `(lambda ()
  29. (interactive)
  30. (exwm-workspace-switch-create ,i))))
  31. (require 'exwm-randr)
  32. (setq exwm-randr-workspace-output-plist '(1 "HDMI1" 2 "HDMI1"
  33. 3 "HDMI1" 4 "HDMI1"
  34. 5 "HDMI1"))
  35. (exwm-randr-enable)
  36. ;; Global keybindings
  37. ;; TODO: swap-windows
  38. (dkellner/exwm-bind-keys
  39. '("s-b" . ivy-switch-buffer)
  40. '("s-q" . exwm-reset)
  41. '("s-x" . dkellner/run)
  42. '("s-<return>" . dkellner/new-eshell)
  43. '("s-f" . dkellner/browse/body)
  44. '("s-p" . (lambda () (interactive)
  45. (dkellner/run "~/dev/passman/passman submitform")))
  46. '("s-P" . (lambda () (interactive)
  47. (dkellner/run "~/dev/passman/passman onlypw submitform")))
  48. '("s-Z" . (lambda () (interactive) (dkellner/run "dm-tool lock")))
  49. '("s-n" . windmove-left)
  50. '("s-t" . windmove-right)
  51. '("s-g" . windmove-up)
  52. '("s-r" . windmove-down)
  53. '("s-N" . (lambda () (interactive) (shrink-window-horizontally 2)))
  54. '("s-T" . (lambda () (interactive) (enlarge-window-horizontally 2)))
  55. '("s-Q" . dkellner/shutdown-or-reboot/body)
  56. '("<XF86MonBrightnessUp>" . (lambda () (interactive)
  57. (dkellner/run "~/hacks/backlightctl.sh inc")))
  58. '("<XF86MonBrightnessDown>" . (lambda () (interactive)
  59. (dkellner/run "~/hacks/backlightctl.sh dec")))
  60. '("<XF86AudioRaiseVolume>" . (lambda () (interactive)
  61. (dkellner/run "~/hacks/volumectl.sh inc")))
  62. '("<XF86AudioLowerVolume>" . (lambda () (interactive)
  63. (dkellner/run "~/hacks/volumectl.sh dec")))
  64. '("<XF86AudioMute>" . (lambda () (interactive)
  65. (dkellner/run "~/hacks/volumectl.sh toggle")))
  66. '("<XF86AudioMicMute>" . (lambda () (interactive)
  67. (dkellner/run "~/hacks/volumectl.sh mic_toggle"))))
  68. ;; Input simulation
  69. (add-to-list 'exwm-input-prefix-keys ?\C-p) ; Projectile
  70. (setq exwm-input-simulation-keys
  71. '(([?\M-<] . [home])
  72. ([?\M->] . [end])
  73. ([?\C-k] . [S-end ?\C-x])
  74. ([?\C-w] . [?\C-x])
  75. ([?\C-s] . [?\C-f])
  76. ([?\C-g] . [esc])
  77. ([?\C-x ?\C-s] . [?\C-s])
  78. ([?\M-w] . [?\C-c])
  79. ([?\C-y] . [?\C-v])))
  80. ;; Hooks
  81. (add-hook 'exwm-update-class-hook #'dkellner/exwm-update-class-hook)
  82. (add-hook 'exwm-update-title-hook #'dkellner/exwm-update-title-hook)
  83. ;; Misc
  84. (require 'exwm-systemtray)
  85. (exwm-systemtray-enable)
  86. (use-package exwm-edit)
  87. ;; see https://github.com/ch11ng/exwm/wiki#an-issue-with-ediff-mode-in-magit
  88. (setq ediff-window-setup-function 'ediff-setup-windows-plain))
  89. ;; from https://github.com/dakra/dmacs
  90. (defun dkellner/exwm-counsel-yank-pop ()
  91. "Same as `counsel-yank-pop' and paste into exwm buffer."
  92. (interactive)
  93. (let ((inhibit-read-only t)
  94. ;; Make sure we send selected yank-pop candidate to
  95. ;; clipboard:
  96. (yank-pop-change-selection t))
  97. (call-interactively #'counsel-yank-pop))
  98. (when (derived-mode-p 'exwm-mode)
  99. (exwm-input--set-focus (exwm--buffer->id (window-buffer (selected-window))))
  100. (exwm-input--fake-key ?\C-v)))
  101. (defun dkellner/exwm-update-class-hook ()
  102. (unless (dkellner/exwm-use-title-for-buffer-name)
  103. (exwm-workspace-rename-buffer exwm-class-name)))
  104. (defun dkellner/exwm-update-title-hook ()
  105. (when (or (not exwm-instance-name)
  106. (dkellner/exwm-use-title-for-buffer-name))
  107. (exwm-workspace-rename-buffer exwm-title)))
  108. (defun dkellner/exwm-use-title-for-buffer-name ()
  109. (or (string-prefix-p "sun-awt-X11-" exwm-instance-name)
  110. (string= "gimp" exwm-instance-name)
  111. (string= "Navigator" exwm-instance-name)
  112. (string= "gajim" exwm-instance-name)))
  113. (defhydra dkellner/shutdown-or-reboot (:exit t)
  114. "Shutdown/reboot?"
  115. ("s" #'dkellner/shutdown "shutdown")
  116. ("r" #'dkellner/reboot "reboot"))
  117. (defun dkellner/shutdown ()
  118. "Clock out, save buffers and shutdown."
  119. (interactive)
  120. (dkellner/prepare-exit)
  121. (dkellner/run "shutdown -h now"))
  122. (defun dkellner/reboot ()
  123. "Save buffers and reboot."
  124. (interactive)
  125. (dkellner/prepare-exit)
  126. (dkellner/run "shutdown -r now"))
  127. (defun dkellner/prepare-exit ()
  128. (when (org-clock-is-active)
  129. (org-clock-out))
  130. (save-some-buffers)
  131. (recentf-save-list))
  132. (defhydra dkellner/browse (:exit t)
  133. "Browse"
  134. ("o" #'browse-url "url")
  135. ("b" #'dkellner/open-browser-bookmark "bookmark")
  136. ("d" (dkellner/search-online "https://duckduckgo.com/?q=%s") "duckduckgo")
  137. ("w" (dkellner/search-online
  138. "https://www.wikipedia.org/search-redirect.php?language=en&go=Go&search=%s")
  139. "wikipedia")
  140. ("t" (dkellner/lookup-dictionary/body) "dictionary"))
  141. (defhydra dkellner/lookup-dictionary (:exit t)
  142. "Lookup dictionary"
  143. ("e" (dkellner/search-online "https://dict.cc/%s") "DE <-> EN")
  144. ("v" (dkellner/search-online
  145. "http://tratu.coviet.vn/tu-dien-lac-viet.aspx?learn=hoc-tieng-anh&t=A-V&k=%s")
  146. "EN -> VN"))
  147. (defun dkellner/search-online (search-engine-url)
  148. (let ((query (read-string "Query: ")))
  149. (browse-url (format search-engine-url query))))
  150. (use-package gpastel
  151. :hook (exwm-init . gpastel-start-listening))
  152. (provide 'dkellner-exwm)