66 KiB
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))