;; -*- lexical-binding: t; -*- (add-to-list 'load-path "~/.emacs.d/elisp") (setq package-list '(avy corfu devdocs diminish ednc eldoc-box elfeed elfeed-protocol enwc emms expand-region exwm geiser geiser-guile git-gutter git-gutter-fringe go-mode guix pdf-tools magit markdown-mode mastodon nix-mode nov pass pinentry rec-mode tldr transpose-frame yasnippet yasnippet-snippets ws-butler) package-archives '(("elpa" . "https://elpa.gnu.org") ("gnu" . "http://elpa.gnu.org/packages/") ("melpa" . "https://melpa.org/packages/") ("non-gnu" . "https://elpa.nongnu.org/nongnu/") ("melpa-stable" . "https://stable.melpa.org/packages/"))) (package-initialize) (unless package-archive-contents (package-refresh-contents)) ;; install the missing packages (dolist (package package-list) (unless (package-installed-p package) (package-install package))) (load-theme 'BOGO t) (use-package exwm :init (setq exwm-workspace-number 1 exwm-input-global-keys `(([?\s-r] . exwm-reset) ;; s-r: Reset (to line-mode). ;; s-N: Switch to certain workspace. ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . (lambda () (interactive) (tab-bar-select-tab ,i)))) (number-sequence 0 9)))) (exwm-input-set-key (kbd "s-f") 'exwm-layout-toggle-fullscreen) (exwm-input-set-key (kbd "") (lambda () (interactive) (shell-command "scrot -F '/home/mccd/screenshots/%Y-%m-%d_$wx$h.png'"))) (exwm-input-set-key (kbd "C-") (lambda () (interactive) (shell-command "scrot -s -F '/home/mccd/screenshots/%Y-%m-%d_$wx$h.png'"))) (exwm-input-set-key (kbd "") (lambda () (interactive) (let ((inhibit-message t)) (shell-command "amixer set Master toggle 1> /dev/null")))) (exwm-input-set-key (kbd "") (lambda () (interactive) (let ((inhibit-message t)) (shell-command "amixer set Master 10%+ 1> /dev/null")))) (exwm-input-set-key (kbd "") (lambda () (interactive) (let ((inhibit-message t)) (shell-command "amixer set Master 10%- 1> /dev/null")))) (exwm-input-set-key (kbd "") (lambda () (interactive) (let ((inhibit-message t)) (shell-command "brightnessctl set 5%-")))) (exwm-input-set-key (kbd "") (lambda () (interactive) (let ((inhibit-message t)) (shell-command "brightnessctl set +5%")))) (exwm-input-set-key (kbd "s-") (lambda (cmd) ;; s-&: Launch application. (interactive (list (read-shell-command "$ "))) (start-process-shell-command cmd nil cmd))) (push ?\C-\\ exwm-input-prefix-keys) (shell-command "xrdb ~/.Xresources") :custom (ring-bell-function 'ignore) (default-directory "/home/mccd/") (focus-follows-mouse t) (comment-multi-line t) (sentence-end-double-space nil) (require-final-newline t) (kill-do-not-save-duplicates t) (comment-empty-lines t) (lazy-highlight-initial-delay 0) (mouse-autoselect-window t) :hook (;; Make sure titles match X window (exwm-init . (lambda () (interactive) (load-library "/home/mccd/.emacs.d/auth.el.gpg"))) (exwm-update-title . (lambda () (exwm-workspace-rename-buffer (concat exwm-class-name ":" (if (<= (length exwm-title) 50) exwm-title (concat (substring exwm-title 0 49) "...")))))) (exwm-update-class . (lambda () (exwm-workspace-rename-buffer (concat exwm-class-name ":" (if (<= (length exwm-title) 50) exwm-title (concat (substring exwm-title 0 49) "...")))))))) (use-package diminish :ensure t) (use-package ediff :custom (ediff-window-setup-function #'ediff-setup-windows-plain) (ediff-split-window-function #'split-window-horizontally)) (use-package emacs :config (fset 'yes-or-no-p 'y-or-n-p) (menu-bar-mode -1) (tool-bar-mode -1) (setq-default fill-column 80 line-spacing 10 cursor-type 'box cursor-in-non-selected-windows nil frame-title-format '("%b")) :custom (highlight-nonselected-windows nil) (default-frame-alist '((font . "Iosevka SS13 Extended") (height . 150) (line-spacing . 0.5))) (undo-limit 10000000) (undo-outer-limit 20000000) (create-lockfiles nil) (idle-update-delay 1.0) (auto-save-list-file-prefix (expand-file-name "autosave/" user-emacs-directory)) (tramp-auto-save-directory (expand-file-name "tramp-autosave/" user-emacs-directory)) ;; Auto save options (kill-buffer-delete-auto-save-files t) ;; Revert other buffers (e.g, Dired) (global-auto-revert-non-file-buffers t) ;;; recentf ;; `recentf' is an Emacs package that maintains a list of recently ;; accessed files, making it easier to reopen files you have worked on ;; recently. (recentf-max-saved-items 300) ; default is 20 (recehvntf-auto-cleanup 'mode) ;;; saveplace ;; `save-place-mode` enables Emacs to remember the last location within a file ;; upon reopening. This feature is particularly beneficial for resuming work at ;; the precise point where you previously left off. (save-place-file (expand-file-name "saveplace" user-emacs-directory)) (save-place-limit 600) ;;; savehist ;; `savehist` is an Emacs feature that preserves the minibuffer history between ;; sessions. It saves the history of inputs in the minibuffer, such as commands, ;; search strings, and other prompts, to a file. This allows users to retain ;; their minibuffer history across Emacs restarts. (history-length 300) (savehist-save-minibuffer-history t) ;; Default ;; Resizing the Emacs frame can be costly when changing the font. Disable this ;; to improve startup times with fonts larger than the system default. (frame-resize-pixelwise t) ;; However, do not resize windows pixelwise, as this can cause crashes in some ;; cases when resizing too many windows at once or rapidly. (window-resize-pixelwise nil) (resize-mini-windows 'grow-only) (fast-but-imprecise-scrolling t) (blink-cursor-mode -1) (x-stretch-cursor t) (tab-always-indent 'complete) (text-mode-ispell-word-completion nil) (read-extended-command-predicate #'command-completion-default-include-p )) (use-package vc-hooks :custom (vc-make-backup-files nil)) (use-package tab-bar :custom (tab-bar-auto-width t) (tab-bar-close-button-show nil) (tab-bar-format '(tab-bar-format-tabs tab-bar-format-align-right tab-bar-format-global)) :init (tab-bar-mode) (setq tab-bar-new-tab-choice "*scratch*")) (use-package project :ensure t :bind (:map project-prefix-map ("b" . project-list-buffers)) :config (add-to-list 'project-switch-commands '(project-list-buffers "Buffers")) (add-to-list 'project-switch-commands '(project-kill-buffers "Kill Buffers")) (add-to-list 'project-switch-commands '(project-shell "Shell"))) (use-package transpose-frame :ensure t :defer t :bind (("C-x 5 t" . 'transpose-frame))) (use-package ffap :demand t :bind (("C-x C-f" . find-file-at-point)) :init (ffap-bindings) :config (setq ffap-require-prefix nil)) (use-package time :init (display-time-mode) :config (setq display-time-format "%a, %d/%m/%Y %H:%M")) (use-package geiser :ensure t :init (with-eval-after-load 'geiser-guile (add-to-list 'geiser-guile-load-path "~/dev/nonguix"))) (use-package corfu ;; Optional customizations :custom (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' ;; (corfu-auto t) ;; Enable auto completion ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match ;; (corfu-preview-current nil) ;; Disable current candidate preview (corfu-preselect 'prompt) ;; Preselect the prompt ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can ;; be used globally (M-/). See also the customization variable ;; `global-corfu-modes' to exclude certain modes. :init (global-corfu-mode)) (use-package dabbrev ;; Swap M-/ and C-M-/ :bind (("M-/" . dabbrev-completion) ("C-M-/" . dabbrev-expand)) :config (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ") ;; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older. (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode) (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode) (add-to-list 'dabbrev-ignored-buffer-modes 'tags-table-mode)) (use-package scroll-bar :init (scroll-bar-mode -1)) (use-package delsel :init (delete-selection-mode)) (use-package frame :custom (window-divider-default-right-width 2) :config (window-divider-mode)) (use-package window :custom (switch-to-buffer-obey-display-actions t) :bind (("C-x C-}" . enlarge-window-horizontally) ("C-x C-o" . other-window) :repeat-map move-up-repeat-map (("v" . scroll-down-command)) :repeat-map move-down-repeat-map (("v" . scroll-up-command))) :config (add-to-list 'display-buffer-alist '("*Async Shell Command*" display-buffer-no-window (nil)))) (use-package files :custom (make-backup-files nil) (backup-directory-alist `(("." . ,(expand-file-name "backup" user-emacs-directory)))) (tramp-backup-directory-alist backup-directory-alist) (backup-by-copying-when-linked t) (backup-by-copying t) ; Backup by copying rather renaming (delete-old-versions t) ; Delete excess backup versions silently (version-control t) ; Use version numbers for backup files (kept-new-versions 10) (kept-old-versions 10) ;;; Auto revert ;; Auto-revert in Emacs is a feature that automatically updates the ;; contents of a buffer to reflect changes made to the underlying file ;; on disk. (revert-without-query (list ".") ; Do not prompt auto-revert-stop-on-user-input nil auto-revert-verbose t) (auto-save-default t) (auto-save-include-big-deletions t)) (use-package minibuffer :defer t :config (setq completion-cycle-threshold 5 completion-ignore-case t)) (use-package pass :defer t :ensure t) (defun elfeed-refresh () (interactive) (cl-loop for entry in (elfeed-search-selected) do (elfeed-untag-1 entry 'unread)) (elfeed-protocol-fever-reinit "https://freshrss@rss.mccd.space")) (use-package elfeed :ensure t :bind (:map elfeed-search-mode-map ("G" . elfeed-refresh))) (use-package elfeed-protocol :after elfeed :ensure t :demand t :custom (elfeed-use-curl t) (elfeed-curl-extra-arguments '("--insecure")) (elfeed-protocol-fever-update-unread-only t) (elfeed-log-level 'debug) (elfeed-protocol-fever-fetch-category-as-tag t) (elfeed-protocol-feeds '(("fever+https://freshrss@rss.mccd.space" :api-url "https://rss.mccd.space/api/fever.php" :password freshrss-password))) ;; enable elfeed-protocol (elfeed-protocol-enabled-protocols '(fever)) :config (elfeed-set-timeout 36000) (elfeed-protocol-enable)) (use-package select :config (setq x-select-enable-clipboard t x-select-enable-primary t)) (use-package pdf-tools) (use-package imenu :defer t :config (setq imenu-auto-rescan t)) (defun sudo-shell-command (command) (interactive "MShell command (root): ") (with-temp-buffer (cd "/sudo::/") (async-shell-command command))) (use-package nov :defer t :ensure t :init (add-to-list 'auto-mode-alist '("\\.epub'" . nov-mode))) (use-package ednc :after exwm :diminish ednc-mode :ensure t :config (ednc-mode)) (use-package scheme :bind (:map scheme-mode-map ("C-." . nil))) (use-package repeat :demand t :bind (("C-z" . repeat) :repeat-map move-repeat-map ("n" . next-line) ("e" . move-end-of-line) ("a" . move-beginning-of-line) ("b" . backward-char) ("f" . forward-char) ("p" . previous-line) ("o" . avy-goto-char-timer) :repeat-map sexp-move-repeat-map ("n" . forward-list) ("p" . backward-list) ("e" . end-of-defun) ("a" . beginning-of-defun) ("f" . forward-sexp) ("b" . backward-sexp) :repeat-map forward-words-repeat-map ("f" . forward-word) ("e" . forward-sentence) ("a" . backward-sentence) ("b" . backward-word) :repeat-map undo-redo-repeat-map ("/" . undo) ("?" . redo) :repeat-map kill-lines-repeat-map ("k" . kill-line) :repeat-map kill-lines-org-repeat-map ("k" . org-kill-line) :repeat-map delete-repeat-map ("d" . delete-char) :repeat-map kill-word-repeat-map ("d" . kill-word)) :custom (repeat-on-final-keystroke t) (set-mark-command-repeat-pop t) (repeat-exit-key (kbd "i")) :config (repeat-mode 1)) (use-package battery :init (display-battery-mode t)) (use-package comint :bind ((:repeat-map repeat-hist-line-map ("n" . comint-next-input) ("p" . comint-previous-input)))) (use-package eww :custom (eww-auto-rename-buffer t) (eww-buffer-name-length 20) :bind ((:map eww-mode-map ("+" . image-increase-size)))) (use-package enwc :ensure t :custom (enwc-default-backend 'nm) (enwc-wired-device "lo") (enwc-wireless-device "wlp61s0") :init (defun list-notifications () (mapconcat #'ednc-format-notification (ednc-notifications) "")) (nconc global-mode-string '((:eval (list-notifications)))) ; or stack (add-hook 'ednc-notification-presentation-functions (lambda (&rest _) (force-mode-line-update t)))) (use-package git-gutter :diminish git-gutter-mode :hook (go-mode . git-gutter-mode) (prog-mode . git-gutter-mode) :bind (("C-c g p" . git-gutter:previous-hunk) ("C-c g n" . git-gutter:next-hunk) ("C-c g s" . git-gutter:stage-hunk) ("C-c g r" . git-gutter:revert-hunk) ("C-c g =" . git-gutter:popup-hunk) :repeat-map git-gutter-repeat-map ("n" . git-gutter:next-hunk) ("=" . git-gutter:popup-hunk) ("s" . git-gutter:stage-hunk) ("r" . git-gutter:revert-hunk) ("p" . git-gutter:previous-hunk)) :ensure t) (use-package git-gutter-fringe :ensure t) (use-package grep :custom (grep-template (string-join '("ugrep" "--color=never" "--ignore-binary" "--ignore-case" "--include=" "--line-number" "--null" "--recursive" "--regexp=") " "))) (use-package pinentry :ensure t :init (pinentry-start)) (use-package org-crypt :ensure nil :custom (auth-source-debug t) :init (setenv "GPG_AGENT_INFO" nil) (org-crypt-use-before-save-magic)) (use-package epa-file :custom (epa-pinentry-mode 'loopback) (epa-file-select-keys nil) (epg-gpg-program "gpg") :init (epa-file-enable)) (use-package exwm-mff :demand t :load-path "elisp" :hook ((server-after-make-frame . exwm-mff-mode))) (use-package isearch :defer t :bind ((:repeat-map repeat-isearch-map ("o" . avy-isearch) ("s" . isearch-repeat-forward) ("r" . isearch-repeat-backward)))) (use-package avy :ensure t :custom (avy-timeout-seconds 0.2) :bind ("M-o" . avy-goto-char-timer) :config (set-face-attribute 'avy-lead-face nil :inherit 'fixed-pitch) (set-face-attribute 'avy-lead-face-0 nil :inherit 'fixed-pitch) (set-face-attribute 'avy-lead-face-1 nil :inherit 'fixed-pitch) (set-face-attribute 'avy-lead-face-2 nil :inherit 'fixed-pitch) (setf (alist-get ? avy-dispatch-alist) 'avy-action-mark-to-char) (define-key isearch-mode-map (kbd "M-o") 'avy-isearch) (defun avy-action-kill-whole-line (pt) (save-excursion (goto-char pt) (kill-whole-line)) (select-window (cdr (ring-ref avy-ring 0))) t) (setf (alist-get ?k avy-dispatch-alist) 'avy-action-kill-stay (alist-get ?K avy-dispatch-alist) 'avy-action-kill-whole-line) (defun avy-action-copy-whole-line (pt) (save-excursion (goto-char pt) (cl-destructuring-bind (start . end) (bounds-of-thing-at-point 'line) (copy-region-as-kill start end))) (select-window (cdr (ring-ref avy-ring 0))) t) (defun avy-action-yank-whole-line (pt) (avy-action-copy-whole-line pt) (save-excursion (yank)) t) (setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank (alist-get ?w avy-dispatch-alist) 'avy-action-copy (alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line (alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line) (defun avy-action-copy-whole-line (pt) (save-excursion (goto-char pt) (cl-destructuring-bind (start . end) (bounds-of-thing-at-point 'line) (copy-region-as-kill start end))) (select-window (cdr (ring-ref avy-ring 0))) t) (defun avy-action-yank-whole-line (pt) (avy-action-copy-whole-line pt) (save-excursion (yank)) t) (setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank (alist-get ?w avy-dispatch-alist) 'avy-action-copy (alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line (alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line) (defun avy-action-teleport-whole-line (pt) (avy-action-kill-whole-line pt) (save-excursion (yank)) t) (setf (alist-get ?t avy-dispatch-alist) 'avy-action-teleport (alist-get ?T avy-dispatch-alist) 'avy-action-teleport-whole-line) (defun avy-action-mark-to-char (pt) (activate-mark) (goto-char pt)) (setf (alist-get ? avy-dispatch-alist) 'avy-action-mark-to-char)) (use-package flymake :defer t :bind (:repeat-map flymake-repeat-map ("]" . flymake-goto-next-error) ("[" . flymake-goto-prev-error)) :hook ((flymake-mode . (lambda () (define-key flymake-mode-map (kbd "C-c ]") 'flymake-goto-next-error) (define-key flymake-mode-map (kbd "C-c [") 'flymake-goto-prev-error))))) (use-package expand-region :ensure t :bind ("C-." . er/expand-region) ("C--" . er/contract-region)) (use-package devdocs :ensure t :init (global-set-key (kbd "C-h D") 'devdocs-lookup)) (use-package custom-keymaps :load-path "elisp" :config (keymaps-mode) :bind (:map keymaps-mode-map ("C-." . er/expand-region))) (use-package guix :ensure t :bind (("C-c C-g g" . guix) ("C-c C-g o" . (lambda () (interactive) (sudo-shell-command "guix system reconfigure /home/mccd/system/os/config.scm"))) ("C-c C-g h" . (lambda () (interactive) (async-shell-command "guix home reconfigure ~/system/home/config.scm"))))) (use-package ws-butler :ensure t :diminish ws-butler-mode :hook ((prog-mode . ws-butler-mode) (css-mode . ws-butler-mode) (javascript-mode . ws-butler-mode) (html-mode . ws-butler-mode))) (use-package sgml-mode :init (add-to-list 'auto-mode-alist '("\\.njk\\'" . html-mode)) (add-to-list 'auto-mode-alist '("\\.tmpl\\'" . html-mode)) (add-to-list 'auto-mode-alist '("\\.js.tmpl\\'" . javascript-mode)) :config (define-key html-mode-map (kbd "M-") nil) (define-key html-mode-map (kbd "M-o") nil) :hook (css-mode . (lambda ((interactive) (setq-local tab-width 2) (setq sgml-basic-offset 2 indent-tabs-mode t)))) (html-mode . (lambda () (interactive) (setq-local tab-width 2) (setq sgml-basic-offset 2 indent-tabs-mode t)))) (use-package eldoc :ensure t :demand t :diminish eldoc-mode :custom (eldoc-print-after-edit t) (echo-area-display-truncation-message nil) (eldoc-echo-area-prefer-doc-buffer 'maybe) (eldoc-echo-area-use-multiline-p nil) :hook (prog-mode . eldoc-mode)) (use-package eldoc-box :ensure t :demand t :hook (eglot-managed-mode . #'eldoc-box-hover-mode) :config (global-set-key (kbd "C-h .") #'eldoc-box-help-at-point)) (use-package markdown-mode :ensure t :custom (markdown-list-item-bullets '("-")) :config (set-face-attribute 'markdown-code-face nil :inherit 'fixed-pitch) :hook ((markdown-mode . variable-pitch-mode) (markdown-mode . markdown-toggle-url-hiding) (markdown-mode . markdown-toggle-markup-hiding) (markdown-mode . visual-line-mode))) (use-package elec-pair :init (electric-pair-mode 1) :config (global-set-key (kbd "M-{") 'insert-pair) (global-set-key (kbd "M-\"") 'insert-pair) (global-set-key (kbd "M-\'") 'insert-pair) (global-set-key (kbd "M-<") 'insert-pair) (global-set-key (kbd "M-[") 'insert-pair)) (use-package dbus :config (defun ctrl-lock-on () (set-cursor-color "red") (setq ctrl-lock-state t) (force-mode-line-update t)) (defun ctrl-lock-off () (set-cursor-color "black") (setq ctrl-lock-state nil) (force-mode-line-update t)) :bind (("C-x C-2" . split-window-below) ("C-x C-0" . delete-window) ("C-" . newline) ("C-M-d" . kill-word) ("C-x C-3" . split-window-right)) :init (setq ctrl-lock-state nil) (push '(ctrl-lock-state " [CTRL] " "") global-mode-string) (dbus-register-method :session "org.emacs.ctrl" "/on" dbus-interface-introspectable "Introspect" #'ctrl-lock-on) (dbus-register-method :session "org.emacs.ctrl" "/off" dbus-interface-introspectable "Introspect" #'ctrl-lock-off)) (use-package ido :init (ido-mode t)) (use-package calendar :defer t :hook ((diary-mode . variable-pitch-mode) (diary-fancy-display-mode . variable-pitch-mode)) :custom (calendar-week-start-day 1) :config (global-set-key (kbd "C-c d") 'calendar) (calendar-set-date-style 'european) (setq calendar-week-start-day 1)) (use-package nix-mode :ensure t :defer t :hook ((nix-mode . (lambda () (add-hook 'before-save-hook #'nix-format-buffer nil t))) (nix-mode . nix-prettify-mode))) (use-package eglot :config ;; Ensure `nil` is in your PATH. (add-to-list 'eglot-server-programs '(nix-mode . ("nil"))) (fset #'jsonrpc--log-event #'ignore) :bind (:map eglot-mode-map ("C-c r" . eglot-rename) ("C-c o" . eglot-code-actions)) :custom (setq jsonrpc-event-hook nil) :hook (css-mode . eglot-ensure) (html-mode . eglot-ensure) (javascript-mode . eglot-ensure) (nix-mode . eglot-ensure) (go-mode . eglot-ensure)) (use-package tab-line :custom (tab-line-close-button nil) (tab-line-new-button-show nil) :bind (:map eww-mode-map ("M-" . eww-open-in-new-buffer)) :hook (eww-mode . tab-line-mode)) (use-package go-mode :ensure t :defer t :hook ((go-mode . (lambda () (add-hook 'before-save-hook 'eglot-format-buffer nil t))) (go-mode . (lambda () (setq-local compile-command "go build ."))))) (use-package rec-mode :ensure t :defer t :mode "\\.rec\\'" :config (define-key rec-edit-mode-map (kbd "") nil) (define-key rec-mode-map (kbd "") nil) :hook ((rec-mode . variable-pitch-mode) (rec-mode . flymake-mode) (rec-mode . eldoc-mode))) (use-package erc :ensure t :custom (erc-autojoin-channels-alist '(("Libera.Chat" "#emacs" "#permacomputing" "#oldcomputerchallenge" "#go-nuts" "#netbsd" "#nonguix" "#guix"))) :init (global-set-key "\C-ceo" (lambda () "erc - join osm" (interactive) (erc :server "irc.oftc.net" :port "6667" :nick "mccd"))) (global-set-key "\C-cel" (lambda () "erc - join libera chat" (interactive) (erc :server "irc.libera.chat" :port "6667" :nick "mccd" :password libera-chat-pass)))) (use-package ob-rec :ensure nil) (defun sync-org () (interactive) (async-shell-command "org-sync")) ;; Org (use-package org :ensure t :custom (org-refile-targets '((nil :maxlevel . 4) (org-agenda-files :maxlevel . 4))) (org-default-notes-file "~/personal-db/notes/notes.org") (org-hide-emphasis-markers t) (org-link-keep-stored-after-insertion t) (org-startup-folded t) (org-hierarchical-todo-statistics t) (org-refile-allow-creating-parent-nodes 'confirm) (org-outline-path-complete-in-steps nil) (org-refile-use-outline-path 'level1) (org-log-done 'time) (org-indent-line 2) (org-tags-column 0) (org-pretty-entities t) (org-todo-keywords '((sequence "TODO(t)" "|" "DONE(d)") (sequence "UNREAD(u)" "READING(e)" "|" "READ(r)") (sequence "|" "CANCELED(c)"))) (org-agenda-custom-commands '(("t" todo "TODO") ("p" tags-todo "+piva"))) (org-priority-lowest ?E) (org-priority-faces '((?A . (:weight bold :inherit org-priority)) (?D . (:foreground "gray50" :inherit org-priority)) (?E . (:foreground "gray60" :inherit org-priority)))) :init (add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode)) (org-babel-do-load-languages 'org-babel-load-languages '((shell . t) (rec .t))) :config (set-face-attribute 'org-block nil :inherit 'fixed-pitch) (set-face-attribute 'org-code nil :inherit 'fixed-pitch) (set-face-attribute 'org-table nil :foreground "black" :inherit 'fixed-pitch) (set-face-attribute 'org-date nil :inherit 'fixed-pitch) (set-face-attribute 'org-tag nil :inherit 'fixed-pitch) (set-face-attribute 'org-drawer nil :inherit 'fixed-pitch) (set-face-attribute 'org-property-value nil :inherit 'fixed-pitch) (set-face-attribute 'org-special-keyword nil :inherit 'fixed-pitch) (set-face-attribute 'org-meta-line nil :inherit 'fixed-pitch) :hook ((org-mode . org-indent-mode) (org-capture-after-finalize . sync-org) (org-mode . flyspell-mode) (org-mode . (lambda () (auto-revert-mode 1))) (org-mode . visual-line-mode) (org-mode . variable-pitch-mode))) (use-package org-id :after org :init (defun me/org-id-insert-link () "Insert at point a link to any heading from `org-agenda-files'." (interactive) (let ((buffer-pos (org-id-find (org-id-get-with-outline-path-completion '((nil :maxlevel . 5) (org-agenda-files :maxlevel . 5)))))) (save-excursion (with-current-buffer (get-file-buffer (car buffer-pos)) (org-with-wide-buffer (goto-char (cdr buffer-pos)) (call-interactively 'org-store-link)))) (org-insert-all-links 1 "" " "))) :bind (:map org-mode-map (("C-c i" . me/org-id-insert-link))) :custom (org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)) (use-package ol :after org-compat org-macs org-fold :bind (("C-c l" . org-store-link))) (use-package subr :bind (("C-c C-o" . org-open-at-point-global))) (use-package org-capture :custom (org-capture-templates '(("t" "Todo" entry (file+headline "~/personal-db/notes/notes.org" "Todo") "* TODO %?\n%i\n%a\n " :empty-lines 1) ("w" "Work Todo" entry (file+headline "~/personal-db/notes/notes.org" "Todo") "* TODO %? :piva:\n:PROPERTIES:\n:CATEGORY: Pivå\n:END:\n%i\n%a\n " :empty-lines 1) ("b" "Book" entry (file+olp "~/personal-db/notes/notes.org" "References" "Books") "* UNREAD %?\n:PROPERTIES:\n:AUTHOR:\n:END:\n " :empty-lines 1) ("f" "Formula" entry (file+headline "~/personal-db/notes/notes.org" "Formulas") "* %?\n%U" :empty-lines 1) ("f" "Film" entry (file+olp "~/personal-db/notes/notes.org" "References" "Films") "* %?\n:PROPERTIES:\n:DIRECTOR:\n:STATE: unwatched\n:END:\n " :empty-lines 1) ("g" "Log Coffee" entry (file+headline "~/personal-db/notes/notes.org" "Log") "* Brewed pour-over :coffee:cyprus:paramytha:\n:PROPERTIES:\n:WATER: 320g\n:COFFEE: 25g\n:TYPE: [[id:815450d3-d772-4207-9eb4-e1e185fd8356][La Pastora]] | [[id:9d136656-2965-4be9-87cf-4ecafcf62707][Alemayehu]] | [[id:73a92627-f076-4090-a78c-ef8204191611][Los Chorros]]\n:TEMP: 90\n:RATING:\n:PREHEAT: YES\n:TOTALBREWTIME:\n:CLICKS:\n:END:\n%T\n*** Observations " :empty-lines 0 :prepend t) ("r" "Reference" entry (file+headline "~/personal-db/notes/notes.org" "References") "* %?\n%i\n%a\n " :empty-lines 1) ("s" "Schedule" entry (file+headline "~/personal-db/notes/notes.org" "Event") "* TODO %?\nSCHEDULED: %^T" :empty-lines 1) ("a" "Article" entry (file+olp "~/personal-db/notes/notes.org" "References" "Articles") "* %?\n:PROPERTIES:\n:author:\n:END:\n " :empty-lines 1) ("l" "Log" entry (file+headline "~/personal-db/notes/notes.org" "Log") "** %? :cyprus:paramytha:\n%T" :prepend t :empty-lines 0) ("n" "Inbox" entry (file+headline "~/personal-db/notes/notes.org" "Inbox") "* %?\n%U\n" :empty-lines 1))) :bind (("C-c c" . org-capture))) (defun org-agenda-switch-to-narrowed-subtree () (interactive) (org-agenda-switch-to) (org-narrow-to-subtree)) (use-package org-agenda :custom (org-agenda-files '("/home/mccd/personal-db/notes/cal-ios.org" "/home/mccd/dev/sustainably/README.org" "/home/mccd/dev/sustainably/exploration.org" "/home/mccd/system/guix.org" "/home/mccd/personal-db/notes/notes.org")) (org-agenda-remove-tags t) (org-agenda-inhibit-startup nil) :config (advice-add 'org-agenda-quit :before (lambda () (interactive) (org-save-all-org-buffers) (org-id-update-id-locations) (sync-org))) :bind (("C-c a" . org-agenda) :map org-agenda-mode-map ("" . org-agenda-switch-to-narrowed-subtree))) (use-package autorevert :diminish auto-revert-mode) (use-package org-agenda :demand t :ensure nil) (use-package appt :after org-agenda :demand t ;; Taken from https://igormelo.org/you_dont_need_org_alert.html ;; Enables notifications for org :custom (appt-message-warning-time 15) (appt-display-interval 5) (appt-display-mode-line nil) (appt-disp-window-function (lambda (remaining new-time msg) (notifications-notify :title (format "Scheduled for %s minutes" remaining) :body msg :urgency 'critical))) :config (define-advice appt-activate (:after (&optional _arg) hold-your-horses) "`appt-activate' is too eager, rein it in." (remove-hook 'write-file-functions #'appt-update-list) (when (timerp appt-timer) (timer-set-time appt-timer (current-time) 600))) (define-advice appt-check (:before (&optional _force) from-org-agenda) "Read events from Org agenda if possible." (and (featurep 'org-agenda) (ignore-errors (let ((inhibit-message t)) (org-agenda-to-appt t))))) (appt-activate t)) (use-package rec-mode :ensure t) (use-package magit :ensure t :demand t :config (global-key-binding (kbd "C-x p m") 'magit-project-status) (define-key project-prefix-map (kbd "m") 'magit-project-status) (add-to-list 'project-switch-commands '(magit-project-status "magit"))) (use-package magit-extras :demand t :ensure magit) (use-package yasnippet :diminish yas-minor-mode :ensure t :init (yas-global-mode 1)) (use-package flyspell :diminish flyspell-mode :defer t) (use-package face-remap :diminish buffer-face-mode) (use-package org-indent :diminish org-indent-mode) (use-package simple :diminish visual-line-mode) (use-package message :custom (message-expand-name-standard-ui t) (message-wide-reply-confirm-recipients t) (message-interactive t) (message-fcc-handler-function 'rmail-output) (message-citation-line-function 'message-insert-formatted-citation-line) (message-mail-alias-type 'ecomplete) (message-self-insert-commands nil) (message-send-mail-function 'sendmail-send-it) (message-kill-buffer-on-exit t) (message-sendmail-envelope-from 'header)) (use-package sendmail :defer t :init (defun marc/set-msmtp-account () (if (message-mail-p) (save-excursion (let* ((from (save-restriction (message-narrow-to-headers) (message-fetch-field "from"))) (account (cond ((string-match "marcc@fastmail.fr" from) "home") ((string-match "marc.coquand@sustainably.app" from) "work") ((string-match "marc@coquand.email" from) "home") ((string-match "marc@mccd.space" from) "home")))) (setq message-sendmail-extra-arguments (list '"-a" account)))))) :hook (message-send-mail . marc/set-msmtp-account) (message-send-mail . flyspell-mode) (message-setup . mail-abbrevs-setup) :custom (send-mail-function 'sendmail-send-it) (sendmail-program (executable-find "msmtp")) (mail-user-agent 'message-user-agent)) (use-package rmail :init (defvar selected-rmail-account "") (defun rmail-reply-t () "Reply only to the sender of the current message. (See rmail-reply.)" (interactive) (rmail-reply t)) (defun rmail-write-for-patch () "Writes the mail to an mbox file that you can later run git am on to apply it." (interactive) (rmail-output-as-seen "/tmp/new-patch.patch")) :bind (("C-c m" . rmail-open) ("C-c M" . rmail-no-check) :map rmail-mode-map ("r" . rmail-reply-t) ("R" . rmail-reply) ("O" . rmail-write-for-patch)) :config (defun rmail-no-check () (interactive) (rmail-input rmail-file-name)) (defun mail-work () (interactive) (setenv "MAILHOST" "imap.fastmail.com") (setenv "MAIL" (concat "imaps://" "marc.coquand%40sustainably.app" ":" piva-password "@imap.gmail.com:993")) (setq rmail-default-file "~/personal-db/mail/work/RMAIL" rmail-remote-password-required nil rmail-secondary-file-regexp "~/personal-db/mail/work/archives" rmail-file-name "~/personal-db/mail/work/RMAIL" user-mail-address "marc.coquand@sustainably.app" unrmail-mbox-format 'mboxo user-full-name "Marc Coquand" message-default-headers "FCC: ~/personal-db/mail/work/out/sent.mbox" selected-rmail-account "work" message-signature "Marc Coquand\nFounder at Pivå")) (defun mail-home () (interactive) (setenv "MAILHOST" "imap.fastmail.com") (setenv "MAIL" (concat "imaps://" "marcc%40fastmail.fr" ":" fastmail-password "@imap.fastmail.com:993")) (setq rmail-default-file "~/personal-db/mail/home/RMAIL" rmail-remote-password-required nil rmail-secondary-file-regexp "~/personal-db/mail/home/archives/*.mbox" rmail-output-file-alist '(("\\[PATCH.*\\]" . "patch.mbox") (".*" . "archive.mbox")) rmail-file-name "~/personal-db/mail/home/RMAIL" user-mail-address "marc@mccd.space" unrmail-mbox-format 'mboxo user-full-name "Marc Coquand" selected-rmail-account "home" message-default-headers "FCC: ~/personal-db/mail/home/out/sent.mbox" message-signature "Marc")) (easy-menu-define rmail-prompt-account global-map "Account" '("Options" ["Home" mail-home] ["Work" mail-work])) (defun rmail-open () (interactive) (let ((prev selected-rmail-account)) (tmm-prompt rmail-prompt-account) (unless (eq selected-rmail-account prev) ;; First kill all RMAIL buffers to not leave any dangling (kill-matching-buffers "\\.mbox\\|RMAIL"))) (rmail)) :custom (rmail-mime-prefer-html nil) (rmail-displayed-headers "^\\(?:Cc\\|Date\\|From\\|Subject\\|To\\|List-Id\\):")) (use-package mastodon :defer t :custom (mastodon-active-user "marcc") (mastodon-instance-url "https://fosstodon.org")) (use-package eww :custom (browse-url-browser-function 'eww-browse-url) ; Use eww as the default browser (eww-search-prefix "https://lite.duckduckgo.com/lite/?q=") (shr-max-image-proportion 0.3) (shr-width 70)) ;; Can play youtube urls and music. ;; Requires mpv (use-package emms :ensure t :custom (emms-shop-format "on: %s") :init (add-hook 'emms-player-started-hook 'emms-show) :config (emms-all) (emms-default-players)) (put 'secrets-mode 'disabled nil)