nix-configuration/settings.org

66 KiB

Emacs Init

Sane defaults

  (defvar native-comp-deferred-compilation-deny-list nil)
  ;; misc settings
  (menu-bar-mode -1)
  (tool-bar-mode -1)
  (scroll-bar-mode -1)
  (add-hook 'prog-mode-hook (lambda() (display-line-numbers-mode 1)))
  (add-hook 'text-mode-hook (lambda() (display-line-numbers-mode 1)))
  ;;(global-tree-sitter-mode)
  (setq display-line-numbers-type 'relative)
  (electric-pair-mode 1)
  (show-paren-mode 1)
  (setq-default tab-width 2
   standard-indent 2
   indent-tabs-mode nil)	
  (setq completion-cycle-threshold 3)
  (setq tab-always-indent 'complete)
  (setq confirm-kill-emacs 'y-or-n-p)
  (set-frame-font "JetBrainsMono Nerd Font 12" nil t)
  (server-start)

Setting up use-package

(require 'use-package)

(use-package gcmh
    :ensure t
    :config
    (gcmh-mode 1))

Window setup

(setq fit-window-to-buffer-horizontally t
      fit-frame-to-buffer t)

(setq display-buffer-base-action
      '((display-buffer-reuse-window
         display-buffer-in-previous-window
         display-buffer-reuse-mode-window)))

(defun my/display-buffer-reuse-minor-mode-window (buffer alist)
    (let* ((alist-entry (assq 'reusable-frames alist))
           (alist-mode-entry (assq 'minor-mode alist))
	   (frames (cond (alist-entry (cdr alist-entry))
		         ((if (eq pop-up-frames 'graphic-only)
			      (display-graphic-p)
			    pop-up-frames)
			  0)
		         (display-buffer-reuse-frames 0)
		         (t (last-nonminibuffer-frame))))
           (inhibit-same-window-p (cdr (assq 'inhibit-same-window alist)))
	   (windows (window-list-1 nil 'nomini frames))
           (allowed-modes (if alist-mode-entry
                              (cdr alist-mode-entry)))
           (curwin (selected-window))
           (curframe (selected-frame)))
      (unless (listp allowed-modes)
        (setq allowed-modes (list allowed-modes)))
      (let ((same-mode-same-frame)
            (same-mode-other-frame))
        (dolist (window windows)
          (let ((mode?
                 (with-current-buffer (window-buffer window)
                   (cl-some (lambda (m) (and (boundp m) (symbol-value m) 'same))
                            allowed-modes))))
            (when (and mode? (not (and inhibit-same-window-p (eq window curwin))))
              (push window (if (eq curframe (window-frame window))
                               same-mode-same-frame
                             same-mode-other-frame)))))
        (let ((window (car (nconc same-mode-same-frame
                                  same-mode-other-frame))))
          (when (window-live-p window)
            (prog1 (window--display-buffer buffer window 'reuse alist)
              (unless (cdr (assq 'inhibit-switch-frame alist))
                (window--maybe-raise-frame (window-frame window)))))))))

;;;###autoload
(defun buffer-mode (&optional buffer-or-name)
  "Returns the major mode associated with a buffer.
If buffer-or-name is nil return current buffer's mode."
  (buffer-local-value 'major-mode
                      (if buffer-or-name
                          (get-buffer buffer-or-name)
                        (current-buffer))))

(defvar my/occur-grep-modes-list '(occur-mode
                                 grep-mode
                                 xref--xref-buffer-mode
                                ivy-occur-grep-mode
                                 ivy-occur-mode
                                 locate-mode
                                 flymake-diagnostics-buffer-mode
                                 rg-mode)
  "List of major-modes used in occur-type buffers")

;; This does not work at buffer creation since the major-mode for
;; REPLs is not yet set when `display-buffer' is called, but is
;; useful afterwards
(defvar my/repl-modes-list '(matlab-shell-mode
                           eshell-mode
                           geiser-repl-mode
                           shell-mode
                           eat-mode
                           ;; vterm-mode
                           inferior-python-mode
                           cider-repl-mode
                           fennel-repl-mode
                           jupyter-repl-mode
                           inferior-ess-julia-mode)
  "List of major-modes used in REPL buffers")

(defvar my/repl-names-list
  '("^\\*\\(?:.*?-\\)\\{0,1\\}e*shell[^z-a]*\\(?:\\*\\|<[[:digit:]]+>\\)$"
    "\\*.*REPL.*\\*"
    "\\*MATLAB\\*"
    "\\*Python\\*"
    "^\\*jupyter-repl.*?\\(\\*\\|<[[:digit:]]>\\)$"
    "\\*Inferior .*\\*$"
    "^\\*julia.*\\*$"
    "^\\*cider-repl.*\\*$"
    "\\*ielm\\*"
    "\\*edebug\\*")
  "List of buffer names used in REPL buffers")

(defvar my/help-modes-list '(helpful-mode
                           help-mode
                           pydoc-mode
                           eldoc-mode
                           TeX-special-mode)
  "List of major-modes used in documentation buffers")

(defvar my/man-modes-list '(Man-mode woman-mode)
  "List of major-modes used in Man-type buffers")

(defvar my/message-modes-list '(compilation-mode
                                edebug-eval-mode)
  "List of major-modes used in message buffers")

(defun my/helper-window-mode-line-format ()
    "Mode-line format for helper (popup) windows"
   (list " "
       (when (bound-and-true-p winum-format)
             winum--mode-line-segment)
         " POP "
         mode-line-buffer-identification)
    mode-line-format
  )
(setq display-buffer-alist
      '(

        ("^\\*[Ee]shell [Ee]xport: .*\\*$"
         (display-buffer-reuse-window display-buffer-use-some-window))

        ("^\\*julia\\*"
         (display-buffer-reuse-mode-window
          display-buffer-reuse-window
          display-buffer-in-direction
          display-buffer-in-side-window)
         (body-function . select-window)
         (window-height . .35)
         (window-width .  .40)
         ;; (preserve-size . (nil . t))
         (direction . below)
         (side . bottom)
         (slot . 1))
        ;; ----------------------------------------------------------------
        ;; Windows on top
        ;; ----------------------------------------------------------------

        ("\\*\\(?:Org Select\\|Agenda Commands\\)\\*"
         (display-buffer-below-selected
          display-buffer-in-side-window)
         (body-function . select-window)
         (window-height . (lambda (win) (fit-window-to-buffer win nil 12)))
         (side . top)
         (slot . -2)
         (preserve-size . (nil . t))
         (window-parameters . ((mode-line-format . nil))))

        ("\\*Buffer List\\*" (display-buffer-in-side-window)
         (side . top)
         (slot . 0)
         (window-height . shrink-window-if-larger-than-buffer))

        ((lambda (buf act) (member (buffer-mode buf) my/occur-grep-modes-list))
         (display-buffer-reuse-mode-window
          display-buffer-in-direction
          display-buffer-in-side-window)
         (side . top)
         (slot . 5)
         (window-height . (lambda (win) (fit-window-to-buffer win 20 10)))
         (direction . above)
         (body-function . select-window))

        ("\\*\\(Flycheck\\|Package-Lint\\).*"
         (display-buffer-in-direction display-buffer-in-side-window)
         (direction . above)
         (window-height . shrink-window-if-larger-than-buffer)
         ;; (window-height . 0.16)
         (side . top)
         (slot . 1)
         (window-parameters . (;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               (no-other-window . t))))

        ;; ----------------------------------------------------------------
        ;; Windows on the side
        ;; ----------------------------------------------------------------

        ;; ((lambda (buf act) (member (buffer-mode buf) my/man-modes-list))
        ;;  ;; "^\\*\\(?:Wo\\)?Man"
        ;;  (display-buffer-in-side-window)
        ;;  (body-function . select-window)
        ;;  (window-width . 76)       ; See the :hook
        ;;  (side . left)
        ;;  (slot . 9))

        ("\\*Faces\\*" (display-buffer-in-side-window)
         (window-width . 0.25)
         (side . right)
         (slot . -2)
         (window-parameters . ((no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))

        ;; ((lambda (buf act) (or (equal (buffer-mode buf) 'Custom-mode)
        ;;                   (string-match-p "^\\*Customize" (buffer-name))))
        ;;  (display-buffer-in-side-window)
        ;;  (body-function . select-window)
        ;;  (window-width . 74)
        ;;  (side . right)
        ;;  (slot . 5))

        ("\\*undo-tree\\*" ;; (lambda (buf act) (equal (buffer-mode buf) 'undo-tree-visualizer-mode))
         (display-buffer-in-direction)
         (window-width . 35) ;; (lambda (win) (fit-window-to-buffer win nil nil 65 40 t)))
         (direction . right)
         (side . right)
         (slot . -5))
        
        ;; ----------------------------------------------------------------
        ;; Windows at the bottom
        ;; ----------------------------------------------------------------

        ("\\*Backtrace\\*" (display-buffer-in-side-window)
         (window-height . 0.20)
         (side . bottom)
         (slot . -9)
         ;; (preserve-size . (nil . t))
         ;; (window-parameters . (;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
         ;;                       ))
         )

        ("\\*RefTex" (display-buffer-in-side-window)
         (window-height . 0.25)
         (side . bottom)
         (slot . -9)
         ;; (preserve-size . (nil . t))
         ;; (window-parameters . (;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
         ;;                       ))
         )

        ;; ("\\*scratch\\*"
        ;;  display-buffer-in-side-window
        ;;  (body-function . select-window)
        ;;  ;; (window-width 35)
        ;;  (window-height . (lambda (win) (fit-window-to-buffer win 20 nil 85)))
        ;;  (side . bottom)
        ;;  (slot . -8))

        ((lambda (buf act) (member (buffer-mode buf) my/message-modes-list))
         (display-buffer-at-bottom display-buffer-in-side-window)
         (window-height . 0.25)
         (side . bottom)
         (slot . -6)
         ;; (preserve-size . (nil . t))
         ;; (window-parameters . ((no-other-window . #'ignore)
         ;;                       ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
         ;;                       ))
         )

        ("\\*\\(?:Warnings\\|Compile-Log\\|Messages\\)\\*" ;\\|Tex Help\\|TeX errors
         (display-buffer-at-bottom display-buffer-in-side-window display-buffer-in-direction)
         (window-height . (lambda (win) (fit-window-to-buffer
                                         win
                                         (floor (frame-height) 5))))
         (side . bottom)
         (direction . below)
         (slot . -5)
         ;; (preserve-size . (nil . t))
         (window-parameters . ((split-window . #'ignore)
                               ;; (no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))

        ("[Oo]utput\\*" display-buffer-in-side-window
         (window-height . (lambda (win)
                            (fit-window-to-buffer win (floor (frame-height) 2.5))))
         (side . bottom)
         (slot . -4)
         ;; (preserve-size . (nil . t))
         ;; (window-parameters . ((no-other-window . t)
         ;;                       ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
         ;;                       ))
         )
        
        ("\\*Async Shell Command\\*" display-buffer-in-side-window
         (window-height . 0.20)
         (side . bottom)
         (slot . -4)
         ;; (preserve-size . (nil . t))
         (window-parameters . ((no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))

        ("\\*\\(Register Preview\\).*" (display-buffer-in-side-window)
         (window-height . 0.20)       ; See the :hook
         (side . bottom)
         (slot . -3)
         (window-parameters . ((no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))

        ("\\*Completions\\*" (display-buffer-in-side-window)
         (window-height . 0.20)
         (side . bottom)
         (slot . -2)
         ;; (window-parameters . ((no-other-window . t)
         ;;                       ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
         ;;                       ))
         )

        ("\\*Apropos\\*" (display-buffer-in-side-window)
         ;; (window-height . 0.40)
         (window-width . 65)
         (side . right)
         (slot . -2)
         (window-parameters . (;; (no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))


        ((lambda (buf act) (or (seq-some (lambda (regex) (string-match-p regex buf))
                                    my/repl-names-list)
                          (seq-some (lambda (mode)
                                      (equal
                                       (buffer-mode buf)
                                       mode))
                                    my/repl-modes-list)))
         (display-buffer-reuse-window
          display-buffer-in-direction
          display-buffer-in-side-window)
         (body-function . select-window)
         ;; display-buffer-at-bottom
         (window-height . .35)
         (window-width .  .40)
         ;; (preserve-size . (nil . t))
         (direction . below)
         (side . bottom)
         (slot . 1))

        ((lambda (buf act) (member (buffer-mode buf) my/help-modes-list))
         (display-buffer-reuse-window
          display-buffer-in-direction
          display-buffer-in-side-window)
         (body-function . select-window)
         ;; (direction . bottom)
         ;; (window-height . (lambda (win) (fit-window-to-buffer win 25 14)))
         (window-width . 77 ;; (lambda (win) (fit-window-to-buffer win nil nil 75 65))
                       )
         (direction . below)
         (side . right)
         (slot . 2)
         (window-parameters . ((split-window . #'ignore)
                               ;; (no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))

        (;; (lambda (buf act) (equal (buffer-mode buf) 'matlab-shell-help-mode))
         "\\*Matlab Help\\*"
         (display-buffer-reuse-window
          display-buffer-in-side-window
          display-buffer-in-direction)
         (body-function . select-window)
         ;; (direction . bottom)
         ;; (window-height . (lambda (win) (fit-window-to-buffer win 25 14)))
         (window-width . 86 ;; (lambda (win) (fit-window-to-buffer win nil nil 75 65))
                       )
         (direction . right)
         (side . right)
         (slot . 2)
         (window-parameters . ((split-window . #'ignore)
                               ;; (no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))

        ("^\\*eldoc\\*$"
         (display-buffer-reuse-window
          display-buffer-in-direction
          display-buffer-in-side-window)
         (body-function . select-window)
         ;; (direction . bottom)
         ;; (window-height . (lambda (win) (fit-window-to-buffer win 25 14)))
         (window-width . 82 ;; (lambda (win) (fit-window-to-buffer win nil nil 75 65))
                       )
         (direction . below)
         (side . below)
         (slot . 2)
         (window-parameters . ((split-window . #'ignore)
                               ;; (no-other-window . t)
                               ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
                               )))

        ((lambda (buf act) (member (buffer-mode buf) '(ibuffer-mode bookmark-bmenu-mode)))
         (;; display-buffer-reuse-window
          ;; display-buffer-in-side-window
          ;;display-buffer-at-bottom
          display-buffer-below-selected)
         (body-function . select-window)
         (direction . below)
         (window-height . (lambda (win) (fit-window-to-buffer win 30 7)))
         ;; (dedicated . t)
         ;; (window-width . (lambda (win) (fit-window-to-buffer win nil nil 85 55)))
         ;; (direction . right)
         (side . bottom)
         (slot . 2))
         
        
        ;; ((lambda (buf act) (with-current-buffer buf view-mode))
        ;;  (display-buffer-in-side-window)
        ;;  (window-height . (/ (frame-height) 3))
        ;;  (side . bottom)
        ;;  (slot . 10)
        ;;  ;; (window-parameters . (;; (no-other-window . t)
        ;;  ;;                       ;; (mode-line-format . (:eval (my/helper-window-mode-line-format)))
        ;;  ;;                       ))
        ;;  )

 
        ;; ("\\*elfeed-entry\\*" (lambda (buf act) (let ((parent-win (get-buffer-window)))
        ;;                                      (display-buffer-in-direction buf act)
        ;;                                      (select-window parent-win)
        ;;                                      ))
        ;;  (direction . below)
        ;;  (window-height . 0.5)
        ;;  )
        ))

(setq window-combination-resize t
      even-window-sizes 'height-only
      window-sides-vertical nil
      fit-window-to-buffer-horizontally t
      window-resize-pixelwise t
      fit-frame-to-buffer t
      )

;;;###autoload
(defun my/display-buffer-at-bottom ()
  "Move the current buffer to the bottom of the frame.  This is
useful to take a buffer out of a side window.

The window parameters of this function are provided mostly for
didactic purposes."
  (interactive)
  (let ((buffer (current-buffer)))
    (with-current-buffer buffer
      (delete-window)
      (display-buffer-at-bottom
       buffer '((window-height . (lambda (win)
                                   (fit-window-to-buffer
                                    win (/ (frame-height) 3)))))))))

(eval-after-load 'org
  (progn 
    (defun +org-fix-delete-other-windows-a (orig-fn &rest args)
      "docstring"
      (interactive "P")
      (if popper-mode 
          (cl-letf (((symbol-function #'delete-other-windows)
                     (symbol-function #'ignore))
                    ((symbol-function #'delete-window)
                     (symbol-function #'ignore)))
            (apply orig-fn args))
        (apply orig-fn args)))

    (dolist (org-function '(org-add-log-note
                            org-capture-place-template
                            org-export--dispatch-ui
                            org-agenda-get-restriction-and-command
                            org-fast-tag-selection
                            org-fast-todo-selection))

      (advice-add org-function :around #'+org-fix-delete-other-windows-a))))

Editor utils

  (savehist-mode)

  (use-package undo-fu
    :ensure t)
  ; evil
  (use-package evil
    :ensure t
    :init
    (setq evil-want-integration t) ;; This is optional since it's already set to t by default.
    (setq evil-want-keybinding nil)
    (setq evil-undo-system 'undo-fu)
    :config (evil-mode 1))
  (use-package evil-collection
    :after evil
    :ensure t
    :config (evil-collection-init))

  (use-package evil-surround
    :after evil
    :ensure t
    :config (global-evil-surround-mode 1))

  (use-package evil-nerd-commenter
    :after evil
    :ensure t
    :config (evilnc-default-hotkeys))

  ;;(use-package evil-easymotion
  ;;  :after evil
  ;;  :ensure t
  ;;  :config (evilem-default-keybindings "SPC"))

  (defun reload-init-file ()
      "Reload the Emacs init.el file."
      (interactive)
      (load-file (expand-file-name "~/.emacs.d/init.el"))
      (message "Init file reloaded."))
  (use-package general
    :ensure t
    :demand t
    :init (general-evil-setup)
    :config
    (general-define-key
      :states '(normal visual emacs)
      :prefix "SPC"
      ";" 'consult-mode-command
      "f" '(nil :which-key "files")
      "fs" 'save-buffer
      "ff" 'find-file
      "gc" 'comment-line
      "b" '(nil :which-key "buffers")
      "bb" 'consult-buffer
      "bn" 'next-buffer
      "be" 'reload-init-file
      "bp" 'previous-buffer
      "bd" 'evil-delete-buffer
      "l" '(nil :which-key "language functions")
      "lp" 'run-python
      "lc" 'compile
      "i" '(nil :which-key "config files")
      "ii"  'open-init-file
      "in" 'open-nix-config-file))
  (defun open-init-file ()
    "Open the Emacs init file."
    (interactive)
    (find-file "~/.emacs.d/settings.org"))
  (defun open-nix-config-file ()
    "Open the Emacs init file."
    (interactive)
    (find-file "~/nix-configuration/configuration.nix"))
  (use-package which-key
    :ensure t
    :demand t
    :init (which-key-mode))

Tools

    (use-package magit
        :ensure t
        :general
        (general-nmap
        :prefix "SPC v"
        "" '(nil :which-key "magit")
        "m" 'magit))

  (use-package treemacs
      :ensure t)

  (use-package gitignore-templates
    :ensure t)


  (use-package project-tasks
    :defer t
    :ensure t
    :commands (project-tasks)

    :init
    ;; Show project-tasks when switching projects
    (add-to-list 'project-switch-commands '(project-tasks "tasks") t)
    ;; Add action to embark-file map
    (with-eval-after-load 'embark
        (define-key embark-file-map (kbd "P") #'project-tasks-in-dir))

    :custom
    ;; Set the default filename in project
    (project-tasks-file "tasks.org")
    ;; Set the function to get current project dir
    (project-tasks-root-func #'project-tasks-project-root)

    ;; Bind project-tasks to project keymap
    :bind
    (:map project-prefix-map
             ("P" . project-tasks)
             ("o" . project-tasks-capture)
             ("O" . project-tasks-jump)))
  
  (use-package dape
    :ensure t
    :config
    (setq dape-cwd-fn 'projectile-project-root))

Interface

    (use-package catppuccin-theme
      :ensure t
      :config
      (load-theme 'catppuccin t))

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

    (use-package rainbow-mode
     :ensure t
     :config (add-hook 'prog-mode-hook #'rainbow-mode)
     (add-hook 'text-mode-hook #'rainbow-mode))

    (use-package dashboard
      :ensure t
      :init (dashboard-setup-startup-hook)
      :config
      (setq dashboard-startup-banner "~/Nextcloud/0x4d6165 Art/mae-small.png")
      (setq dashboard-center-content t)
      (setq dashboard-items '((recents  . 5)
                            (projects . 5)
                            (registers . 5))))
  (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")))

    (use-package nerd-icons
      :ensure t)

    (use-package nerd-icons-completion
      :ensure t
      :init (nerd-icons-completion-mode)
      :config (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))

    (use-package doom-modeline
      :ensure t
      :after nerd-icons
      :config
      (setq doom-modeline-battery t)
      (setq doom-modeline-time t)
      ;; (add-hook 'doom-modeline-mode-hook
      ;;           (lambda ()
      ;;               (doom-modeline-set-modeline 'my-custom-modeline 'default)))
      ;; (doom-modeline-def-segment todo-count
      ;; "Display the remaining number of todo items."
      ;; (let ((todo-count (count-todos-in-org-files)))
      ;;       (propertize (format " %s" todo-count)
      ;;                   'face '(:foreground "#eed49f")))) 
      ;; (doom-modeline-def-modeline 'my-custom-modeline
      ;; '(bar workspace-name window-number modals matches buffer-info remote-host buffer-position word-count parrot selection-info)
      ;; '(objed-state misc-info persp-name grip todo-count irc mu4e gnus github debug input-method indent-info buffer-encoding lsp major-mode process vcs checker battery time))

      ;; (setq doom-modeline-modeline 'my-custom-modeline)
      ;; (add-hook 'doom-modeline-mode-hook
      ;;           (lambda ()
      ;;               (doom-modeline-set-modeline 'my-custom-modeline 'default)))
      :hook (after-init . doom-modeline-mode))

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

    (use-package kind-icon
      :ensure t
      :after corfu
      :custom
      (kind-icon-default-face 'corfu-default) ; to compute blended backgrounds correctly
      :config
      (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))

    (use-package ligature
      :ensure t
      :config
      ;; Enable the "www" ligature in every possible major mode
      (ligature-set-ligatures 't '("www"))
      ;; Enable traditional ligature support in eww-mode, if the
      ;; `variable-pitch' face supports it
      (ligature-set-ligatures 'eww-mode '("ff" "fi" "ffi"))
      ;; Enable all Cascadia Code ligatures in programming modes
      (ligature-set-ligatures 'prog-mode '("|||>" "<|||" "<==>" "<!--" "####" "~~>" "***" "||=" "||>"
                                           ":::" "::=" "=:=" "===" "==>" "=!=" "=>>" "=<<" "=/=" "!=="
                                           "!!." ">=>" ">>=" ">>>" ">>-" ">->" "->>" "-->" "---" "-<<"
                                           "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->"
                                           "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "</>" "###" "#_(" "..<"
                                           "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~="
                                           "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|"
                                           "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:"
                                           ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:"
                                           "<$" "<=" "<>" "<-" "<<" "<+" "</" "#{" "#[" "#:" "#=" "#!"
                                           "##" "#(" "#?" "#_" "%%" ".=" ".-" ".." ".?" "+>" "++" "?:"
                                           "?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)"
                                           "\\\\" "://"))
      ;; Enables ligature checks globally in all buffers. You can also do it
      ;; per mode with `ligature-mode'.
      (global-ligature-mode t))

Completion

  (use-package cape
    :ensure t
    :init
    ;; Add `completion-at-point-functions', used by `completion-at-point'.
    ;; NOTE: The order matters!
    (add-to-list 'completion-at-point-functions #'cape-dabbrev)
    (add-to-list 'completion-at-point-functions #'cape-file)
    (add-to-list 'completion-at-point-functions #'cape-elisp-block)
    (add-to-list 'completion-at-point-functions #'cape-keyword))

  (use-package vertico
    :ensure t
    :init (vertico-mode)
    :config
    (defadvice vertico-insert
      (after vertico-insert-add-history activate)
    "Make vertico-insert add to the minibuffer history."
    (unless (eq minibuffer-history-variable t)
      (add-to-history minibuffer-history-variable (minibuffer-contents)))))

  (use-package marginalia
    :ensure t
    :bind (("M-A" . marginalia-cycle)
           :map minibuffer-local-map
           ("M-A" . marginalia-cycle))
    :init
    (marginalia-mode))

  (use-package orderless
    :ensure t
    :custom
    (completion-styles '(orderless basic))
    (completion-category-overrides '((file (styles basic partial-completion)))))

  (use-package rg
    :ensure t)
  (use-package consult
    :ensure t
    :config
     (defun consult-exwm-preview-fix (&rest _args)
    "Kludge to stop EXWM buffers from stealing focus during Consult previews."
    (when (derived-mode-p 'exwm-mode)
      (when-let ((mini (active-minibuffer-window)))
        (select-window (active-minibuffer-window)))))

    (advice-add
     #'consult--buffer-preview :after #'consult-exwm-preview-fix)
    (defun exwm-all-buffers ()
    (seq-filter
     (lambda (buffer)
       (eq 'exwm-mode (buffer-local-value 'major-mode buffer)))
     (buffer-list)))

  (defvar exwm-buffer-source
  `(:name "EXWM"
          :hidden t
          :narrow ?x
          :category buffer
          :state ,#'consult--buffer-state
          :items ,(lambda () (mapcar #'buffer-name (exwm-all-buffers)))))
    (add-to-list 'consult-buffer-sources 'exwm-buffer-source 'append)
    :general
    (general-nmap
      :prefix "SPC"
      "li" 'consult-imenu))

  ;;(use-package consult-eglot
  ;;  :ensure t)

  (use-package embark
    :ensure t
    :general
    (general-nmap
      :prefix "SPC m"
      "" '(nil :which-key "embark")
      "a" 'embark-act
      "d" 'embark-dwim)
    :bind
    (("C-." . embark-act)         ;; pick some comfortable binding
     ("C-;" . embark-dwim)        ;; good alternative: M-.
     ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
    :init
    (setq prefix-help-command #'embark-prefix-help-command)
    (add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target)
    ;; (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)
    :config
    (add-to-list 'display-buffer-alist
                 '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                   nil
                   (window-parameters (mode-line-format . none)))))

  (use-package embark-consult
    :ensure t ; only need to install it, embark loads it after consult if found
    :hook
    (embark-collect-mode . consult-preview-at-point-mode))

  (use-package wgrep
    :ensure t)

  ;; autocomplete
  (setq eglot-report-progress nil)
  (use-package corfu
    :ensure t
    :custom
    (corfu-auto t)
    (corfu-quit-no-match 'separator)
    (corfu-cycle t)           ;; Enable cycling for `corfu-next/previous'
    (corfu-preselect 'prompt) ;; Always preselect the prompt
    (corfu-history-mode 1)
    ;; (corfu-popupinfo-mode 1)
    :config
    (add-to-list 'savehist-additional-variables 'corfu-history)
    ;; (setq corfu-popupinfo-delay 0.5)
    ;; Use TAB for cycling, default is `corfu-complete'.
    ;; (defun my/eglot-capf ()
    ;;   (setq-local completion-at-point-functions
    ;; 	(list (cape-super-capf
    ;; 		#'eglot-completion-at-point
    ;; 		#'tempel-expand
    ;; 		#'cape-file
    ;; 		#'cape-tex))))

    ;; (add-hook 'eglot-managed-mode-hook #'my/eglot-capf)
    (defun my/setup-elisp ()
      (setq-local completion-at-point-functions
          (list (cape-super-capf
                  #'cape-dabbrev
                  #'elisp-completion-at-point
                  #'cape-history))))
    (add-hook 'emacs-lisp-mode-hook #'my/setup-elisp)
    :bind
    (:map corfu-map
          ("TAB" . corfu-next)
          ([tab] . corfu-next)
          ("M-TAB" . corfu-previous)
          ([backtab] . corfu-previous))
    :init
    (global-corfu-mode))

  ;;temple
  (use-package tempel
    :ensure t
    :after corfu
    ;; Require trigger prefix before template name when completing.
    ;; :custom
    ;; (tempel-trigger-prefix "<")

    :bind (("M--" . tempel-complete) ;; Alternative tempel-expand
           ("M-*" . tempel-insert))

    :init

    ;; Setup completion at point
    (defun tempel-setup-capf ()
      ;; Add the Tempel Capf to `completion-at-point-functions'.
      ;; `tempel-expand' only triggers on exact matches. Alternatively use
      ;; `tempel-complete' if you want to see all matches, but then you
      ;; should also configure `tempel-trigger-prefix', such that Tempel
      ;; does not trigger too often when you don't expect it. NOTE: We add
      ;; `tempel-expand' *before* the main programming mode Capf, such
      ;; that it will be tried first.
      (setq-local completion-at-point-functions
                  (cons #'tempel-expand
                        completion-at-point-functions)))

    (add-hook 'prog-mode-hook 'tempel-setup-capf)
    (add-hook 'text-mode-hook 'tempel-setup-capf)
    (global-tempel-abbrev-mode))

  (use-package tempel-collection
    :ensure t
    :after tempel)

Checking

  (use-package jinx
    :config (dolist (hook '(text-mode-hook conf-mode-hook))
   (add-hook hook #'jinx-mode)))

  ;; syntax checking
  (use-package flycheck
    :ensure t
    :init (global-flycheck-mode))

  (use-package eldoc-box
    :ensure t
    :config
    (setq eldoc-box-max-pixel-width 500)
    (setq eldoc-box-max-pixel-height 250)
    (setq eldoc-box-only-multi-line t)
    (add-hook 'emacs-lisp-mode-hook #'eldoc-box-hover-mode t)
    ;; (add-hook 'emacs-lisp-mode-hook #'eldoc-box-hover-at-point-mode t)
    ;; (add-hook 'emacs-lisp-mode-hook #'eldoc-box-help-at-point t)
    (add-hook 'eglot-managed-mode-hook #'eldoc-box-hover-mode t)
    (add-hook 'eglot-managed-mode-hook #'eldoc-box-hover-at-point-mode t))
    ;; (add-hook 'eglot-managed-mode-hook #'eldoc-box-help-at-point t))

  (use-package sideline
    :ensure t
    :init
    (setq sideline-backends-right '((sideline-lsp      . up)
                                    (sideline-flycheck . down)))
    (setq sideline-backends-left-skip-current-line t   ; don't display on current line (left)
          sideline-backends-right-skip-current-line t  ; don't display on current line (right)
          sideline-order-left 'down                    ; or 'up
          sideline-order-right 'up                     ; or 'down
          sideline-format-left "%s   "                 ; format for left aligment
          sideline-format-right "   %s"                ; format for right aligment
          sideline-priority 100                        ; overlays' priority
          sideline-display-backend-name t))            ; display the backend name
  (use-package sideline-flycheck
    :ensure t
    :hook (flycheck-mode . sideline-flycheck-setup))
  ;; lsp
  ;; (use-package lsp-mode
  ;; 	:ensure t
  ;; 	:config
  ;; 	(setq-default flycheck-disabled-checkers '(go-test go-unconvert go-megacheck go-staticcheck go-vet))
  ;; 	:custom
  ;;   (lsp-completion-provider :none) ;; we use Corfu!
  ;;   (gc-cons-threshold 100000000)
  ;;   (read-process-output-max (* 1024 1024))
  ;;   :init
  ;;   (defun my/orderless-dispatch-flex-first (_pattern index _total)
  ;;     (and (eq index 0) 'orderless-flex))

  ;;   (defun my/lsp-mode-setup-completion ()
  ;;     (setf (alist-get 'styles (alist-get -capf completion-category-defaults))
  ;;           '(orderless)))

  ;;   ;; Optionally configure the first word as flex filtered.
  ;;   (add-hook 'orderless-style-dispatchers #'my/orderless-dispatch-flex-first nil 'local)

  ;;   ;; Optionally configure the cape-capf-buster.
  ;;   (setq-local completion-at-point-functions (list (cape-capf-buster #-completion-at-point)))

  ;;   :hook
  ;;   (lsp-completion-mode . my/lsp-mode-setup-completion))
  ;; (use-package lsp-ui
  ;; 	:ensure t
  ;; 	:config
  ;; 	(setq lsp-ui-doc-enable t))

Languages

  (use-package treesit-auto
   :ensure t
   :config
   (global-treesit-auto-mode)
   (setq treesit-auto-install 'prompt))

  ;; (load "~/.emacs.d/org-notmuch.el")
  (use-package popper
    :ensure t
    :config
    (popper-mode +1)
    (popper-echo-mode +1))
  (use-package org
    ;; :straight (:repo "https://git.savannah.gnu.org/git/emacs/org-mode.git" :branch "main" :files ("*.el" "out")
    ;;                  :commit "ca873f7fe47546bca19821f1578a6ab95bf5351c")
    :ensure t
    :after popper
    :config
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((python . t)))
    ;; (load "~/.emacs.d/org-notmuch.el")
    (require 'org-protocol)
    (setq org-agenda-skip-scheduled-if-done t)
    (setq org-todo-keywords
        (quote ((sequence "TODO(t)" "DOING(g)" "|" "DONE(d)"))))

    (setq maeday/org-agenda-directory "~/Nextcloud/org/")
    (defun org-image-resize (frame)
      (when (derived-mode-p 'org-mode)
          (if (< (window-total-width) 80)
          (setq org-image-actual-width (window-pixel-width))
        (setq org-image-actual-width (* 80 (window-font-width))))
          (org-redisplay-inline-images)))

    (add-hook 'window-size-change-functions 'org-image-resize)
    (custom-set-variables
     '(org-directory "~/Nextcloud/org")
     '(org-agenda-files (list org-directory "~/Nextcloud/org/daily")))
    (setq org-capture-templates
        '(("w" "Web site" entry
           (file-head "%<%Y-%m-%d>.org")
              "* %a :https:\n\n%U %?\n\n%:initial")))
    (setq org-startup-with-inline-images t)
    (setq org-image-actual-width nil)
    (setq org-startup-truncated nil))

  (defun count-todos-in-org-files ()
    "Count all TODO items in Org mode files in `org-directory` and its subdirectories."
    (interactive)
    (let ((org-files (directory-files-recursively org-directory "\.org$"))
          (total-todos 0)
          buffer)
      (setq buffer (get-buffer-create "*org-file-tmp*"))
      (dolist (file org-files)
        (if (string-match "\.org$" file) ; Check if it's an Org mode file
            (with-current-buffer buffer
              (erase-buffer)
              (insert-file-contents file)
              (goto-char (point-min))
              (while (re-search-forward "^\\*+\\s-+\\(TODO\\|DOING\\)\\s-+" nil t)
                (setq total-todos (1+ total-todos))))))
      (kill-buffer buffer)
      total-todos))


  (use-package org-modern
    :ensure t
    :config
    (with-eval-after-load 'org (global-org-modern-mode)))

  (use-package org-noter
    :ensure t)

  (use-package nov
    :ensure t
    :config
    (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)))

  (use-package org-super-agenda
    :ensure t
    :config
    (add-hook 'org-mode-hook (lambda () (org-super-agenda-mode)))
    (let ((org-super-agenda-groups
           '(;; Each group has an implicit boolean OR operator between its selectors.

           (:name "Today"  ; Optionally specify section name
                  :time-grid t  ; Items that appear on the time grid
                  :todo "TODAY")  ; Items that have this TODO keyword
           (:name "Deadline Future"
                          :deadline future)
           ;; Groups supply their own section names when none are given
           (:todo "WAITING" :order 8)  ; Set order of this section
           (:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING")
                  ;; Show this group at the end of the agenda (since it has the
                  ;; highest number). If you specified this group last, items
                  ;; with these todo keywords that e.g. have priority A would be
                  ;; displayed in that group instead, because items are grouped
                  ;; out in the order the groups are listed.
                  :order 9)
           (:priority<= "B"
                        ;; Show this section after "Today" and "Important", because
                        ;; their order is unspecified, defaulting to 0. Sections
                        ;; are displayed lowest-number-first.
                        :order 1)
           ;; After the last group, the agenda will display items that didn't
           ;; match any of these groups, with the default order position of 99
           )))))

  (use-package consult-org-roam
    :ensure t
    :config
    (add-hook 'org-mode-hook (lambda () (consult-org-roam-mode))))
  (use-package org-roam
    :ensure t
    :custom
    (org-roam-directory "/home/maedayscout/Nextcloud/org")
    :general
    (general-nmap
      :prefix "SPC o"
      "" '(nil :which-key "org-mode")
      "a" 'org-agenda
      "l" 'org-roam-buffer-toggle
      "f" 'org-roam-node-find
      "g" 'org-roam-graph
      "i" 'org-roam-node-insert
      "c" 'org-roam-capture
      "j" 'org-roam-dailies-capture-today
      "s" 'consult-org-roam-search)
    :config
    (setq org-roam-dailies-capture-templates
             (let ((head "#+title: %<%Y-%m-%d (%A)>\n#+startup: showall\n* [/] Do Today\n* [/]\n"))
               `(("d" "default" entry
                  "* %?"
                  :target (file+head "%<%Y-%m-%d>.org"
                                     "#+title: %<%Y-%m-%d>\n#+filetags :daily:\n"))
                 ("t" "do today" item
                  "TODO "
                  :file-name "daily/%<%Y-%m-%d>"
                  :if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n#+filetags :daily:\n")
                  :head ,head
                  :olp ("Do Today")
                  :immediate-finish t))))
    (defun my/org-roam-copy-todo-to-today ()
      (interactive)
      (let ((org-refile-keep t) ;; Set this to nil to delete the original!
              (org-roam-dailies-capture-templates
              '(("t" "tasks" entry "%?"
                  :if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n" ("Tasks")))))
              (org-after-refile-insert-hook #'save-buffer)
              today-file
              pos)
          (save-window-excursion
          (org-roam-dailies--capture (current-time) t)
          (setq today-file (buffer-file-name))
          (setq pos (point)))

          ;; Only refile if the target file is different than the current file
          (unless (equal (file-truename today-file)
                      (file-truename (buffer-file-name)))
          (org-refile nil nil (list "Tasks" today-file nil pos)))))

      (add-to-list 'org-after-todo-state-change-hook
               (lambda ()
                 (when (equal org-state "DONE")
                   (my/org-roam-copy-todo-to-today))))
    (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))

    (org-roam-db-autosync-mode)
    ;; If using org-roam-protocol
    (require 'org-roam-protocol))

  (use-package org-roam-ui
      :ensure t
      :after org-roam
      :config
      (setq org-roam-ui-sync-theme t
            org-roam-ui-follow t
            org-roam-ui-update-on-save t
            org-roam-ui-open-on-start t))

  (use-package ob-sagemath
    :ensure t
    ;; Ob-sagemath supports only evaluating with a session.
    :config
      (setq org-babel-default-header-args:sage '((:session . t)
                                              (:results . "output")))

      ;; C-c c for asynchronous evaluating (only for SageMath code blocks).
      (with-eval-after-load "org"
          (define-key org-mode-map (kbd "C-c c") 'ob-sagemath-execute-async))

      ;; Do not confirm before evaluation
      (setq org-confirm-babel-evaluate nil)

      ;; Do not evaluate code blocks when exporting.
      (setq org-export-babel-evaluate nil)

      ;; Show images when opening a file.
      (setq org-startup-with-inline-images t)

      ;; Show images after evaluating code blocks.
      (add-hook 'org-babel-after-execute-hook 'org-display-inline-images))

  (use-package org-fragtog
    :ensure t
    :config
    (add-hook 'org-mode-hook 'org-fragtog-mode))

  (use-package org-web-tools
    :ensure t)

  (use-package ledger-mode
    :ensure t)

  (use-package htmlize
    :ensure t)

  (use-package markdown-mode
    :ensure t
    :mode ("README\\.md\\'" . gfm-mode)
    :init (setq markdown-command "multimarkdown")
    :general (general-nmap
               :prefix "SPC"
               "lm" 'markdown-do))

  (add-hook 'c-ts-mode-hook #'eglot-ensure)

  (add-hook 'c++-mode-hook #'eglot-ensure)
  (add-hook 'c++-ts-mode-hook #'eglot-ensure)

  (use-package meson-mode
    :ensure t)

  (use-package web-mode
    :ensure t
    :config
    (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
    (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
    (add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
    (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
    (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
    (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
    (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
    (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)))

  ;; haskell
  (use-package haskell-mode
    :ensure t
    :config
    (setenv "PATH" (concat (getenv "PATH") ":$HOME/.cabal/bin:$HOME/.ghcup/bin"))
    :hook
    (haskell-mode . eglot-ensure ))

  ;; rust
  (use-package rust-mode
    :ensure t
    :config
    (setq flycheck-disabled-checkers '(rust-cargo))
    :hook ((rust-ts-mode . eglot-ensure)
    (rust-mode . eglot-ensure)))

  (use-package pest-mode
    :ensure t
    :mode "\\.pest\\'"
    :hook (pest-mode . flymake-mode))
  ;; forth
  (use-package forth-mode
    :ensure t)

  ;; go
  (use-package go-mode
    :config
    :hook ((go-mode . eglot-ensure)
             (go-ts-mode . eglot-ensure)))
  (add-hook 'go-mode-hook
    (lambda ()
      (setq-default)
      (setq tab-width 2)
      (setq standard-indent 2)
      (setq indent-tabs-mode nil)))
  (add-hook 'go-ts-mode-hook
    (lambda ()
      (setq-default)
      (setq tab-width 2)
      (setq standard-indent 2)
      (setq indent-tabs-mode nil)))
  ;; (add-hook 'go-ts-mode-hook
  ;; 				#'(lambda ()
  ;; 						(add-hook 'before-save-hook 'gofmt-before-save)
  ;; 						(setq tab-width 4)
  ;; 						(setq indent-tabs-mode 1)))
  ;; (add-hook 'go-mode-hook
  ;; 				#'(lambda ()
  ;; 						(add-hook 'before-save-hook 'gofmt-before-save)
  ;; 						(setq tab-width 4)
  ;; 						(setq indent-tabs-mode 1)))

  (use-package gotest
    :ensure t)

  (use-package go-eldoc
    :ensure t
    :hook ((go-mode . go-eldoc-setup)
           (go-ts-mode . go-eldoc-setup)))

  ;; python
  (use-package poetry
    :ensure t
    :config (setq python-shell-interpreter "ipython"
                  python-shell-interpreter-args "-i --simple-prompt --InteractiveShell.display_page=True")
    :hook
    ((python-mode . pipenv-mode)
     (python-ts-mode . pipenv-mode)
     (python-mode . poetry-tracking-mode)
     (python-ts-mode . poetry-tracking-mode)))

  (add-hook 'python-mode-hook #'eglot-ensure)
  (add-hook 'python-ts-mode-hook #'eglot-ensure)

  (use-package pip-requirements
    :ensure t)

  (use-package pipenv
    :hook ((python-mode . pipenv-mode)
     (python-ts-mode . pipenv-mode))
    :ensure t)

  (use-package python-pytest
    :ensure t
    :commands python-pytest-dispatch)

  (use-package sage-shell-mode
    :ensure t
    :init (custom-set-variables
          '(sage-shell:use-prompt-toolkit nil)
          '(sage-shell:use-simple-prompt t)
          '(sage-shell:set-ipython-version-on-startup nil)
          '(sage-shell:check-ipython-version-on-startup nil))
          (sage-shell:define-alias))

  ;; godot
  (use-package gdscript-mode
    :ensure t
    :mode "\\.gd\\'"
    :hook (gdscript-mode . eglot-ensure)
      (gdscript-ts-mode . eglot-ensure))

  ;; lua
  (use-package lua-mode
    :ensure t
    :mode "\\.lua\\'"
    :config
    (add-hook 'lua-mode-hook #'eglot-ensure))

  ;; yuck
  (use-package yuck-mode
    :ensure t
    :mode "\\.yuck\\'")

  ;; uxn
  (use-package uxntal-mode
      :ensure t) 

  ;; nix
  (use-package nix-mode
    :ensure t
    :mode "\\.nix\\'")
  (use-package direnv
    :ensure t
    :config
    (direnv-mode))
  (use-package nix3
    :ensure t)

  ;; LaTeX
  (use-package tex
    :defer t
    :config
    (setq TeX-auto-save t)
    (setq lsp-tex-server 'digestif)
    (add-hook 'LaTeX-mode #'eglot-ensure))

  ;;(use-package auctex-latexmk
  ;;  :after tex
  ;;  :ensure t
  ;;  :config
  ;; (auctex-latexmk-setup))

  (use-package latex-preview-pane
    :after tex
    :ensure t)

  (use-package pdf-tools
    :ensure t)


  (use-package projectile
    :ensure t
    :config
    (projectile-mode +1)
    :general
    (general-nmap
      :prefix "SPC p"
      "" '(nil :which-key "projectile")
      "p" 'projectile-switch-project
      "f" 'projectile-find-file))


  ;; misc editor plugins
  ;;(use-package adaptive-wrap
  ;;  :ensure t
  ;;  :config
  ;;  (add-hook 'LaTeX-mode #'adaptive-wrap-prefix-mode))

  (use-package ialign
    :ensure t)

Apps

      ;; apps
      ;; (use-package consult-notmuch
      ;; 	:ensure t
      ;; 	:config
      ;; 	(setq message-cite-style message-cite-style-gmail)
      ;;   (add-hook 'message-mode-hook
      ;;           (lambda ()
      ;;             (font-lock-add-keywords nil
      ;;                '(("^[ \t]*>[ \t]*>[ \t]*>.*$"
      ;;                   (0 'message-multiply-quoted-text-face))
      ;;                  ("^[ \t]*>[ \t]*>.*$"
      ;;                   (0 'message-double-quoted-text-face))))))
      ;;   (add-hook 'mail-mode-hook
      ;;           (lambda ()
      ;;             (font-lock-add-keywords nil
      ;;                '(("^[ \t]*>[ \t]*>[ \t]*>.*$"
      ;;                   (0 'message-multiply-quoted-text-face))
      ;;                  ("^[ \t]*>[ \t]*>.*$"
      ;;                   (0 'message-double-quoted-text-face))))))
      ;; 	(defun consult-notmuch (&optional initial)
      ;;     "Search for your email in notmuch, showing single messages.
      ;;   If given, use INITIAL as the starting point of the query."
      ;;    (interactive)
      ;;    (consult-notmuch--show (consult-notmuch--search initial)))

      ;; 	(defun consult-notmuch-debian (&optional tree)
      ;;     (interactive "P")
      ;;     (let ((init "tag:debian "))
      ;;       (if tree (consult-notmuch-tree init) (consult-notmuch init))))
      ;;   ;;;###autoload
      ;;   (defun consult-notmuch-tree (&optional initial)
      ;;     "Search for your email in notmuch, showing full candidate tree.
      ;;   If given, use INITIAL as the starting point of the query."
      ;;     (interactive)
      ;;     (consult-notmuch--tree (consult-notmuch--search initial))))

      (use-package popwin
        :ensure t)

      (setq user-mail-address "maeborow@posteo.net")
      (setq user-full-name "Mae Miller")
      ;; (use-package notmuch
      ;; 	:after popwin
      ;; 	:ensure t
      ;; 	:general
      ;;   (general-nmap
      ;;     :prefix "SPC e"
      ;;     "" '(nil :which-key "notmuch")
      ;;     "e" 'notmuch-hello
      ;; 		"c" 'consult-notmuch
      ;; 		"d" 'consult-notmuch-debian
      ;; 		"s" 'notmuch-exec-mbsync)
      ;; 	:config
      ;; 	(setq user-mail-address "maeborow@posteo.net")
      ;; 	(setq user-full-name "Mae Miller")
      ;; 	(setq +notmuch-sync-backend 'mbsync)
      ;; 	(setq smtpmail-stream-type 'ssl
      ;; 				smtpmail-smtp-server "posteo.de"
      ;; 				smtpmail-smtp-service 465)
      ;; 	(add-hook 'message-setup-hook 'mml-secure-sign-pgpmime)
      ;;   (setq +notmuch-sync-backend 'mbsync)
      ;; 	;; (define-key notmuch-show-mode-map "S"
      ;; 	;; 	(lambda ()
      ;; 	;; 			"delete message and move on"
      ;; 	;; 			(notmuch-show-tag '("+deleted" "-unread"))
      ;; 	;; 			(notmuch-show-next-open-message-or-pop)))
      ;;   (defun notmuch-exec-mbsync ()
      ;;       "execute mbsync"
      ;;       (interactive)
      ;;       (set-process-sentinel
      ;;        (start-process-shell-command "mbsync"
      ;;                                     "*mbsync*"
      ;;                                     "/home/maedayscout/scripts/sync-mail.sh")
      ;;        #'(lambda (process event)
      ;;           (notmuch-refresh-all-buffers)
      ;;           (let ((w (get-buffer-window "*mbsync*")))
      ;;             (when w
      ;;               (with-selected-window w (recenter (window-end)))))))
      ;;       (popwin:display-buffer "*mbsync*"))

      ;;   (add-to-list 'popwin:special-display-config
      ;;                '("*mbsync*" :dedicated t :position bottom
      ;;                  :height 0.4 :noselect t))

      ;; 	(setq notmuch-saved-searches
      ;; 				'((:name "inbox"
      ;; 					 :query "tag:inbox"
      ;; 					 :sort-order newest-first)
      ;; 			    (:name "archive"
      ;; 					 :query "tag:archive"
      ;; 					 :sort-order newest-first)
      ;; 					(:name "sent"
      ;; 					 :query "tag:sent"
      ;; 					 :sort-order newest-first)
      ;; 					(:name "debian"
      ;; 					 :query "tag:debian-announce or tag:debian-mentors or tag:debian-bugs or tag:debian"
      ;; 					 :sort-order newest-first)
      ;; 					(:name "trash"
      ;; 					 :query "tag:deleted or folder:Trash"
      ;; 					 :sort-order newest-first))))

      (setq rcirc-server-alist
            '(("chat.sr.ht"
               :port 6697
               :encryption tls
               :nick "x4d6165"
               :user-name "robotfoxears/irc.orpheus.network")))

      (setq erc-email-userid "robotfoxears/irc.orpheus.network")
      (defun run-erc ()
        (interactive)
        (erc-tls :server "chat.sr.ht"
                 :port 6697
                 :nick "x4d6165"))
      (defun kill-all-erc-buffers ()
        "Kill all ERC (Emacs IRC) buffers."
        (interactive)
        (dolist (buffer (buffer-list))
          (when (eq 'erc-mode (buffer-local-value 'major-mode buffer))
            (kill-buffer buffer))))


      (use-package mu4e
         :general
         (general-nmap
           :prefix "SPC e"
           "" '(nil :which-key "notmuch")
           "e" 'mu4e
           "c" 'consult-notmuch
           "d" 'consult-notmuch-debian)
         :config
         ;; refresh mbsync every 10 minutes
         (setq mu4e-update-interval (* 10 60))
         (setq mu4e-get-mail-command "mbsync -a")
         (setq mu4e-maildir "~/.local/share/email/")
         (setq auth-source-debug t)
         (setq auth-source-do-cache nil)
         ;; no reply to self
         (setq mu4e-compose-dont-reply-to-self t)
         (setq mu4e-compose-keep-self-cc nil)
         ;; moving messages renames files to avoid errors
         (setq mu4e-change-filenames-when-moving t)
         ;; Configure the function to use for sending mail
         (setq message-send-mail-function 'smtpmail-send-it)
         ;; Display options
         (setq mu4e-view-show-images t)
         (setq mu4e-view-show-addresses 't)
         ;; Composing mail
         (setq mu4e-compose-dont-reply-to-self t)
         ;; don't keep message buffers around
         (setq message-kill-buffer-on-exit t)
         ;; Don't ask for a 'context' upon opening mu4e
         (setq mu4e-context-policy 'pick-first)
         ;; Don't ask to quit... why is this the default?
         (setq mu4e-confirm-quit nil)

         ;; Set up contexts for email accounts
         (setq mu4e-contexts
               (list
                (make-mu4e-context
                 :name "posteo"
                 :match-func
             (lambda (msg)
                   (when msg
                     (string-prefix-p "/posteo" (mu4e-message-field msg :maildir))))
                 :vars `((user-mail-address . "maeborow@posteo.net")
                         (user-full-name    . "Margaret Miller")
                         (smtpmail-smtp-server  . "posteo.de")
                         (smtpmail-smtp-service . "465")
                         (smtpmail-stream-type  . ssl)
                         (smtpmail-smtp-user . "maeborow@posteo.net")
                         (mu4e-drafts-folder  . "/Drafts")
                         (mu4e-sent-folder  . "/Sent")
                         (mu4e-refile-folder  . "/Archive")
                         (mu4e-trash-folder  . "/Trash")
                         ( mu4e-bookmarks
                           .
                           (( :name  "Unread messages"
                               :query "flag:unread AND NOT flag:trashed"
                               :key ?u)
                               ( :name "Today's messages"
                               :query "date:today..now"
                               :key ?t)
                               ( :name "Inbox"
                               :query "maildir:/INBOX"
                               :hide-unread t
                               :key ?i)
                               ( :name "Full Archive"
                               :query "maildir:/Archive"
                               :hide-unread t
                               :key ?a)
                               ( :name "Sent Messages"
                               :query "maildir:/Sent"
                               :key ?S)
                               )
                         )))))

         (setq m/mu4e-inbox-query
               "(maildir:/INBOX) AND flag:unread")
         (defun m/go-to-inbox ()
           (interactive)
           (mu4e-headers-search m/mu4e-inbox-query))
         ;; start mu4e
         (mu4e t)
         )

      (use-package mu4e-alert
        :init
        (defun perso--mu4e-notif ()
          "Display both mode line and desktop alerts for incoming new emails."
          (interactive)
          (mu4e-update-mail-and-index 1)        ; getting new emails is ran in the background
          (mu4e-alert-enable-mode-line-display) ; display new emails in mode-line
          (mu4e-alert-enable-notifications))    ; enable desktop notifications for new emails
        (defun perso--mu4e-refresh ()
          "Refresh emails every 300 seconds and display desktop alerts."
          (interactive)
          (mu4e t)                            ; start silently mu4e (mandatory for mu>=1.3.8)
          (run-with-timer 0 300 'perso--mu4e-notif))
        :after mu4e
        :config
        ;; Mode line alerts:
        (add-hook 'after-init-hook #'perso--mu4e-notif)
        (add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display)
        ;; Desktop alerts:
        (mu4e-alert-set-default-style 'libnotify)
        (add-hook 'after-init-hook #'mu4e-alert-enable-notifications)
        ;; Only notify for "interesting" (non-trashed) new emails:
        (setq mu4e-alert-interesting-mail-query
              (concat
               "flag:unread maildir:/INBOX"
               " AND NOT flag:trashed")))

      (custom-set-variables
       ;; custom-set-variables 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.
       '(custom-safe-themes
         '("26149a1b5de476aa661bbb9c8f79540509c038fbba58c1c719466851c2968464" default))
       '(mml-secure-openpgp-sign-with-sender t)
       '(org-agenda-files (list org-directory "~/Nextcloud/org/daily"))
       '(org-directory "~/Nextcloud/org")
       '(sage-shell:check-ipython-version-on-startup nil)
       '(sage-shell:set-ipython-version-on-startup nil)
       '(sage-shell:use-prompt-toolkit nil)
       '(sage-shell:use-simple-prompt t)
       '(send-mail-function 'smtpmail-send-it)
       '(warning-suppress-log-types '((use-package))))
      (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.
       )

      (use-package debpaste
        :ensure t)

      (use-package mastodon
       :ensure t
       :config
       (setq mastodon-instance-url "https://hackers.town"
             mastodon-active-user "0x4d6165"))


  (use-package elfeed
    :ensure t
    :commands (elfeed elfeed-update))
  (use-package elfeed-protocol
    :ensure t
    :after elfeed
    :config
    (setq elfeed-use-curl t)
    (elfeed-set-timeout 36000)

    ;; setup feeds
    (setq elfeed-protocol-fever-update-unread-only nil)
    (setq elfeed-protocol-fever-fetch-category-as-tag t)
    (setq elfeed-protocol-feeds '(("fever+https://0x4d6165@feeds.wanderingwires.gay"
                                :api-url "https://feeds.wanderingwires.gay/fever/"
                                :use-authinfo t)))
    ;; enable elfeed-protocol
    (setq elfeed-protocol-enabled-protocols '(fever))
    (elfeed-protocol-enable))

  (use-package elfeed-score
    :ensure t
    :after elfeed
    :config
    (progn
        (elfeed-score-enable)
        (define-key elfeed-search-mode-map "=" elfeed-score-map)))

  (use-package tarock
    :ensure t)

EXWM

  (use-package exwm
    :ensure t
    :config
    (setq exwm-workspace-number 9)
    (setq exwm-workspace-offset 20)
    (require 'exwm-systemtray)
    (exwm-systemtray-enable)
    ;; All buffers created in EXWM mode are named "*EXWM*". You may want to
    ;; change it in `exwm-update-class-hook' and `exwm-update-title-hook', which
    ;; are run when a new X window class name or title is available.  Here's
    ;; some advice on this topic:
    ;; + Always use `exwm-workspace-rename-buffer` to avoid naming conflict.
    ;; + For applications with multiple windows (e.g. GIMP), the class names of
    ;    all windows are probably the same.  Using window titles for them makes
    ;;   more sense.
    ;; In the following example, we use class names for all windows except for
    ;; Java applications and GIMP.
    (add-hook 'exwm-update-class-hook
              (lambda ()
                (unless (or (string-prefix-p "sun-awt-X11-" exwm-instance-name)
                            (string= "gimp" exwm-instance-name))
                  (exwm-workspace-rename-buffer exwm-class-name))))
    (add-hook 'exwm-update-title-hook
              (lambda ()
                (when (or (not exwm-instance-name)
                          (string-prefix-p "sun-awt-X11-" exwm-instance-name)
                          (string= "gimp" exwm-instance-name))
                  (exwm-workspace-rename-buffer exwm-title))))

    ;; Global keybindings can be defined with `exwm-input-global-keys'.
    ;; Here are a few examples:
    (setq exwm-input-global-keys
          `(
            ;; Bind "s-r" to exit char-mode and fullscreen mode.
            ([?\s-s] . exwm-reset)
            ;; Bind "s-w" to switch workspace interactively.
            ([?\s-w] . exwm-workspace-move-window)
            ([?\s-h] . windmove-left)
            ([?\s-l] . windmove-right)
            ([?\s-k] . windmove-up)
            ([?\s-j] . windmove-down)
            ([?\s-a] . exwm-workspace-switch-to-buffer)
            ([?\s-q] . pkill-xinit)
            ([?\s-f] . org-roam-node-find)
            ([?\s-p] . suspend-session)

            ;; application keybinds
            ([?\s-t] . vterm)
            ([?\s-c] . calc)

            ;; Bind "s-0" to "s-9" to switch to a workspace by its index.
            ,@(mapcar (lambda (i)
                        `(,(kbd (format "s-%d" i)) .
                          (lambda ()
                            (interactive)
                            (exwm-workspace-switch-create ,i))))
                      (number-sequence 0 9))
            ([?\s-m] . exwm-workspace-move-window)
            ;; Bind "s-r" to launch applications ('M-&' also works if the output
            ;; buffer does not bother you).
            ([?\s-r] . app-launcher-run-app)
            ;; Bind "s-<f2>" to "i3lock", a simple X display locker.
            ([s-f2] . (lambda ()
            (interactive)
            (start-process "" nil "i3lock")))))

    ;; To add a key binding only available in line-mode, simply define it in
    ;; `exwm-mode-map'.  The following example shortens 'C-c q' to 'C-q'.
    (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)

    ;; The following example demonstrates how to use simulation keys to mimic
    ;; the behavior of Emacs.  The value of `exwm-input-simulation-keys` is a
    ;; list of cons cells (SRC . DEST), where SRC is the key sequence you press
    ;; and DEST is what EXWM actually sends to application.  Note that both SRC
    ;; and DEST should be key sequences (vector or string).
    (setq exwm-input-simulation-keys
          '(
            ;; movement
            ([?\C-b] . [left])
            ([?\M-b] . [C-left])
            ([?\C-f] . [right])
            ([?\M-f] . [C-right])
            ([?\C-p] . [up])
            ([?\C-n] . [down])
            ([?\C-a] . [home])
            ([?\C-e] . [end])
            ([?\M-v] . [prior])
            ([?\C-v] . [next])
            ([?\C-d] . [delete])
            ([?\C-k] . [S-end delete])
            ;; cut/paste.
            ([?\C-w] . [?\C-x])
            ([?\M-w] . [?\C-c])
            ([?\C-y] . [?\C-v])
            ;; search
            ([?\C-s] . [?\C-f])))

    ;; You can hide the minibuffer and echo area when they're not used, by
    ;; uncommenting the following line.
                                          ;(setq exwm-workspace-minibuffer-position 'bottom)
    (defun pkill-xinit ()
    "Kill the xinit process."
      (interactive)
      (if (y-or-n-p "Are you sure you want to kill the X sesession? ")
          (progn
              (shell-command "lxqt-leave")
              (message "xinit killed."))
          (message "xinit not killed.")))

    (defun suspend-session ()
    "Suspend the system."
      (interactive)
      (if (y-or-n-p "Are you sure you want to suspend? ")
          (progn
              (shell-command "systemctl suspend")
              (message "system suspended."))
          (message "system not suspended.")))

    ;; for lemonbar
    ;; (defun my/exwm-workspace-list ()
    ;;     "Return a lemonbar string showing workspace list."
    ;;     (let* ((num (exwm-workspace--count))
    ;;         (sequence (number-sequence 0 (1- num)))
    ;;         (curr (exwm-workspace--position exwm-workspace--current)))
    ;;         (mapconcat (lambda (i)
    ;;             (format (if (= i curr) "[%%{F#c6a0f6}%d%%{F-}] " "%d ") i))
    ;;             sequence "")
    ;;         ))

    ;; (defun my/exwm-report-workspaces-to-lemonbar ()
    ;;     (with-temp-file "/tmp/panel-fifo"
    ;;         (insert (format "WIN%s\n" (my/exwm-workspace-list)))))

    ;; (add-hook 'exwm-workspace-switch-hook #'my/exwm-report-workspaces-to-lemonbar)
    ;; (add-hook 'exwm-init-hook #'my/exwm-report-workspaces-to-lemonbar)
    ;; Do not forget to enable EXWM. It will start by itself when things are
    ;; ready.  You can put it _anywhere_ in your configuration.
    (setenv "GPG_AGENT_INFO" nil)  ;; use emacs pinentry
    (setq auth-source-debug t)

    (setq epg-gpg-program "gpg2")  ;; not necessary
    (require 'epa-file)
    (epa-file-enable)
    (setq epa-pinentry-mode 'loopback)
    (setq epg-pinentry-mode 'loopback)
    (pinentry-start)

    (require 'org-crypt)
    (org-crypt-use-before-save-magic)

    (exwm-enable))


  (use-package vterm
    :ensure t)




  (use-package eat
    :ensure t)
  ;;   :straight '(:type git
  ;;         :host codeberg
  ;;         :repo "akib/emacs-eat"
  ;;         :files ("*.el" ("term" "term/*.el") "*.texi"
  ;;                 "*.ti" ("terminfo/e" "terminfo/e/*")
  ;;                 ("terminfo/65" "terminfo/65/*")
  ;;                 ("integration" "integration/*")
  ;;                 (:exclude ".dir-locals.el" "*-tests.el"))))



  (use-package desktop-environment
    :ensure t 
    :config
    (desktop-environment-mode))

  (use-package browse-kill-ring
    :ensure t)

  (use-package app-launcher
    :ensure t)

Emacs Lisp

(defun my-eval-and-run-all-tests-in-buffer ()
  "Deletes all loaded tests from the runtime, evaluates the current buffer and runs all loaded tests with ert."
  (interactive)
  (ert-delete-all-tests)
  (eval-buffer)
  (ert 't))