Skip to content

Latest commit

 

History

History
2289 lines (1972 loc) · 89.9 KB

config.org

File metadata and controls

2289 lines (1972 loc) · 89.9 KB

Aliyss’ GNU Emacs Config

TABLE OF CONTENTS

IMPORTANT PROGRAMS

Direnv

(setq package-install-upgrade-built-in t)

(use-package direnv
  :config
  (direnv-mode))

Package Manager (Elpaca)

(defvar elpaca-installer-version 0.5)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
                              :ref nil
                              :files (:defaults (:exclude "extensions"))
                              :build (:not elpaca--activate-package)))
(let* ((repo  (expand-file-name "elpaca/" elpaca-repos-directory))
       (build (expand-file-name "elpaca/" elpaca-builds-directory))
       (order (cdr elpaca-order))
       (default-directory repo))
  (add-to-list 'load-path (if (file-exists-p build) build repo))
  (unless (file-exists-p repo)
    (make-directory repo t)
    (when (< emacs-major-version 28) (require 'subr-x))
    (condition-case-unless-debug err
        (if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
                 ((zerop (call-process "git" nil buffer t "clone"
                                       (plist-get order :repo) repo)))
                 ((zerop (call-process "git" nil buffer t "checkout"
                                       (or (plist-get order :ref) "--"))))
                 (emacs (concat invocation-directory invocation-name))
                 ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
                                       "--eval" "(byte-recompile-directory \".\" 0 'force)")))
                 ((require 'elpaca))
                 ((elpaca-generate-autoloads "elpaca" repo)))
            (progn (message "%s" (buffer-string)) (kill-buffer buffer))
          (error "%s" (with-current-buffer buffer (buffer-string))))
      ((error) (warn "%s" err) (delete-directory repo 'recursive))))
  (unless (require 'elpaca-autoloads nil t)
    (require 'elpaca)
    (elpaca-generate-autoloads "elpaca" repo)
    (load "./elpaca-autoloads")))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
;; Install use-package support
(elpaca elpaca-use-package
  ;; Enable :elpaca use-package keyword.
  (elpaca-use-package-mode)
  ;; Assume :elpaca t unless otherwise specified.
  (setq elpaca-use-package-by-default t))

;; Block until current queue processed.
(elpaca-wait)

;;When installing a package which modifies a form used at the top-level
;;(e.g. a package which adds a use-package key word),
;;use `elpaca-wait' to block until that package has been installed/configured.
;;For example:
;;(use-package general :demand t)
;;(elpaca-wait)

Evil Mode

;; Expands to: (elpaca evil (use-package evil :demand t))
(use-package evil
  :init      ;; tweak evil's configuration before loading it
  (setq evil-want-integration t) ;; This is optional since it's already set to t by default.
  (setq evil-want-keybinding nil)
  (setq evil-vsplit-window-right t)
  (setq evil-split-window-below t)
  (evil-mode)
  (evil-set-undo-system 'undo-redo)
  )
(use-package evil-collection
  :after evil
  :diminish
  :config
  (setq evil-collection-mode-list '(dashboard dired ibuffer))
  (evil-collection-init))
(use-package evil-tutor)

;; Company Mode Remap
(with-eval-after-load 'evil

  (with-eval-after-load 'company
    (define-key evil-insert-state-map (kbd "C-n") nil)
    (define-key evil-insert-state-map (kbd "C-p") nil)
    (evil-define-key nil company-active-map (kbd "C-n") #'company-select-next)
    (evil-define-key nil company-active-map (kbd "C-p") #'company-select-previous)))

(with-eval-after-load 'evil-maps
  (define-key evil-motion-state-map (kbd "SPC") nil)
  (define-key evil-motion-state-map (kbd "RET") nil)
  (define-key evil-motion-state-map (kbd "TAB") nil))

(setq org-return-follows-link  t)

General Keybindings

(use-package general
  :diminish
  :config
  (general-evil-setup)

  ;; set up 'SPC' as the global leader key
  (general-create-definer dt/leader-keys
    :states '(normal insert visual emacs)
    :keymaps 'override
    :prefix "SPC" ;; set leader
    :global-prefix "M-SPC") ;; access leader in insert mode

  ;; Top Layer Keybindings
  (dt/leader-keys
    "SPC" '(counsel-M-x :wk "Counsel M-x") ;; Double SPC to replace M-x
    "g c" '(comment-line :wk "Comment lines")) ;; This will be moved to a usable category once I find something fitting.

  ;; Buffer Keybindings
  (dt/leader-keys
    "b" '(:ignore t :wk "Buffer")
    ;; Buffer Navigation
    "b n" '(my-next-buffer :wk "Next buffer") ;; Purposely not using vim-keybindings here
    "b b" '(my-previous-buffer :wk "Previous buffer") ;; Easier for Navigation purposes
    "b r" '(revert-buffer :wk "Reload buffer")
    "b j" '(switch-to-buffer :wk "Switch buffer")
    "b c" '(kill-this-buffer :wk "Close buffer")) ;; Naming this to Close instead of Kill. Hope it is the same.

  ;; Config Keybindings
  (dt/leader-keys
    "c" '(:ignore t :wk "Config")
    "c e" '((lambda () (interactive) (find-file "~/.config/emacs/config.org")) :wk "Edit Emacs")
    "c h" '((lambda () (interactive) (find-file "~/.config/hypr/hyprland.conf")) :wk "Edit Hyprland")
    "c n" '((lambda () (interactive) (find-file "~/.config/flake/configuration.nix")) :wk "Edit Nix")
    "c r" '(reload-init-file :wk "Reload Config (emacs)"))

  ;; Treeview Keybindings
  ;; Description: Using 'e' for Explorer
  (dt/leader-keys
    "e" '(treemacs :wk "Treemacs"))

  ;; Elisp Keybindings
  ;; Description: Currently not using them.
  ;; (dt/leader-keys
  ;;   "e" '(:ignore t :wk "Evaluate")
  ;;   "e b" '(eval-buffer :wk "Evaluate elisp in buffer")
  ;;   "e d" '(eval-defun :wk "Evaluate defun containing or after point")
  ;;   "e e" '(eval-expression :wk "Evaluate and elisp expression")
  ;;   "e l" '(eval-last-sexp :wk "Evaluate elisp expression before point")
  ;;   "e r" '(eval-region :wk "Evaluate elisp in region"))

  ;; File Keybindings
  (dt/leader-keys
    "f" '(:ignore t :wk "File / Feed")
    "f f" '(find-file :wk "Find File")
    "f e" '(elfeed :wk "Elfeed")
    "f r" '(counsel-recentf :wk "Recent Files"))

  ;; Elfeed Keybindings
  (dt/leader-keys elfeed-show-mode-map
    "f p" '(elfeed-tube-mpv :wk "Elfeed Play"))

  ;; Google Calendar Keybindings
  ;; Description: Should only show in org files.
  (dt/leader-keys org-mode-map
    "g" '(:ignore t :wk "Google Calendar")
    "g p" '(org-gcal-post-at-point :wk "Post at Point")
    "g d" '(org-gcal-delete-at-point :wk "Post at Point")
    "g s" '(org-gcal-sync :wk "Sync")
    "g b" '(org-gcal-sync-buffer :wk "Sync Buffer")
    "g f" '(org-gcal-fetch :wk "Fetch"))

  ;; Help Keybindings
  ;; Description: General help or docs
  (dt/leader-keys
    "h" '(:ignore t :wk "Help")
    "h f" '(describe-function :wk "Describe function")
    "h v" '(describe-variable :wk "Describe variable"))

  ;; Ivy
  ;; Description: Honestly no clue if I actually should just remove it... never used.
  (dt/leader-keys
    "i" '(:ignore t :wk "Ivy")
    "i r" '(ivy-resume :wk "Ivy Resume")
    "i b" '(ivy-switch-buffer-other-window :wk "Switch Buffer Other Window"))


  ;; Jump Keybindings
  ;; Description: Theoretically everything one can jump to. I use this, when I know I want to change to something, but need a second to know where exactly.
  (dt/leader-keys
    "j" '(:ignore t :wk "Jump")
    "j b" '(switch-to-buffer :wk "Jump to Buffer")
    "j t" '(consult-outline :wk "Jump To Outline"))

  (general-define-key
   :states '(normal, motion)
   :keymaps 'org-mode-map
   "g d" 'org-open-at-point)

  ;; LSP Keybindings
  ;; Description: Default Keybindings for all languages.
  (dt/leader-keys
    "l" '(:ignore t :wk "LSP")
    "l i" '(lsp-describe-thing-at-point :wk "Describe Entity")
    "l r" '(lsp-rename :wk "Rename Entity")
    "l a" '(lsp-execute-code-action :wk "Code Action")
    "l u" '(lsp-ui-imenu :wk "UI Menu")
    "l d" '(lsp-ui-peek-find-definitions :wk "Find Definitions")
    "l r" '(lsp-ui-peek-find-references :wk "Find References")
    "l q" '(lsp-workspace-restart :wk "Restart Workspace")
    "l e" '(flycheck-list-errors :wk "List Errors") ;; FlyCheck, but keeping it under LSP, since it feels correct here.
    "l c" '(lsp-command-map :wk "LSP Command Map")) ;; Does not work... need to find something else.

  ;; Rust Keybindings
  ;; Description: Should only show in rust files.
  (dt/leader-keys rustic-mode-map
    "l s" '(lsp-rust-analyzer-status :wk "LSP Rust Analyzer Status"))

  ;; Org Keybindings
  ;; Description: Not yet that fluent with org-mode to change anything from the defaults I used in vim.
  (dt/leader-keys
    "m" '(:ignore t :wk "Org")
    "m a" '(org-agenda :wk "Org agenda")
    "m e" '(org-export-dispatch :wk "Org export dispatch")
    "m i" '(org-toggle-item :wk "Org toggle item")
    "m t" '(org-todo :wk "Org todo")
    "m B" '(org-babel-tangle :wk "Org babel tangle")
    "m T" '(org-todo-list :wk "Org todo list")
    ;; Org Tables
    "m b" '(:ignore t :wk "Tables")
    "m b -" '(org-table-insert-hline :wk "Insert hline in table")
    ;; Org Dates & Deadlines
    "m d" '(:ignore t :wk "Date/deadline")
    "m d t" '(org-time-stamp :wk "Org time stamp"))


  ;; Org-Roam Keybindings
  ;; Description: Not yet that fluent with org-mode to change anything from the defaults I used in vim.
  (dt/leader-keys
    "r" '(:ignore t :wk "Roam")
    "r f" '(org-roam-node-find :wk "Node find")
    "r d" '(:ignore t :wk "Roam Dailies")
    "r d y" '(org-roam-dailies-goto-yesterday :wk "Go To Yesterday")
    "r d d" '(org-roam-dailies-goto-today :wk "Go To Today")
    "r d t" '(org-roam-dailies-goto-tomorrow :wk "Go To Tomorrow")
    "r d x" '(org-roam-dailies-goto-date :wk "Go To Date")
    "r i" '(org-roam-node-insert :wk "Node insert")
    "r c" '(completion-at-point :wk "Completion"))

  ;; Projectile Keybindings
  (dt/leader-keys
    "p" '(projectile-command-map :wk "Projectile"))

  ;; Sudo Keybindings
  (dt/leader-keys
    "s" '(:ignore t :wk "Sudo")
    "sf" '(sudo-edit-find-file :wk "Sudo find file")
    "su" '(sudo-edit :wk "Sudo edit file"))

  ;; Terminal Keybindings
  (dt/leader-keys
    "t" '(:ignore t :wk "Terminal")
    ;; Terminal: EShell
    "t e" '(:ignore t :wk "EShell")
    "t e n" '(eshell :wk "Launch EShell")
    "t e h" '(counsel-esh-history :wk "Show EShell History")
    ;; Terminal: Terminal
    "t t" '(vterm-toggle :wk "Toggle Terminal"))

  (dt/leader-keys
    "v" '(:ignore t :wk "View")
    "v l" '(display-line-numbers-mode :wk "Toggle line numbers")
    "v t" '(visual-line-mode :wk "Toggle truncated lines"))

  ;; Window Keybindings
  (dt/leader-keys
    "w" '(:ignore t :wk "Window")
    "w n" '(evil-window-new :wk "New Window")
    "w c" '(evil-window-delete :wk "Close Window")
    ;; Window splits
    "w s" '(evil-window-split :wk "Horizontal Window Split")
    "w v" '(evil-window-vsplit :wk "Vertical Window Split")
    ;; Window Motions
    "w h" '(evil-window-left :wk "Move Window left")
    "w j" '(evil-window-down :wk "Move Window down")
    "w k" '(evil-window-up :wk "Move Window up")
    "w l" '(evil-window-right :wk "Move Window right")
    "w w" '(evil-window-next :wk "GoTo Next Window")
    ;; Window Buffer Movements
    "w b" '(:ignore t :wk "Window Buffer")
    "w b h" '(buf-move-left :wk "Move Buffer left")
    "w b j" '(buf-move-down :wk "Move Buffer down")
    "w b k" '(buf-move-up :wk "Move Buffer up")
    "w b l" '(buf-move-right :wk "Move Buffer right"))
  )

GRAPHICAL USER INTERFACE TWEAKS

Reload Emacs

(defun reload-init-file ()
  (interactive)
  (load-file user-init-file)
  (load-file user-init-file))

Disable Menubar, Toolbars and Scrollbars

(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(setq use-dialog-box nil)

Scrolling

(setq scroll-margin 10
      scroll-step 1
      scroll-conservatively 101
      scroll-up-aggressively 0.01
      scroll-down-aggressively 0.01
      scroll-preserve-screen-position t
      auto-window-vscroll nil)

Editor

;; Spaces vs Tabs
(setq-default indent-tabs-mode nil)

;; Highlight current line
(add-hook 'prog-mode-hook #'hl-line-mode)
(add-hook 'text-mode-hook #'hl-line-mode)
(add-hook 'org-mode-hook #'hl-line-mode)

;; Automatically create matching parenthesis
(add-hook 'prog-mode-hook (electric-pair-mode t))
(add-hook 'prog-mode-hook (show-paren-mode t))

;; Remove unnecessary whitespace on save
(add-hook 'before-save-hook 'delete-trailing-whitespace)

Display Line Numbers and Truncated Lines

(global-display-line-numbers-mode 1)
(set-default 'truncate-lines nil)
(set-default 'word-wrap t)
(add-hook 'org-mode-hook #'visual-line-mode)

(setq display-line-numbers-type 'relative)

Transparency

(set-frame-parameter (selected-frame) 'alpha-background 0.8)
(set-background-color "black")

THEMEING

Themes

Doom Theme

;; (use-package doom-themes
;;   :ensure t
;;   :config
;;   (setq 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-challenger-deep t))

EF Theme

(use-package ef-themes
  :ensure t
  :bind ("C-c m" . ef-themes-toggle)

  :init
  (setq ef-themes-headings
        '((0 . (1.9))
          (1 . (1.3))
          (2 . (1.2))
          (3 . (1.1))
          (4 . (1.0))
          (5 . (1.0)) ; absence of weight means `bold'
          (6 . (1.0))
          (7 . (1.0))
          (t . (1.0))))
  (setq ef-themes-to-toggle '(ef-cherie ef-elea-dark))

  (defvar my:theme 'ef-elea-dark)
  (defvar my:theme-window-loaded nil)
  (defvar my:theme-terminal-loaded nil)

  (if (daemonp)
      (add-hook 'after-make-frame-functions(lambda (frame)
                                             (select-frame frame)
                                             (if (window-system frame)
                                                 (unless my:theme-window-loaded
                                                   (if my:theme-terminal-loaded
                                                       (enable-theme my:theme)
                                                     (load-theme my:theme t)
                                                     )
                                                   (setq my:theme-window-loaded t))
                                               (unless my:theme-terminal-loaded
                                                 (if my:theme-window-loaded
                                                     (enable-theme my:theme)
                                                   (load-theme my:theme t)
                                                   )
                                                 (setq my:theme-terminal-loaded t)))

                                             (set-frame-parameter (selected-frame) 'alpha-background 0.8)
                                             (set-background-color "black")
                                             ))

    (progn
      (load-theme my:theme t)
      (if (display-graphic-p)
          (setq my:theme-window-loaded t)
        (setq my:theme-terminal-loaded t))))

  )

All The Icon

(use-package all-the-icons
  :if (display-graphic-p)
  :config
  ;;(setq all-the-icons-scale-factor 1)
  )

Frame Border

(modify-all-frames-parameters
 '((right-divider-width . 0) ;; Changing this value will do border changes.
   (internal-border-width . 0))) ;; Changing this value will do border changes.

(dolist (face '(window-divider
                window-divider-first-pixel
                window-divider-last-pixel))
  (face-spec-reset-face face)
  (set-face-foreground face (face-attribute 'default :background)))

(set-face-background 'fringe (face-attribute 'default :background))

SRC Blocks

;; (custom-set-faces
;;  '(org-block-begin-line
;;    ((t (:background nil :extend t))))
;;  '(org-block-end-line
;;    ((t (:background nil :extend t))))
;;  )

Rainbow Mode

(use-package rainbow-mode
  :diminish
  :hook org-mode prog-mode)

Rainbow Delimiters

(use-package rainbow-delimiters
  :ensure t
  )
(add-hook 'foo-mode-hook #'rainbow-delimiters-mode)
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)

ADDITIONAL PROGRAMS

IVY (COUNSEL)

(use-package ivy
  :custom
  (setq ivy-use-virtual-buffers t)
  (setq ivy-count-format "(%d/%d) ")
  (setq enable-recursive-minibuffers t)
  :diminish
  :config
  (ivy-mode))

(use-package counsel
  :after ivy
  :diminish
  :config (counsel-mode))

(use-package all-the-icons-ivy-rich
  :ensure t
  :init (all-the-icons-ivy-rich-mode 1))

(use-package ivy-rich
  :after ivy
  :ensure t
  :init (ivy-rich-mode 1) ;; this gets descriptions in M-x.
  :custom
  (ivy-virtual-abbreviate 'full
                          ivy-rich-switch-buffer-align-virtual-buffer t
                          ivy-rich-path-style 'abbrev)
  :diminish
  :config
  (ivy-set-display-transformer 'ivy-switch-buffer
                               'ivy-rich-switch-buffer-transformer)
  )

(with-eval-after-load 'ivy
  (add-to-list 'ivy-ignore-buffers "\\*Async-native-compile-log\\*")
  (add-to-list 'ivy-ignore-buffers "\\*Ibuffer\\*")
  (add-to-list 'ivy-ignore-buffers "\\*Command Line\\*")
  (add-to-list 'ivy-ignore-buffers "\\*Messages\\*"))

(use-package ivy-posframe
  :after ivy
  :ensure t
  :config (ivy-posframe-mode)
  )

;; display at `ivy-posframe-style'
(setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-center)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-window-center)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-bottom-left)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-window-bottom-left)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-top-center)))
                                        ; (ivy-posframe-mode 1)

Diminish

(use-package diminish)

FlyCheck

(use-package flycheck
  :ensure t
  :defer t
  :diminish
  :config (global-flycheck-mode)
  (setq flymake-no-changes-timeout t)
  (setq flymake-start-syntax-check-on-newline t)
  (setq flycheck-check-syntax-automatically '(save mode-enabled))
  )

FlyCheck PosFrame

;; (use-package flycheck-posframe
;;   :ensure t
;;   :after flycheck
;;   :config (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode))

Projectile

(use-package projectile
  :diminish
  :config
  (projectile-mode 1))

Projectile FlyCheck

(use-package flycheck-projectile
  :elpaca '(flycheck-projectile :host github :repo "nbfalcon/flycheck-projectile")
  )

Company

(use-package company
  :defer 2
  :ensure t
  :hook (
         (emacs-lisp-mode . (lambda ()
                              (setq-local company-backends '(company-elisp))))
         (emacs-lisp-mode . company-mode))
  :diminish
  :custom
  (company-begin-commands '(self-insert-command))
  (company-idle-delay .1)
  (company-minimum-prefix-length 1)
  (company-show-numbers t)
  (company-tooltip-align-annotations 't)
  (global-company-mode t))

(use-package company-box
  :after company
  :diminish
  :hook (company-mode . company-box-mode))

Consult

(use-package consult
  :ensure t
  )

Which-Key

(use-package which-key
  :init
  (which-key-mode 1)
  :diminish
  :config
  (setq which-key-side-window-location 'bottom
        which-key-sort-order #'which-key-key-order-alpha
        which-key-sort-uppercase-first nil
        which-key-add-column-padding 1
        which-key-max-display-columns nil
        which-key-min-display-lines 6
        which-key-side-window-slot -10
        which-key-side-window-max-height 0.25
        which-key-idle-delay 0.8
        which-key-max-description-length 25
        which-key-allow-imprecise-window-fit nil
        which-key-allow-evil-operators t
        which-key-show-operator-state-maps t
        which-key-separator "" ))

SUDO

SUDO EDIT

(use-package sudo-edit)

SSH

(defun connect-remote ()
  (interactive)
  (dired "/ssh:[email protected]:/"))

(use-package ssh)
(add-hook 'ssh-mode-hook
          (lambda ()
            (setq ssh-directory-tracking-mode t)
            (shell-dirtrack-mode t)
            (setq dirtrackp nil)))

TERMINALS

EShell

(use-package eshell-syntax-highlighting
  :after esh-mode
  :diminish
  :config
  (eshell-syntax-highlighting-global-mode +1))

;; eshell-syntax-highlighting -- adds fish/zsh-like syntax highlighting.
;; eshell-rc-script -- your profile for eshell; like a bashrc for eshell.
;; eshell-aliases-file -- sets an aliases file for the eshell.

(setq eshell-rc-script (concat user-emacs-directory "eshell/profile")
      eshell-aliases-file (concat user-emacs-directory "eshell/aliases")
      eshell-history-size 5000
      eshell-buffer-maximum-lines 5000
      eshell-hist-ignoredups t
      eshell-scroll-to-bottom-on-input t
      eshell-destroy-buffer-when-process-dies t
      eshell-visual-commands'("bash" "fish" "htop" "ssh" "top" "zsh"))

VTerm

(use-package vterm
  :ensure t
  :diminish
  :config
   (add-hook 'vterm-mode-hook 'turn-off-evil-mode)
)

Vterm-Toggle

(use-package vterm-toggle
  :after vterm
  :diminish
  :config
  (setq vterm-toggle-fullscreen-p nil)
  (setq vterm-toggle-scope 'project)
  (add-to-list 'display-buffer-alist
               '((lambda (buffer-or-name _)
                   (let ((buffer (get-buffer buffer-or-name)))
                     (with-current-buffer buffer
                       (or (equal major-mode 'vterm-mode)
                           (string-prefix-p vterm-buffer-name (buffer-name buffer))))))
                 ;;(display-buffer-reuse-window display-buffer-at-bottom)
                 (display-buffer-reuse-window display-buffer-in-direction)
                 ;;display-buffer-in-direction/direction/dedicated is added in emacs27
                 ;;(direction . bottom)
                 ;;(dedicated . t) ;dedicated is supported in emacs27
                 (reusable-frames . visible)
                 (window-height . 0.3))))

HOMESCREEN

Dashboard

(use-package dashboard
  :ensure t
  :init
  (setq initial-buffer-choice 'dashboard-open)
  (setq dashboard-set-heading-icons t)
  (setq dashboard-set-file-icons t)
  (setq dashboard-icon-type 'all-the-icons) ;; use `all-the-icons' package
  (setq dashboard-banner-logo-title "Aliyss' new Operating System (UwU)")
  ;; (setq dashboard-startup-banner 'logo) ;; use standard emacs logo as banner
  (setq dashboard-startup-banner "~/.config/emacs/images/alice-love.webp")  ;; use custom image as banner
  (setq dashboard-center-content t) ;; set to 't' for centered content
  (setq dashboard-items '((recents . 5)
                          (agenda . 5 )
                          (bookmarks . 3)
                          (projects . 3)
                          (registers . 3)))
  ;; (dashboard-modify-heading-icons '((recents . "file-text")
  ;; (bookmarks . "book")))
  (setq dashboard-footer-messages '("I am not a human, dear reader, but a yeti. A human requires to be, I can only hope not to be another figment of imagination."))
  (setq dashboard-footer-icon nil)
  :config
  (dashboard-setup-startup-hook))

LAUNCHERS

App Launcher

(use-package app-launcher
  :elpaca '(app-launcher :host github :repo "SebastienWae/app-launcher"))

(defun emacs-run-launcher ()
  "Create and select a frame called emacs-run-launcher which consists only of a minibuffer and has specific dimensions. Runs app-launcher-run-app on that frame, which is an emacs command that prompts you to select an app and open it in a dmenu like behaviour. Delete the frame after that command has exited"
  (interactive)
  (with-selected-frame
      (make-frame '((name . "emacs-run-launcher")
                    (minibuffer . only)
                    (fullscreen . 0) ; no fullscreen
                    (undecorated . nil) ; remove title bar
                    ;;(auto-raise . t) ; focus on this frame
                    ;;(tool-bar-lines . 0)
                    ;;(menu-bar-lines . 0)
                    (internal-border-width . 10)
                    (width . 100)
                    (height . 11)))
    (unwind-protect
        (app-launcher-run-app)
      (delete-frame))))

Git

Magit

(use-package magit
  :ensure t)

LANGUAGE SUPPORT

LSP

(use-package yasnippet
  :ensure t
  :config
  (yas-global-mode 1)
  )

(use-package lsp-mode
  :ensure t
  :commands lsp
  :custom
  (lsp-eldoc-render-all t)
  ;; enable / disable the hints as you prefer:
  (lsp-rust-analyzer-server-display-inlay-hints t)
  ;; what to use when checking on-save. "check" is default, I prefer clippy
  (lsp-rust-analyzer-cargo-watch-command "clippy")
  (lsp-rust-analyzer-display-lifetime-elision-hints-enable "skip_trivial")
  (lsp-rust-analyzer-display-chaining-hints t)
  (lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names t)
  (lsp-rust-analyzer-display-closure-return-type-hints t)
  (lsp-rust-analyzer-display-parameter-hints t)
  (lsp-rust-analyzer-display-reborrow-hints t)
  ;; :config
  :config
  (add-hook 'lsp-mode-hook 'lsp-ui-mode)
  (add-hook 'lsp-mode-hook #'lsp-enable-which-key-integration)

  (add-hook 'tsx-ts-mode-hook 'lsp-deferred)
  (add-hook 'tsi-typescript-mode-hook 'lsp-deferred)
  (add-hook 'ts-ls-mode-hook 'lsp-deferred)
  (add-hook 'typescript-mode-hook 'lsp-deferred)
  (add-hook 'javascript-mode-hook 'lsp-deferred)
  (add-hook 'json-mode-hook 'lsp-deferred)
  (add-hook 'nix-mode-hook 'lsp-deferred)
  (add-hook 'dart-mode-hook 'lsp-deferred)
  (setq lsp-auto-guess-root t)
  (setq lsp-log-io nil)
  (setq lsp-restart 'auto-restart)
  (setq lsp-enable-symbol-highlighting t)
  (setq lsp-enable-on-type-formatting t)
  (setq lsp-signature-auto-activate t)
  (setq lsp-signature-render-documentation nil)
  (setq lsp-eldoc-hook nil)
  (setq lsp-modeline-code-actions-enable t)
  (setq lsp-modeline-diagnostics-enable t)
  (setq lsp-headerline-breadcrumb-enable t)
  (setq lsp-semantic-tokens-enable nil)
  (setq lsp-enable-folding t)
  (setq lsp-enable-imenu t)
  (setq lsp-enable-snippet t)
  (setq read-process-output-max (* 1024 1024)) ;; 1MB
  (setq lsp-idle-delay 0.2))

(use-package lsp-ui
  :ensure t
  :commands lsp-ui-mode
  :config
  (setq lsp-ui-doc-enable t)
  (setq lsp-ui-doc-header t)
  (setq lsp-ui-doc-include-signature t)
  (setq lsp-ui-sideline-show-code-actions t)
  (setq lsp-ui-peek-expand-function (lambda (xs) (mapcar #'car xs)))

  ;; (setq lsp-ui-sideline-show-code-diagnostics t)
  (setq lsp-ui-sideline-delay 0.05))
;; eldoc multiline is default enabled, can be disabled if necessary.
(setq eldoc-echo-area-use-multiline-p t)

LSP Performance

(setq gc-cons-threshold 100000000)
(setq read-process-output-max (* 1024 1024)) ;; 1mb

LSP Location Exclusions

Autoformat

(use-package apheleia
  :ensure t
  :config
  (apheleia-global-mode +1))

(add-hook 'nix-mode-hook 'nixpkgs-fmt-on-save-mode)

Syntax Highlighting

(setq font-lock-maximum-decoration t)
(setq auto-mode-alist (append '((".*\\.conf$" . conf-desktop-mode)) auto-mode-alist))
(setq auto-mode-alist (append '((".*\\.env$" . dotenv-mode)) auto-mode-alist))
(setq auto-mode-alist (append '((".*\\.cjs$" . js-mode)) auto-mode-alist))
(setq auto-mode-alist (append '((".*\\.html$" . web-mode)) auto-mode-alist))
(setq auto-mode-alist (append '((".*\\.glsl$" . glsl-mode)) auto-mode-alist))

Modes

(use-package haskell-mode)
(use-package lua-mode)
(use-package json-mode)
(use-package web-mode)
(use-package rust-mode)
(use-package yaml-mode)
(use-package dotenv-mode
  :elpaca '(dotenv-mode :host github :repo "preetpalS/emacs-dotenv-mode")
  :ensure t
  )
(use-package nix-mode
  :mode "\\.nix\\'")

(use-package coverlay
  :ensure t
  )

(use-package origami
  :ensure t)

(use-package lsp-tailwindcss
  :ensure t
  :init
  (setq lsp-tailwindcss-add-on-mode t)
  )

(defun set-flutter-sdk-dir ()
  (direnv-update-environment)
  (setq lsp-dart-flutter-sdk-dir
        (string-trim-right (shell-command-to-string "echo $FLUTTER_SDK"))))

(use-package dart-mode
  :init
  (add-hook 'dart-mode-hook 'set-flutter-sdk-dir)

  :hook (dart-mode . flutter-test-mode))

;; Assuming usage with dart-mode
(use-package dart-mode
  ;; Optional
  )

(use-package lsp-dart
  :ensure t
  :config
  :hook (dart-mode . lsp))

(use-package flutter
  :after dart-mode
  :bind (:map dart-mode-map
              ("C-M-x" . #'flutter-run-or-hot-reload))
  :custom
  (flutter-sdk-path 'set-flutter-sdk-dir))

(add-hook 'before-save-hook 'lsp-tailwindcss-rustywind-before-save)

Treesitter

(use-package tree-sitter
  :ensure t
  :config
  ;; activate tree-sitter on any buffer containing code for which it has a parser available
  (global-tree-sitter-mode)
  ;; you can easily see the difference tree-sitter-hl-mode makes for python, ts or tsx
  ;; by switching on and off
  (add-hook 'typescript-mode-hook #'tree-sitter-hl-mode)
  (add-hook 'typescript-mode-hook #'lsp-mode)
  )

(use-package tree-sitter-langs
  :ensure t
  :after tree-sitter)

GLSL

(provide 'glsl-mode)

(eval-when-compile			; required and optional libraries
  (require 'cc-mode)
  (require 'find-file))

(defconst glsls-version "1.0"
  "OpenGLSL major mode version number.")

(defvar glsl-mode-hook nil)

(defvar glsl-mode-map
  (let ((glsl-mode-map (make-sparse-keymap)))
    (define-key glsl-mode-map [S-iso-lefttab] 'ff-find-other-file)
    glsl-mode-map)
  "Keymap for GLSL major mode")

(add-to-list 'auto-mode-alist '("\\.vert\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.frag\\'" . glsl-mode))

(defconst glsl-font-lock-keywords-1
  (list
   '("\\<\\(b\\(?:ool\\|vec[1-4]\\)\\|float\\|i\\(?:nt\\|vec[1-4]\\)\\|mat[234]\\|sampler\\(?:1D\\(?:Shadow\\)?\\|2D\\(?:Shadow\\)?\\|3D\\|Cube\\)\\|v\\(?:ec[1-4]\\|oid\\)\\)\\>" . font-lock-type-face)
   '("\\<\\(attribute\\|break\\|con\\(?:st\\|tinue\\)\\|d\\(?:iscard\\|o\\)\\|else\\|for\\|i\\(?:nout\\|[fn]\\)\\|out\\|return\\|struct\\|uniform\\|varying\\|while\\)\\>" . font-lock-keyword-face)
   '("\\<\\(a\\(?:bs\\|cos\\|ll\\|ny\\|\\(?:si\\|ta\\)n\\)\\|c\\(?:eil\\|lamp\\|\\(?:o\\|ros\\)s\\)\\|d\\(?:Fd[xy]\\|istance\\|ot\\)\\|e\\(?:qual\\|xp2?\\)\\|f\\(?:aceforward\\|loor\\|ract\\|transform\\|width\\)\\|greaterThan\\(?:Equal\\)?\\|inversesqrt\\|l\\(?:e\\(?:ngth\\|ssThan\\(?:Equal\\)?\\)\\|og2?\\)\\|m\\(?:a\\(?:trixCompMult\\|x\\)\\|in\\|ode\\)\\|no\\(?:ise[1-4]\\|rmalize\\|t\\(?:Equal\\)?\\)\\|pow\\|r\\(?:adians\\|ef\\(?:\\(?:le\\|ra\\)ct\\)\\)\\|s\\(?:hadow\\(?:1D\\(?:Lod\\|Proj\\(?:Lod\\)?\\)?\\|2D\\(?:Lod\\|Proj\\(?:Lod\\)?\\)?\\)\\|i\\(?:g?n\\)\\|moothstep\\|qrt\\|tep\\)\\|t\\(?:an\\|exture\\(?:1D\\(?:Lod\\|Proj\\(?:Lod\\)?\\)?\\|2D\\(?:Lod\\|Proj\\(?:Lod\\)?\\)?\\|3D\\(?:Lod\\|Proj\\(?:Lod\\)?\\)?\\|Cube\\(?:Lod\\)?\\)\\)\\)\\>" . font-lock-builtin-face)
   '("\\<\\(gl_\\(?:Back\\(?:Color\\|Light\\(?:\\(?:Model\\)?Product\\)\\|Material\\|SecondaryColor\\)\\|C\\(?:lipVertex\\|olor\\(?:\\)?\\)\\|DepthRange\\(?:\\)?\\|EyePlane[Q-T]\\|F\\(?:og\\(?:Coord\\)?\\|r\\(?:ag\\(?:Co\\(?:lor\\|ord\\)\\|D\\(?:ata\\|epth\\)\\)\\|ont\\(?:Color\\|Facing\\|Light\\(?:\\(?:Model\\)?Product\\)\\|Material\\|SecondaryColor\\)\\)\\)\\|LightSource\\|M\\(?:ax\\(?:\\(?:C\\(?:lipPlane\\|ombinedTextureImageUnit\\)\\|DrawBuffer\\|FragmentUniformComponent\\|Light\\|Texture\\(?:Coord\\|\\(?:Image\\)?Unit\\)\\|V\\(?:aryingFloat\\|ertex\\(?:Attrib\\|\\(?:TextureImageUni\\|UniformComponen\\)t\\)\\)\\)s\\)\\|odelView\\(?:Matrix\\(?:\\(?:Inver\\(?:seTranspo\\)?\\|Transpo\\)se\\)?\\|ProjectionMatrix\\(?:\\(?:Inver\\(?:seTranspo\\)?\\|Transpo\\)se\\)?\\)\\|ultiTexCoord[0-7]\\)\\|Normal\\(?:Matrix\\|Scale\\)?\\|ObjectPlane[Q-T]\\|P\\(?:o\\(?:int\\(?:Size\\)??\\|sition\\)\\|rojectionMatrix\\(?:\\(?:Inver\\(?:seTranspo\\)?\\|Transpo\\)se\\)?\\)\\|SecondaryColor\\(?:\\)?\\|Tex\\(?:Coord\\|ture\\(?:EnvColor\\|Matrix\\(?:\\(?:Inver\\(?:seTranspo\\)?\\|Transpo\\)se\\)?\\)\\)\\|Vertex\\)\\)\\>" . font-lock-variable-name-face)
   )
  "Minimal highlighting expressions for GLSL mode")

(defvar glsl-font-lock-keywords glsl-font-lock-keywords-1
  "Default highlighting expressions for GLSL mode")

(defvar glsl-mode-syntax-table
  (let ((glsl-mode-syntax-table (make-syntax-table)))
    (modify-syntax-entry ?/ ". 124b" glsl-mode-syntax-table)
    (modify-syntax-entry ?* ". 23" glsl-mode-syntax-table)
    (modify-syntax-entry ?\n "> b" glsl-mode-syntax-table)
    glsl-mode-syntax-table)
  "Syntax table for glsl-mode")

(defvar glsl-other-file-alist
  '(("\\.frag$"
     (".vert"))
    ("\\.vert$"
     (".frag")))
  "Alist of extensions to find given the current file's extension")

(define-derived-mode glsl-mode c-mode "GLSL"
  "Major mode for editing OpenGLSL shader files."
  (set (make-local-variable 'font-lock-defaults) '(glsl-font-lock-keywords))
  (set (make-local-variable 'ff-other-file-alist) 'glsl-other-file-alist)
  )

Python

(setq lsp-pyright-python-executable-cmd "python3")

(use-package lsp-pyright
  :hook (python-mode . (lambda () (require 'lsp-pyright) (lsp-deferred)))
  :init (when (executable-find "python3")
          (setq lsp-pyright-python-executable-cmd "python3")))

Rustic

(use-package rustic
  :ensure t
  :config
  ;; uncomment for less flashiness
  ;; (setq lsp-eldoc-hook nil)
  ;; (setq lsp-enable-symbol-highlighting nil)
  ;; (setq lsp-signature-auto-activate nil)

  ;; comment to disable rustfmt on save
  (setq rustic-format-on-save t))

Javascript / Typescript

(use-package add-node-modules-path
  :ensure t
  :hook ((typescript-mode . add-node-modules-path)))

(use-package typescript-mode
  :after tree-sitter
  :config
  ;; we choose this instead of tsx-mode so that eglot can automatically figure out language for server
  ;; see https://github.com/joaotavora/eglot/issues/624 and https://github.com/joaotavora/eglot#handling-quirky-servers
  (define-derived-mode typescriptreact-mode typescript-mode
    "TypeScript TSX")

  ;; use our derived mode for tsx files
  (setq auto-mode-alist (append '((".*\\.tsx?" . typescriptreact-mode)) auto-mode-alist))
  ;; by default, typescript-mode is mapped to the treesitter typescript parser
  ;; use our derived mode to map both .tsx AND .ts -> typescriptreact-mode -> treesitter tsx
  (add-to-list 'tree-sitter-major-mode-language-alist '(typescriptreact-mode . tsx))

  (add-hook 'typescript-mode-after-on-hook #'lsp-mode)
  )


;; https://github.com/orzechowskid/tsi.el/
;; great tree-sitter-based indentation for typescript/tsx, css, json
(use-package tsi
  :after tree-sitter
  :elpaca '(tsi :host github :repo "orzechowskid/tsi.el")
  ;; define autoload definitions which when actually invoked will cause package to be loaded
  :commands (tsi-typescript-mode tsi-json-mode tsi-css-mode lsp-mode)
  :init
  (add-hook 'typescript-mode-hook (lambda () (tsi-typescript-mode 1)))
  (add-hook 'json-mode-hook (lambda () (tsi-json-mode 1)))
  (add-hook 'css-mode-hook (lambda () (tsi-css-mode 1)))
  (add-hook 'scss-mode-hook (lambda () (tsi-scss-mode 1))))

Eglot

(use-package eglot
  :ensure t
  :config
  ;; Ensure `nil` is in your PATH.
  (add-to-list 'eglot-server-programs '(nix-mode . ("nil")))
  ;;(add-to-list 'eglot-server-programs '(typescript-mode . ("typescript-language-server" "--stdio")))
  :hook
  (nix-mode . eglot-ensure)
  ;;(typescript-mode . eglot-ensure)
  )

Tide

;; (use-package tide
;; :ensure t
;; :after (typescript-mode company flycheck)
;;   :hook ((typescript-mode . tide-setup)
;;          (typescript-mode . tide-hl-identifier-mode)
;;          (before-save . tide-format-before-save))
;;   :config
;;   (flycheck-add-next-checker 'typescript-tide 'javascript-eslint)
;;   (setq tide-completion-enable-autoimport-suggestions t
;;         tide-save-buffer-after-code-edit nil
;;         tide-completion-show-source t
;;         tide-hl-identifier-mode t
;;         tide-hl-identifier-idle-time 1.5
;;         tide-recenter-after-jump t

;;         web-mode-enable-auto-quoting nil
;;         web-mode-markup-indent-offset 2
;;         web-mode-code-indent-offset 2
;;         web-mode-attr-indent-offset 2
;;         web-mode-attr-value-indent-offset 2

;;         )
;;   )

;; ;; hooks
;; (add-hook 'before-save-hook 'tide-format-before-save)

;; (add-hook 'web-mode-hook 'company-mode)
;; (add-hook 'web-mode-hook 'prettier-js-mode)
;; (add-hook 'web-mode-hook #'turn-on-smartparens-mode t)

Eslint

  (use-package eslintd-fix)

  (setq flycheck-javascript-eslint-executable "eslint_d")
  (setq eslintd-fix-executable "/usr/local/bin/eslint_d")
  (add-hook 'typescript-tsx-mode-hook 'eslintd-fix-mode)
  (add-hook 'typescript-mode-hook 'eslintd-fix-mode)
  (add-hook 'web-mode-hook 'eslintd-fix-mode)

  ;; (use-package flymake-json)
  ;; use local eslint from node_modules before global
  ;; http://emacs.stackexchange.com/questions/21205/flycheck-with-file-relative-eslint-executable
  (defun my/use-eslint-from-node-modules ()
    (let* ((root (locate-dominating-file
                  (or (buffer-file-name) default-directory)
                  "node_modules"))
           (eslint (and root
                        (expand-file-name "node_modules/eslint/bin/eslint.js"
                                          root))))
      (when (and eslint (file-executable-p eslint))
        (setq-local flycheck-javascript-eslint-executable eslint))))
  (add-hook 'flycheck-mode-hook #'my/use-eslint-from-node-modules)
(add-hook 'json-mode-hook 'flymake-json-mode)

Debugger

Node

;; (setq dap-auto-configure-features '(sessions locals controls tooltip))

;; (defun my-setup-dap-node ()
;;   "Require dap-node feature and run dap-node-setup if VSCode module isn't already installed"
;;   (require 'dap-node)
;;   (unless (file-exists-p dap-node-debug-path) (dap-node-setup)))

;; (add-hook 'typescript-mode-hook 'my-setup-dap-node)
;; (add-hook 'javascript-mode-hook 'my-setup-dap-node)

WINDOWS

Treemacs

(use-package treemacs
  :ensure t
  :defer t
  :init
  :config
  (progn
    (setq treemacs-collapse-dirs                 (if (executable-find "python3") 3 0)
          treemacs-deferred-git-apply-delay      0.5
          treemacs-display-in-side-window        t
          treemacs-eldoc-display                 t
          treemacs-file-event-delay              5000
          treemacs-file-follow-delay             0.2
          treemacs-follow-after-init             t
          treemacs-git-command-pipe              ""
          treemacs-goto-tag-strategy             'refetch-index
          treemacs-indentation                   2
          treemacs-indentation-string            " "
          treemacs-is-never-other-window         nil
          treemacs-max-git-entries               5000
          treemacs-missing-project-action        'ask
          treemacs-no-png-images                 nil
          treemacs-no-delete-other-windows       t
          treemacs-project-follow-cleanup        nil
          treemacs-persist-file                  (expand-file-name ".cache/treemacs-persist" user-emacs-directory)
          treemacs-recenter-distance             0.1
          treemacs-recenter-after-file-follow    nil
          treemacs-recenter-after-tag-follow     nil
          treemacs-recenter-after-project-jump   'always
          treemacs-recenter-after-project-expand 'on-distance
          treemacs-show-cursor                   nil
          treemacs-show-hidden-files             t
          treemacs-silent-filewatch              t
          treemacs-silent-refresh                nil
          treemacs-default-visit-action          'treemacs-visit-node-close-treemacs
          treemacs-sorting                       'alphabetic-asc
          treemacs-space-between-root-nodes      t
          treemacs-tag-follow-cleanup            t
          treemacs-tag-follow-delay              1.5
          treemacs-width                         30)
    (treemacs-resize-icons 11)

    (treemacs-follow-mode t)
    (treemacs-filewatch-mode t)
    (treemacs-fringe-indicator-mode t)

    (pcase (cons (not (null (executable-find "git")))
                 (not (null (executable-find "python3"))))
      (`(t . t)
       (treemacs-git-mode 'deferred))
      (`(t . _)
       (treemacs-git-mode 'simple))))
  )



(use-package treemacs-evil
  :after treemacs evil
  :ensure t)

(use-package treemacs-all-the-icons
  :after treemacs all-the-icons
  :ensure t
  :config
  (treemacs-load-theme "all-the-icons")
  )

(with-eval-after-load 'treemacs-evil
  (evil-define-key 'treemacs treemacs-mode-map (kbd "SPC e") #'treemacs)
  (evil-define-key 'treemacs treemacs-mode-map (kbd "l") #'treemacs-TAB-action)
  )

(use-package treemacs-projectile
  :ensure t
  :after (treemacs projectile)
  )

(use-package treemacs-magit
  :ensure t
  :after (treemacs magit)
  )

(add-hook 'projectile-after-switch-project-hook 'treemacs-display-current-project-exclusively)

Winum

(use-package winum
  :ensure t
  :config
  (winum-mode)
  )

BUFFERS

Buffer Ignore

(defcustom my-skippable-buffers '("*Messages*" "*scratch*" "*Help*" "*Async-native-compile-log*" "*lsp-log*" "*ts-ls*" "*ts-ls::stderr*" "*eslint*" "*eslint::stderr*" "*tailwindcss*" "*tailwindcss::stderr*")
  "Buffer names ignored by `my-next-buffer' and `my-previous-buffer'."
  :type '(repeat string))

(defun my-change-buffer (change-buffer)
  "Call CHANGE-BUFFER until current buffer is not in `my-skippable-buffers'."
  (let ((initial (current-buffer)))
    (funcall change-buffer)
    (let ((first-change (current-buffer)))
      (catch 'loop
        (while (member (buffer-name) my-skippable-buffers)
          (funcall change-buffer)
          (when (eq (current-buffer) first-change)
            (switch-to-buffer initial)
            (throw 'loop t)))))))

(defun my-next-buffer ()
  "Variant of `next-buffer' that skips `my-skippable-buffers'."
  (interactive)
  (my-change-buffer 'next-buffer))

(defun my-previous-buffer ()
  "Variant of `previous-buffer' that skips `my-skippable-buffers'."
  (interactive)
  (my-change-buffer 'previous-buffer))

Buffer Movement

(require 'windmove)

Buffer Move Up

                                                                                                                            ;;;###autoload
(defun buf-move-up ()
  "Swap the current buffer and the buffer above the split.
                                                                                                                               If there is no split, ie now window above the current one, an
                                                                                                                               error is signaled."
  ;;  "Switches between the current buffer, and the buffer above the
  ;;  split, if possible."
  (interactive)
  (let* ((other-win (windmove-find-other-window 'up))
         (buf-this-buf (window-buffer (selected-window))))
    (if (null other-win)
        (error "No window above this one")
      ;; swap top with this one
      (set-window-buffer (selected-window) (window-buffer other-win))
      ;; move this one to top
      (set-window-buffer other-win buf-this-buf)
      (select-window other-win))))

Buffer Move Down

                                                                                                                            ;;;###autoload
(defun buf-move-down ()
  "Swap the current buffer and the buffer under the split.
                                                                                                                               If there is no split, ie now window under the current one, an
                                                                                                                               error is signaled."
  (interactive)
  (let* ((other-win (windmove-find-other-window 'down))
         (buf-this-buf (window-buffer (selected-window))))
    (if (or (null other-win)
            (string-match "^ \\*Minibuf" (buffer-name (window-buffer other-win))))
        (error "No window under this one")
      ;; swap top with this one
      (set-window-buffer (selected-window) (window-buffer other-win))
      ;; move this one to top
      (set-window-buffer other-win buf-this-buf)
      (select-window other-win))))

Buffer Move Left

                                                                                                                            ;;;###autoload
(defun buf-move-left ()
  "Swap the current buffer and the buffer on the left of the split.
                                                                                                                               If there is no split, ie now window on the left of the current
                                                                                                                               one, an error is signaled."
  (interactive)
  (let* ((other-win (windmove-find-other-window 'left))
         (buf-this-buf (window-buffer (selected-window))))
    (if (null other-win)
        (error "No left split")
      ;; swap top with this one
      (set-window-buffer (selected-window) (window-buffer other-win))
      ;; move this one to top
      (set-window-buffer other-win buf-this-buf)
      (select-window other-win))))

Buffer Move Right

(defun buf-move-right ()
  "Swap the current buffer and the buffer on the right of the split.
                             If there is no split, ie now window on the right of the current
                             one, an error is signaled."
  (interactive)
  (let* ((other-win (windmove-find-other-window 'right))
         (buf-this-buf (window-buffer (selected-window))))
    (if (null other-win)
        (error "No right split")
      ;; swap top with this one
      (set-window-buffer (selected-window) (window-buffer other-win))
      ;; move this one to top
      (set-window-buffer other-win buf-this-buf)
      (select-window other-win))))

Buffer Backups

(setq backup-directory-alist '(("." . "~/.local/share/Trash/files")))
(setq make-backup-files t               ; backup of a file the first time it is saved.
      backup-by-copying t               ; don't clobber symlinks
      version-control t                 ; version numbers for backup files
      delete-old-versions t             ; delete excess backup files silently
      delete-by-moving-to-trash t
      kept-old-versions 6               ; oldest versions to keep when a new numbered backup is made (default: 2)
      kept-new-versions 9               ; newest versions to keep when a new numbered backup is made (default: 2)
      auto-save-default t               ; auto-save every buffer that visits a file
      auto-save-timeout 20              ; number of seconds idle time before auto-save (default: 30)
      auto-save-interval 200            ; number of keystrokes between auto-saves (default: 300)
      )

Automatically update buffers when contents change on disk

(global-auto-revert-mode 1)

FONTS

Setting the Font-Face

(set-face-attribute 'default nil
                    :font "JetBrainsMonoNLNerdFont"
                    :height 160
                    :weight 'regular)
(set-face-attribute 'variable-pitch nil
                    :font "JetBrainsMonoNLNerdFont"
                    :height 180
                    :weight 'regular)
(set-face-attribute 'fixed-pitch nil
                    :font "JetBrainsMonoNLNerdFont"
                    :height 160
                    :weight 'regular)
;; Makes commented text and keywords italics.
;; This is working in emacsclient but not emacs.
;; Your font must have an italic face available.
(set-face-attribute 'font-lock-comment-face nil
                    :weight 'light
                    :slant 'italic)
(set-face-attribute 'font-lock-keyword-face nil
                    :slant 'italic)

;; This sets the default font on all graphical frames created after restarting Emacs.
;; Does the same thing as 'set-face-attribute default' above, but emacsclient fonts
;; are not right unless I also add this method of setting the default font.
(add-to-list 'default-frame-alist '(font . "JetBrainsMonoNLNerdFont-16"))

;; Uncomment the following line if line spacing needs adjusting.
;; (setq-default line-spacing 0.12)

Zooming In/Out

(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "<C-wheel-up>") 'text-scale-increase)
(global-set-key (kbd "<C-wheel-down>") 'text-scale-decrease)

;; (defadvice text-scale-increase (around all-buffers (arg) activate)
;;   (dolist (buffer (buffer-list))
;;     (with-current-buffer buffer
;;       ad-do-it)))

PDF MODE

Enabling Pdf

(use-package pdf-tools)
(setq auto-mode-alist (append '((".*\\.pdf$" . pdf-view-mode)) auto-mode-alist))

ORG MODE

Enabling Table of Contents

(use-package toc-org
  :commands toc-org-enable
  :init (add-hook 'org-mode-hook 'toc-org-enable))

Org Modern Indent

(setq org-startup-indented t)

(use-package org-modern-indent
  :elpaca '(org-modern-indent :host github :repo "jdtsmith/org-modern-indent")
  :config ; add late to hook
  (add-hook 'org-mode-hook #'org-modern-indent-mode 90))

Org Modern

(use-package org-modern
  :ensure t
  :custom
  (org-modern-hide-stars nil)		; adds extra indentation
  (org-modern-table nil)
  (org-modern-tag nil)
  (org-hide-emphasis-markers t)
  (org-modern-block-name nil)
  ;; (org-modern-block-fringe 10)
  (org-pretty-entities t)
  (org-modern-list
   '(;; (?- . "-")
     (?* . "")
     (?+ . "")))
  :hook
  (org-mode . org-modern-mode)
  (org-agenda-finalize . org-modern-agenda))

Org-Mode Functionality

(setq org-log-done 'time)
(setq org-log-done 'note)
(setq org-list-allow-alphabetical t)

Enabling Org Bullets

(add-hook 'org-mode-hook 'org-indent-mode)
(use-package org-bullets)
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))

Org-Roam

(use-package org-roam
  :ensure t
  :custom
  (org-roam-directory "~/Projects/life/loewe")
  (org-roam-completion-everywhere t)
  :config (org-roam-db-autosync-mode)
  )

Org Agenda Files

(defun org-get-agenda-files-recursively (dir)
  "Get org agenda files from root DIR."
  (directory-files-recursively dir "\.org$"))

(defun org-set-agenda-files-recursively (dir)
  "Set org-agenda files from root DIR."
  (setq org-agenda-files
        (org-get-agenda-files-recursively dir)))

(defun org-add-agenda-files-recursively (dir)
  "Add org-agenda files from root DIR."
  (nconc org-agenda-files
         (org-get-agenda-files-recursively dir)))

(org-set-agenda-files-recursively "~/Projects/life/loewe/daily")

(defun org-agenda-current-buffer ()
  (interactive)
  (let ((org-agenda-files (list (buffer-file-name (current-buffer)))))
    (org-agenda)))

(define-key global-map (kbd "C-c a") #'org-agenda-current-buffer)

Disable Electric Indent

(electric-indent-mode -1)
(add-hook 'org-mode-hook (lambda ()
                           (setq-local electric-pair-inhibit-predicate
                                       `(lambda (c)
                                          (if (char-equal c ?<) t (,electric-pair-inhibit-predicate c))))))

Format emacs-lisp src blocks in Org Files

(defun edit-src-block (src fn language)
  "Replace SRC org-element's value property with the result of FN.
                                                                                                                               FN is a function that operates on org-element's value and returns a string.
                                                                                                                               LANGUAGE is a string referring to one of orb-babel's supported languages.
                                                                                                                               (https://orgmode.org/manual/Languages.html#Languages)"
  (let ((src-language (org-element-property :language src))
        (value (org-element-property :value src)))
    (when (string= src-language language)
      (let ((copy (org-element-copy src)))
        (org-element-put-property copy :value
                                  (funcall fn value))
        (org-element-set-element src copy)))))

(defun format-elisp-string (string)
  "Indents elisp buffer string and reformats dangling parens."
  (with-temp-buffer
    (let ((inhibit-message t))
      (emacs-lisp-mode)
      (insert
       (replace-regexp-in-string "[[:space:]]*
                                                                                                                                                                                                  [[:space:]]*)" ")" string))
      (indent-region (point-min) (point-max))
      (buffer-substring (point-min) (point-max)))))

(defun format-elisp-src-blocks ()
  "Format Elisp src blocks in the current org buffer"
  (interactive)
  (save-mark-and-excursion
    (let ((AST (org-element-parse-buffer)))
      (org-element-map AST 'src-block
        (lambda (element)
          (edit-src-block element #'format-elisp-string "emacs-lisp")))
      (delete-region (point-min) (point-max))
      (insert (org-element-interpret-data AST)))))

Source Code Block Tag Expansion

Typing the below + TABExpands to …
<a’#+BEGIN_EXPORT ascii’ … ‘#+END_EXPORT
<c’#+BEGIN_CENTER’ … ‘#+END_CENTER’
<C’#+BEGIN_COMMENT’ … ‘#+END_COMMENT’
<e’#+BEGIN_EXAMPLE’ … ‘#+END_EXAMPLE’
<E’#+BEGIN_EXPORT’ … ‘#+END_EXPORT’
<h’#+BEGIN_EXPORT html’ … ‘#+END_EXPORT’
<l’#+BEGIN_EXPORT latex’ … ‘#+END_EXPORT’
<q’#+BEGIN_QUOTE’ … ‘#+END_QUOTE’
<s’#+BEGIN_SRC’ … ‘#+END_SRC’
<v’#+BEGIN_VERSE’ … ‘#+END_VERSE’
(require 'org-tempo)

Never leaving Emacs

Google Calendar Sync

Dependencies

(use-package request
  :ensure t)

(use-package alert
  :ensure t)

(use-package persist
  :ensure t)

(use-package aio
  :ensure t)

(use-package oauth2-auto
  :elpaca '(oauth2-auto :host github :repo "telotortium/emacs-oauth2-auto")
  :ensure t)

(use-package f)

Org-GCal Sync

;;  (fset 'epg-wait-for-status 'ignore)

(setq epg-pinentry-mode 'loopback)
(require 'epa-file)
(epa-file-enable)

(setq plstore-cache-passphrase-for-symmetric-encryption t)
;; Stores google calendar events to my org `work-calendar' file. Sync by running `M-x org-gcal-sync'.

(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")

(use-package org-gcal
  :elpaca '(org-gcal :host github :repo "kidd/org-gcal.el")
  :init
  (setq org-gcal-client-id (f-read-text (expand-file-name ".local/org-gcal/org-gcal-client-id" user-emacs-directory))
        org-gcal-client-secret (f-read-text (expand-file-name ".local/org-gcal/org-gcal-client-secret" user-emacs-directory))
        org-gcal-dir (expand-file-name ".local/org-gcal/" user-emacs-directory))

  :config
  (setq org-gcal-down-days 30
        org-gcal-up-days 30
        org-gcal-remove-api-cancelled-events t)
  ;; https://github.com/kidd/org-gcal.el/issues/107
  (setq org-id-locations-file (expand-file-name ".local/.org-id-locations" user-emacs-directory))

  (let (
        (loewe-calendar (expand-file-name "calendars/loewe.org" "~/Projects/life/aliyss"))
        (aliyss-calendar (expand-file-name "calendars/aliyss.org" "~/Projects/life/aliyss"))
        (isaac-calendar (expand-file-name "calendars/isaac.org" "~/Projects/life/aliyss"))
        (stain-calendar (expand-file-name "calendars/stain.org" "~/Projects/life/aliyss"))
        (yara-calendar (expand-file-name "calendars/yara.org" "~/Projects/life/aliyss"))
        )
    (setq org-gcal-file-alist `(
                                ("[email protected]" . ,loewe-calendar)
                                ("[email protected]" . ,aliyss-calendar)
                                ("[email protected]" . ,isaac-calendar)
                                ("[email protected]" . ,stain-calendar)
                                ("[email protected]" . ,yara-calendar)
                                ))
    (add-to-list 'org-agenda-files loewe-calendar)
    (add-to-list 'org-agenda-files aliyss-calendar)
    (add-to-list 'org-agenda-files isaac-calendar)
    (add-to-list 'org-agenda-files stain-calendar)
    (add-to-list 'org-agenda-files yara-calendar)

    (add-to-list 'my-skippable-buffers "loewe.org")
    (add-to-list 'my-skippable-buffers "aliyss.org")
    (add-to-list 'my-skippable-buffers "isaac.org")
    (add-to-list 'my-skippable-buffers "stain.org")
    (add-to-list 'my-skippable-buffers "yara.org")

    (add-to-list 'recentf-exclude "loewe.org")
    (add-to-list 'recentf-exclude "aliyss.org")
    (add-to-list 'recentf-exclude "isaac.org")
    (add-to-list 'recentf-exclude "stain.org")
    (add-to-list 'recentf-exclude "yara.org")

    (add-to-list 'ivy-ignore-buffers "loewe.org")
    (add-to-list 'ivy-ignore-buffers "aliyss.org")
    (add-to-list 'ivy-ignore-buffers "isaac.org")
    (add-to-list 'ivy-ignore-buffers "stain.org")
    (add-to-list 'ivy-ignore-buffers "yara.org")
    ))

(defun aliyss/refresh-work-calendar ()
  "Fetch Google calendar events and add the proper file tag(s)."
  (interactive)
  (org-gcal-fetch))

(defvar aliyss--timer:update-work-calendar nil)

(defun aliyss/start-work-calendar-update-timer ()
  (interactive)
  (setq aliyss--timer:update-work-calendar
        (run-at-time t (* 30 60) #'aliyss/refresh-work-calendar)))

(defun aliyss/stop-work-calendar-timer ()
  (interactive)
  (cancel-timer aliyss--timer:update-work-calendar))

RSS Feed

(use-package elfeed)

(setq elfeed-feeds '(
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCEKJKJ3FO-9SFv5x5BzyxhQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCTH6s1SMIQicvyd8OLBYMtQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC51WtMXgM71IkLnTc4O63_g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCtEwVJZABCd0tels2KIpKGQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCov_51F0betb6hJ6Gumxg3Q" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCNJ1Ymd5yFuUPtn21xtRbbw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCN__G2hSqRKuqedN3M0JCDg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCeh-pJYRZTBJDXMNZeWSUVA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCrxUQQiGK_XarxsiYsL7P4g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCLtOpyx344v-l0kreCSUEFg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC4NNPgQ9sOkBjw6GlkgCylg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC1OR9yjgsvoFK3xxhCs-19Q" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCSPLhwvj0gBufjDRzSQb3GQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCb5QRUn5w8_g0j8QVaWzcjQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCwkDQ8tE_3UhB8LcnvUv0Fw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCdp4_l1vPmpN-gDbUwhaRUQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCngn7SVujlvskHRvRKc1cTw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC8JOgFXp-I3YV6dsKqqQdUw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVJ65ACOGn5FCitRoD9qXEw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC6LEH0rS9V0BF5aNhVYdykQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCjREVt2ZJU8ql-NC9Gu-TJw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCaSCt8s_4nfkRglWCvNSDrg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCrsLPlwxUInDoNubOP85EWQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC9P0bchnch7IqfrbTib4nrA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC4QZ_LsYcvcq7qOsOhpAX4A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCHzK6q9IjJgo1w51nuwPtcA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCltwa_Ol4wfxWE5AGr7UJQg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCL9Y2MYhBUT0rgOi1q6JeCQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC3KV2kFy2YhjYvverIy2WnA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVls1GmFKf6WlTraIb_IaJg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCmfp0LHfhwW1Trw-maUiWsw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCWQaM7SpSECp9FELz-cHzuQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCUFFHXvzAMRSD8Bq4bJppxQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCDq5v10l4wkV5-ZBIJJFbzQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCxddeIv7GdHNcVPZI9JvGXQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVLw9wKPHxdBbboXEduN5jA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCWEVAMMyXF2NP5txDESGemg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCcddcRNcQfVwCMmvV2QWf8Q" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC_wIxplYNdht7HTw-wGUcpg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC1MohIlyjb5npB1rKhD-Y3A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCEaEuLUvy4Y1DqpxiDvnxeQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC7M-Wz4zK8oikt6ATcoTwBA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCHDxYLv8iovIbhrfl16CNyg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCPUe9uOcp1UMpVi6Vll60Jw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCV4k4vV6Od6XPAqfcsHwfmw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCRrI36DlobH2OgknMjC3Rfw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCWo4IA01TXzBeGJJKWHOG9g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCii9ezsUa_mBiSdw0PtSOaw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCqjVP9gAanUGFgTA5BRDvyA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCmEzz-dPBVrsy4ZluSsYHDg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCJLZe_NoiG0hT7QCX_9vmqw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCeTfBygNb1TahcNpZyELO8g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCfIi1OrrUajcVWA2hq7FxvA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCYwVxWpjeKFWwu8TML-Te9A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC_hukbByJP7OZ3Xm2tszacQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCuK9ofevgGxPVl57p_fSpuA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCCuoqzrsHlwv1YyPKLuMDUQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCx0L2ZdYfiq-tsAXb8IXpQg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCa8W2_uf81Ew6gYuw0VPSeA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCm8EsftbfNzSiRHzc7I59KQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC7Lo7dT0Y6yz5ndQGGP7H3A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCx8C_9jxBi7g5PsGmoo6R9A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCD4XIm3ZFhT72WjqhIXMN9w" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCCZ40QwZtFs_7h5MZ0ZTTwg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCBC04kJUBrs8FgNKP7rQ10Q" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCSp-OaMpsO8K0KkOqyBl7_w" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCZRoNJu1OszFqABP8AuJIuw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC6biysICWOJ-C3P4Tyeggzg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCEBtnFwHUmcZ2ajvAoLl7Wg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCZiotb1j89oPlg0FyQ3r40g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCEHp_b02I0GvTYCBPX_0w1g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCXx0JWOKERPZdzczPfY-huA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UChpleBmo18P08aKCIgti38g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCIGRhqYssT6IGPYOnZBFYKw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCj8orMezFWVcoN-4S545Wtw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC_OttpBEWWzSUlZbk5qmhSA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCoOss5XiPpnLHGmLrBvNkJg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCZdrTo_md37z3iogKYrVgCw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCmFeOdJI3IXgTBDzqBLD8qg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCBs2Y3i14e1NWQxOGliatmg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCSdma21fnJzgmPodhC9SJ3g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCSillZr7X-5u-j_-ps_ijqA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC5_Y-BKzq1uW_2rexWkUzlA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCUMwY9iS8oMyWDYIe6_RmoA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCMp-0bU-PA7BNNR-zIvEydA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCuUHDELv0TZM7VeDchmZrFQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVHxJghKAB_kA_5LMM8MD3w" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC3AwZ0mkVtOxm9xVpC9vJyA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCq4xfqZCp6yt0Q_GcHY9AZg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCir93b_ftqInEaDpsWYbo_g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCqJ5EkPzmVHTTrrHtmgWeeg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCi8C7TNs2ohrc6hnRQ5Sn2w" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC0zkY5mBfyov8wPGR981hbw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC1rFmaGLYr0Ve_Y_soxZNWQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCXIa1dlKtpeCEBHObZFQgsA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCfHmyqCntYHQ81ZukNu66rg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCK8XIGR5kRidIw2fWqwyHRA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCct9aR7HC79Cv2g-9oDOTLw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCah7IyEzRnRdttwDGDdy_gw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCiSAjbPtn733_ZBSQ-6T4wQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCGrJIWs0kYoqtwFgP6-SEQQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCmU0pxYK_ZwjZ_QihFUeH8A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCDAjO0-hd_RS8ZYJ4W-Iq5Q" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCWvq4kcdNI1r1jZKFw9TiUA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCmtyQOKKmrMVaKuRXz02jbQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCDzVUXiTr3hClI-zzCWbYzg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCuD-OWq0lLKLGkuWuNs35sA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCbvjXcT9ojfSrA8QrOKeY_w" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC7cmH--tFhYduIshTKzQUJQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCtUbO6rBht0daVIOGML3c8w" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCB6dvaWu0N8uVq2yKsZ5s5g" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCMpdK0UaW9K2WGkL6z2sSWg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCAiiOTio8Yu69c3XnR7nQBQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCIjUIjWig0r5DIixQrt6A3A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCqMYm98sWtbzN8FnHT2mCOg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCl_dlV_7ofr4qeP1drJQ-qg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCeeFfhMcJa1kjtfZAGskOCA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCkSMDOtrKr43OGSSmKnx6tQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCBmhDcQmctiuAwyqOuX7cag" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCRG_N2uO405WO4P3Ruef9NA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCxNlX8AUIh2nlLf4IL1DWzg" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCkS_HP3m9NXOgswVAKbMeJQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCbRP3c757lWg9M-U7TyEkXA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC8ENHE5xdFSwx71u3fDH5Xw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCUyeluBRhGPCW4rPe_UvBZQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCJ-vHE5CrGaL_ITEg-n3OeA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVk4b-svNJoeytrrlOixebQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCCVclxslsRWT3LHFu8mQhNA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCaXh9z3or5QbM0HPGen2Quw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCBa659QWEk1AI4Tg--mrJ2A" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCbAn7pVK2VIyo-UysfWGdZQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC6-JmqeHcRIdA3ErhyUXlfA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCZ4oRX0e157gHeJHp0XOULA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCSIvk78tK2TiviLQn4fSHaw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCRzS48bskynAxoI38BFypfQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCt3JiNkefsfbA2N4SgEkoiQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC6nSFpj9HTCZ5t-N3Rm3-HA" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVWhVAZwCdQsPZL-mDLcxPQ" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCs76MNovGkuNYNZCmrxcb3Q" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCuOuOjhkq6A2jh9oJxvrkMw" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UC0i9_dNHK8VoAqD69v_b3og" youtube author)
                     ("https://www.youtube.com/feeds/videos.xml?channel_id=UCuNlrb3G0BLLDbwhz7EqF8w" youtube author)
                     )
      )

Elfeed YouTube

(use-package elfeed-tube
  :ensure t ;; or :straight t
  :after elfeed
  :demand t
  :config
  ;; (setq elfeed-tube-auto-save-p nil) ; default value
  ;; (setq elfeed-tube-auto-fetch-p t)  ; default value
  (elfeed-tube-setup)

  :bind (:map elfeed-show-mode-map
              ("F" . elfeed-tube-fetch)
              ([remap save-buffer] . elfeed-tube-save)
              :map elfeed-search-mode-map
              ("F" . elfeed-tube-fetch)
              ([remap save-buffer] . elfeed-tube-save)))

(use-package elfeed-tube-mpv
  :ensure t ;; or :straight t
  :bind (:map elfeed-show-mode-map
              ("C-c C-f" . elfeed-tube-mpv-follow-mode)
              ("C-c C-w" . elfeed-tube-mpv-where)))