* Systems and custom functions #+BEGIN_SRC emacs-lisp (if (string-equal system-type "android") (setq fileroot "/storage/emulated/0/Documents/") (setq fileroot "~/Documents/drive/")) #+END_SRC Firstly, tell Emacs where to look for custom functions (via [[https://www.emacswiki.org/emacs/LoadingLispFiles][EmacsWiki]]). #+BEGIN_SRC emacs-lisp (defun load-directory (dir) "Add all files in a directory to load-path" (let ((load-it (lambda (f) (load-file (concat (file-name-as-directory dir) f))))) (mapc load-it (directory-files dir nil "\\.el$")))) (load-directory "~/.emacs.d/custom/") (load-directory (concat (file-name-as-directory fileroot) "admin/emacs/custom/")) #+END_SRC * =$whoami=, a big neckbeard, that’s who Set name and location based on who I’m being right now. #+BEGIN_SRC emacs-lisp (if (string-equal user-login-name "3055822") (load-file (concat (file-name-as-directory fileroot) "admin/emacs/identity-work.el")) (if workhours (load-file (concat (file-name-as-directory fileroot) "admin/emacs/identity-work.el")) (load-file (concat (file-name-as-directory fileroot) "admin/emacs/identity-home.el")))) #+END_SRC * Sonic arts Stop Emacs making sounds. I don’t think it ever made sounds before, but everyone is very insistent about the need to stop Emacs making sounds. #+BEGIN_SRC emacs-lisp (setq ring-bell-function 'ignore) (setq visible-bell t) #+END_SRC Also suppress certain warnings that would otherwise come up all the time and contribute very little to the experience. #+BEGIN_SRC emacs-lisp (setq ad-redefinition-action 'accept) (setq python-indent-guess-indent-offset-verbose nil) (setq byte-compile-warnings '(cl-functions)) #+END_SRC * Miscellaneous changes to make to the basic config I don’t want finding files to be case-sensitive, same as in =zsh=: #+BEGIN_SRC emacs-lisp (setq completion-ignore-case t) (setq read-file-name-completion-ignore-case t) (setq read-buffer-completion-ignore-case t) #+END_SRC Make the +window+ /frame/ look nice and clean. Scroll bars behave pointlessly on Windows anyway. Not hiding the menu bar because I’m not quite that leet yet. One day … #+BEGIN_SRC emacs-lisp (setq inhibit-startup-screen t) (tool-bar-mode -1) (unless (string-equal system-type "android") (scroll-bar-mode -1)) (tooltip-mode -1) #+END_SRC Make everything just a little tiny bit transparent unless I’m using the boring Windows desktop. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (unless (string-equal user-login-name "3055822") (set-frame-parameter (selected-frame) 'alpha 95) (add-to-list 'default-frame-alist '(alpha . 95)))) #+END_SRC Stop creating all those =~= files everywhere. Put them somewhere that I can ignore them. #+BEGIN_SRC emacs-lisp (setq backup-directory-alist '(("." . "~/.emacs.d/backups"))) #+END_SRC This gives buffers sensible names. #+BEGIN_SRC emacs-lisp (require 'uniquify) (setq uniquify-buffer-name-style 'forward) #+END_SRC Give me an excuse to use regex more often (from [[https://git.sr.ht/~technomancy/better-defaults][Better Defaults]]). #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-s") 'isearch-forward-regexp) (global-set-key (kbd "C-r") 'isearch-backward-regexp) (global-set-key (kbd "C-M-s") 'isearch-forward) (global-set-key (kbd "C-M-r") 'isearch-backward) #+END_SRC Go back to the same place in a file. #+BEGIN_SRC emacs-lisp (save-place-mode 1) #+END_SRC Turn on automatic bracket/quotation mark matching. #+BEGIN_SRC emacs-lisp (electric-pair-mode 1) #+END_SRC Stop =init.el= getting forcibly appended with package information. #+BEGIN_SRC emacs-lisp (defun package--save-selected-packages (&rest opt) nil) #+END_SRC SOMETIMES I WANT TO UPCASE OR DOWNCASE AN ENTIRE REGION, WHAT OF IT. #+BEGIN_SRC emacs-lisp (put 'upcase-region 'disabled nil) (put 'downcase-region 'disabled nil) #+END_SRC And to narrow to them. #+BEGIN_SRC emacs-lisp (put 'narrow-to-region 'disabled nil) #+END_SRC It’s +2022+ 2023. #+BEGIN_SRC emacs-lisp (setq python-shell-interpreter "python3") #+END_SRC Make new directories automatically (from [[https://emacsredux.com/blog/2022/06/12/auto-create-missing-directories/][Emacs Redux]]). #+BEGIN_SRC emacs-lisp (defun er-auto-create-missing-dirs () "Make new directories automatically" (let ((target-dir (file-name-directory buffer-file-name))) (unless (file-exists-p target-dir) (make-directory target-dir t)))) (add-to-list 'find-file-not-found-functions #'er-auto-create-missing-dirs) #+END_SRC Indent using spaces. #+BEGIN_SRC emacs-lisp (setq-default indent-tabs-mode nil) #+END_SRC ** OS-specific stuff On Linux, I have to tell Emacs to use +Chrome+ Vivaldi for web links. #+BEGIN_SRC emacs-lisp (when (string-equal system-type "gnu/linux") (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "vivaldi")) #+END_SRC Honestly I don’t know if I’ll ever use macOS again, but in case I do, I need the meta key to work. #+BEGIN_SRC emacs-lisp (when (string-equal system-type "darwin") (setq ns-alternate-modifier 'meta) (setq ns-right-alternate-modifier 'none)) #+END_SRC Windows likes to set the default directory to the folder where the Emacs binary is stored, which it probably thinks is helpful, but is in fact Very Stupid. #+BEGIN_SRC emacs-lisp (when (string-equal system-type "windows-nt") (setq default-directory "~/")) #+END_SRC Android has enormous issues with keybindings, so requiring =yes-or-no-p= where possible helps a bit. #+BEGIN_SRC emacs-lisp (when (string-equal system-type "android") (defalias 'y-or-n-p 'yes-or-no-p)) #+END_SRC * =use-package= Set up package handling, including =use-package=. Some of the =org= tools I use are from Non-GNU ELPA, I think. Most of this is the standard =use-package= setup stuff. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (package-initialize) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/")) (setq package-check-signature nil) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package-ensure) (setq use-package-always-ensure t)) #+END_SRC * Packages, modes, etc. ** =bibtex= I use BibLaTeX for better compatibility with accented characters and generally being more sensible. #+BEGIN_SRC (unless (string-equal system-type "android") (use-package bibtex :mode ("\\.bib" . bibtex-mode) :config (setq bibtex-dialect 'biblatex))) #+END_SRC ** =calibredb= This may work only on Linux (it uses SQL???), but my ebooks are only on Linux so that’s ok. #+BEGIN_SRC emacs-lisp (when (string-equal system-type "gnu/linux") (use-package calibredb :defer t :config (setq calibredb-root-dir "~/Documents/drive/calibre/ebooks") (setq calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir)) (setq calibredb-library-alist '(("~/Documents/drive/calibre/ebooks") ("~/Documents/drive/calibre/ffff") ("~/Documents/drive/calibre/ovely"))) (setq calibredb-sort-by 'author) (setq calibredb-order 'asc))) #+END_SRC ** =deft= Let me search my journal files when I’m not at work, and reading notes otherwise. Set regexp search by default. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package deft :config (setq deft-extensions '("org")) (if (string-equal user-login-name "3055822") (progn (setq deft-directory deft-secret-filepath) (setq deft-use-filename-as-title t)) (setq deft-directory "~/Documents/drive/org/journal")) (setq deft-current-sort-method 'title) (setq deft-incremental-search nil) (setq deft-recursive t))) #+END_SRC ** =dimmer= Dims inactive buffers. Adjustments for =modus-themes= as suggested. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package dimmer :config (setq dimmer-fraction 0.4) (setq dimmer-adjustment-mode :foreground) (setq dimmer-use-colorspace :rgb) (dimmer-mode 1))) #+END_SRC ** =doom-modeline= Much nicer-looking modeline, and still my favourite over newer, trendier options. Last time I tried installing this from MELPA it made Emacs crash; I don’t know if this is fixed yet. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package doom-modeline :init (doom-modeline-mode 1) :config (setq doom-modeline-buffer-file-name-style 'buffer-name) (setq doom-modeline-minor-modes t) (setq doom-modeline-enable-word-count t) (setq doom-modeline-continuous-word-count-modes '(markdown-mode gfm-mode)) (setq doom-modeline-buffer-encoding nil))) #+END_SRC ** =elfeed= Obviously I use an =org= file to manage my feeds. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package elfeed-org :config (elfeed-org) (setq rmh-elfeed-org-files (list "~/Documents/drive/org/feeds.org")))) #+END_SRC Standard =elfeed= settings: #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (defun elfeed-load-db-and-open () "Load and open the elfeed DB" (interactive) (elfeed-db-load) (elfeed) (elfeed-search-update--force) (elfeed-update)) (global-set-key (kbd "C-x w") 'elfeed-load-db-and-open) (defalias 'elfeed-toggle-star (elfeed-expose #'elfeed-search-toggle-all 'star)) (eval-after-load 'elfeed-search '(define-key elfeed-search-mode-map (kbd "m") 'elfeed-toggle-star)) (defun elfeed-save-db-and-bury () "Save and close the elfeed DB" (interactive) (elfeed-db-save) (quit-window)) (use-package elfeed :bind (:map elfeed-search-mode-map ("q" . elfeed-save-db-and-bury)) :custom (elfeed-sort-order 'ascending) (elfeed-db-directory "~/Documents/drive/org/elfeed"))) #+END_SRC I am a huge supporter of big-endian date formats. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (defun elfeed-search-format-date (date) "Set elfeed to display big-endian dates" (format-time-string "%Y-%m-%d %H:%M" (seconds-to-time date)))) #+END_SRC This apparently deletes really old entries from the database. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (add-hook 'elfeed-new-entry-hook (elfeed-make-tagger :before "6 months ago" :remove 'unread))) #+END_SRC Save elfeed state properly when exiting Emacs. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (defun save-if-elfeed () "Save the elfeed DB if elfeed is running" (if (get-buffer "*elfeed-search*") (progn (elfeed-db-save) (message "Elfeed DB saved")))) (add-hook 'kill-emacs-hook 'save-if-elfeed)) #+END_SRC ** =git-gutter= Shows, or at least purports to show, =git diff= in the left margin if the file is being tracked by =git=. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package git-gutter :config (global-git-gutter-mode 1) (set-face-foreground 'git-gutter:added "forest green") (set-face-foreground 'git-gutter:modified "goldenrod") (set-face-foreground 'git-gutter:deleted "brown") (setq git-gutter:added-sign "+" git-gutter:modified-sign "×" git-gutter:deleted-sign "-"))) #+END_SRC ** isearch From [[https://zck.org/improved-emacs-search][here]]: #+BEGIN_SRC emacs-lisp (setq isearch-lazy-count t) (setq lazy-count-prefix-format nil) (setq lazy-count-suffix-format " (%s/%s)") #+END_SRC ** =lastfm= #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (unless (string-equal user-login-name "3055822") (use-package lastfm))) #+END_SRC ** =markdown-mode= I kind of hate markdown but I still have to use it sometimes. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package markdown-mode :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)) :hook (markdown-mode . auto-fill-mode) :config (setq markdown-asymmetric-header t) :custom (markdown-header-scaling t) :custom-face (markdown-header-face ((t (:inherit (default font-lock-function-name-face) :weight bold)))))) #+END_SRC ** =minions= Lists minor modes in a menu. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package minions :config (minions-mode))) #+END_SRC ** =mu4e= I really only use this for DW posts, but I’m constantly surprised by how well it works. This package is the reason I can’t upgrade to =emacs28=, because it doesn’t currently seem to work; also, it uses =cl=, which is deprecated, hence suppressing warnings about it above. #+BEGIN_SRC emacs-lisp (when (string-equal system-type "gnu/linux") (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e") (load-file "~/.emacs.d/mail.el") (require 'mu4e) (setq send-mail-function 'smtpmail-send-it)) #+END_SRC ** =neotree= Show a nice filetree with icons. I use this much less often than I should. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package neotree :init (global-set-key [f8] 'neotree-toggle) :config (setq neo-theme (if (display-graphic-p) 'icons 'arrow)))) #+END_SRC ** =nXML-mode= Attempting to do TEI stuff at work but I can’t link directly to the =.rnc= file here; have to list it in a =schemas.xml= file first, which references the =.rnc= file locally (not sure how we would do an absolute filepath for this). #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (setq rng-schema-locating-files '("schemas.xml" "~/.emacs.d/tei/schemas.xml" "c:/Program Files/Emacs/x86_64/share/emacs/27.1/etc/schema/schemas.xml")) (defun indent-the-file () (interactive) (indent-region (point-min) (point-max))) (add-hook 'nxml-mode-hook (lambda () (local-set-key (kbd "C-c C-i") 'indent-the-file))) (add-hook 'nxml-mode-hook (lambda () (local-set-key (kbd "") 'completion-at-point)))) #+END_SRC Show path of current element (from [[https://emacs.stackexchange.com/questions/28606/how-to-show-xpath-for-current-location-in-an-xml-hierarchy-in-the-modeline][here]]). #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (defun nxml-where () "Display the hierarchy of XML elements the point is on as a path." (interactive) (let ((path nil)) (save-excursion (save-restriction (widen) (while (and (< (point-min) (point)) ;; Doesn't error if point is at beginning of buffer (condition-case nil (progn (nxml-backward-up-element) ; always returns nil t) (error nil))) (setq path (cons (xmltok-start-tag-local-name) path))) (if (called-interactively-p t) (message "/%s" (mapconcat 'identity path "/")) (format "/%s" (mapconcat 'identity path "/"))))))) (defun xml-find-file-hook () (when (derived-mode-p 'nxml-mode) (which-function-mode t) (setq which-func-mode t) (add-hook 'which-func-functions 'nxml-where t t))) (add-hook 'find-file-hook 'xml-find-file-hook t)) #+END_SRC ** =nov= For reading ebooks. Only on Linux because I (supposedly) use it with my calibre library. #+BEGIN_SRC emacs-lisp (when (string-equal system-type "gnu/linux") (use-package nov :init (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))) (defun my-nov-font-setup () "Set the font for nov-mode" (face-remap-add-relative 'variable-pitch :family "Liberation Serif" :height 2.0)) (add-hook 'nov-mode-hook 'my-nov-font-setup)) #+END_SRC ** =org= my love *** Initial settings I want to indent under headings, I don’t want pointless line breaks when text can just wrap sensibly in the window, and I want to be able to ignore asterisks etc. when I skip to the beginning of lines. #+BEGIN_SRC emacs-lisp (add-hook 'org-mode-hook 'org-indent-mode) (add-hook 'org-mode-hook 'visual-line-mode) (setq org-special-ctrl-a/e t) #+END_SRC Display images in =org= buffers. I’ve increased the width to 500px because 300 was quite small. I’m assuming this doesn’t work on mobile, but why? #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (setq org-display-inline-images t) (setq org-redisplay-inline-images t) (setq org-startup-with-inline-images "inlineimages") (setq org-image-actual-width '(500))) #+END_SRC Load the common agenda settings, i.e. those that I use in conky as well. #+BEGIN_SRC emacs-lisp (load-file "~/.emacs.d/agenda-common.el") #+END_SRC Set general TODO keywords. #+BEGIN_SRC emacs-lisp (setq org-todo-keywords '((sequence "TODO" "|" "DONE" "CANCELLED"))) #+END_SRC Track when I complete todos. #+BEGIN_SRC emacs-lisp (setq org-log-done 'time) #+END_SRC *** Export settings This can set certain headlines not to be exported. I haven’t used it yet but it sounds useful. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package org-contrib) (require 'ox-extra) (ox-extras-activate '(ignore-headlines))) #+END_SRC Add a couple of classes for LaTeX export. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (add-to-list 'org-latex-classes '("article-std" "\\documentclass{article} [NO-DEFAULT-PACKAGES] \\input{$HOME/.emacs.d/header.tex} %$\n% latexbib" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))) (add-to-list 'org-latex-classes '("memoir" "\\documentclass[11pt,a5paper,extrafontsizes]{memoir} [NO-DEFAULT-PACKAGES] \\usepackage[namechapters]{optional} \\input{$HOME/.emacs.d/fic-export-files/header.tex} %$" ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}")))) #+END_SRC Settings for export, mostly for DW post previews but also fic?? And work I guess, I do that sometimes. #+BEGIN_SRC emacs-lisp (setq org-export-headline-levels 6) (setq org-html-head-include-default-style nil) (setq org-html-head "") (setq org-footnote-define-inline t) (setq org-export-with-creator nil) (setq org-export-with-toc nil) (setq org-export-time-stamp-file nil) (unless (string-equal system-type "android") (if (string-equal user-login-name "3055822") (progn (setq org-export-with-author nil) (setq org-latex-default-class "article-std")) (if workhours (progn (setq org-export-with-author nil) (setq org-latex-default-class "article-std")) (setq org-latex-default-class "memoir"))) (setq org-latex-compiler "xelatex")) (setq org-html-validation-link nil) (setq org-html-doctype "html5") #+END_SRC Export non-breaking spaces properly; from, believe it or not, [[https://orgmode.org/manual/Advanced-Export-Configuration.html][the Org Manual]]. #+BEGIN_SRC emacs-lisp (defun my-html-filter-nobreaks (text backend info) "Keep non-breaking spaces in HTML org export" (when (org-export-derived-backend-p backend 'html) (replace-regexp-in-string " " " " text))) (if (string-equal system-type "android") (setq org-export-filter-plain-text-functions 'my-html-filter-nobreaks) (add-to-list 'org-export-filter-plain-text-functions 'my-html-filter-nobreaks)) (unless (string-equal system-type "android") (defun my-latex-filter-nobreaks (text backend info) "Keep non-breaking spaces in LaTeX org export" (when (org-export-derived-backend-p backend 'latex) (replace-regexp-in-string " " "~" text))) (add-to-list 'org-export-filter-plain-text-functions 'my-latex-filter-nobreaks)) #+END_SRC *** Packages **** =org-agenda-property= Let properties be inherited by subheadings. I use this a lot for =:LOCATION:= on recurring events. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package org-agenda-property)) #+END_SRC **** =org-journal= Automate a tiny part of something I was previously doing manually. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (if (string-equal user-login-name "3055822") (progn (use-package org-journal :bind ("C-c j" . org-journal-new-entry) :config (setq org-journal-dir "~/Documents/drive/org") (setq org-journal-file-type 'yearly) (setq org-journal-file-format "journal-dump-%Y.org") (setq org-journal-find-file 'find-file) (setq org-journal-date-format "%Y-%m-%d") (setq org-journal-time-format "%H:%M\n"))) (progn (defun org-journal-file-header-func (time) "Set the header for org-journal files" (concat "<" (format-time-string "%Y-%m-%d %a") ">\n\n")) (use-package org-journal :bind ("C-c j" . org-journal-new-entry) :config (setq org-journal-dir "~/Documents/drive/org/journal") (setq org-journal-file-format "%Y/%m/%Y-%m-%d.org") (setq org-journal-find-file 'find-file) (setq org-journal-date-format "journal") (setq org-journal-time-format "%H:%M\n") (setq org-journal-file-header 'org-journal-file-header-func))))) #+END_SRC **** =org-modern= Use =org-modern=. [[https://github.com/minad/org-modern/issues/5#issuecomment-1318003940][Fix for issue with table widths]]. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package org-modern :hook (org-mode . org-modern-mode)) (set-face-attribute 'org-table nil :inherit 'fixed-pitch) (custom-set-variables '(org-modern-table nil))) #+END_SRC **** =org-noter= RIP =interleave=, but this does ok as a replacement. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package org-noter :config (setq org-noter-property-doc-file "INTERLEAVE_PDF" org-noter-property-note-location "INTERLEAVE_PAGE_NOTE"))) #+END_SRC **** =org-sidebar= Display the file outline in a sidebar. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package org-sidebar :bind ("C-c C-x s" . org-sidebar-tree))) #+END_SRC **** =org-wc= Display word counts next to org headings. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package org-wc :bind ("C-c C-x w" . org-wc-display))) #+END_SRC *** Agenda settings Set the keybinding, set the week to start on Monday because I’m not the University of Oxford. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-c a") 'org-agenda) (setq calendar-week-start-day 1) (setq org-agenda-start-on-weekday nil) #+END_SRC Set the files to be included. #+BEGIN_SRC emacs-lisp (if (string-equal system-type "android") (if workhours (setq org-agenda-files '("/storage/emulated/0/Documents/org/calendar/admin.org" "/storage/emulated/0/Documents/org/calendar/music.org" "/storage/emulated/0/Documents/org/calendar/work.org" "/storage/emulated/0/Documents/org/calendar/acwri.org")) (setq org-agenda-files '("/storage/emulated/0/Documents/org/calendar/admin.org" "/storage/emulated/0/Documents/org/calendar/music.org" "/storage/emulated/0/Documents/org/calendar/personal.org" "/storage/emulated/0/Documents/org/calendar/habit.org"))) (progn (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/music.org") (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/admin.org") (if (string-equal user-login-name "3055822") (progn (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/work.org") (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/acwri.org")) (progn (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/home.org") (if workhours (progn (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/work.org") (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/acwri.org")) (progn (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/personal.org") (add-to-list 'org-agenda-files "~/Documents/drive/org/calendar/habit.org"))))))) #+END_SRC Set how the agenda looks. #+BEGIN_SRC emacs-lisp (setq org-agenda-prefix-format '((todo . "%-2c %b") (tags . "%-2c %b") (agenda . "%-2c %?-12t%?-12s"))) (setq org-use-property-inheritance (quote ("LOCATION"))) (setq org-agenda-todo-ignore-scheduled t) (setq org-agenda-todo-ignore-deadlines t) #+END_SRC Add period information to the agenda header (this has a very weird output, completely different when you insert a function from just using text, utterly bizarre). #+BEGIN_SRC emacs-lisp (setq org-agenda-custom-commands '(("a" "Slightly modified agenda view" ((agenda "" ((org-agenda-overriding-header (periodise)))))))) #+END_SRC Use a horizontal line to divide each day from the next. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (setq org-agenda-format-date (lambda (date) (concat "\n" (make-string (window-width) 9472) "\n" (org-agenda-format-date-aligned date))))) #+END_SRC Set up habit display. #+BEGIN_SRC emacs-lisp (add-to-list 'org-modules 'org-habit t) (setq org-habit-show-all-today t) #+END_SRC ** =paren= Highlights matching bracket. #+BEGIN_SRC emacs-lisp (show-paren-mode +1) #+END_SRC ** =pdf-tools= and =doc-view= Use the superior package for viewing PDFs on the superior operating system, and use a less reliable one otherwise. Ghostscript has to be installed on Windows, but it’s indispensable anyway. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (if (string-equal system-type "windows-nt") (use-package doc-view :config (setq doc-view-ghostscript-program "gswin32c")) (use-package pdf-tools :config (pdf-tools-install) (define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward) (add-hook 'pdf-view-mode-hook (lambda () (cua-mode 0))) (setq pdf-view-resize-factor 1.1)))) #+END_SRC ** =recentf= Gives me a dialog with recently opened files. Package management and =elfeed= stuff have to be manually excluded for obvious reasons. Surely I don’t have to call =add-to-list= separately every time, but I haven’t found a more sensible way of doing it. #+BEGIN_SRC emacs-lisp (recentf-mode 1) (setq recentf-max-menu-items 20) (setq recentf-max-saved-items 20) (global-set-key (kbd "C-x C-r") 'recentf-open-files) (add-to-list 'recentf-exclude (expand-file-name "~/.emacs.d/elpa/*")) (add-to-list 'recentf-exclude (expand-file-name "~/.emacs.d/bookmarks")) (add-to-list 'recentf-exclude (expand-file-name "~/Documents/drive/org/elfeed/*")) #+END_SRC ** =tex= As previously described, “the big boy”. I know little about most of these settings, but I think they’re the default ones. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package tex :ensure auctex :mode ("\\.tex\\'" . latex-mode) :init (add-hook 'LaTeX-mode-hook 'turn-on-auto-fill) (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer) :config (setq TeX-auto-save t) (setq TeX-parse-self t) (setq-default TeX-master nil) (setq-default TeX-engine 'xetex) (setq-default TeX-PDF-mode t) (setq TeX-view-program-selection '((output-pdf "PDF Tools")) TeX-source-correlate-start-server t))) #+END_SRC ** =typo= Automatically use smart quotes. (Can’t be set to =text-mode-hook=, unfortunately, as this messes things up in LaTeX; but the only other text-modes I use are =org= and Markdown, I think.) Also, best to /unset/ this mode in source blocks in =org=, [[https://emacs.stackexchange.com/questions/55944/disable-minor-mode-inside-source-blocks][hook taken from here]]. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package typo :custom (typo-global-mode 1) :hook (org-mode . typo-mode) (markdown-mode . typo-mode)) (defun unsmart-hook () "Turn off smart quotes for source blocks within org mode" (add-hook 'typo-disable-electricity-functions 'org-in-src-block-p nil :local)) (add-hook 'org-mode-hook 'unsmart-hook)) #+END_SRC ** =web-mode= This is good for auto indentation, folding, killing elements, apparently XPath?? but I’ve failed to make faces work like they do in normal =html-mode=. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package web-mode :mode (("\\.html?\\'" . web-mode) ("\\.css" . web-mode)) :config (setq web-mode-markup-indent-offset 2) (setq web-mode-css-indent-offset 2) (setq web-mode-enable-html-entities-fontification t) (setq web-mode-enable-current-element-highlight t) :bind ("C-c /" . web-mode-element-close))) #+END_SRC ** =yasnippet= Per-mode text expansion. What a lifechanger. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package yasnippet :config (setq yas-snippet-dirs '("~/.emacs.d/snippets")) (setq yas-triggers-in-field t)) (yas-global-mode 1)) #+END_SRC * Aesthetics ** Packages *** =all-the-icons= Shows nice icons in the modeline and in =neotree=. Fonts need to be installed manually on Windows, possibly because of permissions issues or because of where the Emacs binary lives or maybe both those things. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package all-the-icons :config (unless (string-equal system-type "windows-nt") (when (not (member "all-the-icons" (font-family-list))) (all-the-icons-install-fonts t))))) #+END_SRC *** =emojify= Support for various types of emoge. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package emojify :hook (text-mode . emojify-mode) (org-agenda-mode . emojify-mode))) #+END_SRC *** =hl-line= Highlights current line. #+BEGIN_SRC emacs-lisp (global-hl-line-mode 1) #+END_SRC ** Theme/colours Set a theme from =modus-themes=. This is built in for version 28 and above. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package modus-themes)) (setq modus-themes-bold-constructs t) (setq modus-themes-italic-constructs t) (setq modus-themes-mixed-fonts t) (setq modus-themes-org-blocks 'gray-background) (load-theme 'modus-operandi-tinted t) #+END_SRC ** Fonts Use Noto fonts to match my system fonts on Linux. This has to be done differently on Windows for some reason. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (if (string-equal system-type "windows-nt") (custom-set-faces '(default ((t (:family "Noto Mono" :foundry "outline" :slant normal :weight normal :height 98 :width normal)))) '(italic ((t (:slant italic)))) '(variable-pitch ((t (:family "Noto Sans" :height 90)))) '(fixed-pitch ((t (:family "Noto Mono" :height 90))))) (custom-set-faces '(italic ((t (:slant italic)))) '(variable-pitch ((t (:family "Noto Sans" :height 90)))) '(fixed-pitch ((t (:family "Noto Mono" :height 100)))) '(modus-themes-fixed-pitch ((t (:family "Noto Mono" :height 100))))))) #+END_SRC Use the =mixed-pitch= package to determine the font intelligently in modes that contain both text and prog elements. #+BEGIN_SRC emacs-lisp (unless (string-equal system-type "android") (use-package mixed-pitch :hook (LaTeX-mode . mixed-pitch-mode) (org-mode . mixed-pitch-mode) (markdown-mode . mixed-pitch-mode))) #+END_SRC * Startup Set the =*scratch*= buffer to =org-mode=. #+BEGIN_SRC emacs-lisp (setq initial-major-mode 'org-mode) #+END_SRC Tell me what version of Emacs I’m using so I know if there are packages I can’t use. #+BEGIN_SRC emacs-lisp (setq initial-scratch-message (concat "# emacs " (number-to-string emacs-major-version) " on " (symbol-name system-type) "\n\n")) #+END_SRC Finally, because =org= gets very confused by all these settings, give it a friendly reload. #+BEGIN_SRC emacs-lisp (org-reload) #+END_SRC