diff --git a/home/emacs/default.nix b/home/emacs/default.nix index 3bc5a989..5359d17a 100644 --- a/home/emacs/default.nix +++ b/home/emacs/default.nix @@ -3,7 +3,6 @@ { xdg.configFile = { "emacs/init.el".source = ./init.el; - "emacs/config.org".source = ./config.org; "emacs/snippets".source = ./snippets; }; programs.emacs = { diff --git a/home/emacs/init.el b/home/emacs/init.el index f2238936..3f59bba5 100644 --- a/home/emacs/init.el +++ b/home/emacs/init.el @@ -1,2 +1,865 @@ -(package-initialize) -(org-babel-load-file (locate-user-emacs-file "config.org")) +(setq user-full-name "Evie Litherland-Smith" + user-mail-address "evie@xenia.me.uk" + custom-file (locate-user-emacs-file "custom.el") + load-prefer-newer t + indent-tabs-mode nil + global-auto-revert-non-file-buffers t + dired-auto-revert-buffer t + dired-dwim-target t + tab-always-indent 'complete + completion-cycle-threshold 3 + completions-detailed t + xref-show-definitions-function #'xref-show-definitions-completing-read + kill-do-not-save-duplicates t + auto-window-vscroll nil + fast-but-imprecise-scrolling t + scroll-conservatively 101 + scroll-margin 0 + scroll-preserve-screen-position 1) + +(set-default-coding-systems 'utf-8) +(set-terminal-coding-system 'utf-8) +(set-keyboard-coding-system 'utf-8) + +(global-auto-revert-mode +1) +(delete-selection-mode) + +;; Misc useful keymaps +(keymap-global-set "M-#" #'dictionary-lookup-definition) +(keymap-global-set "C-c r" #'recentf) +(keymap-global-set "C-c b" #'ibuffer) +(keymap-global-set "C-c p l" #'list-packages) +(keymap-global-set "C-c p r" #'package-refresh-contents) +(keymap-global-set "C-c p i" #'package-install) +(keymap-global-set "C-c p d" #'package-delete) + +;; turn on spell checking, if available. +(when (and (require 'ispell nil :noerror) (executable-find ispell-program-name)) + (add-hook 'text-mode-hook #'flyspell-mode) + (add-hook 'prog-mode-hook #'flyspell-prog-mode)) + +;; Make shebang (#!) file executable when saved +(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) + +(when (require 'package nil :noerror) + (add-to-list 'package-archives '("stable" . "https://stable.melpa.org/packages/")) + (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) + + (setq package-archive-priorities '(("gnu" . 99) + ("nongnu" . 80) + ("stable" . 70) + ("melpa" . 0)))) + +(setq org-directory "~/Org" + org-default-notes-file (expand-file-name "notes.org" org-directory) + org-pretty-entities-include-sub-superscripts t + org-pretty-entities-include-sub-superscripts t + org-tags-column 0 + org-modern-tag nil + org-outline-path-complete-in-steps nil + org-refile-use-outline-path t + org-refile-allow-creating-parent-nodes t + org-refile-use-outline-path 'file + org-refile-targets '((nil :maxlevel . 3) + (org-agenda-files :maxlevel . 3))) + +(keymap-global-set "C-c o a" #'org-agenda) +(keymap-global-set "C-c o n" #'org-capture) +(keymap-global-set "C-c o l" #'org-capture-goto-last-stored) +(keymap-global-set "C-c o j j" #'org-journal-new-entry) +(keymap-global-set "C-c o j n" #'org-journal-new-date-entry) +(keymap-global-set "C-c o j s" #'org-journal-new-scheduled-entry) + +(add-hook 'org-mode-hook #'org-modern-mode) +(add-hook 'org-agenda-finalize-hook #'org-modern-agenda) + +(setq org-agenda-files (list (expand-file-name org-directory) + (expand-file-name "journal" org-directory) + (expand-file-name "projects" org-directory)) + org-agenda-sticky nil + org-agenda-window-setup 'current-window + org-agenda-prefix-format '((agenda . " %-12:c%?-12t% s") + (todo . " %-12:c") + (tags . " %-12:c") + (search . " %-12:c"))) + +(setq org-journal-dir (expand-file-name "journal" org-directory) + org-journal-file-type 'monthly + org-journal-file-format "%Y-%m.org") + +(setq org-capture-templates + '(("n" "Note" entry + (file+headline "inbox.org" "Note") + "* %?" + :prepend t + :empty-lines 1) + ("t" "Task" entry + (file+headline "inbox.org" "Task") + "* TODO %?" + :prepend t + :empty-lines 1) + ("m" "Email Workflow") + ("mf" "Follow Up" entry (file+olp "mail.org" "Follow Up") + "* TODO Follow up with %:fromname on %a\nSCHEDULED:%t\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i") + ("mr" "Read Later" entry (file+olp "mail.org" "Read Later") + "* TODO Read %:subject\nSCHEDULED:%t\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%a\n\n%i") + )) + +(setq citar-bibliography '("~/.references/main.bib") + citar-library-paths '("~/.references/library") + citar-notes-paths '("~/.references/notes") + citar-symbols '((file "F" . "󰂺") + (note "N" . "󰎞") + (link "L" . "󰌹"))) +(when (require 'citar nil :noerror) + (keymap-global-set "C-c o c o" #'citar-open)) + +(setq khalel-import-org-file (expand-file-name "calendar.org" org-directory) + khalel-import-org-file-read-only nil + khalel-import-org-file-confirm-overwrite nil + khalel-import-start-date "-30d" + khalel-import-end-date "+30d") +(when (require 'khalel nil :noerror) + (add-hook 'org-agenda-mode-hook #'khalel-import-events) + (khalel-add-capture-template "e")) + +(setq use-dialog-box nil + fill-column 80 + truncate-lines nil + truncate-partial-width-windows nil) + +(menu-bar-mode -1) +(tab-bar-mode -1) +(tool-bar-mode -1) +(scroll-bar-mode -1) +(line-number-mode) +(global-display-line-numbers-mode -1) +(global-prettify-symbols-mode +1) +(global-visual-line-mode +1) +;; (set-frame-font "FiraCode Nerd Font-12") +;; (set-frame-parameter nil 'alpha-background 80) + +;; Nerd-Icons modes +(when (require 'nerd-icons) + (nerd-icons-set-font "Symbols Nerd Font Mono") + (when (require 'nerd-icons-dired nil :noerror) + (add-hook 'dired-mode-hook #'nerd-icons-dired-mode)) + + (when (require 'nerd-icons-ibuffer nil :noerror) + (add-hook 'ibuffer-mode-hook #'nerd-icons-ibuffer-mode)) + + (when (require 'nerd-icons-completion nil :noerror) + (nerd-icons-completion-mode) + (when (require 'marginalia nil :noerror) + (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup)))) + +;; Doom-Modeline +(setq doom-modeline-icon t + doom-modeline-mu4e nil ;; Use mu4e own formatting + doom-modeline-modal nil + doom-modeline-modal-icon nil + doom-modeline-persp-name nil + doom-modeline-persp-icon nil) +(when (require 'doom-modeline nil :noerror) + (doom-modeline-mode +1)) + +;; Dashboard +(setq initial-buffer-choice 'dashboard-open + dashboard-icon-type 'nerd-icons + dashboard-set-heading-icons t + dashboard-set-file-icons t + dashboard-set-navigator t + dashboard-set-init-info t + dashboard-startup-banner 'ascii + dashboard-projects-backend 'project-el + dashboard-projects-switch-function 'project-switch-project + dashboard-projects-show-base t + dashboard-recentf-show-base 'align + dashboard-items '((recents . 5) + (agenda . 15)) + dashboard-heading-icons '((recents . "nf-oct-history") + (agenda . "nf-oct-calendar")) + dashboard-banner-ascii (concat " .000000. \n" + " .0. .0. \n" + " .00. .00. \n" + " .000cl. .lc000. \n" + ".0 0.\n" + "0. .o0000o. .0\n" + " 00 .0' '0. 00 \n" + " 00 .0 0. 00 \n" + " HHHHH HHHHHHHHHHHH HHHHH \n" + "HHHH HHH HHHHHHHHHHHHHH HHHH\n" + " HHHHHH HHHHHHHHH HHHHHHHH \n" + " HHH HHHH HHHHHHHHH HHHH \n" + " HHH HHHHHH \n" + " HHHHH HH \n")) +(when (require 'dashboard nil :noerror) + (keymap-global-set "C-c d" #'dashboard-open) + (add-hook 'dashboard-mode-hook #'khalel-import-events)) + +;; Extra minor-modes +(when (require 'git-gutter nil :noerror) + (global-git-gutter-mode +1)) + +(when (require 'which-key nil :noerror) + (which-key-mode +1)) + +(when (require 'page-break-lines nil :noerror) + (global-page-break-lines-mode +1)) + +;;;; Help Buffers + +;; Make `describe-*' screens more helpful +(when (require 'helpful nil :noerror) + (keymap-set helpful-mode-map " " #'helpful-update) + (keymap-global-set " " #'helpful-command) + (keymap-global-set " " #'helpful-callable) + (keymap-global-set " " #'helpful-key) + (keymap-global-set " " #'helpful-symbol) + (keymap-global-set " " #'helpful-variable) + (keymap-global-set "C-h F" #'helpful-function)) + +;; Bind extra `describe-*' commands +(keymap-global-set "C-h K" #'describe-keymap) + +;; add visual pulse when changing focus, like beacon but built-in +;; from from https://karthinks.com/software/batteries-included-with-emacs/ +(defun pulse-line (&rest _) + "Pulse the current line." + (pulse-momentary-highlight-one-line (point))) + +(dolist (command '(scroll-up-command + scroll-down-command + recenter-top-bottom + other-window)) + (advice-add command :after #'pulse-line)) + + +;;; custom-ui-config.el ends here + +(setq sendmail-program (executable-find "msmtp") + send-mail-function #'smtpmail-send-it + message-sendmail-f-is-evil t + message-sendmail-extra-arguments '("--read-envelope-from") + message-send-mail-function #'message-send-mail-with-sendmail + message-kill-buffer-on-exit t + mail-user-agent 'mu4e-user-agent + read-mail-command 'mu4e + mu4e-maildir "~/Mail" + mu4e-attachment-dir "~/Downloads" + mu4e-get-mail-command "mbsync -a" + mu4e-update-interval (* 5 60) ; Every 5 minutes + mu4e-sent-messages-behavior 'sent + mu4e-change-filenames-when-moving t + mu4e-context-policy 'pick-first + mu4e-use-fancy-chars t + mu4e-headers-thread-single-orphan-prefix '("─>" . "─▶") + mu4e-headers-thread-orphan-prefix '("┬>" . "┬▶") + mu4e-headers-thread-connection-prefix '("│ " . "│ ") + mu4e-headers-thread-first-child-prefix '("├>" . "├▶") + mu4e-headers-thread-child-prefix '("├>" . "├▶") + mu4e-headers-thread-last-child-prefix '("└>" . "╰▶") + mu4e-modeline-all-read '("R:" . "󰑇 ") + mu4e-modeline-all-clear '("C:" . "󰚭 ") + mu4e-modeline-new-items '("N:" . "󰎔 ") + mu4e-modeline-unread-items '("U:" . "󰶊 ") + mu4e-search-full-label '("F" . "󱊖 ") + mu4e-search-hide-label '("H" . "󰘓 ") + mu4e-search-related-label '("R" . "󰌹 ") + mu4e-search-skip-duplicates-label '("D" . "󰆑 ") + mu4e-search-threaded-label'("T" . "󱇫 ") + mu4e-alert-modeline-formatter 'mu4e-alert-default-mode-line-formatter + mu4e-headers-fields '((:human-date . 12) + (:flags . 6) + (:from-or-to . 25) + (:subject)) + mu4e-headers-actions '(("org capture message" . mu4e-org-store-and-capture) + ("capture message" . mu4e-action-capture-message) + ("show this thread" . mu4e-action-show-thread)) + mu4e-maildir-shortcuts '((:maildir "/Proton/Inbox/" :key ?p) + (:maildir "/iCloud/Inbox/" :key ?i) + (:maildir "/Outlook/Inbox/" :key ?w))) + +(when (require 'mu4e nil :noerror) + (keymap-global-set "C-c m m" #'mu4e) + (keymap-global-set "C-c m u" #'mu4e-update-index) + (keymap-global-set "C-c m c" #'mu4e-compose-new) + + (when (require 'mu4e-alert nil :noerror) + (mu4e-alert-set-default-style 'libnotify) + (mu4e-alert-enable-notifications) + (mu4e-alert-enable-mode-line-display)) + + (setq mu4e-contexts (list + (make-mu4e-context + :name "Xenia" + :vars '((user-mail-address . "evie@xenia.me.uk") + (mu4e-sent-folder . "/Proton/Sent") + (mu4e-drafts-folder . "/Proton/Drafts") + (mu4e-trash-folder . "/Proton/Trash") + (mu4e-refile-folder . "/Proton/Archive"))) + (make-mu4e-context + :name "Proton" + :match-func (lambda (msg) (when msg (string-prefix-p "/Proton" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "e.litherlandsmith@proton.me") + (mu4e-sent-folder . "/Proton/Sent") + (mu4e-drafts-folder . "/Proton/Drafts") + (mu4e-trash-folder . "/Proton/Trash") + (mu4e-refile-folder . "/Proton/Archive"))) + (make-mu4e-context + :name "iCloud" + :match-func (lambda (msg) (when msg (string-prefix-p "/iCloud" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "e.litherlandsmith@icloud.com") + (mu4e-sent-folder . "/iCloud/Sent Messages") + (mu4e-drafts-folder . "/iCloud/Drafts") + (mu4e-trash-folder . "/iCloud/Deleted Messages") + (mu4e-refile-folder . "/iCloud/Archive"))) + (make-mu4e-context + :name "Work" + :match-func (lambda (msg) (when msg (string-prefix-p "/Outlook" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "evie.litherland-smith@ukaea.uk") + (mu4e-sent-folder . "/Outlook/Sent") + (mu4e-drafts-folder . "/Outlook/Drafts") + (mu4e-trash-folder . "/Outlook/Trash") + (mu4e-refile-folder . "/Outlook/Archive")))))) + +(let ((elfeed-base-directory "~/.elfeed")) + (setq elfeed-db-directory (expand-file-name "db" elfeed-base-directory) + elfeed-enclosure-default-dir (expand-file-name "enclosures" elfeed-base-directory) + rmh-elfeed-org-files (list (expand-file-name "feeds.org" elfeed-base-directory)))) + +(when (require 'elfeed nil :noerror) + (keymap-global-set "C-c f f" #'elfeed) + (add-hook 'elfeed-search-mode-hook #'elfeed-update) + (when (require 'elfeed-org nil :noerror) + (elfeed-org)) + (when (require 'elfeed-tube nil :noerror) + (elfeed-tube-setup))) + +(when (require 'rainbow-delimiters nil :noerror) + (add-hook 'prog-mode-hook #'rainbow-delimiters-mode)) + +(when (require 'treesit-aut nil :noerror) + (global-treesit-auto-mode +1)) + +(setq apheleia-remote-algorithm 'local) +(when (require 'apheleia nil :noerror) + (keymap-global-set "C-c c f" #'apheleia-format-buffer) + (apheleia-global-mode +1)) + +(when (require 'eglot nil :noerror) + (eglot-ensure)) + +(setq direnv-always-show-summary nil) +(when (require 'direnv nil :noerror) + (direnv-mode +1)) + +(when (require 'yasnippet nil :noerror) + (require 'yasnippet-snippets nil :noerror) + (yas-reload-all) + (add-hook 'prog-mode-hook #'yas-minor-mode)) + +(defun fira-code-mode--make-alist (list) + "Generate prettify-symbols alist from LIST." + (let ((idx -1)) + (mapcar + (lambda (s) + (setq idx (1+ idx)) + (let* ((code (+ #Xe100 idx)) + (width (string-width s)) + (prefix ()) + (suffix '(?\s (Br . Br))) + (n 1)) + (while (< n width) + (setq prefix (append prefix '(?\s (Br . Bl)))) + (setq n (1+ n))) + (cons s (append prefix suffix (list (decode-char 'ucs code)))))) + list))) + +(defconst fira-code-mode--ligatures + '("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\" + "{-" "[]" "::" ":::" ":=" "!!" "!=" "!==" "-}" + "--" "---" "-->" "->" "->>" "-<" "-<<" "-~" + "#{" "#[" "##" "###" "####" "#(" "#?" "#_" "#_(" + ".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*" + "/**" "/=" "/==" "/>" "//" "///" "&&" "||" "||=" + "|=" "|>" "^=" "$>" "++" "+++" "+>" "=:=" "==" + "===" "==>" "=>" "=>>" "<=" "=<<" "=/=" ">-" ">=" + ">=>" ">>" ">>-" ">>=" ">>>" "<*" "<*>" "<|" "<|>" + "<$" "<$>" "