diff --git a/init.el b/init.el index 2a45910..be72a1d 100644 --- a/init.el +++ b/init.el @@ -5,6 +5,7 @@ (scroll-bar-mode 0) (column-number-mode 1) +(setq package-native-compile t) (setq use-package-verbose t) (setq use-package-compute-statistics t) @@ -12,18 +13,25 @@ (global-visual-line-mode 1) (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 -(defvar custom-tab-width 8) +(defvar custom-tab-width 4) ;; Disable bell/messages sound on windows (when (eq window-system 'w32) - (set-message-beep 'silent)) + (set-message-beep 'silent)) ;; Temporary file config (setq backup-directory-alist - `((".*" . ,temporary-file-directory))) + `((".*" . ,temporary-file-directory))) (setq auto-save-file-name-transforms - `((".*" ,temporary-file-directory t))) + `((".*" ,temporary-file-directory t))) ;; Fixes to stop weird window geometry issues (setq frame-inhibit-implied-resize t) @@ -39,20 +47,20 @@ (setq-default indent-tabs-mode 't) (setq indent-tabs-mode 't) (advice-add 'indent-to :around - (lambda (orig-fun column &rest args) - (when (eq indent-tabs-mode 'only) - (setq column (* tab-width (round column tab-width)))) - (apply orig-fun column args))) + (lambda (orig-fun column &rest args) + (when (eq indent-tabs-mode 'only) + (setq column (* tab-width (round column tab-width)))) + (apply orig-fun column args))) (defvaralias 'c-basic-offset 'tab-width) (electric-indent-mode 0) ;; Hide all minor modes from the modeline (setq mode-line-modes - (mapcar (lambda (elem) - (pcase elem - (`(:propertize (,_ minor-mode-alist . ,_) . ,_) "") - (t elem))) - mode-line-modes)) + (mapcar (lambda (elem) + (pcase elem + (`(:propertize (,_ minor-mode-alist . ,_) . ,_) "") + (t elem))) + mode-line-modes)) ;; Clipboard config (setopt select-active-regions nil) @@ -62,38 +70,38 @@ (setopt interprogram-cut-function #'gui-select-text) ;; Midnight Mode -; Automatically clean up old unused buffers + ; Automatically clean up old unused buffers (midnight-mode 1) ;; Font configuration -; Global font + ; Global font (set-frame-font "MesloLGL Nerd Font 20") -; Buffer fonts + ; Buffer fonts (defun set-buffer-local-font () - "Set font for normal buffers." - (face-remap-add-relative 'default :height 260)) + "Set font for normal buffers." + (face-remap-add-relative 'default :height 260)) (add-hook 'prog-mode-hook #'set-buffer-local-font) (add-hook 'text-mode-hook #'set-buffer-local-font) -; Emacsclient new frame fonts + ; Emacsclient new frame fonts (setq default-frame-alist '((font . "MesloLGL Nerd Font 20"))) ;; Emacsclient Configuration (defun client-config () - "Ran on new emacslient frame creations." - (scroll-bar-mode 0)) + "Ran on new emacslient frame creations." + (scroll-bar-mode 0)) (add-hook 'after-make-frame-functions #'(lambda (frame) - (select-frame frame) - (client-config))) + (select-frame frame) + (client-config))) ;; Ensure TAB key ACTUALLY works like a TAB key (defun my/complete-or-tab () - "Complete at point or insert a tab if no characters before point." - (interactive) - (if (and (char-before) (not (member (char-before) '(?\s ?\t ?\n)))) ; Check for whitespace, tabs or newline - (completion-at-point) ; If yes, do completion at point - (insert-tab))) ; If no, insert a tab character + "Complete at point or insert a tab if no characters before point." + (interactive) + (if (and (char-before) (not (member (char-before) '(?\s ?\t ?\n)))) ; Check for whitespace, tabs or newline + (completion-at-point) ; If yes, do completion at point + (insert-tab))) ; If no, insert a tab character (global-set-key (kbd "TAB") 'my/complete-or-tab) (define-key global-map [remap backward-delete-char-untabify] 'backward-delete-char) @@ -104,27 +112,27 @@ (define-key global-map [remap digit-argument] "") ;; Optimisation -; GCMH -;Enforce a sneaky Garbage Collection strategy to minimize GC interference with user activity. -;During normal use a high GC threshold is set. -;When idling GC is triggered and a low threshold is set. -;This greatly improves performance/startup time of emacs. + ; GCMH + ;Enforce a sneaky Garbage Collection strategy to minimize GC interference with user activity. + ;During normal use a high GC threshold is set. + ;When idling GC is triggered and a low threshold is set. + ;This greatly improves performance/startup time of emacs. (use-package gcmh - :ensure t - :init + :ensure t + :init (gcmh-mode 1) ;; Ensure garbage collector does not run TOO frequently which causes random freezes (defun gcmh-mode-optimisation-setup-hook () - (setq gc-cons-threshold most-positive-fixnum)) + (setq gc-cons-threshold most-positive-fixnum)) (defun gcmh-mode-optimisation-exit-hook () - (setq gc-cons-threshold 800000)) + (setq gc-cons-threshold 800000)) (add-hook 'minibuffer-setup-hook 'gcmh-mode-optimisation-setup-hook) (add-hook 'minibuffer-exit-hook 'gcmh-mode-optimisation-exit-hook)) -; Fontification + ; Fontification (jit-lock-mode 1) (jit-lock-debug-mode 1) (setq jit-lock-stealth-time 1.25) @@ -133,139 +141,144 @@ (setq jit-lock-defer-time 0) (with-eval-after-load 'evil - (add-hook 'evil-insert-state-entry-hook - (lambda () - (setq jit-lock-defer-time 0.25)) nil t) - (add-hook 'evil-insert-state-exit-hook - (lambda () - (setq jit-lock-defer-time 0)) nil t)) + (add-hook 'evil-insert-state-entry-hook + (lambda () + (setq jit-lock-defer-time 0.25)) nil t) + (add-hook 'evil-insert-state-exit-hook + (lambda () + (setq jit-lock-defer-time 0)) nil t)) ;; TRAMP -;TRAMP edit files over SSH configuration + ;TRAMP edit files over SSH configuration (use-package tramp - :ensure t - :config + :ensure t + :config ;; To speed up connections (setq tramp-verbose 0 - tramp-chunksize 2000 - tramp-use-ssh-controlmaster-options nil - tramp-default-method "ssh" - tramp-verbose 1 - tramp-default-remote-shell "/bin/sh" - tramp-connection-local-default-shell-variables - '((shell-file-name . "/bin/bash") - (shell-command-switch . "-c"))) + tramp-chunksize 2000 + tramp-use-ssh-controlmaster-options nil + tramp-default-method "ssh" + tramp-verbose 1 + tramp-default-remote-shell "/bin/sh" + tramp-connection-local-default-shell-variables + '((shell-file-name . "/bin/bash") + (shell-command-switch . "-c"))) (add-to-list 'tramp-remote-path 'tramp-own-remote-path) (when (eq window-system 'w32) - (setq tramp-default-method "plink"))) + (setq tramp-default-method "plink"))) -; Tramp RPC - Alternate backend promising more speed + ; Tramp RPC - Alternate backend promising more speed (use-package tramp-rpc - :ensure (:host github :repo "ArthurHeymans/emacs-tramp-rpc") - :after tramp - :config + :ensure (:host github :repo "ArthurHeymans/emacs-tramp-rpc") + :after tramp + :config (setq tramp-rpc-deploy-local-cache-directory - "~/.cache/emacs/tramp-rpc-binaries")) + "~/.cache/emacs/tramp-rpc-binaries")) ;; Org Mode Config -; Agenda + ; Agenda (defun org-agenda-toggle-day-view () - "Toggle between daily and weekly view in org agenda." - (interactive) - (if (eq org-agenda-current-span 'day) - (org-agenda-week-view) - (org-agenda-day-view))) -;For Org-Agenda, you can set a location of your Org Agenda file here. Set Agenda Directory: + "Toggle between daily and weekly view in org agenda." + (interactive) + (if (eq org-agenda-current-span 'day) + (org-agenda-week-view) + (org-agenda-day-view))) + ;For Org-Agenda, you can set a location of your Org Agenda file here. Set Agenda Directory: (use-package org - :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. - :hook - (org-agenda-mode . (lambda() (org-agenda-entry-text-mode 1))) - :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 - ;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-startup-folded t) - (setq org-hide-emphasis-markers 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. + :config + ;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. + (setq org-fold-core-style 'overlays) + (setq org-startup-folded t) + (setq org-hide-emphasis-markers nil)) (with-eval-after-load 'org (with-eval-after-load 'evil - ; Unbind stubborn org mode bindings + ; Unbind stubborn org mode bindings (define-key org-mode-map (kbd "M-h") nil) (define-key org-mode-map (kbd "M-l") nil) (evil-define-key* '(normal) org-mode-map (kbd "M-h") nil) (evil-define-key* '(normal) org-mode-map (kbd "M-l") nil))) (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-k") 'evil-previous-line) (define-key org-agenda-mode-map "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 - :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 :ensure t - :after (org sound-wav) + :after (org org-agenda sound-wav) :config - (setq org-pomodoro-manual-break t) - (setq org-pomodoro-keep-killed-pomodoro-time t) - (setq org-pomodoro-play-sounds t) - (setq org-pomodoro-ticking-sound-p nil) - (setq org-pomodoro-audio-player "mpv")) + (setq org-pomodoro-manual-break t) + (setq org-pomodoro-keep-killed-pomodoro-time t) + (setq org-pomodoro-play-sounds t) + (setq org-pomodoro-ticking-sound-p nil) + (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 - :ensure t - :config + :ensure t + :config (alert-define-style 'custom-org-alert-notification - :title "Custom Notification" - :notifier + :title "Custom Notification" + :notifier (lambda (info) - ; 'info' is a plist containing :title, :message, :severity, etc. + ; 'info' is a plist containing :title, :message, :severity, etc. (notifications-notify - :title "Emacs Alert" - :body (plist-get info :message)) - (sound-alert (concat "ORG ALERT: " - ;(plist-get info :title) - (plist-get info :message))))) + :title "Emacs Alert" + :body (plist-get info :message)) + (sound-alert (concat "ORG ALERT: " + ;(plist-get info :title) + (plist-get info :message))))) (setq alert-default-style 'custom-org-alert-notification)) -; System notifications of org agenda items + ; System notifications of org agenda items (use-package org-wild-notifier - :ensure t - :after org - :config + :ensure t + :after org-agenda + :config ;; Notifications fire N minutes before an event (setq org-wild-notifier-alert-time '(1 10 30)) ;; Notification title and icon (setq org-wild-notifier-notification-title "Org Reminder") - ;(setq org-wild-notifier-notification-icon "/path/to/icon.png") + ;(setq org-wild-notifier-notification-icon "/path/to/icon.png") ;; Remind about day-wide events at 10am and 8pm (setq org-wild-notifier-day-wide-alert-times '("10:00" "20:00")) @@ -276,28 +289,28 @@ (setq org-wild-notifier-extra-alert-plist '(:persistent t)) (org-wild-notifier-mode)) -; Upcoming agenda items in modeline + ; Upcoming agenda items in modeline (use-package org-upcoming-modeline - :ensure t - :after org ; if you don't want it to start until org has been loaded - :config + :ensure t + :after org-agenda ; if you don't want it to start until org has been loaded + :config (org-upcoming-modeline-mode)) -; Org Mode Journalling + ; Org Mode Journalling (use-package org-journal - :ensure t - :after org - :config + :ensure t + :after org-agenda + :config (setq org-journal-dir "~/Nextcloud/Journal/") (setq org-journal-file-type 'daily) (setq org-journal-file-format "%Y%m%d.org")) ;; Org Latex Preview Scale -; Automatically toggle Org mode LaTeX fragment previews as the cursor enters and exits them + ; Automatically toggle Org mode LaTeX fragment previews as the cursor enters and exits them (use-package org-fragtog - :ensure t - :after org - :config + :ensure t + :after org + :config (add-hook 'org-mode-hook 'org-latex-preview) (add-hook 'org-mode-hook 'org-fragtog-mode) (setq org-format-latex-options (plist-put org-format-latex-options :scale 3.0))) @@ -305,8 +318,8 @@ ;; Emacs minibuffer configurations. (use-package emacs - :ensure nil - :custom + :ensure nil + :custom (tab-always-indent 'complete) ;; Enable context menu. `vertico-multiform-mode' adds a menu in the minibuffer @@ -320,45 +333,48 @@ (read-extended-command-predicate #'command-completion-default-include-p) ;; Do not allow the cursor in the minibuffer prompt (minibuffer-prompt-properties - '(read-only t cursor-intangible t face minibuffer-prompt))) + '(read-only t cursor-intangible t face minibuffer-prompt))) ;; Doom Theme (use-package doom-themes - :ensure t - :config + :ensure t + :config ;; Global settings (defaults) + (setcdr (assoc 'gnus-group-news-low-empty doom-themes-base-faces) + '(:inherit 'gnus-group-mail-1-empty :weight 'normal)) + (setq - 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-bold t ; if nil, bold is universally disabled + doom-themes-enable-italic t) ; if nil, italics is universally disabled (load-theme 'doom-gruvbox-light t)) ;; Autocompletion configuration -;(use-package ido-vertical-mode -; :ensure t -; :config (ido-vertical-mode 1)) + ;(use-package ido-vertical-mode + ; :ensure t + ; :config (ido-vertical-mode 1)) ;; Enable Vertico. (use-package vertico - :ensure t - ;;:custom - ;; (vertico-scroll-margin 0) ;; Different scroll margin - ;; (vertico-count 20) ;; Show more candidates - ;; (vertico-resize t) ;; Grow and shrink the Vertico minibuffer - ;; (vertico-cycle t) ;; Enable cycling for `vertico-next/previous' - :config + :ensure t + ;;:custom + ;; (vertico-scroll-margin 0) ;; Different scroll margin + ;; (vertico-count 20) ;; Show more candidates + ;; (vertico-resize t) ;; Grow and shrink the Vertico minibuffer + ;; (vertico-cycle t) ;; Enable cycling for `vertico-next/previous' + :config (define-key vertico-map (kbd "C-k") 'vertico-previous) (define-key vertico-map (kbd "C-j") 'vertico-next) - :init + :init (vertico-mode)) ;; Fuzzy matching for completion frameworks like Vertico (use-package orderless - :ensure t - :custom + :ensure t + :custom (completion-styles '(orderless flex basic)) (completion-category-overrides '((file (styles partial-completion)))) (completion-pcm-leading-wildcard t)) ;; Emacs 31: partial-completion behaves like substring @@ -366,8 +382,8 @@ ;; Enhanced commands that Vertico can make use of (use-package consult - :ensure t - :config + :ensure t + :config (define-key global-map [remap isearch-forward] 'consult-ripgrep) (define-key global-map [remap switch-to-buffer] 'consult-buffer) (define-key global-map [remap list-buffers] 'consult-buffer) @@ -378,446 +394,603 @@ ;; Persist history over Emacs restarts. Vertico sorts by history position. (use-package savehist - :ensure nil - :init + :ensure nil + :init (savehist-mode)) ;; Corfu Autocomplete in buffer (use-package corfu - :ensure t - :hook + :ensure t + :hook (prog-mode . corfu-mode) (html-ts-mode . corfu-mode) (css-ts-mode . corfu-mode) - ;; (shell-mode . corfu-mode) - ;; (eshell-mode . corfu-mode)) - :config + ;; (shell-mode . corfu-mode) + ;; (eshell-mode . corfu-mode)) + :config (setq - auto nil - corfu-preselect 'first)) + auto nil + corfu-preselect 'first)) - ;;(global-corfu-mode) +;;(global-corfu-mode) ;; Evil Config -; Vim Bindings + ; Vim Bindings (use-package evil - :ensure t - :bind (("" . keyboard-escape-quit)) - :init + :ensure t + :bind + (("" . 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 (setq evil-want-keybinding nil) - (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-mode 1)) -; Evil Collection, configs evil bindings for more packages + ; Evil Collection, configs evil bindings for more packages (use-package evil-collection - :after evil - :ensure t - :config + :after evil + :ensure t + :config + (setq evil-collection-setup-minibuffer t) (evil-collection-init)) +;; Proced config +(with-eval-after-load 'proced + (define-key proced-mode-map [remap proced-undo] 'proced-update)) ;; Eshell config -; Like zoxide +(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 (use-package eshell-z - :ensure t - :after tramp - :config + :ensure t + :after tramp + :config (add-hook 'eshell-mode-hook - (defun my-eshell-mode-hook () - (require 'eshell-z)))) + (defun my-eshell-mode-hook () + (require 'eshell-z)))) -; Bash completion commands in eshell + ; Bash completion commands in eshell (use-package bash-completion - :ensure t - :init + :ensure t + :init (autoload 'bash-completion-dynamic-complete - "bash-completion" - "BASH completion hook") + "bash-completion" + "BASH completion hook") (add-hook 'shell-dynamic-complete-functions - 'bash-completion-dynamic-complete) + 'bash-completion-dynamic-complete) (add-hook 'eshell-mode-hook - (lambda () - (add-hook 'completion-at-point-functions - 'bash-completion-capf-nonexclusive nil t)))) + (lambda () + (add-hook 'completion-at-point-functions + 'bash-completion-capf-nonexclusive nil t)))) -; Import bash aliases to eshell + ; Import bash aliases to eshell (defun eshell-load-bash-aliases () - "Read Bash aliases and add them to the list of eshell aliases." - ;; Bash needs to be run - temporarily - interactively - ;; in order to get the list of aliases. - (with-temp-buffer - (call-process "bash" nil '(t nil) nil "-ci" "alias") - (goto-char (point-min)) + "Read Bash aliases and add them to the list of eshell aliases." + ;; Bash needs to be run - temporarily - interactively + ;; in order to get the list of aliases. + (with-temp-buffer + (call-process "bash" nil '(t nil) nil "-ci" "alias") + (goto-char (point-min)) - ; Bash aliases to exclude - (flush-lines "^alias magit\\|^alias oc\\|^alias z\\|^alias zi\\|^alias cd\\|^alias cdi\\|^alias sudo") + ; Bash aliases to exclude + (flush-lines "^alias magit\\|^alias oc\\|^alias z\\|^alias zi\\|^alias cd\\|^alias cdi\\|^alias sudo") - (while (re-search-forward "alias \\(.+\\)='\\(.+\\)'$" nil t) - (add-to-list 'eshell-command-aliases-list (list (match-string 1) (match-string 2)))))) + (while (re-search-forward "alias \\(.+\\)='\\(.+\\)'$" nil t) + (add-to-list 'eshell-command-aliases-list (list (match-string 1) (match-string 2)))))) ;; We only want Bash aliases to be loaded when Eshell loads its own aliases, ;; rather than every time `eshell-mode' is enabled. (add-hook 'eshell-first-time-mode-hook 'eshell-load-bash-aliases t) -; Eat is a terminal emulator that can integrate nicely with eshell, allows us to run full ncurses applications inside eshell. + ; Eat is a terminal emulator that can integrate nicely with eshell, allows us to run full ncurses applications inside eshell. (use-package eat - :ensure t - :init + :ensure t + :init ;; For `eat-eshell-mode'. (add-hook 'eshell-load-hook #'eat-eshell-mode) ;; For `eat-eshell-visual-command-mode'. (add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode)) -; New create new eshell instance + ; New create new eshell instance (defun eshell/new () - (interactive) - (eshell t)) + (interactive) + (eshell t)) ;; Sudo edit command to escalate priv if need be (use-package sudo-edit - :ensure t - :config + :ensure t + :config (add-hook 'before-save-hook 'sudo-before-save-hook)) (setq tramp-auto-save-directory "~/.emacs.d/tramp-autosave") ;; Magit (use-package transient - :ensure t) + :ensure t) (use-package magit - :ensure t - :after transient) + :ensure t + :after transient) ;; Auth Source Pass - Use pass for authentication with mail (use-package auth-source-pass - :ensure nil - :init - (auth-source-pass-enable)) + :ensure nil + :init + (auth-source-pass-enable)) ;; Mu4e Mail Config (when (executable-find "mu") - (use-package mu4e - :ensure nil - :after (auth-source-pass consult) - :config - (define-key global-map [remap mu4e-search-narrow] 'consult-line) + (use-package mu4e + :ensure nil + :after (auth-source-pass consult) + :config + (define-key global-map [remap mu4e-search-narrow] 'consult-line) - (setq mu4e-mu-binary (executable-find "mu")) + (setq mu4e-mu-binary (executable-find "mu")) - ;; This is set to 't' to avoid mail syncing issues when using mbsync - (setq mu4e-change-filenames-when-moving t) + ;; This is set to 't' to avoid mail syncing issues when using mbsync + (setq mu4e-change-filenames-when-moving t) - ;; Refresh mail using isync every 10 minutes - ;(setq mu4e-update-interval (* 10 60)) - (setq mu4e-get-mail-command "mbsync -a") - (setq mu4e-maildir "~/Mail") + ;; Refresh mail using isync every 10 minutes + ;(setq mu4e-update-interval (* 10 60)) + (setq mu4e-get-mail-command "mbsync -a") + (setq mu4e-maildir "~/Mail") - ;; Sending mail function - (setq message-send-mail-function 'smtpmail-send-it) + ;; Sending mail function + (setq message-send-mail-function 'smtpmail-send-it) - ;; Make sure plain text mails flow correctly for recipients - (setq mu4e-compose-format-flowed t) + ;; Make sure plain text mails flow correctly for recipients + (setq mu4e-compose-format-flowed t) - ;; Use completing read AKA vertico - (setq mu4e-completing-read-function #'completing-read) + ;; Use completing read AKA vertico + (setq mu4e-completing-read-function #'completing-read) - ;; Immediately send SMTP with credentials - (setq smtpmail-servers-requiring-authorization "*") + ;; Immediately send SMTP with credentials + (setq smtpmail-servers-requiring-authorization "*") - (setq mu4e-contexts - (list - ;; Work account - (make-mu4e-context - :name "A CSpark Work" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/work-cspark" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "work@cspark.dev") - (user-full-name . "Curt Spark (Work)") - (smtpmail-smtp-server . "mail.cspark.dev") - (smtpmail-smtp-user . "work@cspark.dev") - (smtpmail-smtp-service . 587) - (smtpmail-stream-type . starttls) - (mu4e-compose-signature . "- Curt") - (mu4e-inbox-folder . "/work-cspark/Inbox") - (mu4e-drafts-folder . "/work-cspark/Drafts") - (mu4e-sent-folder . "/work-cspark/Sent Mail") - (mu4e-trash-folder . "/work-cspark/Trash"))) + (setq mu4e-contexts + (list + ;; Work account + (make-mu4e-context + :name "A CSpark Work" + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/work-cspark" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "work@cspark.dev") + (user-full-name . "Curt Spark (Work)") + (smtpmail-smtp-server . "mail.cspark.dev") + (smtpmail-smtp-user . "work@cspark.dev") + (smtpmail-smtp-service . 587) + (smtpmail-stream-type . starttls) + (mu4e-compose-signature . "- Curt") + (mu4e-inbox-folder . "/work-cspark/Inbox") + (mu4e-drafts-folder . "/work-cspark/Drafts") + (mu4e-sent-folder . "/work-cspark/Sent Mail") + (mu4e-trash-folder . "/work-cspark/Trash"))) - ;; Services account - (make-mu4e-context - :name "B CSpark Services" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/services-cspark" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "services@cspark.dev") - (user-full-name . "Curt Spark (services)") - (smtpmail-smtp-server . "mail.cspark.dev") - (smtpmail-smtp-user . "services@cspark.dev") - (smtpmail-smtp-service . 587) - (smtpmail-stream-type . starttls) - (mu4e-compose-signature . "- Curt") - (mu4e-inbox-folder . "/services-cspark/Inbox") - (mu4e-drafts-folder . "/services-cspark/Drafts") - (mu4e-sent-folder . "/services-cspark/Sent Mail") - (mu4e-trash-folder . "/services-cspark/Trash"))) + ;; Services account + (make-mu4e-context + :name "B CSpark Services" + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/services-cspark" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "services@cspark.dev") + (user-full-name . "Curt Spark (services)") + (smtpmail-smtp-server . "mail.cspark.dev") + (smtpmail-smtp-user . "services@cspark.dev") + (smtpmail-smtp-service . 587) + (smtpmail-stream-type . starttls) + (mu4e-compose-signature . "- Curt") + (mu4e-inbox-folder . "/services-cspark/Inbox") + (mu4e-drafts-folder . "/services-cspark/Drafts") + (mu4e-sent-folder . "/services-cspark/Sent Mail") + (mu4e-trash-folder . "/services-cspark/Trash"))) - ;; Personal account - (make-mu4e-context - :name "C CSpark Personal" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/personal-cspark" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "personal@cspark.dev") - (user-full-name . "Curt Spark (personal)") - (smtpmail-smtp-server . "mail.cspark.dev") - (smtpmail-smtp-user . "personal@cspark.dev") - (smtpmail-smtp-service . 587) - (smtpmail-stream-type . starttls) - (mu4e-compose-signature . "- Curt") - (mu4e-inbox-folder . "/personal-cspark/Inbox") - (mu4e-drafts-folder . "/personal-cspark/Drafts") - (mu4e-sent-folder . "/personal-cspark/Sent Mail") - (mu4e-trash-folder . "/personal-cspark/Trash"))) + ;; Personal account + (make-mu4e-context + :name "C CSpark Personal" + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/personal-cspark" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "personal@cspark.dev") + (user-full-name . "Curt Spark (personal)") + (smtpmail-smtp-server . "mail.cspark.dev") + (smtpmail-smtp-user . "personal@cspark.dev") + (smtpmail-smtp-service . 587) + (smtpmail-stream-type . starttls) + (mu4e-compose-signature . "- Curt") + (mu4e-inbox-folder . "/personal-cspark/Inbox") + (mu4e-drafts-folder . "/personal-cspark/Drafts") + (mu4e-sent-folder . "/personal-cspark/Sent Mail") + (mu4e-trash-folder . "/personal-cspark/Trash"))) - ;; Alerts account - (make-mu4e-context - :name "D CSpark Alerts" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/alerts-cspark" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "alerts@cspark.dev") - (user-full-name . "Curt Spark (alerts)") - (smtpmail-smtp-server . "mail.cspark.dev") - (smtpmail-smtp-user . "alerts@cspark.dev") - (smtpmail-smtp-service . 587) - (smtpmail-stream-type . starttls) - (mu4e-compose-signature . "- Curt") - (mu4e-inbox-folder . "/alerts-cspark/Inbox") - (mu4e-drafts-folder . "/alerts-cspark/Drafts") - (mu4e-sent-folder . "/alerts-cspark/Sent Mail") - (mu4e-trash-folder . "/alerts-cspark/Trash"))) + ;; Alerts account + (make-mu4e-context + :name "D CSpark Alerts" + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/alerts-cspark" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "alerts@cspark.dev") + (user-full-name . "Curt Spark (alerts)") + (smtpmail-smtp-server . "mail.cspark.dev") + (smtpmail-smtp-user . "alerts@cspark.dev") + (smtpmail-smtp-service . 587) + (smtpmail-stream-type . starttls) + (mu4e-compose-signature . "- Curt") + (mu4e-inbox-folder . "/alerts-cspark/Inbox") + (mu4e-drafts-folder . "/alerts-cspark/Drafts") + (mu4e-sent-folder . "/alerts-cspark/Sent Mail") + (mu4e-trash-folder . "/alerts-cspark/Trash"))) - ;; Tuxtank Services account - (make-mu4e-context - :name "E Tuxtank Services" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/personal-tuxtank" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "personal@tuxtank.dev") - (user-full-name . "Tuxtank (personal)") - (smtpmail-smtp-server . "mail.tuxtank.dev") - (smtpmail-smtp-user . "personal@tuxtank.dev") - (smtpmail-smtp-service . 587) - (smtpmail-stream-type . starttls) - (mu4e-compose-signature . "- Tuxtank") - (mu4e-inbox-folder . "/personal-tuxtank/Inbox") - (mu4e-drafts-folder . "/personal-tuxtank/Drafts") - (mu4e-sent-folder . "/personal-tuxtank/Sent Mail") - (mu4e-trash-folder . "/personal-tuxtank/Trash"))) + ;; Tuxtank Services account + (make-mu4e-context + :name "E Tuxtank Services" + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/personal-tuxtank" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "personal@tuxtank.dev") + (user-full-name . "Tuxtank (personal)") + (smtpmail-smtp-server . "mail.tuxtank.dev") + (smtpmail-smtp-user . "personal@tuxtank.dev") + (smtpmail-smtp-service . 587) + (smtpmail-stream-type . starttls) + (mu4e-compose-signature . "- Tuxtank") + (mu4e-inbox-folder . "/personal-tuxtank/Inbox") + (mu4e-drafts-folder . "/personal-tuxtank/Drafts") + (mu4e-sent-folder . "/personal-tuxtank/Sent Mail") + (mu4e-trash-folder . "/personal-tuxtank/Trash"))) - ;; Tuxtank Alerts account - (make-mu4e-context - :name "F Tuxtank Alerts" - :match-func - (lambda (msg) - (when msg - (string-prefix-p "/alerts-tuxtank" (mu4e-message-field msg :maildir)))) - :vars '((user-mail-address . "alerts@tuxtank.dev") - (user-full-name . "Tuxtank (alerts)") - (smtpmail-smtp-server . "mail.tuxtank.dev") - (smtpmail-smtp-user . "alerts@tuxtank.dev") - (smtpmail-smtp-service . 587) - (smtpmail-stream-type . starttls) - (mu4e-compose-signature . "- Tuxtank") - (mu4e-inbox-folder . "/alerts-tuxtank/Inbox") - (mu4e-drafts-folder . "/alerts-tuxtank/Drafts") - (mu4e-sent-folder . "/alerts-tuxtank/Sent Mail") - (mu4e-trash-folder . "/alerts-tuxtank/Trash"))))))) + ;; Tuxtank Alerts account + (make-mu4e-context + :name "F Tuxtank Alerts" + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/alerts-tuxtank" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "alerts@tuxtank.dev") + (user-full-name . "Tuxtank (alerts)") + (smtpmail-smtp-server . "mail.tuxtank.dev") + (smtpmail-smtp-user . "alerts@tuxtank.dev") + (smtpmail-smtp-service . 587) + (smtpmail-stream-type . starttls) + (mu4e-compose-signature . "- Tuxtank") + (mu4e-inbox-folder . "/alerts-tuxtank/Inbox") + (mu4e-drafts-folder . "/alerts-tuxtank/Drafts") + (mu4e-sent-folder . "/alerts-tuxtank/Sent Mail") + (mu4e-trash-folder . "/alerts-tuxtank/Trash"))))))) - ;(setq mu4e-maildir-shortcuts - ; '(("/Gmail/Inbox" . ?i) - ; ("/Gmail/[Gmail]/Sent Mail" . ?s) - ; ("/Gmail/[Gmail]/Trash" . ?t) - ; ("/Gmail/[Gmail]/Drafts" . ?d) - ; ("/Gmail/[Gmail]/All Mail" . ?a))) + ;(setq mu4e-maildir-shortcuts + ; '(("/Gmail/Inbox" . ?i) + ; ("/Gmail/[Gmail]/Sent Mail" . ?s) + ; ("/Gmail/[Gmail]/Trash" . ?t) + ; ("/Gmail/[Gmail]/Drafts" . ?d) + ; ("/Gmail/[Gmail]/All Mail" . ?a))) -; Elfeed RSS Reader + ; Elfeed RSS Reader (use-package elfeed - :ensure t - :config + :ensure t + :config (define-key global-map [remap elfeed-search-untag-all-unread] 'elfeed-update) (setq elfeed-feeds - '(("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/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)))) (use-package elfeed-goodies - :ensure t - :after elfeed - :config + :ensure t + :after elfeed + :config (elfeed-goodies/setup) (setq elfeed-goodies/entry-pane-position 'bottom) (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 "") '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 (use-package emacs-everywhere - :ensure t) + :ensure t) ;; Parinfer mode - We will use conventional 2 spaces instead of tabs for lisp -; Causing issues so will switch -;(use-package parinfer-rust-mode -; :ensure (:host github :repo "justinbarclay/parinfer-rust-mode") -; :hook -; ((emacs-lisp-mode . (lambda() -; (setq-local tab-width 2) -; (indent-tabs-mode -1) -; (parinfer-rust-mode))) -; (common-lisp-mode . (lambda() -; (setq-local tab-width 2) -; (indent-tabs-mode -1) -; (parinfer-rust-mode))))) + ; Causing issues so will switch + ;(use-package parinfer-rust-mode + ; :ensure (:host github :repo "justinbarclay/parinfer-rust-mode") + ; :hook + ; ((emacs-lisp-mode . (lambda() + ; (setq-local tab-width 2) + ; (indent-tabs-mode -1) + ; (parinfer-rust-mode))) + ; (common-lisp-mode . (lambda() + ; (setq-local tab-width 2) + ; (indent-tabs-mode -1) + ; (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 (use-package rainbow-delimiters - :ensure t - :hook + :ensure t + :hook (prog-mode . rainbow-delimiters-mode)) ;; Treesit Config (use-package treesit - :ensure nil - :commands (treesit-install-language-grammar nf/treesit-install-all-languages) - :init + :ensure nil + :commands (treesit-install-language-grammar nf/treesit-install-all-languages) + :init (setq treesit-language-source-alist - '((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) - (c . ("https://github.com/tree-sitter/tree-sitter-c")) - (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) - (css . ("https://github.com/tree-sitter/tree-sitter-css")) - (cmake . ("https://github.com/uyha/tree-sitter-cmake")) - (go . ("https://github.com/tree-sitter/tree-sitter-go")) - (html . ("https://github.com/tree-sitter/tree-sitter-html")) - (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript")) - (json . ("https://github.com/tree-sitter/tree-sitter-json")) - (julia . ("https://github.com/tree-sitter/tree-sitter-julia")) - (lua . ("https://github.com/Azganoth/tree-sitter-lua")) - (make . ("https://github.com/alemuller/tree-sitter-make")) - (ocaml . ("https://github.com/tree-sitter/tree-sitter-ocaml" "master" "ocaml/src")) - (python . ("https://github.com/tree-sitter/tree-sitter-python")) - (php . ("https://github.com/tree-sitter/tree-sitter-php")) - (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")) - (tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")) - (ruby . ("https://github.com/tree-sitter/tree-sitter-ruby")) - (rust . ("https://github.com/tree-sitter/tree-sitter-rust")) - (swift . ("https://github.com/tree-sitter/swift-tree-sitter")) - (nix . ("https://github.com/nix-community/tree-sitter-nix")) - (sql . ("https://github.com/m-novikov/tree-sitter-sql")) - (toml . ("https://github.com/tree-sitter/tree-sitter-toml")) - (zig . ("https://github.com/GrayJack/tree-sitter-zig")))) + '((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) + (c . ("https://github.com/tree-sitter/tree-sitter-c")) + (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) + (css . ("https://github.com/tree-sitter/tree-sitter-css")) + (cmake . ("https://github.com/uyha/tree-sitter-cmake")) + (go . ("https://github.com/tree-sitter/tree-sitter-go")) + (html . ("https://github.com/tree-sitter/tree-sitter-html")) + (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript")) + (json . ("https://github.com/tree-sitter/tree-sitter-json")) + (julia . ("https://github.com/tree-sitter/tree-sitter-julia")) + (lua . ("https://github.com/Azganoth/tree-sitter-lua")) + (make . ("https://github.com/alemuller/tree-sitter-make")) + (ocaml . ("https://github.com/tree-sitter/tree-sitter-ocaml" "master" "ocaml/src")) + (python . ("https://github.com/tree-sitter/tree-sitter-python")) + (php . ("https://github.com/tree-sitter/tree-sitter-php")) + (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")) + (tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")) + (ruby . ("https://github.com/tree-sitter/tree-sitter-ruby")) + (rust . ("https://github.com/tree-sitter/tree-sitter-rust")) + (swift . ("https://github.com/tree-sitter/swift-tree-sitter")) + (nix . ("https://github.com/nix-community/tree-sitter-nix")) + (sql . ("https://github.com/m-novikov/tree-sitter-sql")) + (toml . ("https://github.com/tree-sitter/tree-sitter-toml")) + (zig . ("https://github.com/GrayJack/tree-sitter-zig")))) - :config ;; Credit to https://github.com/Nathan-Furnal/dotemacs/blob/df9b845563a84a927ff762e172334cf772253a44/init.el#L1154 + :config ;; Credit to https://github.com/Nathan-Furnal/dotemacs/blob/df9b845563a84a927ff762e172334cf772253a44/init.el#L1154 (defun nf/treesit-install-all-languages () "Install all languages specified by `treesit-language-source-alist'." (interactive) (let ((languages (mapcar 'car treesit-language-source-alist))) - (dolist (lang languages) - (treesit-install-language-grammar lang) - (message "`%s' parser was installed." lang) - (sit-for 0.75))))) + (dolist (lang languages) + (treesit-install-language-grammar lang) + (message "`%s' parser was installed." lang) + (sit-for 0.75))))) (setq treesit-font-lock-level 4) -; Remap basic modes to treesit equivalent + ; Remap basic modes to treesit equivalent (use-package bash-ts-mode - :ensure nil - :mode "\\.sh\\'") + :ensure nil + :mode "\\.sh\\'") (use-package c-ts-mode - :ensure nil - :mode "\\.c\\'") + :ensure nil + :mode "\\.c\\'") (use-package rust-ts-mode - :ensure nil - :mode "\\.rs\\'") + :ensure nil + :mode "\\.rs\\'") (use-package swift-ts-mode - :ensure t - :mode "\\.swift\\'") + :ensure t + :mode "\\.swift\\'") (use-package nix-ts-mode - :ensure t - :mode "\\.nix\\'") + :ensure t + :mode "\\.nix\\'") (use-package html-ts-mode - :ensure nil - :mode "\\.html\\'") + :ensure nil + :mode "\\.html\\'") (use-package css-ts-mode - :ensure nil - :mode "\\.css\\'") + :ensure nil + :mode "\\.css\\'") (use-package js-ts-mode - :ensure nil - :mode "\\.js\\'") + :ensure nil + :mode "\\.js\\'") (use-package typescript-ts-mode - :ensure nil - :mode "\\.ts\\'") + :ensure nil + :mode "\\.ts\\'") (use-package tsx-ts-mode - :ensure nil - :mode "\\.tsx\\'") -;(use-package emacs-lisp-ts-mode -; :ensure t) -; Remap base modes to their treesitter counterpart + :ensure nil + :mode "\\.tsx\\'") + ;(use-package emacs-lisp-ts-mode + ; :ensure t) + ; Remap base modes to their treesitter counterpart (setq major-mode-remap-alist - '( - ;(emacs-lisp-mode . emacs-lisp-ts-mode) + '( + ;(emacs-lisp-mode . emacs-lisp-ts-mode) - (c-mode . c-ts-mode) - (rust-mode . rust-ts-mode) - (nix-mode . nix-ts-mode) - (rustic-mode . rust-ts-mode) - (python-mode . python-ts-mode) - (html-mode . html-ts-mode) - (css-mode . css-ts-mode) - (js-mode . js-ts-mode) - (javascript-mode . js-ts-mode))) + (c-mode . c-ts-mode) + (rust-mode . rust-ts-mode) + (nix-mode . nix-ts-mode) + (rustic-mode . rust-ts-mode) + (python-mode . python-ts-mode) + (html-mode . html-ts-mode) + (css-mode . css-ts-mode) + (js-mode . js-ts-mode) + (javascript-mode . js-ts-mode))) ;; Programming treesit style config -; Enforcing tabs as programming style + ; Enforcing tabs as programming style (add-hook 'prog-mode-hook - (lambda () - (setq-local tab-width custom-tab-width) - (setq-local indent-tabs-mode 't))) + (lambda () + (setq-local tab-width custom-tab-width) + (setq-local indent-tabs-mode 't))) (add-hook 'nix-ts-mode-hook - (lambda () - (setq-local nix-ts-mode-indent-offset custom-tab-width))) + (lambda () + (setq-local nix-ts-mode-indent-offset custom-tab-width))) (add-hook 'c-ts-mode-hook - (lambda () - (setq-local c-ts-mode-indent-style 'linux) - (setq-local c-ts-mode-indent-offset custom-tab-width) - (c-ts-mode-toggle-comment-style -1))) + (lambda () + (setq-local c-ts-mode-indent-style 'linux) + (setq-local c-ts-mode-indent-offset custom-tab-width) + (c-ts-mode-toggle-comment-style -1))) (add-hook 'rust-ts-mode-hook - (lambda () - (setq-local rust-ts-mode-indent-offset custom-tab-width))) + (lambda () + (setq-local rust-ts-mode-indent-offset custom-tab-width))) ;; Flymake Configuration (use-package flymake - :ensure nil - :hook + :ensure nil + :hook (prog-mode . flymake-mode) (emacs-lisp-mode . flymake-mode)) -; Flyover for nice in buffer flymake error/warning messages. + ; Flyover for nice in buffer flymake error/warning messages. (use-package flyover - :ensure t - :hook + :ensure t + :hook (flymake-mode . flyover-mode) - :custom + :custom ;; Checker settings (flyover-checkers '(flymake)) @@ -830,197 +1003,248 @@ ;; LSP Configuration (use-package eglot - :ensure nil - :hook + :ensure nil + :hook ((( - bash-ts-mode - c-ts-mode - rust-ts-mode - swift-ts-mode - nix-ts-mode - html-ts-mode - css-ts-mode - js-ts-mode - typescript-ts-mode - tsx-ts-mode) - . eglot-ensure)) - :custom + bash-ts-mode + c-ts-mode + rust-ts-mode + swift-ts-mode + nix-ts-mode + html-ts-mode + css-ts-mode + js-ts-mode + typescript-ts-mode + tsx-ts-mode) + . eglot-ensure)) + :custom (eglot-ignored-server-capabilities '(:documentOnTypeFormattingProvider))) ;; HTML Emmet Snippets (use-package emmet-mode - :ensure t - :hook + :ensure t + :hook (typescript-ts-mode . emmet-mode) (tsx-ts-mode . emmet-mode) (html-ts-mode . emmet-mode) (css-ts-mode . emmet-mode) - :config + :config (setq emmet-indentation custom-tab-width)) ;; JS Prettier Mode (use-package prettier-js - :ensure t - :hook + :ensure t + :hook (js-ts-mode . prettier-js-mode) (typescript-ts-mode . prettier-js-mode) (tsx-ts-mode . prettier-js-mode) - :config + :config (setq prettier-js-use-modules-bin t)) ;; Emacs desktop environment -; Emacs Wayland Manager (EWM) + ; Emacs Wayland Manager (EWM) (when (and (executable-find "ewm-launch") (string= (getenv "XDG_SESSION_DESKTOP") "ewm")) - ; Dynamic Tab (Workspace) Setup - (use-package tab-line - :ensure nil) - (setq tab-bar-show 1) ; Hide the bar if only 1 tab exists - (setq tab-bar-new-tab-choice "*scratch*") + ; Dynamic Tab (Workspace) Setup + (use-package tab-line + :ensure nil) + (tab-bar-mode) + (setq tab-bar-show 1) ; Hide the bar if only 1 tab exists + (setq tab-bar-new-tab-choice "*scratch*") - (defun dynamic-tab-ensure-scratch-tab () - "Ensures there is always a tab dedicated to *scratch*." - (let* ((tabs (funcall tab-bar-tabs-function)) - (tab-names (mapcar (lambda (tab) (alist-get 'name tab)) tabs)) - (spare-exists (member "dynamic *scratch*" tab-names)) - (is-child-frame (frame-parent))) - - ;; If we are currently IN the spare tab and it's not *scratch* anymore, - ;; or if we just want to ensure it exists at the end: - (unless (or spare-exists is-child-frame) - (let ((current-tab (tab-bar--current-tab-index))) - (tab-bar-new-tab 999) - (tab-bar-rename-tab "dynamic *scratch*") - ;; Return to original tab if we were just initializing - (tab-bar-select-tab (1+ current-tab)))))) - - (defun dynamic-tab-handle-tab-persistence () - "Create new tab if current scratch tab is being used." - (when (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*") - (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." - (when (and (not already-redirecting-p) - (string= (buffer-name) "*scratch*") - (not (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*"))) - (setq already-redirecting-p t) - (unwind-protect - (switch-to-buffer nil) - (tab-bar-select-tab-by-name "dynamic *scratch*") - (setq already-redirecting-p nil)))) + (defun dynamic-tab-ensure-scratch-tab (&rest _) + "Ensure dynamic scratch tab available if there are active buffers." + (let* ((tabs (funcall tab-bar-tabs-function)) + (tab-names (mapcar (lambda (tab) (alist-get 'name tab)) tabs)) + (spare-exists (car (member "dynamic *scratch*" tab-names))) + (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) - (defun dynamic-tab-handle-buffer-check-and-close-tab () - "Check if we need to close the tab and action accordingly." - (let* ((is-last-tab (<= (length (tab-bar-tabs)) 2)) - (is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2))) - (when (and (not is-last-tab) is-last-buffer) - (tab-close)))) - - (defun dynamic-tab-handle-tab-cleanup-kill (orig-fun &rest args) - "Free tab if all reserved in use buffers for that tab killed." - (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-overriden (nth 1 args)) - (is-target-focused (and (eq (current-buffer) (car args)))) - (is-called-interactively (called-interactively-p 'any))) + ((and is-dynamic-tab-focused (not is-scratch-buffer-focused)) t) + ((and (not is-dynamic-tab-focused) is-scratch-buffer-focused) (tab-close)) - (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))) + (t nil)))) - ((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))) + (when is-new-tab-needed + (tab-bar-rename-tab "") + (let ((current-tab (tab-bar--current-tab-index))) + (tab-bar-new-tab 999) + (tab-bar-rename-tab "dynamic *scratch*") + ;; Return to original tab if we were just initializing + (tab-bar-select-tab (1+ current-tab)))))) - ((and (not is-last-tab) (not is-last-buffer) (bury-buffer))) + (defvar dynamic-tab-is-already-redirecting-p nil + "Whether we are already redirecting to scratch tab or not.") + (defun dynamic-tab-redirect-to-scratch-tab () + "Redirect to dedicated scratch tab if scratch buffer accessed on other tab." + (when (and (not dynamic-tab-is-already-redirecting-p) + (string= (buffer-name) "*scratch*") + (string= (buffer-name) "dynamic *scratch*")) + (setq dynamic-tab-is-already-redirecting-p t) + (unwind-protect + (switch-to-buffer nil) + (tab-bar-select-tab-by-name "dynamic *scratch*") + (setq dynamic-tab-is-already-redirecting-p nil)))) - (t 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 () + "Check if we need to close the tab and action accordingly." + (let* ((is-last-tab (<= (length (tab-bar-tabs)) 2)) + (is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 1))) + (when (and (not is-last-tab) is-last-buffer) + (tab-close)))) + (defun dynamic-tab-handle-tab-cleanup-kill () + "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)) + (is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2)) + (is-marked-to-kill (cond + ;((and is-last-tab is-last-buffer) t) + ;((and is-last-tab (not is-last-buffer)) t) + ;((and is-last-tab (not is-last-buffer) (bury-buffer))) - (when (and (not is-overriden) is-target-focused) - (dynamic-tab-handle-buffer-check-and-close-tab)))) + ((and (not is-last-tab) (not is-last-buffer) dynamic-tab-soft-kill-p) (bury-buffer)) - (defun dynamic-tab-handle-tab-cleanup-close (&rest _) - "Free tab if last window open is attempted to be closed." - (if (and (> (length (tab-bar-tabs)) 2) - (= (length (window-list)) 1) - (not (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*"))) - (tab-close) - t)) + (t t)))) - ;; Helper functions for EWM - ; Switch monitor - (defun ewm-switch-to-monitor (target) - (interactive) - (select-frame-set-input-focus (car (last (seq-filter (lambda (f) - (string= target - (cdr (assq 'name (frame-monitor-attributes f))))) - (frame-list)))))) + (dynamic-tab-handle-buffer-check-and-close-tab) + is-marked-to-kill)) - ; EWM - Emacs Wayland Manager - (use-package ewm - :ensure nil - :custom - (ewm-output-config - '(("DP-1" - :width 1920 - :height 1080 - :scale 1.0 - :x 0 - :y 0 - :refresh 240) - ("HDMI-A-1" - :width 1920 - :height 1080 - :scale 1.0 - :x 1920 - :y 0 - :transform 3 - :refresh 75))) - (ewm-input-config - '((touchpad :natural-scroll t :tap t :dwt t) - (mouse :accel-profile "flat") - (keyboard :repeat-delay 150 :repeat-rate 35 - :xkb-layouts "gb"))) - ;; Per-device override (exact name from libinput) - ;("ELAN0676:00 04F3:3195 Touchpad" :tap nil :accel-speed -0.2))) - :bind (:map ewm-mode-map + (defun dynamic-tab-block-buffer-kill () + "Block buffer from being killed." + (message "You cannot kill the dynamic buffer") + nil) + (defun dynamic-tab-mark-buffer-unkillable () + "Mark buffer as unkillable." + (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 + ; Switch monitor + (defun ewm-switch-to-monitor (target) + "Switch focus to target monitor." + (interactive) + (select-frame-set-input-focus (car (last (seq-filter (lambda (f) + (string= target + (cdr (assq 'name (frame-monitor-attributes f))))) + (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 + (use-package ewm + :ensure nil + :after evil + :custom + (ewm-output-config + '(("DP-1" + :width 1920 + :height 1080 + :scale 1.0 + :x 0 + :y 0 + :refresh 240) + ("HDMI-A-1" + :width 1920 + :height 1080 + :scale 1.0 + :x 1920 + :y 0 + :transform 3 + :refresh 75))) + (ewm-input-config + '((touchpad :natural-scroll t :tap t :dwt t) + (mouse :accel-profile "flat") + (keyboard :repeat-delay 150 :repeat-rate 35 + :xkb-layouts "gb"))) + ;; Per-device override (exact name from libinput) + ;("ELAN0676:00 04F3:3195 Touchpad" :tap nil :accel-speed -0.2))) + ; Main bindings + :bind* + (:map ewm-mode-map ("M-d" . ewm-launch-app) ("s-l" . ewm-lock-session) ("M-" . eshell) ("" . (lambda () - (interactive) - (start-process-shell-command - "screenshot-process" - nil - "grim -g \"$(slurp)\" - | wl-copy"))) + (interactive) + (start-process-shell-command + "screenshot-process" + nil + "grim -g \"$(slurp)\" - | wl-copy"))) ("M-w" . (lambda () - (interactive) - (kill-buffer))) - - ; Monitor switching, find current focused monitor name via - ;(cdr (assq 'name (frame-monitor-attributes)) + (interactive) + (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 + ;(cdr (assq 'name (frame-monitor-attributes)) ("M-o" . (lambda () - (interactive) - (ewm-switch-to-monitor "XG2431"))) + (interactive) + (ewm-switch-to-monitor "XG2431"))) ("M-p" . (lambda () - (interactive) - (ewm-switch-to-monitor "24B2W1G5"))) - + (interactive) + (ewm-switch-to-monitor "24B2W1G5"))) + ;;("M-f" . (lambda () ;; (interactive) ;; (start-process-shell-command @@ -1032,40 +1256,64 @@ ("M-l" . tab-bar-switch-to-next-tab) ("M-k" . windmove-up) ("M-j" . windmove-down)) - :config - (add-to-list 'ewm-intercept-prefixes ?\M-d) - (add-to-list 'ewm-intercept-prefixes ?\M-w) - (add-to-list 'ewm-intercept-prefixes ?\M-o) - (add-to-list 'ewm-intercept-prefixes ?\M-p) - (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-l) - :init - ;; Dynamic Tabs/Workspaces setup - ; Hooks - (advice-add 'consult-buffer - :after (lambda (&rest _) - (dynamic-tab-handle-tab-persistence) - (dynamic-tab-redirect-to-scratch-tab))) - (advice-add 'delete-window :before-while #'dynamic-tab-handle-tab-cleanup-close) - (advice-add 'kill-buffer :around #'dynamic-tab-handle-tab-cleanup-kill) - ;(add-hook 'buffer-list-update-hook #'dynamic-tab-redirect-to-scratch-tab) - (add-hook 'window-configuration-change-hook #'dynamic-tab-handle-tab-persistence) - ; Initialize on startup - (dynamic-tab-ensure-scratch-tab)) + :config + (add-to-list 'ewm-intercept-prefixes '("" :fullscreen)) + (add-to-list 'ewm-intercept-prefixes ?\M-d) + (add-to-list 'ewm-intercept-prefixes ?\M-w) + (add-to-list 'ewm-intercept-prefixes ?\M-o) + (add-to-list 'ewm-intercept-prefixes ?\M-p) + (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-l) + (ewm--send-intercept-keys) + :init + ;; Dynamic Tabs + (dynamic-tab-init) - ; Desktop notifications in Emacs - (use-package ednc - :ensure t - :init - (ednc-mode))) - ;(use-package ednc-popup - ; :ensure (:host git :repo "https://codeberg.org/akib/emacs-ednc-popup.git") - ; :after ednc - ; :config - ; (add-hook 'ednc-notification-presentation-functions - ; #'ednc-popup-presentation-function)) + ;; Autostart + (ewm-autostart-application "qpwgraph") + (ewm-autostart-application "kdeconnect-indicator") + (ewm-autostart-application "udiskie") + (ewm-autostart-application "nextcloud") + (ewm-autostart-application "wlsunset" "-l 51.5 -L 0.1")) + + ; Desktop notifications in Emacs + (use-package posframe + :ensure t) + (use-package ednc + :ensure t + :after posframe + :init + (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 + ; :ensure (:host git :repo "https://codeberg.org/akib/emacs-ednc-popup.git") + ; :after ednc + ; :config + ; (add-hook 'ednc-notification-presentation-functions + ; #'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 was added by Custom. @@ -1073,12 +1321,20 @@ ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(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-service 25)) -(custom-set-faces) +(custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. - + )