diff --git a/.gitignore b/.gitignore index 1f219ea..cce4598 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,4 @@ flycheck_*.el /idlwave/ /games/ /calc.el +/README.el diff --git a/README.org b/README.org index 37ccf76..554ba0d 100644 --- a/README.org +++ b/README.org @@ -6,5 +6,1207 @@ Personal Emacs config. Clone to =~/.config/emacs/= (or =~/.emacs.d/=). -To install packages on non-NixOS systems run ~make~ (or ~make -install~), or execute ~install.el~ with Emacs. +* Config + +** Initial copy from =init.el= +#+begin_src emacs-lisp + ;; Customise `use-package' behaviour, must be set before first time + ;; it's used. Configure packages archives with priority + (setopt use-package-check-before-init t + use-package-enable-imenu-support t) + + (setq custom-file (locate-user-emacs-file "custom.el")) + (when (and custom-file + (file-exists-p custom-file)) + (load custom-file nil 'nomessage)) + + (use-package package + :custom + (package-archive-priorities '(("melpa" . 4) ("stable" . 3) ("nongnu" . 2) ("gnu" . 1))) + (package-selected-packages + '( + ;; UI + base16-theme all-the-icons nerd-icons nerd-icons-completion + nerd-icons-corfu nerd-icons-dired nerd-icons-ibuffer minions + ligature which-key diff-hl + + ;; Completion + vertico orderless marginalia cape corfu corfu-terminal + consult consult-eglot flyspell-correct tempel + + ;; IDE + treesit-auto magit forge apheleia envrc rainbow-delimiters + flymake-shellcheck flymake-yamllint flymake-clippy + flymake-eslint markdown-mode pandoc-mode python-docstring + nix-mode lua-mode + + ;; Org + LaTeX + org-roam org-noter citar auctex htmlize + + ;; Other + password-store emms bbdb ement scad-mode + + )) + :config + (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) + (add-to-list 'package-archives '("stable" . "https://stable.melpa.org/packages/")) + (package-initialize) + + (defun my/package-ensure () + "Update package archives and ensure packages are installed." + (interactive) + (package-refresh-contents) + (package-install-selected-packages) + (package-autoremove))) + + (set-default-coding-systems 'utf-8) + + (setq user-full-name "Evie Litherland-Smith" + user-mail-address "evie@xenia.me.uk" + inhibit-splash-screen t + use-short-answers t + tab-always-indent 'complete + completion-cycle-threshold nil + completions-detailed t + kill-do-not-save-duplicates t + initial-frame-alist nil + default-frame-alist nil) + + (setq-default truncate-lines t + truncate-partial-width-windows nil) + + (setopt indent-tabs-mode nil + async-shell-command-display-buffer nil + compilation-scroll-output t) + + (global-prettify-symbols-mode +1) + (global-auto-revert-mode +1) + (delete-selection-mode +1) + (which-function-mode +1) + (tool-bar-mode -1) + (scroll-bar-mode -1) + + (use-package pixel-scroll + :init + (pixel-scroll-precision-mode +1)) + + (use-package mwheel + :custom + (mouse-wheel-scroll-amount '(1 ((shift) . 1))) + (mouse-wheel-progressive-speed nil) + (mouse-wheel-follow-mouse t)) + + ;; Bind normal forward/back buttons on mouse to next/previous buffer respectively + (keymap-global-set "" #'previous-buffer) + (keymap-global-set "" #'next-buffer) + + ;; Quick bind for calling `git-sync-all' + (defun my/git-sync-all () + "Run shell command `git-sync-all' asynchronously." + (interactive) + (async-shell-command "git-sync-all" "*git-sync-all*" "*git-sync-errors*")) + (keymap-global-set "C-c g s" #'my/git-sync-all) + + ;; Make shebang (#!) file executable when saved + (add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) + + ;; Remap `upcase-word' and `downcase-word' to DWIM versions + (keymap-global-set " " 'upcase-dwim) + (keymap-global-set " " 'downcase-dwim) + + (setq backup-directory-alist '(("." . "~/.local/state/emacs/backups"))) + + (use-package savehist + :demand + :config + (savehist-mode +1)) + + (use-package dired + :custom + (dired-auto-revert-buffer t) + (dired-dwim-target t)) + + (use-package recentf + :config + (run-at-time nil (* 5 60) 'recentf-save-list) + (recentf-mode +1) + :custom + (recentf-max-saved-items 2048)) + + (use-package auth-source + :custom + (auth-sources '("secrets:Login"))) + + (use-package auth-source-pass + :requires auth-source + :config + (auth-source-pass-enable)) + + ;; Bind extra `describe-*' commands + (keymap-global-set "C-h K" #'describe-keymap) + + ;; turn on spell checking, if available. + (use-package ispell + :custom + (ispell-dictionary "en_GB")) + + (use-package flyspell + :hook ((text-mode . flyspell-mode) + (prog-mode . flyspell-prog-mode)) + :init + (require 'ispell) + :custom + (flyspell-use-meta-tab nil)) + + (use-package flyspell-correct + :if (package-installed-p 'flyspell-correct) + :after flyspell + :bind ( :map flyspell-mode-map + ("C-;" . flyspell-correct-wrapper))) + + (use-package ibuffer + :defines ibuffer-filter-groups + :bind (("C-c b" . ibuffer))) + + (use-package shell + :bind (("C-c t s" . shell))) + + (use-package eshell + :bind (("C-c t e" . eshell)) + :config + (require 'esh-mode)) + + (use-package esh-mode + :defines eshell-mode-map + :bind ( :map eshell-mode-map + (" " . consult-history))) + + (use-package calc + :bind (("" . calc))) + + (use-package xref + :custom + (xref-show-definitions-function 'xref-show-definitions-completing-read)) + + (use-package appt + :custom + (appt-display-diary nil) + (appt-display-format 'echo)) + + (use-package calendar + :after appt + :bind (("C-c >" . calendar)) + :hook ((calendar-today-visible . calendar-mark-today)) + :custom + (calendar-date-style 'iso) + (calendar-mark-holidays-flag t) + (calendar-mark-diary-entries-flag nil) + (calendar-view-holidays-initially-flag nil) + (calendar-view-diary-initially-flag nil) + :config + (appt-activate +1) + (add-to-list 'display-buffer-alist + '("\\*Calendar\\*" + (display-buffer-in-side-window) + (side . bottom) + (slot . 0) + (window-height . 0.2) + (window-parameters . ((no-delete-other-windows . t)))))) + + (add-hook 'prog-mode-hook #'(lambda () (display-line-numbers-mode +1))) + + (use-package which-key + :if (package-installed-p 'which-key) + :functions which-key-mode + :config (which-key-mode +1)) + + (use-package elec-pair + :config + (electric-pair-mode +1)) + + (use-package paren + :config + (show-paren-mode +1)) + + ;; 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))) + + (use-package base16-theme + :if (package-installed-p 'base16-theme) + :demand + :defines (base16-one-light-theme-colors + my/load-theme-and-configure) + :hook (server-after-make-frame . my/load-theme-and-configure) + :custom + (base16-theme-distinct-fringe-background nil) + (base16-theme-highlight-mode-line 'contrast) + :init + (defun my/load-theme-and-configure () + "Load theme and configure some faces." + (load-theme 'base16-one-light t) + + ;; Change outline headers to follow rainbow order + (require 'outline) + (dolist (pairing '((outline-1 . :base08) + (outline-2 . :base09) + (outline-3 . :base0A) + (outline-4 . :base0B) + (outline-5 . :base0C) + (outline-6 . :base0D) + (outline-7 . :base0E) + (outline-8 . :base0F))) + (set-face-attribute (car pairing) nil + :foreground + (plist-get base16-one-light-theme-colors (cdr pairing))))) + :config + (if (display-graphic-p) (my/load-theme-and-configure))) + + (use-package nerd-icons + :if (package-installed-p 'nerd-icons) + :functions (nerd-icons-octicon)) + + (use-package nerd-icons-dired + :requires nerd-icons + :hook (dired-mode)) + + (use-package nerd-icons-ibuffer + :requires nerd-icons + :hook (ibuffer-mode)) + + (use-package nerd-icons-completion + :functions nerd-icons-completion-mode + :requires nerd-icons + :hook (after-init . (lambda () (nerd-icons-completion-mode +1)))) + + (use-package minions + :if (package-installed-p 'minions) + :functions minions-mode + :hook (after-init . (lambda () (minions-mode +1))) + :custom + (minions-prominent-modes '(envrc-mode flymake-mode))) + + (use-package ligature + :if (package-installed-p 'ligature) + :functions (ligature-set-ligatures + global-ligature-mode) + :config + (ligature-set-ligatures + '(text-mode prog-mode org-mode) + '("<--" "<---" "<-" "->" "-->" "--->" + "<==" "<===" "<=" "=>" "==>" "===>" + "<->" "<-->" "<--->" "<---->" + "<=>" "<==>" "<===>" "<====>" + "==" "!=" "===" "!==" "!===" + "<|" "<|>" "|>" "<>" "" "/>" + "/*" "*/" "+++" "<~~" "~~>" "")) + (global-ligature-mode +1)) + + (use-package whitespace + :custom + (whitespace-style '(face + empty + trailing + tab-mark + indentation::space)) + (whitespace-action '(report-on-bogus + cleanup + auto-cleanup))) + + (setq mode-line-compact 'long) + + (line-number-mode -1) + (column-number-mode -1) + (size-indication-mode +1) + + ;; (require 'battery) + ;; (when (and battery-status-function + ;; (not ( string-match-p "unknown" + ;; ( battery-format "%B" + ;; (funcall battery-status-function))))) + ;; (display-battery-mode +1)) + + (use-package time + :custom + (display-time-24hr-format t)) + + (use-package diff-hl + :if (package-installed-p 'diff-hl) + :functions (diff-hl-magit-pre-refresh + diff-hl-magit-post-refresh + global-diff-hl-mode) + :init + (add-hook 'magit-pre-refresh-hook #'diff-hl-magit-pre-refresh) + (add-hook 'magit-post-refresh-hook #'diff-hl-magit-post-refresh) + :custom + (diff-hl-disable-on-remote nil) + (diff-hl-draw-borders t) + :config + (global-diff-hl-mode)) + + (setq split-height-threshold nil + split-width-threshold 160) + + (use-package winner + :demand + :config + (winner-mode)) + + (use-package ediff + :bind (("C-c d f" . ediff-files) + ("C-c d b" . ediff-buffers) + ("C-c d 3 f" . ediff-files3) + ("C-c d 3 b" . ediff-buffers3)) + :custom + (ediff-window-setup-function #'ediff-setup-windows-plain)) + + (use-package emms + :defines (emms-browser-mode-map + emms-playlist-mode-map) + :functions (emms-all + emms-default-players + emms-mpris-enable + emms-cache-enable + emms-show) + :bind (("C-c e e" . emms-smart-browse) + ("C-c e p" . emms-pause) + ("C-c e s" . emms-stop) + ("C-c e z" . emms-toggle-repeat-track) + ("C-c e C-r" . emms-toggle-repeat-playlist) + ("C-c e C-b" . emms-browser) + ("C-c e C-p" . emms-playlist-mode-go) + ("" . emms-pause) + ("" . emms-previous) + ("" . emms-next) + :map emms-browser-mode-map + ("e" . emms-smart-browse) + ("P" . emms-pause) + ("S" . emms-stop) + ("z" . emms-toggle-repeat-track) + :map emms-playlist-mode-map + ("e" . emms-smart-browse)) + :custom + (emms-source-file-default-directory "~/Music/") + (emms-lyrics-dir (expand-file-name "lyrics" "~/Music/")) + (emms-browser-covers #'emms-browser-cache-thumbnail-async) + (emms-browser-default-covers (list (expand-file-name "placeholder.jpg" "~/Music/"))) + (emms-repeat-playlist t) + :config + (emms-all) + (emms-default-players) + (emms-mpris-enable) + (emms-cache-enable) + (add-hook 'emms-player-started-hook #'emms-show)) + + (use-package org + :demand + :defines org-mode-map + :hook ((org-mode . turn-on-auto-fill)) + :bind ( :map org-mode-map + (" " . consult-org-heading) + (" " . consult-org-heading)) + :custom + (org-directory "~/Documents/org") + (org-default-notes-file (expand-file-name "notes.org" org-directory)) + (org-archive-location "::* Archived Tasks") + (org-hide-emphasis-markers t) + (org-use-sub-superscripts '{}) + (org-pretty-entities t) + (org-pretty-entities-include-sub-superscripts t) + (org-fontify-done-headline t) + (org-fontify-todo-headline t) + (org-fontify-emphasized-text t) + (org-fontify-quote-and-verse-blocks t) + (org-tags-column 0) + (org-enforce-todo-dependencies t) + (org-enforce-todo-checkbox-dependencies t) + (org-yank-folded-subtrees nil) + (org-yank-adjusted-subtrees t) + (org-display-remote-inline-images 'cache) + (org-M-RET-may-split-line '((default . nil) + (headline . nil) + (item . nil) + (table . t)))) + + (use-package ox + :after org + :custom + (org-export-with-sub-superscripts org-use-sub-superscripts)) + + (use-package org-faces + :after org + :config + ;; Ensure tables and src blocks use fixed-pitch font. + (set-face-attribute 'org-block nil :inherit 'fixed-pitch) + (set-face-attribute 'org-code nil :inherit 'fixed-pitch) + (set-face-attribute 'org-table nil :inherit 'fixed-pitch) + (set-face-attribute 'org-verbatim nil :inherit 'org-code) + ;; Let quote and verse blocks use variable-pitch font, if configured + (set-face-attribute 'org-quote nil :inherit 'variable-pitch) + (set-face-attribute 'org-verse nil :inherit 'variable-pitch)) + + (use-package org-keys + :after org + :custom + (org-return-follows-link t) + (org-mouse-1-follows-link t)) + + (use-package org-indent + :after org + :hook org-mode) + + (use-package org-attach + :after org + :custom + (org-attach-id-dir (expand-file-name "data/" org-directory)) + (org-attach-dir-relative t) + (org-attach-use-inheritance nil)) + + (use-package org-refile + :after (org org-agenda) + :custom + (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))))) + + (use-package org-src + :after org + :custom + (org-src-window-setup 'reorganize-frame)) + + (use-package ob-core + :after org + :custom + (org-babel-no-eval-on-ctrl-c-ctrl-c t) + (org-confirm-babel-evaluate nil) + :config + (let (babel-languages) + (push '(lua . t) babel-languages) + (push '(python . t) babel-languages) + (push '(emacs-lisp . t) babel-languages) + (org-babel-do-load-languages 'org-babel-load-languages babel-languages))) + + (use-package ob-python + :after ob-core + :custom + (org-babel-python-command "python3")) + + (use-package org-capture + :after org + :bind ("C-c o n" . org-capture) + :custom (org-capture-templates + '(("t" "TODO" entry + (file+olp "tasks.org.gpg" "Inbox") + "* TODO %?\nDEADLINE: %t\n %i\n %a") + ("#" "used by gnus-icalendar-org" entry + (file+olp "calendar/email.org.gpg" "Inbox") + "%i" :immediate-finish t)))) + + (if (executable-find "sqlite3") + (use-package org-roam + :if (package-installed-p 'org-roam) + :after org + :defines org-roam-directory + :functions org-roam-db-autosync-mode + :bind (("C-c o r i" . org-roam-node-insert) + ("C-c o r f" . org-roam-node-find) + ("C-c o r n" . org-roam-capture) + ("C-c o r j" . org-roam-dailies-capture-today) + ("M-g j" . org-roam-dailies-goto-today) + ("M-g C-j" . org-roam-dailies-goto-date) + :map org-mode-map + ("C-c o r b" . org-roam-buffer-toggle)) + :custom + (org-roam-directory (expand-file-name "roam" org-directory)) + (org-roam-completion-everywhere nil) + (org-roam-node-display-template (concat + "${title:*} " + (propertize "${tags:24}" 'face 'org-tag))) + (org-roam-capture-templates '(("d" "default" plain "%?" + :target (file+head "${slug}.org" "#+title: ${title}\n") + :unnarrowed t))) + :config + (mkdir org-roam-directory t) + (add-to-list 'display-buffer-alist + '("\\*org-roam\\*" + (display-buffer-in-side-window) + (side . right) + (slot . 0) + (window-width . 0.33) + (window-parameters . ((no-delete-other-windows . t))))) + (org-roam-db-autosync-mode +1))) + + (use-package org-roam-dailies + :after org-roam + :custom + (org-roam-dailies-directory "./") + (org-roam-dailies-capture-templates + '(("d" "default" entry + "* %?" + :target (file+datetree "journal.org.gpg" week))))) + + (use-package org-clock + :after org + :custom + (org-clock-rounding-minutes 15)) + + (use-package org-agenda + :after (org appt) + :bind (("C-c o a" . org-agenda) + ("C-c o C-a" . org-agenda-list)) + :hook (org-agenda-finalize . org-agenda-to-appt) + :custom + (org-agenda-span 'day) + (org-agenda-start-on-weekday 1) + (org-agenda-sticky nil) + (org-agenda-window-setup 'current-window) + (org-agenda-tags-column 0) + (org-agenda-diary-file (expand-file-name "calendar/diary.org.gpg" org-directory)) + (org-agenda-include-diary nil) + (org-agenda-include-deadlines t) + (org-agenda-todo-ignore-scheduled 'future) + (org-agenda-todo-ignore-deadlines 'far) + (org-agenda-clockreport-parameter-plist '(:link t :maxlevel 6 :emphasize t :stepskip0 t :fileskip0 t :filetitle t :properties ("WON"))) + (org-agenda-start-with-clockreport-mode t) + (org-agenda-start-with-log-mode t) + (org-agenda-prefix-format '((agenda . " %-12:c%?-12t% s") + (todo . " %-12:c") + (tags . " %-12:c") + (search . " %-12:c"))) + (org-agenda-file-regexp "\\`[^.].*\\.org\\\(\\.gpg\\\)?\\'") + (org-agenda-files (list + (expand-file-name org-directory) + (expand-file-name "calendar" org-directory) + (expand-file-name "roam/journal.org.gpg" org-directory) + (expand-file-name "roam/analysis_notes.org" org-directory))) + :config + (appt-activate +1)) + + (use-package ox-icalendar + :after org + :custom + (org-icalendar-store-UID t) + (org-icalendar-alarm-time 15) + (org-icalendar-include-body t) + (org-icalendar-include-sexps t) + (org-icalendar-include-todo t) + (org-icalendar-combined-name "org-mode") + (org-icalendar-combined-description "Emacs org-mode combined export")) + + (use-package org-noter + :after (org doc-view citar) + :commands org-noter + :custom + (org-noter-always-create-frame nil) + (org-noter-kill-frame-at-session-end nil) + (org-noter-auto-save-last-location t) + (org-noter-default-notes-file-names '("noter.org")) + (org-noter-doc-property-in-notes t) + (org-noter-notes-search-path + (list (expand-file-name "notes" org-directory) + (car citar-notes-paths))) + (org-noter-prefer-root-as-file-level nil)) + + (use-package citar + :defines (citar-bibliography + citar-indicators) + :functions (citar-indicator-create + citar-has-files + citar-has-links + citar-has-notes + citar-is-cited) + :hook + (LaTeX-mode . citar-capf-setup) + (org-mode . citar-capf-setup) + :custom + (citar-bibliography + (list + (expand-file-name "citar/main.bib" org-directory))) + (citar-notes-paths + (list + (expand-file-name "citar/notes/" org-directory))) + (citar-library-paths + (list + (expand-file-name "~/Documents/library/"))) + :config + (require 'org) + (require 'nerd-icons) + (setopt org-cite-insert-processor 'citar + org-cite-follow-processor 'citar + org-cite-activate-processor 'citar) + (dolist (bibfile citar-bibliography) + (add-to-list 'org-cite-global-bibliography bibfile)) + (defvar citar-indicator-files-icons + (citar-indicator-create + :symbol (nerd-icons-octicon + "nf-oct-file" + :face 'nerd-icons-green + :v-adjust -0.1) + :function #'citar-has-files + :padding " " ; need this because the default padding is too low for these icons + :tag "has:files")) + (defvar citar-indicator-links-icons + (citar-indicator-create + :symbol (nerd-icons-octicon + "nf-oct-link" + :face 'nerd-icons-orange + :v-adjust 0.01) + :function #'citar-has-links + :padding " " ; need this because the default padding is too low for these icons + :tag "has:links")) + (defvar citar-indicator-notes-icons + (citar-indicator-create + :symbol (nerd-icons-octicon + "nf-oct-note" + :face 'nerd-icons-blue + :v-adjust -0.3) + :function #'citar-has-notes + :padding " " ; need this because the default padding is too low for these icons + :tag "has:notes")) + (defvar citar-indicator-cited-icons + (citar-indicator-create + :symbol (nerd-icons-octicon + "nf-oct-circle" + :face 'nerd-icon-green) + :function #'citar-is-cited + :padding " " ; need this because the default padding is too low for these icons + :tag "is:cited")) + (setq citar-indicators (list citar-indicator-files-icons + citar-indicator-links-icons + citar-indicator-notes-icons + citar-indicator-cited-icons))) + + (setq org-latex-compiler "lualatex") + (setq org-preview-latex-default-process 'dvisvgm) + + (use-package vertico + :if (package-installed-p 'vertico) + :functions vertico-mode + :hook (after-init . (lambda () (vertico-mode +1))) + :custom + (vertico-cycle t) + :config + (require 'vertico-directory)) + + (use-package marginalia + :if (package-installed-p 'marginalia) + :functions marginalia-mode + :hook (after-init . (lambda () (marginalia-mode +1))) + :custom + (marginalia-annotators '(marginalia-annotators-heavy + marginalia-annotators-light + nil)) + :config (marginalia-mode +1)) + + (use-package orderless + :if (package-installed-p 'orderless) + :custom + (completion-styles '(orderless basic)) + (completion-category-defaults nil) + (completion-category-overrides '((file (styles basic partial-completion)) + (eglot (styles orderless)) + (eglot-capf (styles orderless))))) + + (use-package nerd-icons-corfu + :functions nerd-icons-corfu-formatter + :requires nerd-icons) + + (use-package corfu + :if (package-installed-p 'corfu) + :defines (corfu-map + corfu-mode-map + corfu-margin-formatters) + :functions (corfu-mode + global-corfu-mode + corfu-history-mode) + :hook ((after-init . (lambda () (global-corfu-mode +1))) + (minibuffer-setup . (lambda () + "Enable `corfu-mode' for `M-:' and `M-!'." + (when (local-variable-p 'completion-at-point-functions) + (corfu-mode +1))))) + :bind ( :map corfu-map + ("M-SPC" . corfu-insert-separator) + ("RET" . nil) + ("TAB" . corfu-insert) + ([tab] . corfu-insert)) + :custom + (corfu-cycle t) + (corfu-auto nil) + (corfu-preselect 'directory) + :config + (require 'corfu-history) + (when (require 'nerd-icons-corfu nil :noerror) + (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) + (when (require 'corfu-popupinfo nil :noerror) + (corfu-popupinfo-mode +1)) + (when (and (require 'corfu-terminal nil :noerror) + (not (display-graphic-p))) + (corfu-terminal-mode +1))) + + (use-package corfu-history + :requires (corfu savehist) + :functions corfu-history + :config + (add-to-list 'savehist-additional-variables #'corfu-history)) + + (use-package corfu-popupinfo + :requires corfu + :defines corfu-popupinfo-map + :functions corfu-popupinfo-mode + :bind ( :map corfu-popupinfo-map + ("M-d" . corfu-popupinfo-toggle) + ("M-n" . corfu-popupinfo-scroll-up) + ("M-p" . corfu-popupinfo-scroll-down)) + :custom + (corfu-popupinfo-delay 0.3)) + + (use-package corfu-terminal + :requires corfu + :functions corfu-terminal-mode) + + (use-package cape + :if (package-installed-p 'cape) + :after corfu + :functions (cape-emoji + cape-file + cape-dabbrev) + :hook ((conf-mode prog-mode text-mode) . (lambda () + (dolist (cape-fn '(cape-dabbrev + cape-file + cape-emoji)) + (add-hook 'completion-at-point-functions cape-fn nil t)))) + :custom + (cape-dabbrev-min-length (+ corfu-auto-prefix 1))) + + (use-package consult + :if (package-installed-p 'consult) + :functions (consult-org-heading + consult-history) + :bind ((" " . consult-imenu) + (" " . consult-buffer) + (" " . consult-project-buffer) + ("C-c s l" . consult-line) + ("C-c s o" . consult-outline) + ("C-c s f" . consult-fd) + ("C-c s g" . consult-ripgrep) + ("C-c s e" . consult-flymake) + ("C-c s i" . consult-info) + :map minibuffer-local-map + (" " . consult-history) + :map comint-mode-map + (" " . consult-history))) + + (use-package consult-eglot + :after (consult eglot) + :bind (("C-c s s" . consult-eglot-symbols))) + + (use-package tempel + :if (package-installed-p 'tempel) + :defines tempel-path + :functions (tempel-expand + tempel-abbrev-mode) + :bind (("M-+" . tempel-complete) + ("M-*" . tempel-insert)) + :hook ((conf-mode prog-mode text-mode) . (lambda () (add-hook 'completion-at-point-functions 'tempel-complete nil t))) + :custom + (tempel-trigger-prefix "+")) + + (require 'tramp) + (setq org-publish-project-alist + `(("xenia.me.uk" + :base-directory ,(expand-file-name "www/xenia.me.uk" "~/Projects/") + :base-extension "org" + :exclude "setup.org" + :recursive t + :publishing-function org-html-publish-to-html + :publishing-directory "/sshx:pixelifytica@legion:/var/www/xenia.me.uk" + :auto-sitemap t + :sitemap-title "Sitemap" + :section-numbers nil + :with-author t + :with-email t + :with-toc nil + :html-link-home "/" + :html-link-up "../" + ;; :html-head "" + ))) + + (use-package rainbow-delimiters + :if (package-installed-p 'rainbow-delimiters) + :hook (prog-mode)) + + (use-package envrc + :if (package-installed-p 'envrc) + :hook (after-init . envrc-global-mode) + :custom + (envrc-show-summary-in-minibuffer t)) + + (use-package gud + :defer t + :defines gdb-many-windows + :config + (setq gdb-many-windows t)) + + (use-package treesit + :custom + (treesit-font-lock-level 3)) + + (use-package treesit-auto + :if (package-installed-p 'treesit-auto) + :requires treesit + :functions (treesit-auto-add-to-auto-mode-alist + global-treesit-auto-mode) + :hook (after-init . (lambda () (global-treesit-auto-mode +1))) + :config + (treesit-auto-add-to-auto-mode-alist)) + + (use-package eldoc + :custom + (eldoc-echo-area-display-truncation-message nil) + (eldoc-echo-area-prefer-doc-buffer 'maybe) + (eldoc-echo-area-use-multiline-p 3)) + + (use-package eglot + :bind ( :map prog-mode-map + ("C-c c a" . eglot-code-actions) + ("C-c c r" . eglot-rename)) + :hook ((eglot-managed-mode . (lambda () (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t))) + (nix-mode . (lambda () (if (and (project-current nil) (executable-find "nixd" t)) + (eglot-ensure)))) + (python-base-mode . (lambda () (if (and (project-current nil) (executable-find "pylsp" t)) + (eglot-ensure)))) + (lua-mode . (lambda () (if (and (project-current nil) (executable-find "lua-language-server" t)) + (eglot-ensure)))) + ((rust-ts-mode rust-mode) . (lambda () (if (and (project-current nil) (executable-find "rust-analyzer" t)) + (eglot-ensure)))) + ((js-base-mode typescript-ts-base-mode) . (lambda () (if (and (project-current nil) (executable-find "typescript-language-server" t)) + (eglot-ensure)))) + ) + :custom + (eglot-menu-string "lsp") + (eglot-send-changes-idle-time 1) + (eglot-extend-to-xref t) + (eglot-autoshutdown t) + (eglot-sync-connect nil) + (eglot-autoreconnect (* 60 5)) + (eglot-events-buffer-config '(:size 0)) + (eglot-ignored-server-capabilities + '(:documentHighlightProvider + :documentFormattingProvider + :documentRangeFormattingProvider + :documentOnTypeFormattingProvider + :documentLinkProvider + :colorProvider + :foldingRangeProvider)) + :init + (setq eglot-stay-out-of '(flymake)) + :config + (setq-default eglot-workspace-configuration + '( :nil ( :nix + ( :maxMemoryMB nil + :flake + ( :autoArchive t + :nixpkgsInputName "nixpkgs"))) + :pylsp ( :plugins + ( :autopep8 (:enabled nil) + :flake8 (:enabled nil) + :jedi_completion ( :enabled t + :include_params t + :include_class_objects t + :include_function_objects t + :fuzzy t) + :jedi_definition (:enabled t) + :jedi_hover (:enabled t) + :mccabe (:enabled nil) + :preload (:enabled nil) + :pycodestyle (:enabled nil) + :pydocstyle (:enabled nil) + :pyflakes (:enabled nil) + :pylint (:enabled nil) + :rope_autoimport ( :completions (:enabled t) + :code_actions (:enabled t)) + :rope_completion (:enabled t) + :yapf (:enabled nil))))) + ) + + (use-package apheleia + :if (package-installed-p 'apheleia) + :defines (apheleia-formatters + apheleia-mode-alist) + :bind (("C-c c f" . apheleia-format-buffer)) + :hook (prog-mode) + :custom (apheleia-remote-algorithm 'cancel) + :config + (add-to-list 'apheleia-mode-alist '(python-ts-mode . (ruff ruff-isort))) + (add-to-list 'apheleia-mode-alist '(python-mode . (ruff ruff-isort)))) + + (use-package flymake + :bind (("C-c C-." . flymake-goto-next-error) + ("C-c C-," . flymake-goto-prev-error)) + :hook ((prog-mode yaml-ts-mode) . (lambda () (flymake-mode +1))) + :custom + (flymake-no-changes-timeout 1) + (flymake-show-diagnostics-at-end-of-line 'short)) + + (use-package flymake-shellcheck + :if (package-installed-p 'flymake-shellcheck) + :functions flymake-shellcheck-load + :requires flymake + :hook (sh-mode . (lambda () (if (executable-find "shellcheck" t) + (flymake-shellcheck-load))))) + + (use-package flymake-yamllint + :if (package-installed-p 'flymake-yamllint) + :functions flymake-yamllint-setup + :requires flymake + :hook (yaml-ts-mode . (lambda () (if (executable-find "yamllint" t) + (flymake-yamllint-setup))))) + + (use-package flymake-clippy + :if (package-installed-p 'flymake-clippy) + :functions flymake-clippy-setup-backend + :requires flymake + :hook (rust-mode . (lambda () (if (executable-find "clippy" t) + (flymake-clippy-setup-backend))))) + + (use-package flymake-eslint + :if (package-installed-p 'flymake-eslint) + :functions flymake-eslint-enable + :requires flymake + :hook ((js-base-mode typescript-ts-base-mode) . (lambda () (if (executable-find "eslint" t) + (flymake-eslint-enable))))) + + (use-package project + :functions (project-forget-zombie-projects + project-remember-projects-under) + :custom + (project-switch-use-entire-map t) + (project-switch-commands '((project-find-file "Find file") + (project-find-regexp "Find regexp") + (project-find-dir "Find directory") + (project-eshell "Eshell") + (magit-project-status "Magit"))) + :config + (defun my/project-find-common-projects () + "Search and remember common project directories. + + Calls `project-remember-projects-under' for ~/Projects/" + (interactive) + (require 'project) + (project-forget-zombie-projects) + (project-remember-projects-under user-emacs-directory nil) + (project-remember-projects-under "/etc/nixos/" nil) + (project-remember-projects-under "~/Projects" t) + )) + + (use-package magit + :bind (("C-c g g" . magit-status) + ("C-c g d" . magit-dispatch) + ("C-c g f" . magit-file-dispatch) + ("C-c g b" . magit-blame-addition) + (" " . magit-project-status) + :map project-prefix-map + ("m" . magit-project-status)) + :custom + (magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1) + (magit-define-global-key-bindings nil) + (magit-show-long-lines-warning nil) + (magit-clone-default-directory "~/Projects/") + (magit-clone-set-remote.pushDefault t) + (magit-commit-show-diff t) + (magit-commit-diff-inhibit-same-window t) + (magit-diff-adjust-tab-width t) + (magit-diff-refine-hunk 'all) + (magit-diff-refine-ignore-whitespace t) + (magit-clone-name-alist '(("\\`\\(?:github:\\|gh:\\)?\\([^:]+\\)\\'" "github.com" "github.user") + ("\\`\\(?:gitlab:\\|gl:\\)\\([^:]+\\)\\'" "gitlab.com" "gitlab.user") + ("\\`\\(?:sourcehut:\\|sh:\\)\\([^:]+\\)\\'" "git.sr.ht" "sourcehut.user") + ("\\`\\(?:gitea:\\|gt:\\)\\([^:]+\\)\\'" "git.xenia.me.uk" "gitea.user")))) + + (use-package nix-mode + :if (package-installed-p 'nix-mode) + :mode "\\.nix\\'" + :functions nix-prettify-global-mode + :config + (require 'nix) + (require 'nix-flake) + (require 'nix-repl) + (require 'nix-store) + (nix-prettify-global-mode +1)) + + (defun my/enable-fill-column (col) + "Set and enable fill column to `COL'." + (set-fill-column col) + (display-fill-column-indicator-mode +1)) + + (use-package python + :hook ((python-base-mode . (lambda () (my/enable-fill-column 88))) + (python-base-mode . (lambda () (setq-local + python-check-command (cond + ((executable-find "mypy" t) "mypy --check-untyped-defs --warn-unreachable --show-error-codes --ignore-missing-imports") + (t "pyflakes")) + python-flymake-command (cond + ((executable-find "ruff" t) '("ruff" "check" "--output-format=concise" "--stdin-filename=stdin" "-")) + ((executable-find "flake8" t) '("flake8" "--max-line-length" "88" "-")) + (t '("pyflakes"))))))) + :custom + (python-shell-interpreter "python3") + (python-shell-dedicated nil) + (python-shell-completion-native-enable nil) + (python-indent-def-block-scale 1) + :config + (setq python-ts-mode-hook python-mode-hook)) + + (use-package python-docstring + :if (package-installed-p 'python-docstring) + :hook python-base-mode) + + (use-package files + :custom + (view-read-only t) + (enable-remote-dir-locals t)) + + (use-package tramp + :defer t + :custom + (tramp-default-method "scpx") + (tramp-backup-directory-alist backup-directory-alist) + (tramp-auto-save-directory (cdr (assoc "." tramp-backup-directory-alist))) + :config + (add-to-list 'tramp-remote-path 'tramp-own-remote-path) + (add-to-list 'tramp-remote-path "~/.local/bin/")) + + (connection-local-set-profile-variables + 'remote-no-corfu-auto + '((corfu-auto . nil))) + + (connection-local-set-profiles + '(:application tramp) + 'remote-no-corfu-auto) + + (use-package doc-view + :defer t + :bind ( :map doc-view-mode-map + ("" . doc-view-previous-page) + ("" . doc-view-next-page)) + :custom + (doc-view-resolution 200) + (doc-view-imenu-enabled t) + (doc-view-scale-internally t) + (doc-view-image-width 850)) + + (use-package markdown-mode + :if (package-installed-p 'markdown-mode) + :hook + ((markdown-mode . turn-on-auto-fill)) + :custom + (markdown-enable-math t) + (markdown-enable-html t) + :config + (set-face-attribute 'markdown-code-face nil :inherit 'fixed-pitch) + (set-face-attribute 'markdown-inline-code-face nil :inherit 'fixed-pitch) + (set-face-attribute 'markdown-table-face nil :inherit 'fixed-pitch) + (set-face-attribute 'markdown-blockquote-face nil :inherit 'variable-pitch) + (set-face-attribute 'markdown-comment-face nil :inherit 'variable-pitch)) + + (use-package pandoc-mode + :if (package-installed-p 'pandoc-mode) + :after (markdown-mode) + :hook (markdown-mode . conditionally-turn-on-pandoc)) + + (if (package-installed-p 'mu4e) + (load-file (locate-user-emacs-file "modules/my-mu4e.el"))) + + (use-package bbdb + :bind (("M-g b" . bbdb-display-all-records)) + :custom + (bbdb-file (locate-user-emacs-file "bbdb.gpg"))) + + (use-package erc + :commands erc-compute-nick + :custom + (erc-nick (user-login-name)) + (erc-user-full-name (user-full-name))) + + (defun my/libera-chat-connect () + "Connect to irc.libera.chat directly." + (interactive) + (require 'erc) + (require 'password-store) + (erc-tls + :server "irc.libera.chat" + :password (password-store-get 'social/irc.libera.chat))) + (defun my/znc-connect () + "Connect to my ZNC IRC bouncer." + (interactive) + (require 'erc) + (require 'password-store) + (erc-tls + :server "xenia.me.uk" + :port 6697 + :nick (concat (erc-compute-nick) "/liberachat") + :password (password-store-get 'local/znc))) + + (use-package eww + :defer t + :custom + (browse-url-browser-function 'browse-url-default-browser) + (browse-url-secondary-browser-function 'browse-url-default-browser) + (browse-url-new-window-flag t) + (eww-default-download-directory "~/Downloads/") + (eww-auto-rename-buffer 'title) + (eww-browse-url-new-window-is-tab nil)) + + (use-package password-store + :defer t + :functions password-store-get) + + ;; Scratch buffer shortcut + (keymap-global-set "C-c w x" #'scratch-buffer) + + ;; Config file shortcut + (defun my/open-init-file () + "Open Emacs init file." + (interactive) + (find-file (locate-user-emacs-file "init.el"))) + (keymap-global-set "C-c w e" #'my/open-init-file) + + ;; Tempel template file shortcut + (defun my/open-template-file () + "Open `tempel' template file." + (interactive) + (require 'tempel) + (find-file tempel-path)) + (keymap-global-set "C-c w t" #'my/open-template-file) + + ;; Org directory shortcut + (defun my/open-org-directory () + "Open base `org-mode' directory in Dired." + (interactive) + (require 'org) + (find-file org-directory)) + (keymap-global-set "C-c w o" #'my/open-org-directory) + + (defun my/open-global-bibliography () + "Open `org-cite-global-bibliography'." + (interactive) + (require 'citar) + (find-file (car org-cite-global-bibliography))) + (keymap-global-set "C-c w b" #'my/open-global-bibliography) + + (defun my/open-documents-directory () + "Open Documents directory." + (interactive) + (find-file "~/Documents/")) + (defun my/open-downloads-directory () + "Open Downloads directory." + (interactive) + (find-file "~/Downloads/")) + (keymap-global-set "C-c w d" #'my/open-documents-directory) + (keymap-global-set "C-c w C-d" #'my/open-downloads-directory) +#+end_src diff --git a/init.el b/init.el index 5f034d1..a20564b 100644 --- a/init.el +++ b/init.el @@ -2,1214 +2,8 @@ ;;; Commentary: ;;; Code: -;; Customise `use-package' behaviour, must be set before first time -;; it's used. Configure packages archives with priority -(setopt use-package-check-before-init t - use-package-enable-imenu-support t) - -(setq custom-file (locate-user-emacs-file "custom.el")) -(when (and custom-file - (file-exists-p custom-file)) - (load custom-file nil 'nomessage)) - -(use-package package - :custom - (package-archive-priorities '(("melpa" . 4) ("stable" . 3) ("nongnu" . 2) ("gnu" . 1))) - (package-selected-packages - '( - ;; UI - base16-theme all-the-icons nerd-icons nerd-icons-completion - nerd-icons-corfu nerd-icons-dired nerd-icons-ibuffer minions - ligature which-key diff-hl - - ;; Completion - vertico orderless marginalia cape corfu corfu-terminal - consult consult-eglot flyspell-correct tempel - - ;; IDE - treesit-auto magit forge apheleia envrc rainbow-delimiters - flymake-shellcheck flymake-yamllint flymake-clippy - flymake-eslint markdown-mode pandoc-mode python-docstring - nix-mode lua-mode - - ;; Org + LaTeX - org-roam org-noter citar auctex htmlize - - ;; Other - password-store emms bbdb ement scad-mode - - )) - :config - (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) - (add-to-list 'package-archives '("stable" . "https://stable.melpa.org/packages/")) - (package-initialize) - - (defun my/package-ensure () - "Update package archives and ensure packages are installed." - (interactive) - (package-refresh-contents) - (package-install-selected-packages) - (package-autoremove))) - -(set-default-coding-systems 'utf-8) - -(setq user-full-name "Evie Litherland-Smith" - user-mail-address "evie@xenia.me.uk" - inhibit-splash-screen t - use-short-answers t - tab-always-indent 'complete - completion-cycle-threshold nil - completions-detailed t - kill-do-not-save-duplicates t - initial-frame-alist nil - default-frame-alist nil) - -(setq-default truncate-lines t - truncate-partial-width-windows nil) - -(setopt indent-tabs-mode nil - async-shell-command-display-buffer nil - compilation-scroll-output t) - -(global-prettify-symbols-mode +1) -(global-auto-revert-mode +1) -(delete-selection-mode +1) -(which-function-mode +1) -(tool-bar-mode -1) -(scroll-bar-mode -1) - -(use-package pixel-scroll - :init - (pixel-scroll-precision-mode +1)) - -(use-package mwheel - :custom - (mouse-wheel-scroll-amount '(1 ((shift) . 1))) - (mouse-wheel-progressive-speed nil) - (mouse-wheel-follow-mouse t)) - -;; Bind normal forward/back buttons on mouse to next/previous buffer respectively -(keymap-global-set "" #'previous-buffer) -(keymap-global-set "" #'next-buffer) - -;; Quick bind for calling `git-sync-all' -(defun my/git-sync-all () - "Run shell command `git-sync-all' asynchronously." - (interactive) - (async-shell-command "git-sync-all" "*git-sync-all*" "*git-sync-errors*")) -(keymap-global-set "C-c g s" #'my/git-sync-all) - -;; Make shebang (#!) file executable when saved -(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) - -;; Remap `upcase-word' and `downcase-word' to DWIM versions -(keymap-global-set " " 'upcase-dwim) -(keymap-global-set " " 'downcase-dwim) - -(setq backup-directory-alist '(("." . "~/.local/state/emacs/backups"))) - -(use-package savehist - :demand - :config - (savehist-mode +1)) - -(use-package dired - :custom - (dired-auto-revert-buffer t) - (dired-dwim-target t)) - -(use-package recentf - :config - (run-at-time nil (* 5 60) 'recentf-save-list) - (recentf-mode +1) - :custom - (recentf-max-saved-items 2048)) - -(use-package auth-source - :custom - (auth-sources '("secrets:Login"))) - -(use-package auth-source-pass - :requires auth-source - :config - (auth-source-pass-enable)) - -;; Bind extra `describe-*' commands -(keymap-global-set "C-h K" #'describe-keymap) - -;; turn on spell checking, if available. -(use-package ispell - :custom - (ispell-dictionary "en_GB")) - -(use-package flyspell - :hook ((text-mode . flyspell-mode) - (prog-mode . flyspell-prog-mode)) - :init - (require 'ispell) - :custom - (flyspell-use-meta-tab nil)) - -(use-package flyspell-correct - :if (package-installed-p 'flyspell-correct) - :after flyspell - :bind ( :map flyspell-mode-map - ("C-;" . flyspell-correct-wrapper))) - -(use-package ibuffer - :defines ibuffer-filter-groups - :bind (("C-c b" . ibuffer))) - -(use-package shell - :bind (("C-c t s" . shell))) - -(use-package eshell - :bind (("C-c t e" . eshell)) - :config - (require 'esh-mode)) - -(use-package esh-mode - :defines eshell-mode-map - :bind ( :map eshell-mode-map - (" " . consult-history))) - -(use-package calc - :bind (("" . calc))) - -(use-package xref - :custom - (xref-show-definitions-function 'xref-show-definitions-completing-read)) - -(use-package appt - :custom - (appt-display-diary nil) - (appt-display-format 'echo)) - -(use-package calendar - :after appt - :bind (("C-c >" . calendar)) - :hook ((calendar-today-visible . calendar-mark-today)) - :custom - (calendar-date-style 'iso) - (calendar-mark-holidays-flag t) - (calendar-mark-diary-entries-flag nil) - (calendar-view-holidays-initially-flag nil) - (calendar-view-diary-initially-flag nil) - :config - (appt-activate +1) - (add-to-list 'display-buffer-alist - '("\\*Calendar\\*" - (display-buffer-in-side-window) - (side . bottom) - (slot . 0) - (window-height . 0.2) - (window-parameters . ((no-delete-other-windows . t)))))) - -(add-hook 'prog-mode-hook #'(lambda () (display-line-numbers-mode +1))) - -(use-package which-key - :if (package-installed-p 'which-key) - :functions which-key-mode - :config (which-key-mode +1)) - -(use-package elec-pair - :config - (electric-pair-mode +1)) - -(use-package paren - :config - (show-paren-mode +1)) - -;; 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))) - -(use-package base16-theme - :if (package-installed-p 'base16-theme) - :demand - :defines (base16-one-light-theme-colors - my/load-theme-and-configure) - :hook (server-after-make-frame . my/load-theme-and-configure) - :custom - (base16-theme-distinct-fringe-background nil) - (base16-theme-highlight-mode-line 'contrast) - :init - (defun my/load-theme-and-configure () - "Load theme and configure some faces." - (load-theme 'base16-one-light t) - - ;; Change outline headers to follow rainbow order - (require 'outline) - (dolist (pairing '((outline-1 . :base08) - (outline-2 . :base09) - (outline-3 . :base0A) - (outline-4 . :base0B) - (outline-5 . :base0C) - (outline-6 . :base0D) - (outline-7 . :base0E) - (outline-8 . :base0F))) - (set-face-attribute (car pairing) nil - :foreground - (plist-get base16-one-light-theme-colors (cdr pairing))))) - :config - (if (display-graphic-p) (my/load-theme-and-configure))) - -(use-package nerd-icons - :if (package-installed-p 'nerd-icons) - :functions (nerd-icons-octicon)) - -(use-package nerd-icons-dired - :requires nerd-icons - :hook (dired-mode)) - -(use-package nerd-icons-ibuffer - :requires nerd-icons - :hook (ibuffer-mode)) - -(use-package nerd-icons-completion - :functions nerd-icons-completion-mode - :requires nerd-icons - :hook (after-init . (lambda () (nerd-icons-completion-mode +1)))) - -(use-package minions - :if (package-installed-p 'minions) - :functions minions-mode - :hook (after-init . (lambda () (minions-mode +1))) - :custom - (minions-prominent-modes '(envrc-mode flymake-mode))) - -(use-package ligature - :if (package-installed-p 'ligature) - :functions (ligature-set-ligatures - global-ligature-mode) - :config - (ligature-set-ligatures - '(text-mode prog-mode org-mode) - '("<--" "<---" "<-" "->" "-->" "--->" - "<==" "<===" "<=" "=>" "==>" "===>" - "<->" "<-->" "<--->" "<---->" - "<=>" "<==>" "<===>" "<====>" - "==" "!=" "===" "!==" "!===" - "<|" "<|>" "|>" "<>" "" "/>" - "/*" "*/" "+++" "<~~" "~~>" "")) - (global-ligature-mode +1)) - -(use-package whitespace - :custom - (whitespace-style '(face - empty - trailing - tab-mark - indentation::space)) - (whitespace-action '(report-on-bogus - cleanup - auto-cleanup))) - -(setq mode-line-compact 'long) - -(line-number-mode -1) -(column-number-mode -1) -(size-indication-mode +1) - -;; (require 'battery) -;; (when (and battery-status-function -;; (not ( string-match-p "unknown" -;; ( battery-format "%B" -;; (funcall battery-status-function))))) -;; (display-battery-mode +1)) - -(use-package time - :custom - (display-time-24hr-format t)) - -(use-package diff-hl - :if (package-installed-p 'diff-hl) - :functions (diff-hl-magit-pre-refresh - diff-hl-magit-post-refresh - global-diff-hl-mode) - :init - (add-hook 'magit-pre-refresh-hook #'diff-hl-magit-pre-refresh) - (add-hook 'magit-post-refresh-hook #'diff-hl-magit-post-refresh) - :custom - (diff-hl-disable-on-remote nil) - (diff-hl-draw-borders t) - :config - (global-diff-hl-mode)) - -(setq split-height-threshold nil - split-width-threshold 160) - -(use-package winner - :demand - :config - (winner-mode)) - -(use-package ediff - :bind (("C-c d f" . ediff-files) - ("C-c d b" . ediff-buffers) - ("C-c d 3 f" . ediff-files3) - ("C-c d 3 b" . ediff-buffers3)) - :custom - (ediff-window-setup-function #'ediff-setup-windows-plain)) - -(use-package emms - :defines (emms-browser-mode-map - emms-playlist-mode-map) - :functions (emms-all - emms-default-players - emms-mpris-enable - emms-cache-enable - emms-show) - :bind (("C-c e e" . emms-smart-browse) - ("C-c e p" . emms-pause) - ("C-c e s" . emms-stop) - ("C-c e z" . emms-toggle-repeat-track) - ("C-c e C-r" . emms-toggle-repeat-playlist) - ("C-c e C-b" . emms-browser) - ("C-c e C-p" . emms-playlist-mode-go) - ("" . emms-pause) - ("" . emms-previous) - ("" . emms-next) - :map emms-browser-mode-map - ("e" . emms-smart-browse) - ("P" . emms-pause) - ("S" . emms-stop) - ("z" . emms-toggle-repeat-track) - :map emms-playlist-mode-map - ("e" . emms-smart-browse)) - :custom - (emms-source-file-default-directory "~/Music/") - (emms-lyrics-dir (expand-file-name "lyrics" "~/Music/")) - (emms-browser-covers #'emms-browser-cache-thumbnail-async) - (emms-browser-default-covers (list (expand-file-name "placeholder.jpg" "~/Music/"))) - (emms-repeat-playlist t) - :config - (emms-all) - (emms-default-players) - (emms-mpris-enable) - (emms-cache-enable) - (add-hook 'emms-player-started-hook #'emms-show)) - -(use-package org - :demand - :defines org-mode-map - :hook ((org-mode . turn-on-auto-fill)) - :bind ( :map org-mode-map - (" " . consult-org-heading) - (" " . consult-org-heading)) - :custom - (org-directory "~/Documents/org") - (org-default-notes-file (expand-file-name "notes.org" org-directory)) - (org-archive-location "::* Archived Tasks") - (org-hide-emphasis-markers t) - (org-use-sub-superscripts '{}) - (org-pretty-entities t) - (org-pretty-entities-include-sub-superscripts t) - (org-fontify-done-headline t) - (org-fontify-todo-headline t) - (org-fontify-emphasized-text t) - (org-fontify-quote-and-verse-blocks t) - (org-tags-column 0) - (org-enforce-todo-dependencies t) - (org-enforce-todo-checkbox-dependencies t) - (org-yank-folded-subtrees nil) - (org-yank-adjusted-subtrees t) - (org-display-remote-inline-images 'cache) - (org-M-RET-may-split-line '((default . nil) - (headline . nil) - (item . nil) - (table . t)))) - -(use-package ox - :after org - :custom - (org-export-with-sub-superscripts org-use-sub-superscripts)) - -(use-package org-faces - :after org - :config - ;; Ensure tables and src blocks use fixed-pitch font. - (set-face-attribute 'org-block nil :inherit 'fixed-pitch) - (set-face-attribute 'org-code nil :inherit 'fixed-pitch) - (set-face-attribute 'org-table nil :inherit 'fixed-pitch) - (set-face-attribute 'org-verbatim nil :inherit 'org-code) - ;; Let quote and verse blocks use variable-pitch font, if configured - (set-face-attribute 'org-quote nil :inherit 'variable-pitch) - (set-face-attribute 'org-verse nil :inherit 'variable-pitch)) - -(use-package org-keys - :after org - :custom - (org-return-follows-link t) - (org-mouse-1-follows-link t)) - -(use-package org-indent - :after org - :hook org-mode) - -(use-package org-attach - :after org - :custom - (org-attach-id-dir (expand-file-name "data/" org-directory)) - (org-attach-dir-relative t) - (org-attach-use-inheritance nil)) - -(use-package org-refile - :after (org org-agenda) - :custom - (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))))) - -(use-package org-src - :after org - :custom - (org-src-window-setup 'reorganize-frame)) - -(use-package ob-core - :after org - :custom - (org-babel-no-eval-on-ctrl-c-ctrl-c t) - (org-confirm-babel-evaluate nil) - :config - (let (babel-languages) - (push '(lua . t) babel-languages) - (push '(python . t) babel-languages) - (push '(emacs-lisp . t) babel-languages) - (org-babel-do-load-languages 'org-babel-load-languages babel-languages))) - -(use-package ob-python - :after ob-core - :custom - (org-babel-python-command "python3")) - -(use-package org-capture - :after org - :bind ("C-c o n" . org-capture) - :custom (org-capture-templates - '(("t" "TODO" entry - (file+olp "tasks.org.gpg" "Inbox") - "* TODO %?\nDEADLINE: %t\n %i\n %a") - ("#" "used by gnus-icalendar-org" entry - (file+olp "calendar/email.org.gpg" "Inbox") - "%i" :immediate-finish t)))) - -(if (executable-find "sqlite3") - (use-package org-roam - :if (package-installed-p 'org-roam) - :after org - :defines org-roam-directory - :functions org-roam-db-autosync-mode - :bind (("C-c o r i" . org-roam-node-insert) - ("C-c o r f" . org-roam-node-find) - ("C-c o r n" . org-roam-capture) - ("C-c o r j" . org-roam-dailies-capture-today) - ("M-g j" . org-roam-dailies-goto-today) - ("M-g C-j" . org-roam-dailies-goto-date) - :map org-mode-map - ("C-c o r b" . org-roam-buffer-toggle)) - :custom - (org-roam-directory (expand-file-name "roam" org-directory)) - (org-roam-completion-everywhere nil) - (org-roam-node-display-template (concat - "${title:*} " - (propertize "${tags:24}" 'face 'org-tag))) - (org-roam-capture-templates '(("d" "default" plain "%?" - :target (file+head "${slug}.org" "#+title: ${title}\n") - :unnarrowed t))) - :config - (mkdir org-roam-directory t) - (add-to-list 'display-buffer-alist - '("\\*org-roam\\*" - (display-buffer-in-side-window) - (side . right) - (slot . 0) - (window-width . 0.33) - (window-parameters . ((no-delete-other-windows . t))))) - (org-roam-db-autosync-mode +1))) - -(use-package org-roam-dailies - :after org-roam - :custom - (org-roam-dailies-directory "./") - (org-roam-dailies-capture-templates - '(("d" "default" entry - "* %?" - :target (file+datetree "journal.org.gpg" week))))) - -(use-package org-clock - :after org - :custom - (org-clock-rounding-minutes 15)) - -(use-package org-agenda - :after (org appt) - :bind (("C-c o a" . org-agenda) - ("C-c o C-a" . org-agenda-list)) - :hook (org-agenda-finalize . org-agenda-to-appt) - :custom - (org-agenda-span 'day) - (org-agenda-start-on-weekday 1) - (org-agenda-sticky nil) - (org-agenda-window-setup 'current-window) - (org-agenda-tags-column 0) - (org-agenda-diary-file (expand-file-name "calendar/diary.org.gpg" org-directory)) - (org-agenda-include-diary nil) - (org-agenda-include-deadlines t) - (org-agenda-todo-ignore-scheduled 'future) - (org-agenda-todo-ignore-deadlines 'far) - (org-agenda-clockreport-parameter-plist '(:link t :maxlevel 6 :emphasize t :stepskip0 t :fileskip0 t :filetitle t :properties ("WON"))) - (org-agenda-start-with-clockreport-mode t) - (org-agenda-start-with-log-mode t) - (org-agenda-prefix-format '((agenda . " %-12:c%?-12t% s") - (todo . " %-12:c") - (tags . " %-12:c") - (search . " %-12:c"))) - (org-agenda-file-regexp "\\`[^.].*\\.org\\\(\\.gpg\\\)?\\'") - (org-agenda-files (list - (expand-file-name org-directory) - (expand-file-name "calendar" org-directory) - (expand-file-name "roam/journal.org.gpg" org-directory) - (expand-file-name "roam/analysis_notes.org" org-directory))) - :config - (appt-activate +1)) - -(use-package ox-icalendar - :after org - :custom - (org-icalendar-store-UID t) - (org-icalendar-alarm-time 15) - (org-icalendar-include-body t) - (org-icalendar-include-sexps t) - (org-icalendar-include-todo t) - (org-icalendar-combined-name "org-mode") - (org-icalendar-combined-description "Emacs org-mode combined export")) - -(use-package org-noter - :after (org doc-view citar) - :commands org-noter - :custom - (org-noter-always-create-frame nil) - (org-noter-kill-frame-at-session-end nil) - (org-noter-auto-save-last-location t) - (org-noter-default-notes-file-names '("noter.org")) - (org-noter-doc-property-in-notes t) - (org-noter-notes-search-path - (list (expand-file-name "notes" org-directory) - (car citar-notes-paths))) - (org-noter-prefer-root-as-file-level nil)) - -(use-package citar - :defines (citar-bibliography - citar-indicators) - :functions (citar-indicator-create - citar-has-files - citar-has-links - citar-has-notes - citar-is-cited) - :hook - (LaTeX-mode . citar-capf-setup) - (org-mode . citar-capf-setup) - :custom - (citar-bibliography - (list - (expand-file-name "citar/main.bib" org-directory))) - (citar-notes-paths - (list - (expand-file-name "citar/notes/" org-directory))) - (citar-library-paths - (list - (expand-file-name "~/Documents/library/"))) - :config - (require 'org) - (require 'nerd-icons) - (setopt org-cite-insert-processor 'citar - org-cite-follow-processor 'citar - org-cite-activate-processor 'citar) - (dolist (bibfile citar-bibliography) - (add-to-list 'org-cite-global-bibliography bibfile)) - (defvar citar-indicator-files-icons - (citar-indicator-create - :symbol (nerd-icons-octicon - "nf-oct-file" - :face 'nerd-icons-green - :v-adjust -0.1) - :function #'citar-has-files - :padding " " ; need this because the default padding is too low for these icons - :tag "has:files")) - (defvar citar-indicator-links-icons - (citar-indicator-create - :symbol (nerd-icons-octicon - "nf-oct-link" - :face 'nerd-icons-orange - :v-adjust 0.01) - :function #'citar-has-links - :padding " " ; need this because the default padding is too low for these icons - :tag "has:links")) - (defvar citar-indicator-notes-icons - (citar-indicator-create - :symbol (nerd-icons-octicon - "nf-oct-note" - :face 'nerd-icons-blue - :v-adjust -0.3) - :function #'citar-has-notes - :padding " " ; need this because the default padding is too low for these icons - :tag "has:notes")) - (defvar citar-indicator-cited-icons - (citar-indicator-create - :symbol (nerd-icons-octicon - "nf-oct-circle" - :face 'nerd-icon-green) - :function #'citar-is-cited - :padding " " ; need this because the default padding is too low for these icons - :tag "is:cited")) - (setq citar-indicators (list citar-indicator-files-icons - citar-indicator-links-icons - citar-indicator-notes-icons - citar-indicator-cited-icons))) - -(setq org-latex-compiler "lualatex") -(setq org-preview-latex-default-process 'dvisvgm) - -(use-package vertico - :if (package-installed-p 'vertico) - :functions vertico-mode - :hook (after-init . (lambda () (vertico-mode +1))) - :custom - (vertico-cycle t) - :config - (require 'vertico-directory)) - -(use-package marginalia - :if (package-installed-p 'marginalia) - :functions marginalia-mode - :hook (after-init . (lambda () (marginalia-mode +1))) - :custom - (marginalia-annotators '(marginalia-annotators-heavy - marginalia-annotators-light - nil)) - :config (marginalia-mode +1)) - -(use-package orderless - :if (package-installed-p 'orderless) - :custom - (completion-styles '(orderless basic)) - (completion-category-defaults nil) - (completion-category-overrides '((file (styles basic partial-completion)) - (eglot (styles orderless)) - (eglot-capf (styles orderless))))) - -(use-package nerd-icons-corfu - :functions nerd-icons-corfu-formatter - :requires nerd-icons) - -(use-package corfu - :if (package-installed-p 'corfu) - :defines (corfu-map - corfu-mode-map - corfu-margin-formatters) - :functions (corfu-mode - global-corfu-mode - corfu-history-mode) - :hook ((after-init . (lambda () (global-corfu-mode +1))) - (minibuffer-setup . (lambda () - "Enable `corfu-mode' for `M-:' and `M-!'." - (when (local-variable-p 'completion-at-point-functions) - (corfu-mode +1))))) - :bind ( :map corfu-map - ("M-SPC" . corfu-insert-separator) - ("RET" . nil) - ("TAB" . corfu-insert) - ([tab] . corfu-insert)) - :custom - (corfu-cycle t) - (corfu-auto nil) - (corfu-preselect 'directory) - :config - (require 'corfu-history) - (when (require 'nerd-icons-corfu nil :noerror) - (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) - (when (require 'corfu-popupinfo nil :noerror) - (corfu-popupinfo-mode +1)) - (when (and (require 'corfu-terminal nil :noerror) - (not (display-graphic-p))) - (corfu-terminal-mode +1))) - -(use-package corfu-history - :requires (corfu savehist) - :functions corfu-history - :config - (add-to-list 'savehist-additional-variables #'corfu-history)) - -(use-package corfu-popupinfo - :requires corfu - :defines corfu-popupinfo-map - :functions corfu-popupinfo-mode - :bind ( :map corfu-popupinfo-map - ("M-d" . corfu-popupinfo-toggle) - ("M-n" . corfu-popupinfo-scroll-up) - ("M-p" . corfu-popupinfo-scroll-down)) - :custom - (corfu-popupinfo-delay 0.3)) - -(use-package corfu-terminal - :requires corfu - :functions corfu-terminal-mode) - -(use-package cape - :if (package-installed-p 'cape) - :after corfu - :functions (cape-emoji - cape-file - cape-dabbrev) - :hook ((conf-mode prog-mode text-mode) . (lambda () - (dolist (cape-fn '(cape-dabbrev - cape-file - cape-emoji)) - (add-hook 'completion-at-point-functions cape-fn nil t)))) - :custom - (cape-dabbrev-min-length (+ corfu-auto-prefix 1))) - -(use-package consult - :if (package-installed-p 'consult) - :functions (consult-org-heading - consult-history) - :bind ((" " . consult-imenu) - (" " . consult-buffer) - (" " . consult-project-buffer) - ("C-c s l" . consult-line) - ("C-c s o" . consult-outline) - ("C-c s f" . consult-fd) - ("C-c s g" . consult-ripgrep) - ("C-c s e" . consult-flymake) - ("C-c s i" . consult-info) - :map minibuffer-local-map - (" " . consult-history) - :map comint-mode-map - (" " . consult-history))) - -(use-package consult-eglot - :after (consult eglot) - :bind (("C-c s s" . consult-eglot-symbols))) - -(use-package tempel - :if (package-installed-p 'tempel) - :defines tempel-path - :functions (tempel-expand - tempel-abbrev-mode) - :bind (("M-+" . tempel-complete) - ("M-*" . tempel-insert)) - :hook ((conf-mode prog-mode text-mode) . (lambda () (add-hook 'completion-at-point-functions 'tempel-complete nil t))) - :custom - (tempel-trigger-prefix "+")) - -(require 'tramp) -(setq org-publish-project-alist - `(("xenia.me.uk" - :base-directory ,(expand-file-name "www/xenia.me.uk" "~/Projects/") - :base-extension "org" - :exclude "setup.org" - :recursive t - :publishing-function org-html-publish-to-html - :publishing-directory "/sshx:pixelifytica@legion:/var/www/xenia.me.uk" - :auto-sitemap t - :sitemap-title "Sitemap" - :section-numbers nil - :with-author t - :with-email t - :with-toc nil - :html-link-home "/" - :html-link-up "../" - ;; :html-head "" - ))) - -(use-package rainbow-delimiters - :if (package-installed-p 'rainbow-delimiters) - :hook (prog-mode)) - -(use-package envrc - :if (package-installed-p 'envrc) - :hook (after-init . envrc-global-mode) - :custom - (envrc-show-summary-in-minibuffer t)) - -(use-package gud - :defer t - :defines gdb-many-windows - :config - (setq gdb-many-windows t)) - -(use-package treesit - :custom - (treesit-font-lock-level 3)) - -(use-package treesit-auto - :if (package-installed-p 'treesit-auto) - :requires treesit - :functions (treesit-auto-add-to-auto-mode-alist - global-treesit-auto-mode) - :hook (after-init . (lambda () (global-treesit-auto-mode +1))) - :config - (treesit-auto-add-to-auto-mode-alist)) - -(use-package eldoc - :custom - (eldoc-echo-area-display-truncation-message nil) - (eldoc-echo-area-prefer-doc-buffer 'maybe) - (eldoc-echo-area-use-multiline-p 3)) - -(use-package eglot - :bind ( :map prog-mode-map - ("C-c c a" . eglot-code-actions) - ("C-c c r" . eglot-rename)) - :hook ((eglot-managed-mode . (lambda () (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t))) - (nix-mode . (lambda () (if (and (project-current nil) (executable-find "nixd" t)) - (eglot-ensure)))) - (python-base-mode . (lambda () (if (and (project-current nil) (executable-find "pylsp" t)) - (eglot-ensure)))) - (lua-mode . (lambda () (if (and (project-current nil) (executable-find "lua-language-server" t)) - (eglot-ensure)))) - ((rust-ts-mode rust-mode) . (lambda () (if (and (project-current nil) (executable-find "rust-analyzer" t)) - (eglot-ensure)))) - ((js-base-mode typescript-ts-base-mode) . (lambda () (if (and (project-current nil) (executable-find "typescript-language-server" t)) - (eglot-ensure)))) - ) - :custom - (eglot-menu-string "lsp") - (eglot-send-changes-idle-time 1) - (eglot-extend-to-xref t) - (eglot-autoshutdown t) - (eglot-sync-connect nil) - (eglot-autoreconnect (* 60 5)) - (eglot-events-buffer-config '(:size 0)) - (eglot-ignored-server-capabilities - '(:documentHighlightProvider - :documentFormattingProvider - :documentRangeFormattingProvider - :documentOnTypeFormattingProvider - :documentLinkProvider - :colorProvider - :foldingRangeProvider)) - :init - (setq eglot-stay-out-of '(flymake)) - :config - (setq-default eglot-workspace-configuration - '( :nil ( :nix - ( :maxMemoryMB nil - :flake - ( :autoArchive t - :nixpkgsInputName "nixpkgs"))) - :pylsp ( :plugins - ( :autopep8 (:enabled nil) - :flake8 (:enabled nil) - :jedi_completion ( :enabled t - :include_params t - :include_class_objects t - :include_function_objects t - :fuzzy t) - :jedi_definition (:enabled t) - :jedi_hover (:enabled t) - :mccabe (:enabled nil) - :preload (:enabled nil) - :pycodestyle (:enabled nil) - :pydocstyle (:enabled nil) - :pyflakes (:enabled nil) - :pylint (:enabled nil) - :rope_autoimport ( :completions (:enabled t) - :code_actions (:enabled t)) - :rope_completion (:enabled t) - :yapf (:enabled nil))))) - ) - -(use-package apheleia - :if (package-installed-p 'apheleia) - :defines (apheleia-formatters - apheleia-mode-alist) - :bind (("C-c c f" . apheleia-format-buffer)) - :hook (prog-mode) - :custom (apheleia-remote-algorithm 'cancel) - :config - (add-to-list 'apheleia-mode-alist '(python-ts-mode . (ruff ruff-isort))) - (add-to-list 'apheleia-mode-alist '(python-mode . (ruff ruff-isort)))) - -(use-package flymake - :bind (("C-c C-." . flymake-goto-next-error) - ("C-c C-," . flymake-goto-prev-error)) - :hook ((prog-mode yaml-ts-mode) . (lambda () (flymake-mode +1))) - :custom - (flymake-no-changes-timeout 1) - (flymake-show-diagnostics-at-end-of-line 'short)) - -(use-package flymake-shellcheck - :if (package-installed-p 'flymake-shellcheck) - :functions flymake-shellcheck-load - :requires flymake - :hook (sh-mode . (lambda () (if (executable-find "shellcheck" t) - (flymake-shellcheck-load))))) - -(use-package flymake-yamllint - :if (package-installed-p 'flymake-yamllint) - :functions flymake-yamllint-setup - :requires flymake - :hook (yaml-ts-mode . (lambda () (if (executable-find "yamllint" t) - (flymake-yamllint-setup))))) - -(use-package flymake-clippy - :if (package-installed-p 'flymake-clippy) - :functions flymake-clippy-setup-backend - :requires flymake - :hook (rust-mode . (lambda () (if (executable-find "clippy" t) - (flymake-clippy-setup-backend))))) - -(use-package flymake-eslint - :if (package-installed-p 'flymake-eslint) - :functions flymake-eslint-enable - :requires flymake - :hook ((js-base-mode typescript-ts-base-mode) . (lambda () (if (executable-find "eslint" t) - (flymake-eslint-enable))))) - -(use-package project - :functions (project-forget-zombie-projects - project-remember-projects-under) - :custom - (project-switch-use-entire-map t) - (project-switch-commands '((project-find-file "Find file") - (project-find-regexp "Find regexp") - (project-find-dir "Find directory") - (project-eshell "Eshell") - (magit-project-status "Magit"))) - :config - (defun my/project-find-common-projects () - "Search and remember common project directories. - -Calls `project-remember-projects-under' for ~/Projects/" - (interactive) - (require 'project) - (project-forget-zombie-projects) - (project-remember-projects-under user-emacs-directory nil) - (project-remember-projects-under "/etc/nixos/" nil) - (project-remember-projects-under "~/Projects" t) - )) - -(use-package magit - :bind (("C-c g g" . magit-status) - ("C-c g d" . magit-dispatch) - ("C-c g f" . magit-file-dispatch) - ("C-c g b" . magit-blame-addition) - (" " . magit-project-status) - :map project-prefix-map - ("m" . magit-project-status)) - :custom - (magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1) - (magit-define-global-key-bindings nil) - (magit-show-long-lines-warning nil) - (magit-clone-default-directory "~/Projects/") - (magit-clone-set-remote.pushDefault t) - (magit-commit-show-diff t) - (magit-commit-diff-inhibit-same-window t) - (magit-diff-adjust-tab-width t) - (magit-diff-refine-hunk 'all) - (magit-diff-refine-ignore-whitespace t) - (magit-clone-name-alist '(("\\`\\(?:github:\\|gh:\\)?\\([^:]+\\)\\'" "github.com" "github.user") - ("\\`\\(?:gitlab:\\|gl:\\)\\([^:]+\\)\\'" "gitlab.com" "gitlab.user") - ("\\`\\(?:sourcehut:\\|sh:\\)\\([^:]+\\)\\'" "git.sr.ht" "sourcehut.user") - ("\\`\\(?:gitea:\\|gt:\\)\\([^:]+\\)\\'" "git.xenia.me.uk" "gitea.user")))) - -(use-package nix-mode - :if (package-installed-p 'nix-mode) - :mode "\\.nix\\'" - :functions nix-prettify-global-mode - :config - (require 'nix) - (require 'nix-flake) - (require 'nix-repl) - (require 'nix-store) - (nix-prettify-global-mode +1)) - -(defun my/enable-fill-column (col) - "Set and enable fill column to `COL'." - (set-fill-column col) - (display-fill-column-indicator-mode +1)) - -(use-package python - :hook ((python-base-mode . (lambda () (my/enable-fill-column 88))) - (python-base-mode . (lambda () (setq-local - python-check-command (cond - ((executable-find "mypy" t) "mypy --check-untyped-defs --warn-unreachable --show-error-codes --ignore-missing-imports") - (t "pyflakes")) - python-flymake-command (cond - ((executable-find "ruff" t) '("ruff" "check" "--output-format=concise" "--stdin-filename=stdin" "-")) - ((executable-find "flake8" t) '("flake8" "--max-line-length" "88" "-")) - (t '("pyflakes"))))))) - :custom - (python-shell-interpreter "python3") - (python-shell-dedicated nil) - (python-shell-completion-native-enable nil) - (python-indent-def-block-scale 1) - :config - (setq python-ts-mode-hook python-mode-hook)) - -(use-package python-docstring - :if (package-installed-p 'python-docstring) - :hook python-base-mode) - -(use-package files - :custom - (view-read-only t) - (enable-remote-dir-locals t)) - -(use-package tramp - :defer t - :custom - (tramp-default-method "scpx") - (tramp-backup-directory-alist backup-directory-alist) - (tramp-auto-save-directory (cdr (assoc "." tramp-backup-directory-alist))) - :config - (add-to-list 'tramp-remote-path 'tramp-own-remote-path) - (add-to-list 'tramp-remote-path "~/.local/bin/")) - -(connection-local-set-profile-variables - 'remote-no-corfu-auto - '((corfu-auto . nil))) - -(connection-local-set-profiles - '(:application tramp) - 'remote-no-corfu-auto) - -(use-package doc-view - :defer t - :bind ( :map doc-view-mode-map - ("" . doc-view-previous-page) - ("" . doc-view-next-page)) - :custom - (doc-view-resolution 200) - (doc-view-imenu-enabled t) - (doc-view-scale-internally t) - (doc-view-image-width 850)) - -(use-package markdown-mode - :if (package-installed-p 'markdown-mode) - :hook - ((markdown-mode . turn-on-auto-fill)) - :custom - (markdown-enable-math t) - (markdown-enable-html t) - :config - (set-face-attribute 'markdown-code-face nil :inherit 'fixed-pitch) - (set-face-attribute 'markdown-inline-code-face nil :inherit 'fixed-pitch) - (set-face-attribute 'markdown-table-face nil :inherit 'fixed-pitch) - (set-face-attribute 'markdown-blockquote-face nil :inherit 'variable-pitch) - (set-face-attribute 'markdown-comment-face nil :inherit 'variable-pitch)) - -(use-package pandoc-mode - :if (package-installed-p 'pandoc-mode) - :after (markdown-mode) - :hook (markdown-mode . conditionally-turn-on-pandoc)) - -(if (package-installed-p 'mu4e) - (load-file (locate-user-emacs-file "modules/my-mu4e.el"))) - -(use-package bbdb - :bind (("M-g b" . bbdb-display-all-records)) - :custom - (bbdb-file (locate-user-emacs-file "bbdb.gpg"))) - -(use-package erc - :commands erc-compute-nick - :custom - (erc-nick (user-login-name)) - (erc-user-full-name (user-full-name))) - -(defun my/libera-chat-connect () - "Connect to irc.libera.chat directly." - (interactive) - (require 'erc) - (require 'password-store) - (erc-tls - :server "irc.libera.chat" - :password (password-store-get 'social/irc.libera.chat))) -(defun my/znc-connect () - "Connect to my ZNC IRC bouncer." - (interactive) - (require 'erc) - (require 'password-store) - (erc-tls - :server "xenia.me.uk" - :port 6697 - :nick (concat (erc-compute-nick) "/liberachat") - :password (password-store-get 'local/znc))) - -(use-package eww - :defer t - :custom - (browse-url-browser-function 'browse-url-default-browser) - (browse-url-secondary-browser-function 'browse-url-default-browser) - (browse-url-new-window-flag t) - (eww-default-download-directory "~/Downloads/") - (eww-auto-rename-buffer 'title) - (eww-browse-url-new-window-is-tab nil)) - -(use-package password-store - :defer t - :functions password-store-get) - -;; Scratch buffer shortcut -(keymap-global-set "C-c w x" #'scratch-buffer) - -;; Config file shortcut -(defun my/open-init-file () - "Open Emacs init file." - (interactive) - (find-file (locate-user-emacs-file "init.el"))) -(keymap-global-set "C-c w e" #'my/open-init-file) - -;; Tempel template file shortcut -(defun my/open-template-file () - "Open `tempel' template file." - (interactive) - (require 'tempel) - (find-file tempel-path)) -(keymap-global-set "C-c w t" #'my/open-template-file) - -;; Org directory shortcut -(defun my/open-org-directory () - "Open base `org-mode' directory in Dired." - (interactive) - (require 'org) - (find-file org-directory)) -(keymap-global-set "C-c w o" #'my/open-org-directory) - -(defun my/open-global-bibliography () - "Open `org-cite-global-bibliography'." - (interactive) - (require 'citar) - (find-file (car org-cite-global-bibliography))) -(keymap-global-set "C-c w b" #'my/open-global-bibliography) - -;; Elfeed feeds directory shortcut -(defun my/open-feeds-file () - "Open elfeed org source file." - (interactive) - (require 'elfeed) - (require 'elfeed-org) - (find-file (car rmh-elfeed-org-files))) -(keymap-global-set "C-c w f" #'my/open-feeds-file) - -(defun my/open-documents-directory () - "Open Documents directory." - (interactive) - (find-file "~/Documents/")) -(defun my/open-downloads-directory () - "Open Downloads directory." - (interactive) - (find-file "~/Downloads/")) -(keymap-global-set "C-c w d" #'my/open-documents-directory) -(keymap-global-set "C-c w C-d" #'my/open-downloads-directory) +(when (require 'org nil :noerror) + (org-babel-load-file (locate-user-emacs-file "README.org"))) (provide 'init) ;;; init.el ends here