Lot of package changes, correct indentation

This commit is contained in:
Curt Spark 2026-04-04 02:12:51 +01:00
parent ae88fd95b7
commit 15a1de1923
1 changed files with 910 additions and 654 deletions

476
init.el
View File

@ -5,6 +5,7 @@
(scroll-bar-mode 0) (scroll-bar-mode 0)
(column-number-mode 1) (column-number-mode 1)
(setq package-native-compile t)
(setq use-package-verbose t) (setq use-package-verbose t)
(setq use-package-compute-statistics t) (setq use-package-compute-statistics t)
@ -12,8 +13,15 @@
(global-visual-line-mode 1) (global-visual-line-mode 1)
(setq-default visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow)) (setq-default visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow))
;; Minibuffer key chord hints should show up instantly
(setq echo-keystrokes 0.01)
;; Auto delete trailing whitespace - Emacs 31+
(add-hook 'prog-mode-hook #'delete-trailing-whitespace-mode)
(add-hook 'text-mode-hook #'delete-trailing-whitespace-mode)
;; Set custom tab width here ;; Set custom tab width here
(defvar custom-tab-width 8) (defvar custom-tab-width 4)
;; Disable bell/messages sound on windows ;; Disable bell/messages sound on windows
(when (eq window-system 'w32) (when (eq window-system 'w32)
@ -181,22 +189,8 @@
;For Org-Agenda, you can set a location of your Org Agenda file here. Set Agenda Directory: ;For Org-Agenda, you can set a location of your Org Agenda file here. Set Agenda Directory:
(use-package org (use-package org
:ensure nil :ensure nil
:demand t ; Setting org mode to be deferred absolutely breaks everything, with org-agenda-mode-map error. Please switch to eval after load maybe instead. ;:demand t ; Setting org mode to be deferred absolutely breaks everything, with org-agenda-mode-map error. Please switch to eval after load maybe instead.
:hook
(org-agenda-mode . (lambda() (org-agenda-entry-text-mode 1)))
:config :config
(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:
(setq org-agenda-include-diary t)
;Ensure done date/closed timestamps are logged
(setq org-log-done 'time)
;Ensure state changes are logged into logbook
(setq org-log-into-drawer "LOGBOOK")
;Ensure agenda still shows DONE items
(setq org-agenda-skip-scheduled-if-done nil)
(setq agenda-skip-deadline-if-done nil)
;Fold settings ;Fold settings
;Org Mode historically used overlays to hide text, but newer versions moved toward text properties for better performance in large files. This change occasionally causes "stuck" visibility where sub-headers remain hidden until the parent is fully cycled. ;Org Mode historically used overlays to hide text, but newer versions moved toward text properties for better performance in large files. This change occasionally causes "stuck" visibility where sub-headers remain hidden until the parent is fully cycled.
(setq org-fold-core-style 'overlays) (setq org-fold-core-style 'overlays)
@ -210,6 +204,24 @@
(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
(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:
(setq org-agenda-include-diary t)
;Ensure done date/closed timestamps are logged
(setq org-log-done 'time)
;Ensure state changes are logged into logbook
(setq org-log-into-drawer "LOGBOOK")
;Ensure agenda still shows DONE items
(setq org-agenda-skip-scheduled-if-done nil)
(setq agenda-skip-deadline-if-done nil)
;Autostart in day view
(setq org-agenda-span 'day)
(add-hook 'org-agenda-mode-hook #'(lambda ()
(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") 'evil-next-line)
(define-key org-agenda-mode-map (kbd "C-k") 'evil-previous-line) (define-key org-agenda-mode-map (kbd "C-k") 'evil-previous-line)
(define-key org-agenda-mode-map "d" 'org-agenda-toggle-day-view) (define-key org-agenda-mode-map "d" 'org-agenda-toggle-day-view)
@ -217,12 +229,23 @@
; For Org Pomodoro notification sound ; For Org Pomodoro notification sound
(use-package sound-wav (use-package sound-wav
:ensure t) :ensure t
:demand t)
(with-eval-after-load 'sound-wav
(defun sound-alert (alert)
"Play a sound notification and show message ALERT."
(sound-wav-play (expand-file-name (concat user-emacs-directory "elpaca/builds/org-pomodoro/resources/bell.wav")))
(message alert))
; Org timer custom alert
(defun org-timer-sound-alert ()
"Sound notification on org timer finish."
(sound-alert "Timer done!"))
(add-hook 'org-timer-done-hook 'org-timer-sound-alert))
; Org Pomodoro ; Org Pomodoro
(use-package org-pomodoro (use-package org-pomodoro
:ensure t :ensure t
:after (org sound-wav) :after (org org-agenda sound-wav)
:config :config
(setq org-pomodoro-manual-break t) (setq org-pomodoro-manual-break t)
(setq org-pomodoro-keep-killed-pomodoro-time t) (setq org-pomodoro-keep-killed-pomodoro-time t)
@ -230,16 +253,6 @@
(setq org-pomodoro-ticking-sound-p nil) (setq org-pomodoro-ticking-sound-p nil)
(setq org-pomodoro-audio-player "mpv")) (setq org-pomodoro-audio-player "mpv"))
(defun sound-alert (alert)
"Play a sound notification and show message ALERT."
(sound-wav-play (expand-file-name (concat user-emacs-directory "elpaca/builds/org-pomodoro/resources/bell.wav")))
(message alert))
; Org timer custom alert
(defun org-timer-sound-alert ()
"Sound notification on org timer finish."
(sound-alert "Timer done!"))
(add-hook 'org-timer-done-hook 'org-timer-sound-alert)
(use-package alert (use-package alert
:ensure t :ensure t
:config :config
@ -259,7 +272,7 @@
; System notifications of org agenda items ; System notifications of org agenda items
(use-package org-wild-notifier (use-package org-wild-notifier
:ensure t :ensure t
:after org :after org-agenda
:config :config
;; Notifications fire N minutes before an event ;; Notifications fire N minutes before an event
(setq org-wild-notifier-alert-time '(1 10 30)) (setq org-wild-notifier-alert-time '(1 10 30))
@ -279,14 +292,14 @@
; 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 ; if you don't want it to start until org has been loaded :after org-agenda ; if you don't want it to start until org has been loaded
:config :config
(org-upcoming-modeline-mode)) (org-upcoming-modeline-mode))
; Org Mode Journalling ; Org Mode Journalling
(use-package org-journal (use-package org-journal
:ensure t :ensure t
:after org :after org-agenda
:config :config
(setq org-journal-dir "~/Nextcloud/Journal/") (setq org-journal-dir "~/Nextcloud/Journal/")
(setq org-journal-file-type 'daily) (setq org-journal-file-type 'daily)
@ -328,6 +341,9 @@
:ensure t :ensure t
:config :config
;; Global settings (defaults) ;; Global settings (defaults)
(setcdr (assoc 'gnus-group-news-low-empty doom-themes-base-faces)
'(:inherit 'gnus-group-mail-1-empty :weight 'normal))
(setq (setq
doom-themes-enable-bold t ; if nil, bold is universally disabled doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled doom-themes-enable-italic t) ; if nil, italics is universally disabled
@ -404,23 +420,41 @@
; Vim Bindings ; Vim Bindings
(use-package evil (use-package evil
:ensure t :ensure t
:bind (("<escape>" . keyboard-escape-quit)) :bind
(("<escape>" . keyboard-escape-quit)
:map evil-normal-state-map
("U" . undo-redo)
:map evil-insert-state-map
("C-g" . evil-force-normal-state)
:map evil-motion-state-map
([remap evil-search-forward] . 'consult-line))
:init :init
(setq evil-want-keybinding nil) (setq evil-want-keybinding nil)
(evil-mode 1) (evil-mode 1))
:config
(define-key evil-insert-state-map (kbd "C-g") 'evil-force-normal-state)
(define-key evil-motion-state-map [remap evil-search-forward] 'consult-line))
; Evil Collection, configs evil bindings for more packages ; Evil Collection, configs evil bindings for more packages
(use-package evil-collection (use-package evil-collection
:after evil :after evil
:ensure t :ensure t
:config :config
(setq evil-collection-setup-minibuffer t)
(evil-collection-init)) (evil-collection-init))
;; Proced config
(with-eval-after-load 'proced
(define-key proced-mode-map [remap proced-undo] 'proced-update))
;; Eshell config ;; Eshell config
(with-eval-after-load 'eshell-mode
(with-eval-after-load 'evil
; Unbind stubborn eshell bindings
(define-key eshell-mode-map (kbd "M-o") nil)
(define-key eshell-mode-map (kbd "M-p") nil)
(evil-define-key* '(normal) eshell-mode-map (kbd "M-o") nil)
(evil-define-key* '(normal) eshell-mode-map (kbd "M-p") nil)
(evil-define-key* '(normal) eshell-mode-map (kbd "M-h") nil)
(evil-define-key* '(normal) eshell-mode-map (kbd "M-l") nil)))
; Like zoxide ; Like zoxide
(use-package eshell-z (use-package eshell-z
:ensure t :ensure t
@ -662,7 +696,8 @@
(setq elfeed-feeds (setq elfeed-feeds
'(("https://www.reddit.com/r/Clamworks.rss" reddit clamworks) '(("https://www.reddit.com/r/Clamworks.rss" reddit clamworks)
("https://www.reddit.com/r/Losercity.rss" reddit losercity) ("https://www.reddit.com/r/Losercity.rss" reddit losercity)
("https://www.reddit.com/r/Shark_Park.rss" reddit sharkpark)))) ("https://www.reddit.com/r/Shark_Park.rss" reddit sharkpark)
("https://www.reddit.com/r/emacs.rss" reddit emacs))))
(use-package elfeed-goodies (use-package elfeed-goodies
:ensure t :ensure t
:after elfeed :after elfeed
@ -671,6 +706,118 @@
(setq elfeed-goodies/entry-pane-position 'bottom) (setq elfeed-goodies/entry-pane-position 'bottom)
(setq elfeed-goodies/entry-pane-size 0.6)) (setq elfeed-goodies/entry-pane-size 0.6))
;; empv - YouTube search frontend, media library manager
(use-package empv
:ensure t
:config
(add-to-list 'empv-mpv-args "--ytdl-format=bestvideo+bestaudio/best[ext=mp4]/best")
(setq empv-youtube-use-tabulated-results t)
(setq empv-invidious-instance 'ivjs)
(define-key empv-youtube-results-mode-map (kbd "<return>") 'empv-play-media-at-point))
;; EMMS - Emacs Music Player
(use-package emms
:ensure t
:after (evil evil-collection)
:bind*
(([remap emms-isearch-buffer] . consult-line)
:map emms-browser-mode-map
("g g" . evil-goto-first-line)
("G" . evil-goto-line)
("w" . evil-forward-word-begin)
("b" . evil-backward-word-begin)
("h" . evil-backward-char)
("j" . evil-next-line)
("k" . evil-previous-line)
("l" . evil-forward-char)
("x" . emms-pause))
:config
(setq emms-source-file-default-directory (expand-file-name "~/Spool2_Secret/Music/Flac"))
(setq emms-player-mpd-server-name "localhost")
(setq emms-player-mpd-server-port "6600")
(setq emms-player-mpd-music-directory "~/Spool2_Secret/Music/Flac")
(setq emms-source-file-directory-tree-function 'emms-source-file-directory-tree-find)
(setq emms-cache-set-all-from-mpd t)
(emms-all)
(emms-player-mpd-connect)
(add-hook 'emms-playlist-cleared-hook 'emms-player-mpd-clear)
(setq emms-player-list '(emms-player-mpd))
(setq emms-player-mpd-supported-regexp ".")
(add-to-list 'emms-info-functions 'emms-info-mpd)
(define-key emms-playlist-mode-map (kbd "d") nil)
(evil-define-key* '(normal) emms-playlist-mode-map (kbd "d") nil)
(evil-define-key* '(normal) emms-playlist-mode-map (kbd "d d") #'emms-playlist-mode-kill-track)
(evil-define-key* '(visual) emms-playlist-mode-map (kbd "d") #'emms-playlist-mode-kill)
(evil-define-key* '(normal) emms-playlist-mode-map (kbd "q") #'emms-browser-bury-buffer))
;; Embr.el Emacs web browser
;(use-package embr
; :defer t
; :after evil
; :ensure (:host github
; :repo "emacs-os/embr.el"
; :files ("*.el" "*.py" "*.sh" "native/*.c" "native/Makefile"))
; :hook (embr-mode . embr-vimium-mode)
; (evil-mode . (lambda () (turn-off-evil-mode)))
; :config
; (setq embr-hover-rate 30
; embr-default-width 1919
; embr-default-height 950
; embr-screen-width 1920
; embr-screen-height 1080
; embr-color-scheme 'dark
; embr-search-engine 'google
; embr-scroll-method 'instant
; embr-scroll-step 100
; embr-frame-source 'screencast
; embr-render-backend 'canvas
; embr-display-method 'headless
; embr-home-url "about:blank"
; embr-session-restore t
; embr-tab-bar t
; embr-proxy-rules nil))
;(with-eval-after-load 'embr
; (defun embr--start-daemon-overridden ()
; "Start the Python daemon process OVERRIDDEN for NixOS support.
; Respects `embr-display-method' for display modes."
; (when (and embr--process (process-live-p embr--process))
; (delete-process embr--process))
; (setq embr--response-buffer "")
; (let* ((inner (list embr-python embr-script))
; (xvfb (and (eq embr-display-method 'headed-offscreen)
; (executable-find "xvfb-run")))
; (command
; (if xvfb
; (append (list xvfb "--auto-servernum"
; "--server-args=-screen 0 1920x1080x24")
; inner)
; (when (and (eq embr-display-method 'headed-offscreen)
; (not (executable-find "xvfb-run")))
; (message "embr: xvfb-run not found, falling back to headless"))
; inner))
; (process-environment
; (append (list "LD_LIBRARY_PATH=/run/current-system/sw/share/nix-ld/lib"
; (format "EMBR_DISPLAY=%s"
; (if xvfb "headed-offscreen"
; (symbol-name embr-display-method))))
; process-environment)))
; (setq embr--process
; (make-process
; :name "embr"
; :command command
; :connection-type 'pipe
; :noquery t
; :stderr (get-buffer-create "*embr-stderr*")
; :filter #'embr--process-filter
; :sentinel #'embr--process-sentinel))
; (process-put embr--process 'embr-buffer (current-buffer))))
; (advice-add 'embr--start-daemon :override #'embr--start-daemon-overridden))
;; Emacs everywhere - Use emacs for any text input ;; Emacs everywhere - Use emacs for any text input
(use-package emacs-everywhere (use-package emacs-everywhere
:ensure t) :ensure t)
@ -689,6 +836,32 @@
; (indent-tabs-mode -1) ; (indent-tabs-mode -1)
; (parinfer-rust-mode))))) ; (parinfer-rust-mode)))))
;; Evil cleverparens - We will use conventional 2 spaces instead of tabs for lisp
;(use-package evil-cleverparens
; :ensure t
; :bind
; (:map evil-cleverparens-mode-map
; ("M-d" . nil))
; :hook
; ((emacs-lisp-mode . (lambda ()
; (setq-local tab-width 2)
; (indent-tabs-mode -1)
; (electric-indent-mode 1)
; (evil-cleverparens-mode)))
; (common-lisp-mode . (lambda ()
; (setq-local tab-width 2)
; (indent-tabs-mode -1)
; (electric-indent-mode 1)))))
;; Use puni-mode globally and disable it for term-mode.
(defun emacs-lisp-config-init ()
"My personal initial configuration for Emacs Lisp buffers."
(setq-local tab-width 4)
(setq-local lisp-indent-offset 4)
(setq-local lisp-body-indent 4)
(indent-tabs-mode -1)
(electric-indent-mode 1))
(add-hook 'emacs-lisp-mode-hook #'emacs-lisp-config-init)
;; Rainbow delimiters ;; Rainbow delimiters
(use-package rainbow-delimiters (use-package rainbow-delimiters
:ensure t :ensure t
@ -876,104 +1049,147 @@
; Dynamic Tab (Workspace) Setup ; Dynamic Tab (Workspace) Setup
(use-package tab-line (use-package tab-line
:ensure nil) :ensure nil)
(tab-bar-mode)
(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 () (defun dynamic-tab-ensure-scratch-tab (&rest _)
"Ensures there is always a tab dedicated to *scratch*." "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))
(spare-exists (member "dynamic *scratch*" tab-names)) (spare-exists (car (member "dynamic *scratch*" tab-names)))
(is-child-frame (frame-parent))) (is-child-buffer (frame-parent))
(is-mini-buffer (minibufferp))
(is-dynamic-tab-focused (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*"))
(is-scratch-buffer-focused (string= (buffer-name) "*scratch*"))
(is-new-tab-needed
(cond
(is-child-buffer nil)
(is-mini-buffer nil)
((not spare-exists) t)
;; If we are currently IN the spare tab and it's not *scratch* anymore, ((and is-dynamic-tab-focused (not is-scratch-buffer-focused)) t)
;; or if we just want to ensure it exists at the end: ((and (not is-dynamic-tab-focused) is-scratch-buffer-focused) (tab-close))
(unless (or spare-exists is-child-frame)
(t nil))))
(when is-new-tab-needed
(tab-bar-rename-tab "")
(let ((current-tab (tab-bar--current-tab-index))) (let ((current-tab (tab-bar--current-tab-index)))
(tab-bar-new-tab 999) (tab-bar-new-tab 999)
(tab-bar-rename-tab "dynamic *scratch*") (tab-bar-rename-tab "dynamic *scratch*")
;; 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))))))
(defun dynamic-tab-handle-tab-persistence () (defvar dynamic-tab-is-already-redirecting-p nil
"Create new tab if current scratch tab is being used." "Whether we are already redirecting to scratch tab or not.")
(when (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*") (defun dynamic-tab-redirect-to-scratch-tab ()
(unless (or (string= (buffer-name) "*scratch*") (minibufferp))
;; User switched away from scratch in the spare tab, rename it
(tab-bar-rename-tab "")))
;; and create a new spare.
(dynamic-tab-ensure-scratch-tab))
(defvar already-redirecting-p nil)
(defun dynamic-tab-redirect-to-scratch-tab (&rest _)
"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 already-redirecting-p) (when (and (not dynamic-tab-is-already-redirecting-p)
(string= (buffer-name) "*scratch*") (string= (buffer-name) "*scratch*")
(not (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*"))) (string= (buffer-name) "dynamic *scratch*"))
(setq 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 already-redirecting-p nil)))) (setq dynamic-tab-is-already-redirecting-p nil))))
(defvar dynamic-tab-soft-kill-p nil
"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)) 2))) (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 (orig-fun &rest args) "Check if we can kill buffer and free tab if no more reserved buffers in tab."
"Free tab if all reserved in use buffers for that tab killed."
(let* ((is-last-tab (<= (length (tab-bar-tabs)) 2)) (let* ((is-last-tab (<= (length (tab-bar-tabs)) 2))
(is-child-buffer (frame-parent))
(is-mini-buffer (minibufferp))
(is-dynamic-buffer (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*"))
(is-scratch-buffer (string= (alist-get 'name (tab-bar--current-tab)) "*scratch*"))
(is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2)) (is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2))
(is-overriden (nth 1 args)) (is-marked-to-kill (cond
(is-target-focused (and (eq (current-buffer) (car args)))) ;((and is-last-tab is-last-buffer) t)
(is-called-interactively (called-interactively-p 'any))) ;((and is-last-tab (not is-last-buffer)) t)
(cond
((and (not is-overriden) (not is-called-interactively)) (apply orig-fun args))
(is-child-buffer nil)
(is-mini-buffer nil)
(is-dynamic-buffer nil)
(is-scratch-buffer nil)
((and (not is-overriden) is-called-interactively) (apply orig-fun (nbutlast args)))
((and is-last-tab is-last-buffer) (apply orig-fun (nbutlast args)))
((and is-last-tab (not is-last-buffer)) (apply orig-fun (nbutlast args)))
;((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) (bury-buffer))) ((and (not is-last-tab) (not is-last-buffer) dynamic-tab-soft-kill-p) (bury-buffer))
(t nil)) (t t))))
(when (and (not is-overriden) is-target-focused) (dynamic-tab-handle-buffer-check-and-close-tab)
(dynamic-tab-handle-buffer-check-and-close-tab)))) is-marked-to-kill))
(defun dynamic-tab-handle-tab-cleanup-close (&rest _) (defun dynamic-tab-block-buffer-kill ()
"Free tab if last window open is attempted to be closed." "Block buffer from being killed."
(if (and (> (length (tab-bar-tabs)) 2) (message "You cannot kill the dynamic buffer")
(= (length (window-list)) 1) nil)
(not (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*"))) (defun dynamic-tab-mark-buffer-unkillable ()
(tab-close) "Mark buffer as unkillable."
t)) (add-hook 'kill-buffer-query-functions #'dynamic-tab-block-buffer-kill nil t))
(defun dynamic-tab-mark-buffer-reserved ()
"Mark buffer as reserved."
(add-hook 'kill-buffer-query-functions #'dynamic-tab-handle-tab-cleanup-kill nil t))
(defun dynamic-tab-unmark-buffer-reserved ()
"Unmark buffer as reserved."
(remove-hook 'kill-buffer-query-functions #'dynamic-tab-handle-tab-cleanup-kill t))
(defun dynamic-tab-refresh-listeners ()
"Refresh hooks to listen on reserved buffers."
(dolist (buf (tab-line-tabs-window-buffers))
(with-current-buffer buf
(let* ((is-child-buffer (frame-parent))
(is-mini-buffer (minibufferp))
(is-dynamic-buffer (string= (buffer-name) "dynamic *scratch*"))
(is-scratch-buffer (string= (buffer-name) "*scratch*")))
(cond
(is-child-buffer nil)
(is-mini-buffer nil)
(is-dynamic-buffer (dynamic-tab-mark-buffer-unkillable))
(is-scratch-buffer (dynamic-tab-mark-buffer-unkillable))
(t (dynamic-tab-mark-buffer-reserved)))))))
(defun dynamic-tab-remove-listeners ()
"Remove all hooks on reserved buffers."
(dolist (buf (buffer-list))
(with-current-buffer buf
(dynamic-tab-unmark-buffer-reserved))))
(defvar dynamic-tab-last-buffer nil)
(defun dynamic-tab-handle-buffer-switch (&rest _)
"Checks to run when buffer is switched."
(unless (eq (current-buffer) dynamic-tab-last-buffer)
(setq dynamic-tab-last-buffer (current-buffer))
;; Put your "on switch" logic here
(dynamic-tab-ensure-scratch-tab)
(dynamic-tab-redirect-to-scratch-tab)))
(defun dynamic-tab-handle-buffer-create (&rest _)
"Checks to run when buffer is created."
(dynamic-tab-ensure-scratch-tab)
(dynamic-tab-refresh-listeners))
(defun dynamic-tab-init ()
"Initialise dynamic tabs."
(add-hook 'window-buffer-change-functions #'dynamic-tab-handle-buffer-switch)
(add-hook 'after-change-major-mode-hook #'dynamic-tab-handle-buffer-create))
;; Helper functions for EWM ;; Helper functions for EWM
; Switch monitor ; Switch monitor
(defun ewm-switch-to-monitor (target) (defun ewm-switch-to-monitor (target)
"Switch focus to target monitor."
(interactive) (interactive)
(select-frame-set-input-focus (car (last (seq-filter (lambda (f) (select-frame-set-input-focus (car (last (seq-filter (lambda (f)
(string= target (string= target
(cdr (assq 'name (frame-monitor-attributes f))))) (cdr (assq 'name (frame-monitor-attributes f)))))
(frame-list)))))) (frame-list))))))
; Autostart
(defun ewm-autostart-application (target &optional args)
"Autostart application if not already started."
(unless (zerop (shell-command (concat "pidof " target)))
(start-process-shell-command (concat target "-autostart") nil (concat target " " args))))
; EWM - Emacs Wayland Manager ; EWM - Emacs Wayland Manager
(use-package ewm (use-package ewm
:ensure nil :ensure nil
:after evil
:custom :custom
(ewm-output-config (ewm-output-config
'(("DP-1" '(("DP-1"
@ -998,7 +1214,9 @@
:xkb-layouts "gb"))) :xkb-layouts "gb")))
;; Per-device override (exact name from libinput) ;; Per-device override (exact name from libinput)
;("ELAN0676:00 04F3:3195 Touchpad" :tap nil :accel-speed -0.2))) ;("ELAN0676:00 04F3:3195 Touchpad" :tap nil :accel-speed -0.2)))
:bind (:map ewm-mode-map ; Main bindings
:bind*
(:map ewm-mode-map
("M-d" . ewm-launch-app) ("M-d" . ewm-launch-app)
("s-l" . ewm-lock-session) ("s-l" . ewm-lock-session)
("M-<return>" . eshell) ("M-<return>" . eshell)
@ -1010,7 +1228,13 @@
"grim -g \"$(slurp)\" - | wl-copy"))) "grim -g \"$(slurp)\" - | wl-copy")))
("M-w" . (lambda () ("M-w" . (lambda ()
(interactive) (interactive)
(kill-buffer))) (setq dynamic-tab-soft-kill-p t)
(kill-buffer)
(setq dynamic-tab-soft-kill-p nil)))
("C-x k" . (lambda ()
(interactive)
(setq dynamic-tab-soft-kill-p nil)
(call-interactively 'kill-buffer)))
; Monitor switching, find current focused monitor name via ; Monitor switching, find current focused monitor name via
;(cdr (assq 'name (frame-monitor-attributes)) ;(cdr (assq 'name (frame-monitor-attributes))
@ -1033,6 +1257,7 @@
("M-k" . windmove-up) ("M-k" . windmove-up)
("M-j" . windmove-down)) ("M-j" . windmove-down))
:config :config
(add-to-list 'ewm-intercept-prefixes '("<Print>" :fullscreen))
(add-to-list 'ewm-intercept-prefixes ?\M-d) (add-to-list 'ewm-intercept-prefixes ?\M-d)
(add-to-list 'ewm-intercept-prefixes ?\M-w) (add-to-list 'ewm-intercept-prefixes ?\M-w)
(add-to-list 'ewm-intercept-prefixes ?\M-o) (add-to-list 'ewm-intercept-prefixes ?\M-o)
@ -1041,25 +1266,42 @@
(add-to-list 'ewm-intercept-prefixes ?\M-j) (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)
:init :init
;; Dynamic Tabs/Workspaces setup ;; Dynamic Tabs
; Hooks (dynamic-tab-init)
(advice-add 'consult-buffer
:after (lambda (&rest _) ;; Autostart
(dynamic-tab-handle-tab-persistence) (ewm-autostart-application "qpwgraph")
(dynamic-tab-redirect-to-scratch-tab))) (ewm-autostart-application "kdeconnect-indicator")
(advice-add 'delete-window :before-while #'dynamic-tab-handle-tab-cleanup-close) (ewm-autostart-application "udiskie")
(advice-add 'kill-buffer :around #'dynamic-tab-handle-tab-cleanup-kill) (ewm-autostart-application "nextcloud")
;(add-hook 'buffer-list-update-hook #'dynamic-tab-redirect-to-scratch-tab) (ewm-autostart-application "wlsunset" "-l 51.5 -L 0.1"))
(add-hook 'window-configuration-change-hook #'dynamic-tab-handle-tab-persistence)
; Initialize on startup
(dynamic-tab-ensure-scratch-tab))
; Desktop notifications in Emacs ; Desktop notifications in Emacs
(use-package posframe
:ensure t)
(use-package ednc (use-package ednc
:ensure t :ensure t
:after posframe
:init :init
(ednc-mode))) (defun simple-notification-popup (old-notification new-notification)
(unless (eq old-notification new-notification)
(posframe-show
" *simple-notification-popup-alert*"
:string (concat
(ednc-notification-summary new-notification)
"\n"
(ednc-notification-body new-notification))
:position (point)
:poshandler #'posframe-poshandler-frame-top-right-corner
:background-color "gold"
:foreground-color "black"
:timeout 5)))
(add-hook 'ednc-notification-presentation-functions
#'simple-notification-popup)
(ednc-mode))
;(use-package ednc-popup ;(use-package ednc-popup
; :ensure (:host git :repo "https://codeberg.org/akib/emacs-ednc-popup.git") ; :ensure (:host git :repo "https://codeberg.org/akib/emacs-ednc-popup.git")
; :after ednc ; :after ednc
@ -1067,18 +1309,32 @@
; (add-hook 'ednc-notification-presentation-functions ; (add-hook 'ednc-notification-presentation-functions
; #'ednc-popup-presentation-function)) ; #'ednc-popup-presentation-function))
(use-package kdeconnect
:ensure t
:config
(setq kdeconnect-devices '(("My Phone" . "378230a2e3c24b9a9904e7ffb0dfeb07")))
(setq kdeconnect-active-device '("My Phone" . "378230a2e3c24b9a9904e7ffb0dfeb07"))))
(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.
;; Your init file should contain only one such instance. ;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right. ;; If there is more than one, they won't work right.
'(auth-source-save-behavior nil) '(auth-source-save-behavior nil)
'(package-selected-packages nil) '(elfeed-feeds
'(#("Not found!" 0 10 (face error))
("https://www.reddit.com/r/Clamworks.rss" reddit clamworks)
("https://www.reddit.com/r/Losercity.rss" reddit losercity)
("https://www.reddit.com/r/Shark_Park.rss" reddit sharkpark)
("https://www.reddit.com/r/emacs.rss" reddit emacs)))
'(package-selected-packages
'(bash-completion consult corfu eat evil gcmh magit mu4e orderless
org-journal paredit rainbow-delimiters vertico))
'(smtpmail-smtp-server "smtp.cspark.dev") '(smtpmail-smtp-server "smtp.cspark.dev")
'(smtpmail-smtp-service 25)) '(smtpmail-smtp-service 25))
(custom-set-faces) (custom-set-faces
;; custom-set-faces was added by Custom. ;; custom-set-faces 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.
;; Your init file should contain only one such instance. ;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right. ;; If there is more than one, they won't work right.
)