* Systems Define functions that specify what OS I’m on, also whether I’m at work or not. Then I can implement specific packages according to need/compatibility. #+BEGIN_SRC emacs-lisp (defun islin () "Return true if on linux" (string-equal system-type "gnu/linux")) (defun iswin () "Return true if on windows" (string-equal system-type "windows-nt")) (defun ismac () ;; unkikely now, but might as well keep this "Return true if on macos" (string-equal system-type "darwin")) (defun atwork () "Return true if at work" (string-equal user-login-name "3055822")) #+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 (atwork) (load-file "~/Documents/drive/admin/emacs/identity-work.el") (load-file "~/Documents/drive/admin/emacs/identity-home.el")) #+END_SRC * It's not 1986 Set everything to UTF-8. I use accented characters regularly. #+BEGIN_SRC emacs-lisp (prefer-coding-system 'utf-8) (set-default-coding-systems 'utf-8) (set-language-environment 'utf-8) (if (iswin) (set-selection-coding-system 'utf-16-le) (set-selection-coding-system 'utf-8)) #+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 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/") #+END_SRC 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) (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 (atwork) (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 It’s 2022. #+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 ** OS-specific stuff On Linux, I have to tell Emacs to use Chrome for web links. #+BEGIN_SRC emacs-lisp (when (islin) (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "google-chrome")) #+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 (ismac) (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 (iswin) (setq default-directory "~/")) #+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 (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 (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 (islin) (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, not synced to my work computer. Set regexp search by default. #+BEGIN_SRC emacs-lisp (unless (atwork) (use-package deft :config (setq deft-extensions '("org")) (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. #+BEGIN_SRC emacs-lisp (use-package dimmer :init (dimmer-mode t) :config (setq dimmer-fraction 0.4)) #+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 (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 (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 (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 (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 (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 (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=. The colours don’t seem to work properly with the current theme. #+BEGIN_SRC emacs-lisp (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 ** =lastfm= This works only for =emacs27= and above, and I don’t want to use it at work, so here’s a nested =unless= in case my Emacs version ever gets updated there. #+BEGIN_SRC emacs-lisp (unless (version< emacs-version "27") (unless (atwork) (use-package lastfm))) #+END_SRC ** =markdown-mode= I kind of hate markdown but I still have to use it sometimes. #+BEGIN_SRC emacs-lisp (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 (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 (islin) (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 (use-package neotree :init (global-set-key [f8] 'neotree-toggle) :config (setq neo-theme (if (display-graphic-p) 'icons 'arrow))) #+END_SRC ** =nov= For reading ebooks. Only on Linux because I (supposedly) use it with my calibre library. #+BEGIN_SRC emacs-lisp (when (islin) (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. #+BEGIN_SRC emacs-lisp (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 In =emacs27= and above, I can set certain headlines not to be exported. I haven’t used this yet but it sounds useful. #+BEGIN_SRC emacs-lisp (unless (version< emacs-version "27") (use-package org-contrib) (require 'ox-extra) (ox-extras-activate '(ignore-headlines))) #+END_SRC Add the =memoir= class for LaTeX export. #+BEGIN_SRC emacs-lisp (unless (version< emacs-version "27") (add-to-list 'org-latex-classes '("memoir" "\\documentclass[9pt,b6paper]{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?? #+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) (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 (unless (version< emacs-version "27") (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))) (add-to-list 'org-export-filter-plain-text-functions 'my-html-filter-nobreaks) (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 (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 (atwork) (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= and =org-bullets= Use =org-modern= on =emacs27= and above (although I’m still not wild about it), =org-bullets= otherwise. [[https://github.com/minad/org-modern/issues/5#issuecomment-1318003940][Fix for issue with table widths]], which makes me slightly less not-wild. #+BEGIN_SRC emacs-lisp (if (version< emacs-version "27") (progn (use-package org-bullets :custom (org-bullets-bullet-list '("✸")) (org-ellipsis " ⤵") :hook (org-mode . org-bullets-mode))) (progn (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 (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 (version< emacs-version "27") (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 (version< emacs-version "27") (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 (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 (atwork) (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 workday (if (< (string-to-number (format-time-string "%H")) 19) (if (> (string-to-number (format-time-string "%H")) 7) (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"))) (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"))) (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 (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 (use-package paren :config (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 (if (iswin) (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 ** =rainbow-mode= Adds visual indication of colours to CSS files. #+BEGIN_SRC emacs-lisp (use-package rainbow-mode :hook (css-mode . rainbow-mode)) #+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 (use-package recentf :config (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) ;; (global-set-key "\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 (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 (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 ** =yasnippet= Per-mode text expansion. What a lifechanger. #+BEGIN_SRC emacs-lisp (use-package yasnippet :config (setq yas-snippet-dirs '("~/.emacs.d/snippets"))) (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 (use-package all-the-icons :config (unless (iswin) (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 (use-package emojify :hook (text-mode . emojify-mode) (org-agenda-mode . emojify-mode)) #+END_SRC *** =hl-line= Highlights current line. #+BEGIN_SRC emacs-lisp (use-package hl-line :config (global-hl-line-mode 1)) #+END_SRC *** =tao-theme= Nice monochrome-ish light theme, reminiscent of [[https://edwardtufte.github.io/tufte-css/][Tufte CSS]]. #+BEGIN_SRC emacs-lisp (use-package tao-theme) (load-theme 'tao-yang t) #+END_SRC ** Colours #+BEGIN_SRC emacs-lisp (set-cursor-color "#61805c") (set-face-attribute 'region nil :background "#fcf6a7") (set-face-background 'hl-line "#ddffd6") #+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 (if (iswin) (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 90)))))) #+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 (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