Modeline cleanup, agenda bindings, dynamic tab helpers etc

This commit is contained in:
Curt Spark 2026-04-13 22:05:48 +01:00
parent e381030890
commit 0edb7ab98f
2 changed files with 154 additions and 86 deletions

View File

@ -3,4 +3,4 @@
This is a modernised GNU Emacs Configuration, an evolution of my old emacs configuration: This is a modernised GNU Emacs Configuration, an evolution of my old emacs configuration:
`https://git.cspark.dev/cspark/Emacs-Configuration` `https://git.cspark.dev/cspark/Emacs-Configuration`
It is intended to be more focused and clean, using modern more modular/simpler packages or the builtins. Using more modern packages (Switching from company, lsp mode, EXWM to consult/vertico, eglot mode, EWM for example) and personal built emacs lisp.

164
init.el
View File

@ -61,6 +61,14 @@
(`(:propertize (,_ minor-mode-alist . ,_) . ,_) "") (`(:propertize (,_ minor-mode-alist . ,_) . ,_) "")
(t elem))) (t elem)))
mode-line-modes)) mode-line-modes))
; Hide other items
(line-number-mode -1)
(column-number-mode -1)
(setq mode-line-percent-position nil)
(with-eval-after-load 'evil
(setq evil-mode-line-format nil))
; Emacs 31 feature only - Collapse minor modes into one
(setq mode-line-collapse-minor-modes '(not))
;; Clipboard config ;; Clipboard config
(setopt select-active-regions nil) (setopt select-active-regions nil)
@ -204,6 +212,7 @@
(evil-define-key* '(normal) org-mode-map (kbd "M-h") nil) (evil-define-key* '(normal) org-mode-map (kbd "M-h") nil)
(evil-define-key* '(normal) org-mode-map (kbd "M-l") nil))) (evil-define-key* '(normal) org-mode-map (kbd "M-l") nil)))
(with-eval-after-load 'org-agenda (with-eval-after-load 'org-agenda
(with-eval-after-load 'evil
(setq org-agenda-files '("~/Nextcloud/Agenda")) (setq org-agenda-files '("~/Nextcloud/Agenda"))
;This is will integrate the Calendar/Diary into Org-Agenda, so you can get access to dates on public holidays etc. Set diary to true: ;This is will integrate the Calendar/Diary into Org-Agenda, so you can get access to dates on public holidays etc. Set diary to true:
(setq org-agenda-include-diary t) (setq org-agenda-include-diary t)
@ -219,13 +228,28 @@
;Autostart in day view ;Autostart in day view
(setq org-agenda-span 'day) (setq org-agenda-span 'day)
;Auto save agenda buffers on refresh
(advice-add 'org-agenda-redo :before #'org-save-all-org-buffers)
(add-hook 'org-agenda-mode-hook #'(lambda () (add-hook 'org-agenda-mode-hook #'(lambda ()
(org-agenda-entry-text-mode 1))) (org-agenda-entry-text-mode 1)))
(define-key org-agenda-mode-map (kbd "C-j") 'evil-next-line) (define-key org-agenda-mode-map (kbd "C-j") 'org-agenda-goto-date)
(define-key org-agenda-mode-map (kbd "C-k") 'evil-previous-line) (define-key org-agenda-mode-map "j" 'evil-next-line)
(define-key org-agenda-mode-map "d" 'org-agenda-toggle-day-view) (define-key org-agenda-mode-map "k" 'evil-previous-line)
(define-key org-agenda-mode-map "p" 'org-pomodoro))
(define-key org-agenda-mode-map (kbd "V") nil)
(define-key org-agenda-mode-map (kbd "V") 'evil-visual-line)
(define-key org-agenda-mode-map "g" nil)
(define-key org-agenda-mode-map (kbd "g g") 'evil-goto-first-line)
(define-key org-agenda-mode-map (kbd "G") 'evil-goto-line)
(define-key org-agenda-mode-map "s" 'org-agenda-schedule)
(define-key org-agenda-mode-map "d" 'org-agenda-schedule)
(define-key org-agenda-mode-map (kbd "C-d") 'org-agenda-toggle-day-view)
(define-key org-agenda-mode-map "p" 'org-pomodoro)))
; For Org Pomodoro notification sound ; For Org Pomodoro notification sound
(use-package sound-wav (use-package sound-wav
@ -292,7 +316,7 @@
; Upcoming agenda items in modeline ; Upcoming agenda items in modeline
(use-package org-upcoming-modeline (use-package org-upcoming-modeline
:ensure t :ensure t
:after org-agenda ; if you don't want it to start until org has been loaded :after org-agenda
:config :config
(org-upcoming-modeline-mode)) (org-upcoming-modeline-mode))
@ -741,12 +765,17 @@
(setq emms-source-file-directory-tree-function 'emms-source-file-directory-tree-find) (setq emms-source-file-directory-tree-function 'emms-source-file-directory-tree-find)
(setq emms-cache-set-all-from-mpd t) (setq emms-cache-set-all-from-mpd t)
(setq emms-browser-makes-thumbnails t)
(setq emms-browser-thumbnail-small-width 100)
(setq emms-mode-line-length-limit 20)
(emms-all) (emms-all)
(emms-player-mpd-connect) (emms-player-mpd-connect)
(add-hook 'emms-playlist-cleared-hook 'emms-player-mpd-clear) (add-hook 'emms-playlist-cleared-hook 'emms-player-mpd-clear)
(setq emms-player-list '(emms-player-mpd)) (setq emms-player-list '(emms-player-mpd))
(setq emms-player-mpd-supported-regexp ".") (setq emms-player-mpd-supported-regexp "\\`http[s]?://\\|\\.\\([Mm]3[Uu]\\|[Oo][Gg][Gg]\\|[Ff][Ll][Aa][Cc]\\|[Mm][Pp]3\\|[Ww][Aa][Vv]\\|[Mm][Oo][Dd]\\|[Aa][Uu]\\|[Aa][Ii][Ff][Ff]\\|[Oo][Pp][Uu][Ss]\\)\\'")
(add-to-list 'emms-info-functions 'emms-info-mpd) (add-to-list 'emms-info-functions 'emms-info-mpd)
(define-key emms-playlist-mode-map (kbd "d") nil) (define-key emms-playlist-mode-map (kbd "d") nil)
@ -1053,7 +1082,7 @@
(setq tab-bar-show 1) ; Hide the bar if only 1 tab exists (setq tab-bar-show 1) ; Hide the bar if only 1 tab exists
(setq tab-bar-new-tab-choice "*scratch*") (setq tab-bar-new-tab-choice "*scratch*")
(defun dynamic-tab-ensure-scratch-tab (&rest _) (defun dynamic-tab--ensure-scratch-tab (&rest _)
"Ensure dynamic scratch tab available if there are active buffers." "Ensure dynamic scratch tab available if there are active buffers."
(let* ((tabs (funcall tab-bar-tabs-function)) (let* ((tabs (funcall tab-bar-tabs-function))
(tab-names (mapcar (lambda (tab) (alist-get 'name tab)) tabs)) (tab-names (mapcar (lambda (tab) (alist-get 'name tab)) tabs))
@ -1081,28 +1110,28 @@
;; Return to original tab if we were just initializing ;; Return to original tab if we were just initializing
(tab-bar-select-tab (1+ current-tab)))))) (tab-bar-select-tab (1+ current-tab))))))
(defvar dynamic-tab-is-already-redirecting-p nil (defvar dynamic-tab--is-already-redirecting-p nil
"Whether we are already redirecting to scratch tab or not.") "Whether we are already redirecting to scratch tab or not.")
(defun dynamic-tab-redirect-to-scratch-tab () (defun dynamic-tab--redirect-to-scratch-tab ()
"Redirect to dedicated scratch tab if scratch buffer accessed on other tab." "Redirect to dedicated scratch tab if scratch buffer accessed on other tab."
(when (and (not dynamic-tab-is-already-redirecting-p) (when (and (not dynamic-tab--is-already-redirecting-p)
(string= (buffer-name) "*scratch*") (string= (buffer-name) "*scratch*")
(string= (buffer-name) "dynamic *scratch*")) (string= (buffer-name) "dynamic *scratch*"))
(setq dynamic-tab-is-already-redirecting-p t) (setq dynamic-tab--is-already-redirecting-p t)
(unwind-protect (unwind-protect
(switch-to-buffer nil) (switch-to-buffer nil)
(tab-bar-select-tab-by-name "dynamic *scratch*") (tab-bar-select-tab-by-name "dynamic *scratch*")
(setq dynamic-tab-is-already-redirecting-p nil)))) (setq dynamic-tab--is-already-redirecting-p nil))))
(defvar dynamic-tab-soft-kill-p nil (defvar dynamic-tab--soft-kill-p nil
"When t, do not kill buffers only send them to background unless one tab open.") "When t, do not kill buffers only send them to background unless one tab open.")
(defun dynamic-tab-handle-buffer-check-and-close-tab () (defun dynamic-tab--handle-buffer-check-and-close-tab ()
"Check if we need to close the tab and action accordingly." "Check if we need to close the tab and action accordingly."
(let* ((is-last-tab (<= (length (tab-bar-tabs)) 2)) (let* ((is-last-tab (<= (length (tab-bar-tabs)) 2))
(is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 1))) (is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 1)))
(when (and (not is-last-tab) is-last-buffer) (when (and (not is-last-tab) is-last-buffer)
(tab-close)))) (tab-close))))
(defun dynamic-tab-handle-tab-cleanup-kill () (defun dynamic-tab--handle-tab-cleanup-kill ()
"Check if we can kill buffer and free tab if no more reserved buffers in tab." "Check if we can kill buffer and free tab if no more reserved buffers in tab."
(let* ((is-last-tab (<= (length (tab-bar-tabs)) 2)) (let* ((is-last-tab (<= (length (tab-bar-tabs)) 2))
(is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2)) (is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2))
@ -1111,27 +1140,27 @@
;((and is-last-tab (not is-last-buffer)) t) ;((and is-last-tab (not is-last-buffer)) t)
;((and is-last-tab (not is-last-buffer) (bury-buffer))) ;((and is-last-tab (not is-last-buffer) (bury-buffer)))
((and (not is-last-tab) (not is-last-buffer) dynamic-tab-soft-kill-p) (bury-buffer)) ((and (not is-last-tab) (not is-last-buffer) dynamic-tab--soft-kill-p) (bury-buffer))
(t t)))) (t t))))
(dynamic-tab-handle-buffer-check-and-close-tab) (dynamic-tab--handle-buffer-check-and-close-tab)
is-marked-to-kill)) is-marked-to-kill))
(defun dynamic-tab-block-buffer-kill () (defun dynamic-tab--block-buffer-kill ()
"Block buffer from being killed." "Block buffer from being killed."
(message "You cannot kill the dynamic buffer") (message "You cannot kill the dynamic buffer")
nil) nil)
(defun dynamic-tab-mark-buffer-unkillable () (defun dynamic-tab--mark-buffer-unkillable ()
"Mark buffer as unkillable." "Mark buffer as unkillable."
(add-hook 'kill-buffer-query-functions #'dynamic-tab-block-buffer-kill nil t)) (add-hook 'kill-buffer-query-functions #'dynamic-tab--block-buffer-kill nil t))
(defun dynamic-tab-mark-buffer-reserved () (defun dynamic-tab--mark-buffer-reserved ()
"Mark buffer as reserved." "Mark buffer as reserved."
(add-hook 'kill-buffer-query-functions #'dynamic-tab-handle-tab-cleanup-kill nil t)) (add-hook 'kill-buffer-query-functions #'dynamic-tab--handle-tab-cleanup-kill nil t))
(defun dynamic-tab-unmark-buffer-reserved () (defun dynamic-tab--unmark-buffer-reserved ()
"Unmark buffer as reserved." "Unmark buffer as reserved."
(remove-hook 'kill-buffer-query-functions #'dynamic-tab-handle-tab-cleanup-kill t)) (remove-hook 'kill-buffer-query-functions #'dynamic-tab--handle-tab-cleanup-kill t))
(defun dynamic-tab-refresh-listeners () (defun dynamic-tab--refresh-listeners ()
"Refresh hooks to listen on reserved buffers." "Refresh hooks to listen on reserved buffers."
(dolist (buf (tab-line-tabs-window-buffers)) (dolist (buf (tab-line-tabs-window-buffers))
(with-current-buffer buf (with-current-buffer buf
@ -1142,33 +1171,57 @@
(cond (cond
(is-child-buffer nil) (is-child-buffer nil)
(is-mini-buffer nil) (is-mini-buffer nil)
(is-dynamic-buffer (dynamic-tab-mark-buffer-unkillable)) (is-dynamic-buffer (dynamic-tab--mark-buffer-unkillable))
(is-scratch-buffer (dynamic-tab-mark-buffer-unkillable)) (is-scratch-buffer (dynamic-tab--mark-buffer-unkillable))
(t (dynamic-tab-mark-buffer-reserved))))))) (t (dynamic-tab--mark-buffer-reserved)))))))
(defun dynamic-tab-remove-listeners () (defun dynamic-tab--remove-listeners ()
"Remove all hooks on reserved buffers." "Remove all hooks on reserved buffers."
(dolist (buf (buffer-list)) (dolist (buf (buffer-list))
(with-current-buffer buf (with-current-buffer buf
(dynamic-tab-unmark-buffer-reserved)))) (dynamic-tab--unmark-buffer-reserved))))
(defvar dynamic-tab-last-buffer nil) (defvar dynamic-tab--last-buffer nil)
(defun dynamic-tab-handle-buffer-switch (&rest _) (defun dynamic-tab--handle-buffer-switch (&rest _)
"Checks to run when buffer is switched." "Checks to run when buffer is switched."
(unless (eq (current-buffer) dynamic-tab-last-buffer) (unless (eq (current-buffer) dynamic-tab--last-buffer)
(setq dynamic-tab-last-buffer (current-buffer)) (setq dynamic-tab--last-buffer (current-buffer))
;; Put your "on switch" logic here ;; Put your "on switch" logic here
(dynamic-tab-ensure-scratch-tab) (dynamic-tab--ensure-scratch-tab)
(dynamic-tab-redirect-to-scratch-tab))) (dynamic-tab--redirect-to-scratch-tab)))
(defun dynamic-tab-handle-buffer-create (&rest _) (defun dynamic-tab--handle-buffer-create (&rest _)
"Checks to run when buffer is created." "Checks to run when buffer is created."
(dynamic-tab-ensure-scratch-tab) (dynamic-tab--ensure-scratch-tab)
(dynamic-tab-refresh-listeners)) (dynamic-tab--refresh-listeners))
(defun dynamic-tab-init () (defun dynamic-tab-init ()
"Initialise dynamic tabs." "Initialise dynamic tabs."
(add-hook 'window-buffer-change-functions #'dynamic-tab-handle-buffer-switch) (add-hook 'window-buffer-change-functions #'dynamic-tab--handle-buffer-switch)
(add-hook 'after-change-major-mode-hook #'dynamic-tab-handle-buffer-create)) (add-hook 'after-change-major-mode-hook #'dynamic-tab--handle-buffer-create))
(defun dynamic-tab-move-tab-left ()
"Move tab left, no wrapping or moving the dedicated dynamic tab."
(let* ((is-first-tab (= (tab-bar--current-tab-index) 0))
(is-dynamic-tab-focused (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*")))
(when (and (not is-first-tab)
(not is-dynamic-tab-focused))
(tab-bar-move-tab-backward))))
(defun dynamic-tab-move-tab-right ()
"Move tab right, no wrapping or moving past the dedicated dynamic tab."
(let* ((is-last-tab (= (tab-bar--current-tab-index) (- (length (tab-bar-tabs)) 2)))
(is-dynamic-tab-focused (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*")))
(when (and (not is-last-tab)
(not is-dynamic-tab-focused))
(tab-bar-move-tab 1))))
; Generic tab helper functions
(defun delete-window-override (&rest _)
"Override for delete window, close tab if only one window instead."
(if (<= (length (window-list)) 1)
(progn
(tab-close)
nil)
t))
;; Helper functions for EWM ;; Helper functions for EWM
; Switch monitor ; Switch monitor
@ -1228,12 +1281,12 @@
"grim -g \"$(slurp)\" - | wl-copy"))) "grim -g \"$(slurp)\" - | wl-copy")))
("M-w" . (lambda () ("M-w" . (lambda ()
(interactive) (interactive)
(setq dynamic-tab-soft-kill-p t) (setq dynamic-tab--soft-kill-p t)
(kill-buffer) (kill-buffer)
(setq dynamic-tab-soft-kill-p nil))) (setq dynamic-tab--soft-kill-p nil)))
("C-x k" . (lambda () ("C-x k" . (lambda ()
(interactive) (interactive)
(setq dynamic-tab-soft-kill-p nil) (setq dynamic-tab--soft-kill-p nil)
(call-interactively 'kill-buffer))) (call-interactively 'kill-buffer)))
; Monitor switching, find current focused monitor name via ; Monitor switching, find current focused monitor name via
@ -1254,6 +1307,12 @@
("M-h" . tab-bar-switch-to-prev-tab) ("M-h" . tab-bar-switch-to-prev-tab)
("M-l" . tab-bar-switch-to-next-tab) ("M-l" . tab-bar-switch-to-next-tab)
("M-H" . (lambda ()
(interactive)
(dynamic-tab-move-tab-left)))
("M-L" . (lambda ()
(interactive)
(dynamic-tab-move-tab-right)))
("M-k" . windmove-up) ("M-k" . windmove-up)
("M-j" . windmove-down)) ("M-j" . windmove-down))
:config :config
@ -1264,13 +1323,16 @@
(add-to-list 'ewm-intercept-prefixes ?\M-p) (add-to-list 'ewm-intercept-prefixes ?\M-p)
(add-to-list 'ewm-intercept-prefixes ?\M-h) (add-to-list 'ewm-intercept-prefixes ?\M-h)
(add-to-list 'ewm-intercept-prefixes ?\M-j) (add-to-list 'ewm-intercept-prefixes ?\M-j)
(add-to-list 'ewm-intercept-prefixes ?\M-H)
(add-to-list 'ewm-intercept-prefixes ?\M-J)
(add-to-list 'ewm-intercept-prefixes ?\M-k) (add-to-list 'ewm-intercept-prefixes ?\M-k)
(add-to-list 'ewm-intercept-prefixes ?\M-l) (add-to-list 'ewm-intercept-prefixes ?\M-l)
(ewm--send-intercept-keys) (ewm--send-intercept-keys)
:init :init
;; Dynamic Tabs ;; Dynamic Tabs
(dynamic-tab-init) (dynamic-tab-init)
(advice-add 'delete-window :before-while #'delete-window-override))
(with-eval-after-load 'ewm
;; Autostart ;; Autostart
(ewm-autostart-application "qpwgraph") (ewm-autostart-application "qpwgraph")
(ewm-autostart-application "kdeconnect-indicator") (ewm-autostart-application "kdeconnect-indicator")
@ -1286,7 +1348,8 @@
:after posframe :after posframe
:init :init
(defun simple-notification-popup (old-notification new-notification) (defun simple-notification-popup (old-notification new-notification)
(unless (eq old-notification new-notification) (ignore-errors
(when new-notification
(posframe-show (posframe-show
" *simple-notification-popup-alert*" " *simple-notification-popup-alert*"
:string (concat :string (concat
@ -1297,8 +1360,7 @@
:poshandler #'posframe-poshandler-frame-top-right-corner :poshandler #'posframe-poshandler-frame-top-right-corner
:background-color "gold" :background-color "gold"
:foreground-color "black" :foreground-color "black"
:timeout 5))) :timeout 5))))
(add-hook 'ednc-notification-presentation-functions (add-hook 'ednc-notification-presentation-functions
#'simple-notification-popup) #'simple-notification-popup)
(ednc-mode)) (ednc-mode))
@ -1315,6 +1377,12 @@
(setq kdeconnect-devices '(("My Phone" . "378230a2e3c24b9a9904e7ffb0dfeb07"))) (setq kdeconnect-devices '(("My Phone" . "378230a2e3c24b9a9904e7ffb0dfeb07")))
(setq kdeconnect-active-device '("My Phone" . "378230a2e3c24b9a9904e7ffb0dfeb07")))) (setq kdeconnect-active-device '("My Phone" . "378230a2e3c24b9a9904e7ffb0dfeb07"))))
;(use-package elcord
; :ensure t
; :config
; (setq elcord-display-buffer-details nil)
; (elcord-mode)))
(custom-set-variables (custom-set-variables
;; custom-set-variables was added by Custom. ;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful. ;; If you edit it by hand, you could mess it up, so be careful.