commit 001db49fb374f4d0b910e6b3ebdfacc410fe00af Author: Vishakh Pradeep Kumar Date: Tue Jul 1 11:25:42 2025 +0400 Initial commit diff --git a/README.org b/README.org new file mode 100644 index 0000000..ad09fe0 --- /dev/null +++ b/README.org @@ -0,0 +1,59 @@ +#+title: Doom Emacs Configuration +#+author: Shaunsingh + +#+html: +#+html: + +#+attr_org: :width 50% +[[file:./misc/showcase/gura.png]] +[[file:./misc/showcase/org.png]] +[[file:./misc/showcase/vertico.png]] + +=config.org= /generates/ the init.el, config.el, and packages.el files, as well as +about a dozen others. + +Other than that, resources are put in [[file:misc/][misc]], and you may find some packages I'm working on in [[file:lisp/][lisp]]. +* Installation +** Nix +First install nix, and enable both the =nix command= and =flakes= experimental features +#+begin_src shell +git clone --depth 1 https://github.com/shaunsingh/Nyoom.emacs.git && cd Nyoom.emacs +nix develop +#+end_src + +** Regular installation: +First install the following dependencies: +- Emacs (preferably one with =native-comp=, note that doom-emacs does not support emacs29 (HEAD), but I personally use it with no issues. +- sqlite +- fd +- ripgrep + +You can optionally install the following: +- aspell + dictionaries (for spelling support) +- sdcv (for stardict) +- gnuplot (for org-plot) +- pandoc (for ox-pandoc imports/exports) +- languagetool (for grammer checking) +- tectonic (for latex exports and editing) + +As for the plugins themselves +#+begin_src shell +git clone --depth 1 https://github.com/shaunsingh/Nyoom.emacs.git ~/.config/doom +git clone --depth 1 https://github.com/hlissner/doom-emacs ~/.config/emacs +~/.config/emacs/bin/doom install +#+end_src + +* RoadMap +** TODO Add faces for doom modules +*** TODO VC-gutter +*** TODO Flycheck +*** STRT Tree-sitter +** DONE Improve Exports +*** DONE Refactor +*** DONE Use Fira font family +*** DONE Use tectonic +*** DONE Simplify HTML CSS +** DONE Cleanup Config +*** DONE Refactor org-mode config +*** DONE Lazy load and Speedup +*** DONE Restructure config diff --git a/config.el b/config.el new file mode 100644 index 0000000..b3f5dec --- /dev/null +++ b/config.el @@ -0,0 +1,570 @@ +;; [[file:config.org::*Customizations][Customizations:1]] +(setq-default custom-file (expand-file-name ".custom.el" doom-private-dir)) +(when (file-exists-p custom-file) + (load custom-file)) +;; Customizations:1 ends here + +;; [[file:config.org::*Personal information][Personal information:1]] +(setq user-full-name "Shaurya Singh" + user-mail-address "shaunsingh0207@gmail.com") +;; Personal information:1 ends here + +;; [[file:config.org::*Window management][Window management:1]] +(setq evil-vsplit-window-right t + evil-split-window-below t) +;; Window management:1 ends here + +;; [[file:config.org::*Window management][Window management:2]] +(defadvice! prompt-for-buffer (&rest _) + :after '(evil-window-split evil-window-vsplit) + (consult-buffer)) +;; Window management:2 ends here + +;; [[file:config.org::*Better Defaults][Better Defaults:1]] +(setq scroll-margin 2 + auto-save-default t + display-line-numbers-type nil + delete-by-moving-to-trash t + truncate-string-ellipsis "…" + browse-url-browser-function 'xwidget-webkit-browse-url) + +(fringe-mode 0) +(global-subword-mode 1) +;; Better Defaults:1 ends here + +;; [[file:config.org::*Better Defaults][Better Defaults:2]] +(add-to-list 'default-frame-alist '(inhibit-double-buffering . t)) +;; Better Defaults:2 ends here + +;; [[file:config.org::*Better Defaults][Better Defaults:3]] +(cond + ((string-equal system-type "darwin") + (setq frame-resize-pixelwise t + window-resize-pixelwise t))) +;; Better Defaults:3 ends here + +;; [[file:config.org::*Evil][Evil:1]] +(after! evil + (setq evil-ex-substitute-global t ; I like my s/../.. to by global by default + evil-move-cursor-back nil ; Don't move the block cursor when toggling insert mode + evil-kill-on-visual-paste nil)) ; Don't put overwritten text in the kill ring +;; Evil:1 ends here + +;; [[file:config.org::*Evil][Evil:2]] +(setq which-key-allow-multiple-replacements t + which-key-idle-delay 0.5) ;; I need the help, I really do +(after! which-key + (pushnew! + which-key-replacement-alist + '(("" . "\\`+?evil[-:]?\\(?:a-\\)?\\(.*\\)") . (nil . " \\1")) + '(("\\`g s" . "\\`evilem--?motion-\\(.*\\)") . (nil . " \\1")))) +;; Evil:2 ends here + +;; [[file:config.org::*Magit][Magit:1]] +(after! magit + (magit-delta-mode +1)) +;; Magit:1 ends here + +;; [[file:config.org::*Info Colors][Info Colors:1]] +(use-package! info-colors + :commands (info-colors-fontify-node)) + +(add-hook 'Info-selection-hook 'info-colors-fontify-node) +;; Info Colors:1 ends here + +;; [[file:config.org::*Mini-Frame][Mini-Frame:1]] +(use-package! mini-frame + :hook (after-init . mini-frame-mode) + :config + (defcustom my/minibuffer-position 'top + "Minibuffer position, one of 'top or 'bottom" + :type '(choice (const :tag "Top" top) + (const :tag "Bottom" bottom)) + :group 'nano-minibuffer) + + (defun my/minibuffer--frame-parameters () + "Compute minibuffer frame size and position." + + ;; Quite precise computation to align the minibuffer and the + ;; modeline when they are both at top position + (let* ((edges (window-pixel-edges)) ;; (left top right bottom) + (body-edges (window-body-pixel-edges)) ;; (left top right bottom) + (left (nth 0 edges)) ;; Take margins into account + (top (nth 1 edges)) ;; Drop header line + (right (nth 2 edges)) ;; Take margins into account + (bottom (nth 3 body-edges)) ;; Drop header line + (left (if (eq left-fringe-width 0) + left + (- left (frame-parameter nil 'left-fringe)))) + (right (nth 2 edges)) + (right (if (eq right-fringe-width 0) + right + (+ right (frame-parameter nil 'right-fringe)))) + (border 1) + (width (- right left (* 0 border))) + + ;; Window divider mode + (width (- width (if (and (bound-and-true-p window-divider-mode) + (or (eq window-divider-default-places 'right-only) + (eq window-divider-default-places t)) + (window-in-direction 'right (selected-window))) + window-divider-default-right-width + 0))) + (y (- top border))) + + (append `((left-fringe . 0) + (right-fringe . 0) + (user-position . t) + (foreground-color . ,(face-foreground 'highlight nil 'default)) + (background-color . ,(face-background 'highlight nil 'default))) + (cond ((and (eq my/minibuffer-position 'bottom)) + `((top . -1) + (left . 0) + (width . 1.0) + (child-frame-border-width . 0) + (internal-border-width . 0))) + (t + `((left . ,(- left border)) + (top . ,y) + (width . (text-pixels . ,width)) + (child-frame-border-width . ,border) + (internal-border-width . ,border))))))) + + (set-face-background 'child-frame-border (face-foreground 'nano-faded)) + (setq mini-frame-default-height 3) + (setq mini-frame-create-lazy t) + (setq mini-frame-show-parameters 'my/minibuffer--frame-parameters) + (setq mini-frame-ignore-commands + '("edebug-eval-expression" debugger-eval-expression)) + (setq mini-frame-internal-border-color (face-foreground 'nano-faded)) + (setq mini-frame-resize-min-height 3) + (setq mini-frame-resize t) + + (defun my/mini-frame (&optional height foreground background border) + "Create a child frame positionned over the header line whose + width corresponds to the width of the current selected window. + + The HEIGHT in lines can be specified, as well as the BACKGROUND + color of the frame. BORDER width (pixels) and color (FOREGROUND) + can be also specified." + (interactive) + (let* ((foreground (or foreground + (face-foreground 'font-lock-comment-face nil t))) + (background (or background (face-background 'highlight nil t))) + (border (or border 1)) + (height (round (* (or height 8) (window-font-height)))) + (edges (window-pixel-edges)) + (body-edges (window-body-pixel-edges)) + (top (nth 1 edges)) + (bottom (nth 3 body-edges)) + (left (- (nth 0 edges) (or left-fringe-width 0))) + (right (+ (nth 2 edges) (or right-fringe-width 0))) + (width (- right left)) + + ;; Window divider mode + (width (- width (if (and (bound-and-true-p window-divider-mode) + (or (eq window-divider-default-places 'right-only) + (eq window-divider-default-places t)) + (window-in-direction 'right (selected-window))) + window-divider-default-right-width + 0))) + (y (- top border)) + (child-frame-border (face-attribute 'child-frame-border :background))) + (set-face-attribute 'child-frame-border t :background foreground) + (let ((frame (make-frame + `((parent-frame . ,(window-frame)) + (delete-before . ,(window-frame)) + (minibuffer . nil) + (modeline . nil) + (left . ,(- left border)) + (top . ,y) + (width . (text-pixels . ,width)) + (height . (text-pixels . ,height)) + ;; (height . ,height) + (child-frame-border-width . ,border) + (internal-border-width . ,border) + (background-color . ,background) + (horizontal-scroll-bars . nil) + (menu-bar-lines . 0) + (tool-bar-lines . 0) + (desktop-dont-save . t) + (unsplittable . nil) + (no-other-frame . t) + (undecorated . t) + (pixelwise . t) + (visibility . t))))) + (set-face-attribute 'child-frame-border t :background child-frame-border) + frame)))) +;; Mini-Frame:1 ends here + +;; [[file:config.org::*Vertico][Vertico:1]] +(after! vertico + ;; settings + (setq vertico-resize nil ; How to resize the Vertico minibuffer window. + vertico-count 10 ; Maximal number of candidates to show. + vertico-count-format nil) ; No prefix with number of entries + + ;; looks + (setq vertico-grid-separator + #(" | " 2 3 (display (space :width (1)) + face (:background "#ECEFF1"))) + vertico-group-format + (concat #(" " 0 1 (face vertico-group-title)) + #(" " 0 1 (face vertico-group-separator)) + #(" %s " 0 4 (face vertico-group-title)) + #(" " 0 1 (face vertico-group-separator + display (space :align-to (- right (-1 . right-margin) (- +1))))))) + (set-face-attribute 'vertico-group-separator nil + :strike-through t) + (set-face-attribute 'vertico-current nil + :inherit '(nano-strong nano-subtle)) + (set-face-attribute 'completions-first-difference nil + :inherit '(nano-default)) + + ;; minibuffer tweaks + (defun my/vertico--resize-window (height) + "Resize active minibuffer window to HEIGHT." + (setq-local truncate-lines t + resize-mini-windows 'grow-only + max-mini-window-height 1.0) + (unless (frame-root-window-p (active-minibuffer-window)) + (unless vertico-resize + (setq height (max height vertico-count))) + (let* ((window-resize-pixelwise t) + (dp (- (max (cdr (window-text-pixel-size)) + (* (default-line-height) (1+ height))) + (window-pixel-height)))) + (when (or (and (> dp 0) (/= height 0)) + (and (< dp 0) (eq vertico-resize t))) + (window-resize nil dp nil nil 'pixelwise))))) + + (advice-add #'vertico--resize-window :override #'my/vertico--resize-window) + + ;; completion at point + (setq completion-in-region-function + (lambda (&rest args) + (apply (if vertico-mode + #'consult-completion-in-region + #'completion--in-region) + args))) + (defun minibuffer-format-candidate (orig cand prefix suffix index _start) + (let ((prefix (if (= vertico--index index) + "  " + " "))) + (funcall orig cand prefix suffix index _start))) + (advice-add #'vertico--format-candidate + :around #'minibuffer-format-candidate) + (defun vertico--prompt-selection () + "Highlight the prompt" + + (let ((inhibit-modification-hooks t)) + (set-text-properties (minibuffer-prompt-end) (point-max) + '(face (nano-strong nano-salient))))) + (defun minibuffer-vertico-setup () + (setq truncate-lines t) + (setq completion-in-region-function + (if vertico-mode + #'consult-completion-in-region + #'completion--in-region))) + + (add-hook 'vertico-mode-hook #'minibuffer-vertico-setup) + (add-hook 'minibuffer-setup-hook #'minibuffer-vertico-setup)) +;; Vertico:1 ends here + +;; [[file:config.org::*Marginalia][Marginalia:1]] +(after! marginalia + (setq marginalia--ellipsis "…" ; Nicer ellipsis + marginalia-align 'right ; right alignment + marginalia-align-offset -1)) ; one space on the right +;; Marginalia:1 ends here + +;; [[file:config.org::*Pixel-scroll][Pixel-scroll:1]] +(if (boundp 'mac-mouse-wheel-smooth-scroll) + (setq mac-mouse-wheel-smooth-scroll t)) + +(if (> emacs-major-version 28) + (pixel-scroll-precision-mode)) +;; Pixel-scroll:1 ends here + +;; [[file:config.org::*Nano][Nano:1]] +(setq-default line-spacing 0.24) +;; Nano:1 ends here + +;; [[file:config.org::*Window Padding][Window Padding:1]] +;; Vertical window divider +(setq-default window-divider-default-right-width 24 + window-divider-default-places 'right-only + left-margin-width 0 + right-margin-width 0 + window-combination-resize nil) ; Do not resize windows proportionally + +(window-divider-mode 1) +;; Window Padding:1 ends here + +;; [[file:config.org::*Window Padding][Window Padding:2]] +;; Default frame settings +(setq default-frame-alist '((min-height . 1) '(height . 45) + (min-width . 1) '(width . 81) + (vertical-scroll-bars . nil) + (internal-border-width . 24) + (left-fringe . 0) + (right-fringe . 0) + (tool-bar-lines . 0) + (menu-bar-lines . 0))) + +(setq initial-frame-alist default-frame-alist) +;; Window Padding:2 ends here + +;; [[file:config.org::*Colorscheme][Colorscheme:1]] +(defun shaunsingh/apply-nano-theme (appearance) + "Load theme, taking current system APPEARANCE into consideration." + (mapc #'disable-theme custom-enabled-themes) + (pcase appearance + ('light (nano-light)) + ('dark (nano-dark)))) +;; Colorscheme:1 ends here + +;; [[file:config.org::*Colorscheme][Colorscheme:2]] +(use-package nano-theme + :hook (after-init . nano-light) + :config + ;; If emacs has been built with system appearance detection + ;; add a hook to change the theme to match the system + ;; (if (boundp 'ns-system-appearance-change-functions) + ;; (add-hook 'ns-system-appearance-change-functions #'shaunsingh/apply-nano-theme)) + ;; Now to add some missing faces + (custom-set-faces + `(flyspell-incorrect ((t (:underline (:color ,nano-light-salient :style line))))) + `(flyspell-duplicate ((t (:underline (:color ,nano-light-salient :style line))))) + + `(git-gutter:modified ((t (:foreground ,nano-light-salient)))) + `(git-gutter-fr:added ((t (:foreground ,nano-light-popout)))) + `(git-gutter-fr:modified ((t (:foreground ,nano-light-salient)))) + + `(lsp-ui-doc-url:added ((t (:background ,nano-light-highlight)))) + `(lsp-ui-doc-background:modified ((t (:background ,nano-light-highlight)))) + + `(vterm-color-red ((t (:foreground ,nano-light-critical)))) + `(vterm-color-blue ((t (:foreground ,nano-light-salient)))) + `(vterm-color-green ((t (:foreground ,nano-light-popout)))) + `(vterm-color-yellow ((t (:foreground ,nano-light-popout)))) + `(vterm-color-magenta ((t (:foreground ,nano-light-salient)))) + + `(scroll-bar ((t (:background ,nano-light-background)))) + `(child-frame-border ((t (:foreground ,nano-light-faded)))) + + `(avy-lead-face-1 ((t (:foreground ,nano-light-subtle)))) + `(avy-lead-face ((t (:foreground ,nano-light-popout :weight bold)))) + `(avy-lead-face-0 ((t (:foreground ,nano-light-salient :weight bold)))))) +;; Colorscheme:2 ends here + +;; [[file:config.org::*Colorscheme][Colorscheme:3]] +;; (use-package! nano-modeline +;; :hook (after-init . nano-modeline-mode) +;; :config +;; (setq nano-modeline-prefix 'status +;; nano-modeline-prefix-padding 1 +;; nano-modeline-position 'bottom)) + +(use-package! minions + :hook (after-init . minions-mode)) + +;; Add a zero-width tall character to add padding to modeline +(setq-default mode-line-format + (cons (propertize "\u200b" 'display '((raise -0.35) (height 1.4))) mode-line-format)) +;; Colorscheme:3 ends here + +;; [[file:config.org::*Dimming][Dimming:1]] +;; Dim inactive windows +(use-package! dimmer + :hook (after-init . dimmer-mode) + :config + (setq dimmer-fraction 0.5 + dimmer-adjustment-mode :foreground + dimmer-use-colorspace :rgb + dimmer-watch-frame-focus-events nil) + (dimmer-configure-which-key) + (dimmer-configure-magit) + (dimmer-configure-posframe)) +;; Dimming:1 ends here + +;; [[file:config.org::*Dimming][Dimming:2]] +(defun add-list-to-list (dst src) + "Similar to `add-to-list', but accepts a list as 2nd argument" + (set dst + (append (eval dst) src))) + +(use-package! focus + :commands focus-mode + :config + ;; add whatever lsp servers you use to this list + (add-list-to-list 'focus-mode-to-thing + '((lua-mode . lsp-folding-range) + (rust-mode . lsp-folding-range) + (latex-mode . lsp-folding-range) + (python-mode . lsp-folding-range)))) +;; Dimming:2 ends here + +;; [[file:config.org::*Writeroom][Writeroom:1]] +(setq +zen-text-scale 0.8) +;; Writeroom:1 ends here + +;; [[file:config.org::*Org-Mode][Org-Mode:1]] +(after! org + (setq org-directory "~/org" ; let's put files here + org-ellipsis " ﬋" ; cute icon for folded org blocks + org-list-allow-alphabetical t ; have a. A. a) A) list bullets + org-use-property-inheritance t ; it's convenient to have properties inherited + org-catch-invisible-edits 'smart ; try not to accidently do weird stuff in invisible regions + org-log-done 'time ; having the time a item is done sounds convenient + org-roam-directory "~/org/roam/")) ; same thing, for roam +;; Org-Mode:1 ends here + +;; [[file:config.org::*Org-Mode][Org-Mode:2]] +(after! org + (setq org-src-fontify-natively t + org-fontify-whole-heading-line t + org-inline-src-prettify-results '("⟨" . "⟩") + org-fontify-done-headline t + org-fontify-quote-and-verse-blocks t)) +;; Org-Mode:2 ends here + +;; [[file:config.org::*Org-Mode][Org-Mode:3]] +(after! org + (setq org-babel-default-header-args + '((:session . "none") + (:results . "replace") + (:exports . "code") + (:cache . "no") + (:noweb . "no") + (:hlines . "no") + (:tangle . "no") + (:comments . "link")))) +;; Org-Mode:3 ends here + +;; [[file:config.org::*Org-Mode][Org-Mode:4]] +(after! org + (setq org-list-demote-modify-bullet '(("+" . "-") ("-" . "+") ("*" . "+") ("1." . "a.")))) +;; Org-Mode:4 ends here + +;; [[file:config.org::*Org-Mode][Org-Mode:5]] +(font-lock-add-keywords 'org-mode + '(("^ *\\([-]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))) +(font-lock-add-keywords 'org-mode + '(("^ *\\([+]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "◦")))))) +;; Org-Mode:5 ends here + +;; [[file:config.org::*Org-Mode][Org-Mode:6]] +(after! ox + (org-link-set-parameters "yt" :export #'+org-export-yt) + (defun +org-export-yt (path desc backend _com) + (cond ((org-export-derived-backend-p backend 'html) + (format "" path (or "" desc))) + ((org-export-derived-backend-p backend 'latex) + (format "\\href{https://youtu.be/%s}{%s}" path (or desc "youtube"))) + (t (format "https://youtu.be/%s" path))))) +;; Org-Mode:6 ends here + +;; [[file:config.org::*HTML export][HTML export:1]] +(defun org-inline-css-hook (exporter) + "Insert custom inline css" + (when (eq exporter 'html) + (let* ((dir (ignore-errors (file-name-directory (buffer-file-name)))) + (path (concat dir "style.css")) + (homestyle (or (null dir) (null (file-exists-p path)))) + (final (if homestyle (expand-file-name "misc/org-css/style.css" doom-private-dir) path))) + (setq org-html-head-include-default-style nil) + (setq org-html-head (concat + "\n"))))) + +(defun org-inline-js-hook (exporter) + "Insert custom inline css" + (when (eq exporter 'html) + (let* ((dir (ignore-errors (file-name-directory (buffer-file-name)))) + (path (concat dir "style.js")) + (homestyle (or (null dir) (null (file-exists-p path)))) + (final (if homestyle (expand-file-name "misc/org-css/style.js" doom-private-dir) path))) + (setq org-html-head-include-default-style nil) + (setq org-html-head (concat + "\n"))))) + +(defun org-inline-html-hook (exporter) + "Insert custom inline css" + (when (eq exporter 'html) + (let* ((dir (ignore-errors (file-name-directory (buffer-file-name)))) + (path (concat dir "style.html")) + (homestyle (or (null dir) (null (file-exists-p path)))) + (final (if homestyle (expand-file-name "misc/org-css/style.html" doom-private-dir) path))) + (setq org-html-head-include-default-style nil) + (setq org-html-head (concat + (with-temp-buffer + (insert-file-contents final) + (buffer-string)) + "\n"))))) + +(add-hook 'org-export-before-processing-hook 'org-inline-css-hook) +(add-hook 'org-export-before-processing-hook 'org-inline-js-hook) +(add-hook 'org-export-before-processing-hook 'org-inline-html-hook) +;; HTML export:1 ends here + +;; [[file:config.org::*HTML export][HTML export:2]] +(after! ox-html + (setq org-html-mathjax-options + '((path "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" ) + (scale "1") + (autonumber "ams") + (multlinewidth "85%") + (tagindent ".8em") + (tagside "right"))) + + (setq org-html-mathjax-template + " + ")) +;; HTML export:2 ends here + +;; [[file:config.org::*HTML export][HTML export:3]] +(use-package! org-preview-html + :commands org-preview-html-mode + :config + (setq org-preview-html-refresh-configuration 'save + org-preview-html-viewer 'xwidget)) +;; HTML export:3 ends here + +;; [[file:config.org::*HTML export][HTML export:4]] +(setq org-startup-with-inline-images t) +;; HTML export:4 ends here diff --git a/config.org b/config.org new file mode 100644 index 0000000..22ba043 --- /dev/null +++ b/config.org @@ -0,0 +1,2848 @@ +#+title: DOOM Emacs +#+subtitle: Copyright (C) 2025 ─ Vishakh Kumar, Shaurya Singh, Henrik Lissner +#+author: Vishakh Kumar +#+description: A GNU Emacs configuration +#+startup: show2levels indent hidestars +#+options: coverpage:yes +#+property: header-args:emacs-lisp :tangle yes :comments link + +#+begin_quote +Let us change our traditional attitude to the construction of programs: +Instead of imagining that our main task is to instruct a computer what to do, +let us concentrate rather on explaining to human beings what we want a +computer to do. @@latex:\mbox{@@--- Donald Knuth@@latex:}@@ +#+end_quote + +* Doom Configuration +** Modules +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Doom has this lovely /modular configuration base/ that takes a lot of work out of +configuring Emacs. Each module (when enabled) can provide a list of packages to +install (on ~doom sync~) and configuration to be applied. The modules can also +have flags applied to tweak their behaviour. + +#+name: init.el +#+attr_html: :collapsed t +#+begin_src emacs-lisp :tangle "init.el" :noweb no-export :comments no +;;; init.el -*- lexical-binding: t; -*- + +;; This file controls what Doom modules are enabled and what order they load in. +;; Press 'K' on a module to view its documentation, and 'gd' to browse its directory. + +(doom! :completion + <> + + :ui + <> + + :editor + <> + + :emacs + <> + + :term + <> + + :checkers + <> + + :tools + <> + + :os + <> + + :lang + <> + + :email + <> + + :app + <> + + :config + <>) +#+end_src + +***** Structure +As you may have noticed by this point, this is a [[https://en.wikipedia.org/wiki/Literate_programming][literate]] configuration. Doom +has good support for this which we access though the ~literate~ module. + +While we're in the src_elisp{:config} section, we'll use Dooms nicer defaults, +along with the bindings and smartparens behaviour (the flags aren't documented, +but they exist). +#+name: doom-config +#+begin_src emacs-lisp +literate +(default +bindings +smartparens) +#+end_src + +***** Interface +There's a lot that can be done to enhance Emacs' capabilities. +I reckon enabling half the modules Doom provides should do it. +#+name: doom-completion +#+begin_src emacs-lisp +(company ; the ultimate code completion backend + +childframe) ; ... when your children are better than you +(vertico +icons) ; the search engine of the future +#+end_src + +#+name: doom-ui +#+begin_src emacs-lisp +doom-dashboard ; a nifty splash screen for Emacs +doom-quit ; DOOM quit-message prompts when you quit Emacs +(ligatures ; ligatures and symbols to make your code pnoretty again + +extra) ; for those who dislike letters +minimap ; show a map of the code on the side +ophints ; highlight the region an operation acts on +(popup ; tame sudden yet inevitable temporary windows + +all ; catch all popups that start with an asterix + +defaults) ; default popup rules +vc-gutter ; vcs diff in the fringe +workspaces ; tab emulation, persistence & separate workspaces +zen ; distraction-free coding or writing +#+end_src + +#+name: doom-editor +#+begin_src emacs-lisp +(evil +everywhere) ; come to the dark side, we have cookies +format ; automated prettiness +#+end_src + +#+name: doom-emacs +#+begin_src emacs-lisp +(dired +icons) ; making dired pretty [functional] +electric ; smarter, keyword-based electric-indent +(ibuffer +icons) ; interactive buffer management +undo ; persistent, smarter undo for your inevitable mistakes +vc ; version-control and Emacs, sitting in a tree +#+end_src + +#+name: doom-term +#+begin_src emacs-lisp +vterm ; the best terminal emulation in Emacs +#+end_src + +#+name: doom-checkers +#+begin_src emacs-lisp +syntax ; tasing you for every semicolon you forget +(:if (executable-find "aspell") spell) ; tasing you for misspelling mispelling +(:if (executable-find "languagetool") grammar) ; tasing grammar mistake every you make +#+end_src + +#+name: doom-tools +#+begin_src emacs-lisp +biblio ; Writes a PhD for you (citation needed) +(debugger +lsp) ; FIXME stepping through code, to help you add bugs +(eval +overlay) ; run code, run (also, repls) +(lookup ; helps you navigate your code and documentation + +dictionary ; dictionary/thesaurus is nice + +docsets) ; ...or in Dash docsets locally +lsp ; Language Server Protocol +(magit ; a git porcelain for Emacs + +forge) ; interface with git forges +pdf ; pdf enhancements +rgb ; creating color strings +tree-sitter ; Syntax and Parsing sitting in a tree +#+end_src + +#+name: doom-os +#+begin_src emacs-lisp +(:if IS-MAC macos) ; improve compatibility with macOS +#+end_src + +***** Language support +We can be rather liberal with enabling support for languages as the associated +packages/configuration are (usually) only loaded when first opening an +associated file. + +#+name: doom-lang +#+begin_src emacs-lisp +;;agda ; types of types of types of types... +;;beancount ; mind the GAAP +(cc +lsp +tree-sitter) ; C/C++/Obj-C madness +(clojure +lsp) ; java with a lisp +;;common-lisp ; if you've seen one lisp, you've seen them all +;;coq ; proofs-as-programs +;;crystal ; ruby at the speed of c +;;csharp ; unity, .NET, and mono shenanigans +;;data ; config/data formats +;;(dart +flutter) ; paint ui and not much else +;;dhall ; JSON with FP sprinkles +;;elixir ; erlang done right +;;elm ; care for a cup of TEA? +emacs-lisp ; drown in parentheses +;;erlang ; an elegant language for a more civilized age +;;ess ; emacs speaks statistics +;;faust ; dsp, but you get to keep your soul +;;fsharp ; ML stands for Microsoft's Language +;;fstar ; (dependent) types and (monadic) effects and Z3 +;;gdscript ; the language you waited for +;;(go +lsp) ; the hipster dialect +;;(haskell +lsp) ; a language that's lazier than I am +;;hy ; readability of scheme w/ speed of python +;;idris ; +;;json ; At least it ain't XML +;;(java +lsp) ; the poster child for carpal tunnel syndrome +;;(javascript +lsp) ; all(hope(abandon(ye(who(enter(here)))))) +;;(julia +lsp) ; Python, R, and MATLAB in a blender +;;(kotlin +lsp) ; a better, slicker Java(Script) +(latex ; writing papers in Emacs has never been so fun + ;;+fold ; fold the clutter away nicities + +latexmk ; modern latex plz + ;;+cdlatex ; quick maths symbols + +lsp) +;;lean ; proof that mathematicians need help +;;factor ; for when scripts are stacked against you +;;ledger ; an accounting system in Emacs +(lua +lsp +fennel) ; one-based indices? one-based indices +(markdown +grip) ; writing docs for people to ignore +;;nim ; python + lisp at the speed of c +(nix +tree-sitter) ; I hereby declare "nix geht mehr!" +;;ocaml ; an objective camel +(org ; organize your plain life in plain text + ;;+pretty ; yessss my pretties! (nice unicode symbols) + ;;+dragndrop ; drag & drop files/images into org buffers + ;;+hugo ; use Emacs for hugo blogging + +noter ; enhanced PDF notetaking + +jupyter ; ipython/jupyter support for babel + +pandoc ; export-with-pandoc support + +gnuplot ; who doesn't like pretty pictures + +pomodoro ; be fruitful with the tomato technique + +present ; using org-mode for presentations + +roam2) ; wander around notes +;;php ; perl's insecure younger brother +;;plantuml ; diagrams for confusing people more +;;purescript ; javascript, but functional +(python ; beautiful is better than ugly + +lsp + +pyright + +tree-sitter + +conda) +;;qt ; the 'cutest' gui framework ever +;;racket ; a DSL for DSLs +;;raku ; the artist formerly known as perl6 +;;(rust +;; +lsp +;; +tree-sitter) ; Fe2O3.unwrap().unwrap().unwrap() +;;scala ; java, but good +;;scheme ; a fully conniving family of lisps +;;(sh +lsp +fish +tree-sitter) ; she sells {ba,z,fi}sh shells on the C xor +;;sml ; no, the /other/ ML +;;solidity ; do you need a blockchain? No. +;;swift ; who asked for emoji variables? +;;terra ; Earth and Moon in alignment for performance. +;;(web +lsp) ; the tubes +;;yaml ; JSON, but readable +;;zig ; C, but simpler +#+end_src + +***** Everything in Emacs + +While interesting, I prefer using Outlook for email, Reeder for RSS, and Jellyfin for media. I'm not too sure if my Emacs config is stable enough to really replace the others, tbh. + +#+name: doom-email +#+begin_src emacs-lisp +;; (:if (executable-find "mu") (mu4e +org +gmail)) +#+end_src + +#+name: doom-app +#+begin_src emacs-lisp +;;calendar ; A dated approach to timetabling +;;emms ; Multimedia in Emacs is music to my ears +;;everywhere ; *leave* Emacs!? You must be joking. +;; (rss +org) ; emacs as an RSS reader +#+end_src + +** Packages +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Unlike most literate configurations I +am lazy+ like to keep all my packages in +one place +#+name: packages.el +#+attr_html: :collapsed t +#+begin_src emacs-lisp :tangle "packages.el" :noweb no-export :comments no +;; -*- no-byte-compile: t; -*- +;;; $DOOMDIR/packages.el + +;;org +<> + +;;latex +<> + +;;looks +<> + +;;emacs additions +<> + +;;fun +<> +#+end_src + +***** Org: +The majority of my work in emacs is done in org mode, even this configuration +was written in org! It makes sense that the majority of my packages are for +tweaking org then +#+name: org +#+begin_src emacs-lisp +(package! doct) +(package! websocket) +(package! org-appear) +(package! org-roam-ui) +(package! org-preview-html) +#+end_src + +***** $\LaTeX$: +When I'm not working in org, I'm probably exporting it to latex. Lets adjust +that a bit too +#+name: latex +#+begin_src emacs-lisp +(package! aas) +(package! laas) +(package! engrave-faces) +(package! ox-chameleon + :recipe (:host github :repo "tecosaur/ox-chameleon")) +#+end_src + +***** Looks: +Making emacs look good is first priority, actually working in it is second +#+name: looks +#+begin_src emacs-lisp +(package! focus) +(package! dimmer) +(package! minions) +(package! mini-frame) +(package! solaire-mode :disable t) + +;; nano stuff +(package! nano-theme) +(package! svg-tag-mode) +;; (package! nano-modeline) +#+end_src + +***** Emacs Tweaks: +Emacs is missing just a few packages to improve things here and there. Mainly +- better dictionary support +- improved modal editing +- ebook support +- more colorful docs +#+name: emacs +#+begin_src emacs-lisp +(package! nov) +(package! lexic) +(package! info-colors) +(package! magit-delta :recipe (:host github :repo "dandavison/magit-delta")) +#+end_src + +***** Fun: +We do a little trolling (and reading) +#+name: fun +#+begin_src emacs-lisp +(package! xkcd) +(package! md4rd) +(package! smudge) +(package! elcord) +(package! monkeytype) +#+end_src + +* Basic Configuration +** Customizations +Customizations done through the emacs gui should go into their own file, in my doom-dir. +#+begin_src emacs-lisp +(setq-default custom-file (expand-file-name ".custom.el" doom-private-dir)) +(when (file-exists-p custom-file) + (load custom-file)) +#+end_src + +** Personal information +Of course we need to tell emacs who I am +#+begin_src emacs-lisp +(setq user-full-name "Shaurya Singh" + user-mail-address "shaunsingh0207@gmail.com") +#+end_src + +** Window management +First, we'll enter the new window +#+begin_src emacs-lisp +(setq evil-vsplit-window-right t + evil-split-window-below t) +#+end_src + +Then, we'll pull up a buffer prompt. +#+begin_src emacs-lisp +(defadvice! prompt-for-buffer (&rest _) + :after '(evil-window-split evil-window-vsplit) + (consult-buffer)) +#+end_src + +** COMMENT Shell +Vterm is my terminal emulator of choice. We can tell it to use ligatures, and also tell it to compile automatically +Vterm clearly wins the terminal war. Also doesn't need much configuration out of +the box, although the shell integration does. + +Fixes a weird bug with native-comp +#+begin_src emacs-lisp +(setq vterm-always-compile-module t) +#+end_src + +If the process exits, kill the =vterm= buffer +#+begin_src emacs-lisp +(setq vterm-kill-buffer-on-exit t) +#+end_src + +Useful functions for the shell-side integration provided by vterm. +#+begin_src emacs-lisp +(after! vterm + (setf (alist-get "magit-status" vterm-eval-cmds nil nil #'equal) + '((lambda (path) + (magit-status path))))) +#+end_src + +Use ligatures from within vterm, we do this by redefining the variable where /not/ to show ligatures. On the other hand, in select modes we want to use extra ligatures, so lets enable that. +#+begin_src emacs-lisp +(setq +ligatures-in-modes t) +#+end_src + +** COMMENT LSP +I think the LSP is a bit intrusive (especially with inline suggestions), so lets make it behave a bit more +#+begin_src emacs-lisp +(after! lsp-mode + (setq lsp-enable-symbol-highlighting nil)) + +(after! lsp-ui + (setq lsp-ui-sideline-enable nil ; no more useful than flycheck + lsp-ui-doc-enable nil)) ; redundant with K +#+end_src + +*** Company +I think company is a bit too quick to recommend some stuff +#+begin_src emacs-lisp +(after! company + (setq company-idle-delay 0.1 + company-selection-wrap-around t + company-require-match 'never + company-dabbrev-downcase nil + company-dabbrev-ignore-case t + company-dabbrev-other-buffers nil + company-tooltip-limit 5 + company-tooltip-minimum-width 40) + (set-company-backend! + '(text-mode + markdown-mode + gfm-mode) + '(:seperate + company-files))) +#+end_src + +** Better Defaults +The defaults for emacs aren't so good nowadays. Lets fix that up a bit +#+begin_src emacs-lisp +(setq scroll-margin 2 + auto-save-default t + display-line-numbers-type nil + delete-by-moving-to-trash t + truncate-string-ellipsis "…" + browse-url-browser-function 'xwidget-webkit-browse-url) + +(fringe-mode 0) +(global-subword-mode 1) +#+end_src + +There's issues with emacs flickering on mac (and sometimes wayland). This should +fix it +#+begin_src emacs-lisp +(add-to-list 'default-frame-alist '(inhibit-double-buffering . t)) +#+end_src + +Heres some fixes for yabai, we obviously only want that under darwin (macOS) though +#+begin_src emacs-lisp +(cond + ((string-equal system-type "darwin") + (setq frame-resize-pixelwise t + window-resize-pixelwise t))) +#+end_src + +** Evil +When we do =s/../..= I usually want a global =/g= at the end, so lets make that the default (along with some other tweaks) +#+begin_src emacs-lisp +(after! evil + (setq evil-ex-substitute-global t ; I like my s/../.. to by global by default + evil-move-cursor-back nil ; Don't move the block cursor when toggling insert mode + evil-kill-on-visual-paste nil)) ; Don't put overwritten text in the kill ring +#+end_src + +Which key shows those extra =evil-= hints, feels redundant +#+begin_src emacs-lisp +(setq which-key-allow-multiple-replacements t + which-key-idle-delay 0.5) ;; I need the help, I really do +(after! which-key + (pushnew! + which-key-replacement-alist + '(("" . "\\`+?evil[-:]?\\(?:a-\\)?\\(.*\\)") . (nil . " \\1")) + '(("\\`g s" . "\\`evilem--?motion-\\(.*\\)") . (nil . " \\1")))) +#+end_src + +** COMMENT Mu4e +[[xkcd:1796]] + +I'm trying out emails in emacs, should be nice. Related, check .mbsyncrc to +setup your emails first. Usually I'll still prefer the mail app, so lets not go all out +#+begin_src emacs-lisp +(after! mu4e + (setq mu4e-index-cleanup nil + mu4e-index-lazy-check t + mu4e-update-interval 300) + (set-email-account! "shaunsingh0207" + '((mu4e-sent-folder . "/Sent Mail") + (mu4e-drafts-folder . "/Drafts") + (mu4e-trash-folder . "/Trash") + (mu4e-refile-folder . "/All Mail") + (smtpmail-smtp-user . "shaunsingh0207@gmail.com")))) +#+end_src + +We can also send messages using msmtp +#+begin_src emacs-lisp +(after! mu4e + (setq sendmail-program "msmtp" + send-mail-function #'smtpmail-send-it + message-sendmail-f-is-evil t + message-sendmail-extra-arguments '("--read-envelope-from") + message-send-mail-function #'message-send-mail-with-sendmail)) +#+end_src + +** Magit +Delta is a git diff syntax highlighter written in rust. The author also wrote a package to hook this into the magit diff view (which don’t get any syntax highlighting by default). This requires the delta binary. It’s packaged on some distributions, but most reliably installed through Rust’s package manager cargo. +#+begin_src emacs-lisp +(after! magit + (magit-delta-mode +1)) +#+end_src + +** COMMENT Monkeytype +Now that we have some nice keyboard sounds, lets test that keyboard with an elisp clone of Monkeytype! +Notably here we want to start in insert mode. +#+begin_src emacs-lisp +(use-package! monkeytype + :commands (monkeytype-region monkeytype-buffer monkeytype-region-as-words) + :config + (setq monkeytype-directory "~/.config/monkeytype" + monkeytype-file-name "%a-%d-%b-%Y-%H-%M-%S" + monkeytype-randomize t + monkeytype-delete-trailing-whitespace t + monkeytype-excluded-chars-regexp "[^[:alnum:]']")) +#+end_src + +** COMMENT Smudge +Honestly this probably shouldn't be in emacs, but my music addiction requires it. Those authentication credentials are unique to me, you probably want to change them to your own. +#+begin_src emacs-lisp +(use-package! smudge + :commands global-smudge-remote-mode + :config + (setq smudge-transport 'connect + smudge-oauth2-client-secret "8f5525c076544cd6b25588c868b9b3d7" + smudge-oauth2-client-id "4b2b46899e604b6884714cd7ca47e0e3") + (map! :map smudge-mode-map "M-p" #'smudge-command-map)) +#+end_src + +* Visual configuration +** COMMENT Dashboard +Lets clean up the dashboard a bit, and add a cute message, whether that be some corporate BS, an developer excuse, or a fun (useless) fact. +#+begin_src emacs-lisp +(setq fancy-splash-image (expand-file-name "misc/splash-images/kaori.png" doom-private-dir) ;; ibm, kaori, fennel + +doom-dashboard-banner-padding '(0 . 0)) + +(defvar splash-phrase-source-folder + (expand-file-name "misc/splash-phrases" doom-private-dir) + "A folder of text files with a fun phrase on each line.") + +(defvar splash-phrase-sources + (let* ((files (directory-files splash-phrase-source-folder nil "\\.txt\\'")) + (sets (delete-dups (mapcar + (lambda (file) + (replace-regexp-in-string "\\(?:-[0-9]+-\\w+\\)?\\.txt" "" file)) + files)))) + (mapcar (lambda (sset) + (cons sset + (delq nil (mapcar + (lambda (file) + (when (string-match-p (regexp-quote sset) file) + file)) + files)))) + sets)) + "A list of cons giving the phrase set name, and a list of files which contain phrase components.") + +(defvar splash-phrase-set + (nth (random (length splash-phrase-sources)) (mapcar #'car splash-phrase-sources)) + "The default phrase set. See `splash-phrase-sources'.") + +(defun splase-phrase-set-random-set () + "Set a new random splash phrase set." + (interactive) + (setq splash-phrase-set + (nth (random (1- (length splash-phrase-sources))) + (cl-set-difference (mapcar #'car splash-phrase-sources) (list splash-phrase-set)))) + (+doom-dashboard-reload t)) + +(defvar splase-phrase--cache nil) + +(defun splash-phrase-get-from-file (file) + "Fetch a random line from FILE." + (let ((lines (or (cdr (assoc file splase-phrase--cache)) + (cdar (push (cons file + (with-temp-buffer + (insert-file-contents (expand-file-name file splash-phrase-source-folder)) + (split-string (string-trim (buffer-string)) "\n"))) + splase-phrase--cache))))) + (nth (random (length lines)) lines))) + +(defun splash-phrase (&optional set) + "Construct a splash phrase from SET. See `splash-phrase-sources'." + (mapconcat + #'splash-phrase-get-from-file + (cdr (assoc (or set splash-phrase-set) splash-phrase-sources)) + " ")) + +(defun doom-dashboard-phrase () + "Get a splash phrase, flow it over multiple lines as needed, and make fontify it." + (mapconcat + (lambda (line) + (+doom-dashboard--center + +doom-dashboard--width + (with-temp-buffer + (insert-text-button + line + 'action + (lambda (_) (+doom-dashboard-reload t)) + 'face 'doom-dashboard-menu-title + 'mouse-face 'doom-dashboard-menu-title + 'help-echo "Random phrase" + 'follow-link t) + (buffer-string)))) + (split-string + (with-temp-buffer + (insert (splash-phrase)) + (setq fill-column (min 70 (/ (* 2 (window-width)) 3))) + (fill-region (point-min) (point-max)) + (buffer-string)) + "\n") + "\n")) + +(defadvice! doom-dashboard-widget-loaded-with-phrase () + :override #'doom-dashboard-widget-loaded + (setq line-spacing 0.2) + (insert + "\n\n" + (propertize + (+doom-dashboard--center + +doom-dashboard--width + (doom-display-benchmark-h 'return)) + 'face 'doom-dashboard-loaded) + "\n" + (doom-dashboard-phrase) + "\n")) + +;; remove useless dashboard info +(remove-hook '+doom-dashboard-functions #'doom-dashboard-widget-shortmenu) +(add-hook! '+doom-dashboard-mode-hook (hide-mode-line-mode 1) (hl-line-mode -1)) +(setq-hook! '+doom-dashboard-mode-hook evil-normal-state-cursor (list nil)) +#+end_src + +** Info Colors +This makes manual pages nicer to look at by adding variable pitch fontification +and colouring. + +To use this we'll just hook it into =Info=. +#+begin_src emacs-lisp +(use-package! info-colors + :commands (info-colors-fontify-node)) + +(add-hook 'Info-selection-hook 'info-colors-fontify-node) +#+end_src + +** COMMENT Minibuffer +Here we set up a cute minibuffer to better fit with our nano-themed niceties. A little more intriqute (and slower) than the default doom setups, but its nice to have. +#+begin_src emacs-lisp +(setq minibuffer-prompt-properties '(read-only t + cursor-intangible t + face minibuffer-prompt) + enable-recursive-minibuffers t) + +(defun my/minibuffer-header () + "Minibuffer header" + (let ((depth (minibuffer-depth))) + (concat + (propertize (concat "  " (if (> depth 1) + (format "Minibuffer (%d)" depth) + "Minibuffer ") + "\n") + 'face `(:inherit (nano-subtle nano-strong) + :box (:line-width (1 . 3) + :color ,(face-background 'nano-subtle) + :style flat) + :extend t))))) + +(defun my/mini-frame-reset (frame) + "Reset FRAME size and position. + + Move frame at the top of parent frame and resize it + horizontally to fit the width of current selected window." + (interactive) + (let* ((border (frame-parameter frame 'internal-border-width)) + (height (frame-parameter frame 'height))) + (with-selected-frame (frame-parent frame) + (let* ((edges (window-pixel-edges)) + (body-edges (window-body-pixel-edges)) + (top (nth 1 edges)) + (bottom (nth 3 body-edges)) + (left (- (nth 0 edges) (or left-fringe-width 0))) + (right (+ (nth 2 edges) (or right-fringe-width 0))) + (width (- right left)) + (y (- top border))) + (set-frame-width frame width nil t) + (set-frame-height frame height) + (set-frame-position frame (- left border) y))))) + +(defun my/mini-frame-shrink (frame &optional delta) + "Make the FRAME DELTA lines smaller. + + If no argument is given, make the frame one line smaller. If + DELTA is negative, enlarge frame by -DELTA lines." + (interactive) + (let ((delta (or delta -1))) + (when (and (framep frame) + (frame-live-p frame) + (frame-visible-p frame)) + (set-frame-parameter frame 'height + (+ (frame-parameter frame 'height) delta))))) + +(defun my/minibuffer-setup () + "Install a header line in the minibuffer via an overlay (and a hook)" + (set-window-margins nil 0 0) + (set-fringe-style '(0 . 0)) + (cursor-intangible-mode t) + (face-remap-add-relative 'default + :inherit 'highlight) + (let* ((overlay (make-overlay (+ (point-min) 0) (+ (point-min) 0))) + (inhibit-read-only t)) + + (save-excursion + (goto-char (point-min)) + (insert (propertize + (concat (my/minibuffer-header) + (propertize "\n" 'face `(:height 0.33)) + (propertize " ")) + 'cursor-intangible t + 'read-only t + 'field t + 'rear-nonsticky t + 'front-sticky t))))) + + +(add-hook 'minibuffer-setup-hook #'my/minibuffer-setup) +#+end_src + +** Mini-Frame +And to go with that, we want to put our minibuffer in a posframe. This can either be placed at the bottom or top of the window, align it with your statusline. +#+begin_src emacs-lisp +(use-package! mini-frame + :hook (after-init . mini-frame-mode) + :config + (defcustom my/minibuffer-position 'top + "Minibuffer position, one of 'top or 'bottom" + :type '(choice (const :tag "Top" top) + (const :tag "Bottom" bottom)) + :group 'nano-minibuffer) + + (defun my/minibuffer--frame-parameters () + "Compute minibuffer frame size and position." + + ;; Quite precise computation to align the minibuffer and the + ;; modeline when they are both at top position + (let* ((edges (window-pixel-edges)) ;; (left top right bottom) + (body-edges (window-body-pixel-edges)) ;; (left top right bottom) + (left (nth 0 edges)) ;; Take margins into account + (top (nth 1 edges)) ;; Drop header line + (right (nth 2 edges)) ;; Take margins into account + (bottom (nth 3 body-edges)) ;; Drop header line + (left (if (eq left-fringe-width 0) + left + (- left (frame-parameter nil 'left-fringe)))) + (right (nth 2 edges)) + (right (if (eq right-fringe-width 0) + right + (+ right (frame-parameter nil 'right-fringe)))) + (border 1) + (width (- right left (* 0 border))) + + ;; Window divider mode + (width (- width (if (and (bound-and-true-p window-divider-mode) + (or (eq window-divider-default-places 'right-only) + (eq window-divider-default-places t)) + (window-in-direction 'right (selected-window))) + window-divider-default-right-width + 0))) + (y (- top border))) + + (append `((left-fringe . 0) + (right-fringe . 0) + (user-position . t) + (foreground-color . ,(face-foreground 'highlight nil 'default)) + (background-color . ,(face-background 'highlight nil 'default))) + (cond ((and (eq my/minibuffer-position 'bottom)) + `((top . -1) + (left . 0) + (width . 1.0) + (child-frame-border-width . 0) + (internal-border-width . 0))) + (t + `((left . ,(- left border)) + (top . ,y) + (width . (text-pixels . ,width)) + (child-frame-border-width . ,border) + (internal-border-width . ,border))))))) + + (set-face-background 'child-frame-border (face-foreground 'nano-faded)) + (setq mini-frame-default-height 3) + (setq mini-frame-create-lazy t) + (setq mini-frame-show-parameters 'my/minibuffer--frame-parameters) + (setq mini-frame-ignore-commands + '("edebug-eval-expression" debugger-eval-expression)) + (setq mini-frame-internal-border-color (face-foreground 'nano-faded)) + (setq mini-frame-resize-min-height 3) + (setq mini-frame-resize t) + + (defun my/mini-frame (&optional height foreground background border) + "Create a child frame positionned over the header line whose + width corresponds to the width of the current selected window. + + The HEIGHT in lines can be specified, as well as the BACKGROUND + color of the frame. BORDER width (pixels) and color (FOREGROUND) + can be also specified." + (interactive) + (let* ((foreground (or foreground + (face-foreground 'font-lock-comment-face nil t))) + (background (or background (face-background 'highlight nil t))) + (border (or border 1)) + (height (round (* (or height 8) (window-font-height)))) + (edges (window-pixel-edges)) + (body-edges (window-body-pixel-edges)) + (top (nth 1 edges)) + (bottom (nth 3 body-edges)) + (left (- (nth 0 edges) (or left-fringe-width 0))) + (right (+ (nth 2 edges) (or right-fringe-width 0))) + (width (- right left)) + + ;; Window divider mode + (width (- width (if (and (bound-and-true-p window-divider-mode) + (or (eq window-divider-default-places 'right-only) + (eq window-divider-default-places t)) + (window-in-direction 'right (selected-window))) + window-divider-default-right-width + 0))) + (y (- top border)) + (child-frame-border (face-attribute 'child-frame-border :background))) + (set-face-attribute 'child-frame-border t :background foreground) + (let ((frame (make-frame + `((parent-frame . ,(window-frame)) + (delete-before . ,(window-frame)) + (minibuffer . nil) + (modeline . nil) + (left . ,(- left border)) + (top . ,y) + (width . (text-pixels . ,width)) + (height . (text-pixels . ,height)) + ;; (height . ,height) + (child-frame-border-width . ,border) + (internal-border-width . ,border) + (background-color . ,background) + (horizontal-scroll-bars . nil) + (menu-bar-lines . 0) + (tool-bar-lines . 0) + (desktop-dont-save . t) + (unsplittable . nil) + (no-other-frame . t) + (undecorated . t) + (pixelwise . t) + (visibility . t))))) + (set-face-attribute 'child-frame-border t :background child-frame-border) + frame)))) +#+end_src + +** Minad Suite +I feel in love with these packages right away, so much better than icky ivy! +*** Vertico +Small tweaks, just some themeing here and there to better fit with our minibuffer changes +#+begin_src emacs-lisp +(after! vertico + ;; settings + (setq vertico-resize nil ; How to resize the Vertico minibuffer window. + vertico-count 10 ; Maximal number of candidates to show. + vertico-count-format nil) ; No prefix with number of entries + + ;; looks + (setq vertico-grid-separator + #(" | " 2 3 (display (space :width (1)) + face (:background "#ECEFF1"))) + vertico-group-format + (concat #(" " 0 1 (face vertico-group-title)) + #(" " 0 1 (face vertico-group-separator)) + #(" %s " 0 4 (face vertico-group-title)) + #(" " 0 1 (face vertico-group-separator + display (space :align-to (- right (-1 . right-margin) (- +1))))))) + (set-face-attribute 'vertico-group-separator nil + :strike-through t) + (set-face-attribute 'vertico-current nil + :inherit '(nano-strong nano-subtle)) + (set-face-attribute 'completions-first-difference nil + :inherit '(nano-default)) + + ;; minibuffer tweaks + (defun my/vertico--resize-window (height) + "Resize active minibuffer window to HEIGHT." + (setq-local truncate-lines t + resize-mini-windows 'grow-only + max-mini-window-height 1.0) + (unless (frame-root-window-p (active-minibuffer-window)) + (unless vertico-resize + (setq height (max height vertico-count))) + (let* ((window-resize-pixelwise t) + (dp (- (max (cdr (window-text-pixel-size)) + (* (default-line-height) (1+ height))) + (window-pixel-height)))) + (when (or (and (> dp 0) (/= height 0)) + (and (< dp 0) (eq vertico-resize t))) + (window-resize nil dp nil nil 'pixelwise))))) + + (advice-add #'vertico--resize-window :override #'my/vertico--resize-window) + + ;; completion at point + (setq completion-in-region-function + (lambda (&rest args) + (apply (if vertico-mode + #'consult-completion-in-region + #'completion--in-region) + args))) + (defun minibuffer-format-candidate (orig cand prefix suffix index _start) + (let ((prefix (if (= vertico--index index) + "  " + " "))) + (funcall orig cand prefix suffix index _start))) + (advice-add #'vertico--format-candidate + :around #'minibuffer-format-candidate) + (defun vertico--prompt-selection () + "Highlight the prompt" + + (let ((inhibit-modification-hooks t)) + (set-text-properties (minibuffer-prompt-end) (point-max) + '(face (nano-strong nano-salient))))) + (defun minibuffer-vertico-setup () + (setq truncate-lines t) + (setq completion-in-region-function + (if vertico-mode + #'consult-completion-in-region + #'completion--in-region))) + + (add-hook 'vertico-mode-hook #'minibuffer-vertico-setup) + (add-hook 'minibuffer-setup-hook #'minibuffer-vertico-setup)) +#+end_src + +*** Marginalia +More small tweaks +#+begin_src emacs-lisp +(after! marginalia + (setq marginalia--ellipsis "…" ; Nicer ellipsis + marginalia-align 'right ; right alignment + marginalia-align-offset -1)) ; one space on the right +#+end_src + +** COMMENT Elcord +What’s even the point of using Emacs unless you’re constantly telling everyone about it? What we're doing here is replacing the buffer details with something less revealing, then replacing the icon set used via creating a custom discord application. Theoretically this config should work for anyone, but I haven't tested it yet. Thank you cae for the [[file:./misc/lang_icons][icons]] +#+begin_src emacs-lisp +(defun shaunsingh/elcord-buffer-details-format () + "Return the buffer details string shown on discord." + (format "Text is a Magical Thing")) + +(use-package! elcord + :commands elcord-mode + :config + (setq elcord-mode-icon-alist '((dashboard-mode . "elisp-mode_icon") + (fundamental-mode . "elisp-mode_icon") + (c-mode . "c-mode_icon") + (c++-mode . "c_-mode_icon") + (crystal-mode . "crystal-mode_icon") + (clojure-mode . "clojure-mode_icon") + (css-mode . "css-mode_icon") + (emacs-lisp-mode . "elisp-mode_icon") + (eshell-mode . "elisp-mode_icon") + (haskell-mode . "haskell-mode_icon") + (haxe-mode . "haxe-mode_icon") + (haskell-interactive-mode . "haskell-mode_icon") + (js-mode . "javascript-mode_icon") + (magit-mode . "magit-mode_icon") + (markdown-mode . "markdown-mode_icon") + (nixos-mode . "nixos-mode_icon") + (latex-mode . "latex-mode_icon") + (text-mode . "elisp-mode_icon") + (org-mode . "org-mode_icon") + ("^slime-.*" . "lisp-mode_icon") + ("^sly-.*$" . "lisp-mode_icon") + (typescript-mode . "typescript-mode_icon") + (writer-mode . "org-mode_icon") + (term-mode . "x-mode_icon") + (shell-mode . "x-mode_icon") + (vterm-mode . "x-mode_icon"))) + (setq elcord-client-id "930927487867834408") ;; You can set your own check elcord's readme + (setq elcord-quiet t + elcord-editor-icon "elisp-mode_icon" + elcord-buffer-details-format-function 'shaunsingh/elcord-buffer-details-format + elcord-display-buffer-details t + elcord-display-elapsed nil + elcord-show-small-icon nil + elcord-use-major-mode-as-main-icon t + elcord-refresh-rate 0.25)) +#+end_src + +** Pixel-scroll +Default doom scrolling is pretty slow, so lets improve on that with pixel-scrolling. However, =emacs-mac= has its own version of pixel scroll, and so does =emacs29=, so we want to enable this under specific cases +#+begin_src emacs-lisp +(if (boundp 'mac-mouse-wheel-smooth-scroll) + (setq mac-mouse-wheel-smooth-scroll t)) + +(if (> emacs-major-version 28) + (pixel-scroll-precision-mode)) +#+end_src + +** Nano +Some UI tweaks to make emacs comfier + +Lets start off by just giving the text a little more space to breathe +#+begin_src emacs-lisp +(setq-default line-spacing 0.24) +#+end_src + +*** Window Padding +Making things spacier. Add padding around emacs and between splits +#+begin_src emacs-lisp +;; Vertical window divider +(setq-default window-divider-default-right-width 24 + window-divider-default-places 'right-only + left-margin-width 0 + right-margin-width 0 + window-combination-resize nil) ; Do not resize windows proportionally + +(window-divider-mode 1) +#+end_src + +#+begin_src emacs-lisp +;; Default frame settings +(setq default-frame-alist '((min-height . 1) '(height . 45) + (min-width . 1) '(width . 81) + (vertical-scroll-bars . nil) + (internal-border-width . 24) + (left-fringe . 0) + (right-fringe . 0) + (tool-bar-lines . 0) + (menu-bar-lines . 0))) + +(setq initial-frame-alist default-frame-alist) +#+end_src + +*** Colorscheme +We want to use the nano theme created by the excellent rougier. Heres a small function to change the appearence of the theme based on the system setting. I find myself preferring the light theme, so its disabled but here it is anyways. +#+begin_src emacs-lisp +(defun shaunsingh/apply-nano-theme (appearance) + "Load theme, taking current system APPEARANCE into consideration." + (mapc #'disable-theme custom-enabled-themes) + (pcase appearance + ('light (nano-light)) + ('dark (nano-dark)))) +#+end_src + +And now to setup the actual theme. Some extra faces I added because doom modules lookd odd without them +#+begin_src emacs-lisp +(use-package nano-theme + :hook (after-init . nano-light) + :config + ;; If emacs has been built with system appearance detection + ;; add a hook to change the theme to match the system + ;; (if (boundp 'ns-system-appearance-change-functions) + ;; (add-hook 'ns-system-appearance-change-functions #'shaunsingh/apply-nano-theme)) + ;; Now to add some missing faces + (custom-set-faces + `(flyspell-incorrect ((t (:underline (:color ,nano-light-salient :style line))))) + `(flyspell-duplicate ((t (:underline (:color ,nano-light-salient :style line))))) + + `(git-gutter:modified ((t (:foreground ,nano-light-salient)))) + `(git-gutter-fr:added ((t (:foreground ,nano-light-popout)))) + `(git-gutter-fr:modified ((t (:foreground ,nano-light-salient)))) + + `(lsp-ui-doc-url:added ((t (:background ,nano-light-highlight)))) + `(lsp-ui-doc-background:modified ((t (:background ,nano-light-highlight)))) + + `(vterm-color-red ((t (:foreground ,nano-light-critical)))) + `(vterm-color-blue ((t (:foreground ,nano-light-salient)))) + `(vterm-color-green ((t (:foreground ,nano-light-popout)))) + `(vterm-color-yellow ((t (:foreground ,nano-light-popout)))) + `(vterm-color-magenta ((t (:foreground ,nano-light-salient)))) + + `(scroll-bar ((t (:background ,nano-light-background)))) + `(child-frame-border ((t (:foreground ,nano-light-faded)))) + + `(avy-lead-face-1 ((t (:foreground ,nano-light-subtle)))) + `(avy-lead-face ((t (:foreground ,nano-light-popout :weight bold)))) + `(avy-lead-face-0 ((t (:foreground ,nano-light-salient :weight bold)))))) +#+end_src + +Originally I was going to use nano-modeline, but I prefer the default one anyways. We can use the excellent minions package to clean it up though. +#+begin_src emacs-lisp +;; (use-package! nano-modeline +;; :hook (after-init . nano-modeline-mode) +;; :config +;; (setq nano-modeline-prefix 'status +;; nano-modeline-prefix-padding 1 +;; nano-modeline-position 'bottom)) + +(use-package! minions + :hook (after-init . minions-mode)) + +;; Add a zero-width tall character to add padding to modeline +(setq-default mode-line-format + (cons (propertize "\u200b" 'display '((raise -0.35) (height 1.4))) mode-line-format)) +#+end_src + +** COMMENT SVG-tag-mode +Replaced org-modern with this, a little heavier on emacs but looks better (imo). +#+begin_src emacs-lisp +(use-package svg-tag-mode + :commands svg-tag-mode + :config + (defconst date-re "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}") + (defconst time-re "[0-9]\\{2\\}:[0-9]\\{2\\}") + (defconst day-re "[A-Za-z]\\{3\\}") + (defconst day-time-re (format "\\(%s\\)? ?\\(%s\\)?" day-re time-re)) + + (defun svg-progress-percent (value) + (svg-image (svg-lib-concat + (svg-lib-progress-bar (/ (string-to-number value) 100.0) + nil :margin 0 :stroke 2 :radius 3 :padding 2 :width 11) + (svg-lib-tag (concat value "%") + nil :stroke 0 :margin 0)) :ascent 'center)) + + (defun svg-progress-count (value) + (let* ((seq (mapcar #'string-to-number (split-string value "/"))) + (count (float (car seq))) + (total (float (cadr seq)))) + (svg-image (svg-lib-concat + (svg-lib-progress-bar (/ count total) nil + :margin 0 :stroke 2 :radius 3 :padding 2 :width 11) + (svg-lib-tag value nil + :stroke 0 :margin 0)) :ascent 'center))) + + (setq svg-tag-tags + `( + ;; Org tags + (":\\([A-Za-z0-9]+\\)" . ((lambda (tag) (svg-tag-make tag)))) + (":\\([A-Za-z0-9]+[ \-]\\)" . ((lambda (tag) tag))) + + ;; Task priority + ("\\[#[A-Z]\\]" . ( (lambda (tag) + (svg-tag-make tag :face 'org-priority + :beg 2 :end -1 :margin 0)))) + + ;; Progress + ("\\(\\[[0-9]\\{1,3\\}%\\]\\)" . ((lambda (tag) + (svg-progress-percent (substring tag 1 -2))))) + ("\\(\\[[0-9]+/[0-9]+\\]\\)" . ((lambda (tag) + (svg-progress-count (substring tag 1 -1))))) + + ;; TODO / DONE + ("TODO" . ((lambda (tag) (svg-tag-make "TODO" :face 'org-todo :inverse t :margin 0)))) + ("DONE" . ((lambda (tag) (svg-tag-make "DONE" :face 'org-done :margin 0)))) + + + ;; Citation of the form [cite:@Knuth:1984] + ("\\(\\[cite:@[A-Za-z]+:\\)" . ((lambda (tag) + (svg-tag-make tag + :inverse t + :beg 7 :end -1 + :crop-right t)))) + ("\\[cite:@[A-Za-z]+:\\([0-9]+\\]\\)" . ((lambda (tag) + (svg-tag-make tag + :end -1 + :crop-left t)))) + + + ;; Active date (with or without day name, with or without time) + (,(format "\\(<%s>\\)" date-re) . + ((lambda (tag) + (svg-tag-make tag :beg 1 :end -1 :margin 0)))) + (,(format "\\(<%s \\)%s>" date-re day-time-re) . + ((lambda (tag) + (svg-tag-make tag :beg 1 :inverse nil :crop-right t :margin 0)))) + (,(format "<%s \\(%s>\\)" date-re day-time-re) . + ((lambda (tag) + (svg-tag-make tag :end -1 :inverse t :crop-left t :margin 0)))) + + ;; Inactive date (with or without day name, with or without time) + (,(format "\\(\\[%s\\]\\)" date-re) . + ((lambda (tag) + (svg-tag-make tag :beg 1 :end -1 :margin 0 :face 'org-date)))) + (,(format "\\(\\[%s \\)%s\\]" date-re day-time-re) . + ((lambda (tag) + (svg-tag-make tag :beg 1 :inverse nil :crop-right t :margin 0 :face 'org-date)))) + (,(format "\\[%s \\(%s\\]\\)" date-re day-time-re) . + ((lambda (tag) + (svg-tag-make tag :end -1 :inverse t :crop-left t :margin 0 :face 'org-date))))))) +#+end_src + +** Dimming +#+begin_src emacs-lisp +;; Dim inactive windows +(use-package! dimmer + :hook (after-init . dimmer-mode) + :config + (setq dimmer-fraction 0.5 + dimmer-adjustment-mode :foreground + dimmer-use-colorspace :rgb + dimmer-watch-frame-focus-events nil) + (dimmer-configure-which-key) + (dimmer-configure-magit) + (dimmer-configure-posframe)) +#+end_src + +Similar to that, I want to dim surrounding text using the focus package +#+begin_src emacs-lisp +(defun add-list-to-list (dst src) + "Similar to `add-to-list', but accepts a list as 2nd argument" + (set dst + (append (eval dst) src))) + +(use-package! focus + :commands focus-mode + :config + ;; add whatever lsp servers you use to this list + (add-list-to-list 'focus-mode-to-thing + '((lua-mode . lsp-folding-range) + (rust-mode . lsp-folding-range) + (latex-mode . lsp-folding-range) + (python-mode . lsp-folding-range)))) +#+end_src + +** Writeroom +For starters, I think Doom is a bit over-zealous when zooming in +#+begin_src emacs-lisp +(setq +zen-text-scale 0.8) +#+end_src + +** COMMENT RSS +RSS is a nice simple way of getting my news. Lets set that up +#+begin_src emacs-lisp +(map! :map elfeed-search-mode-map + :after elfeed-search + [remap kill-this-buffer] "q" + [remap kill-buffer] "q" + :n doom-leader-key nil + :n "q" #'+rss/quit + :n "e" #'elfeed-update + :n "r" #'elfeed-search-untag-all-unread + :n "u" #'elfeed-search-tag-all-unread + :n "s" #'elfeed-search-live-filter + :n "RET" #'elfeed-search-show-entry + :n "p" #'elfeed-show-pdf + :n "+" #'elfeed-search-tag-all + :n "-" #'elfeed-search-untag-all + :n "S" #'elfeed-search-set-filter + :n "b" #'elfeed-search-browse-url + :n "y" #'elfeed-search-yank) +(map! :map elfeed-show-mode-map + :after elfeed-show + [remap kill-this-buffer] "q" + [remap kill-buffer] "q" + :n doom-leader-key nil + :nm "q" #'+rss/delete-pane + :nm "o" #'ace-link-elfeed + :nm "RET" #'org-ref-elfeed-add + :nm "n" #'elfeed-show-next + :nm "N" #'elfeed-show-prev + :nm "p" #'elfeed-show-pdf + :nm "+" #'elfeed-show-tag + :nm "-" #'elfeed-show-untag + :nm "s" #'elfeed-show-new-live-search + :nm "y" #'elfeed-show-yank) + +(after! elfeed-search + (set-evil-initial-state! 'elfeed-search-mode 'normal)) +(after! elfeed-show-mode + (set-evil-initial-state! 'elfeed-show-mode 'normal)) + +(after! evil-snipe + (push 'elfeed-show-mode evil-snipe-disabled-modes) + (push 'elfeed-search-mode evil-snipe-disabled-modes)) + +(after! elfeed + (elfeed-org) + (use-package! elfeed-link) + (setq rmh-elfeed-org-files '("~/org/elfeed.org")) + + (setq elfeed-search-filter "@1-week-ago +unread" + elfeed-search-print-entry-function '+rss/elfeed-search-print-entry + elfeed-search-title-min-width 80 + elfeed-show-entry-switch #'pop-to-buffer + elfeed-show-entry-delete #'+rss/delete-pane + elfeed-show-refresh-function #'+rss/elfeed-show-refresh--better-style + shr-max-image-proportion 0.6) + + (add-hook! 'elfeed-show-mode-hook (hide-mode-line-mode 1)) + (add-hook! 'elfeed-search-update-hook #'hide-mode-line-mode) + + (defface elfeed-show-title-face '((t (:weight ultrabold :slant italic :height 1.5))) + "title face in elfeed show buffer" + :group 'elfeed) + (defface elfeed-show-author-face `((t (:weight light))) + "title face in elfeed show buffer" + :group 'elfeed) + (set-face-attribute 'elfeed-search-title-face nil + :foreground 'nil + :weight 'light) + + (defadvice! +rss-elfeed-wrap-h-nicer () + "Enhances an elfeed entry's readability by wrapping it to a width of +`fill-column' and centering it with `visual-fill-column-mode'." + :override #'+rss-elfeed-wrap-h + (setq-local truncate-lines nil + shr-width 120 + visual-fill-column-center-text t + default-text-properties '(line-height 1.1)) + (let ((inhibit-read-only t) + (inhibit-modification-hooks t)) + (visual-fill-column-mode) + ;; (setq-local shr-current-font '(:family "Merriweather" :height 1.2)) + (set-buffer-modified-p nil))) + + (defun +rss/elfeed-search-print-entry (entry) + "Print ENTRY to the buffer." + (let* ((elfeed-goodies/tag-column-width 40) + (elfeed-goodies/feed-source-column-width 30) + (title (or (elfeed-meta entry :title) (elfeed-entry-title entry) "")) + (title-faces (elfeed-search--faces (elfeed-entry-tags entry))) + (feed (elfeed-entry-feed entry)) + (feed-title + (when feed + (or (elfeed-meta feed :title) (elfeed-feed-title feed)))) + (tags (mapcar #'symbol-name (elfeed-entry-tags entry))) + (tags-str (concat (mapconcat 'identity tags ","))) + (title-width (- (window-width) elfeed-goodies/feed-source-column-width + elfeed-goodies/tag-column-width 4)) + + (tag-column (elfeed-format-column + tags-str (elfeed-clamp (length tags-str) + elfeed-goodies/tag-column-width + elfeed-goodies/tag-column-width) + :left)) + (feed-column (elfeed-format-column + feed-title (elfeed-clamp elfeed-goodies/feed-source-column-width + elfeed-goodies/feed-source-column-width + elfeed-goodies/feed-source-column-width) + :left))) + + (insert (propertize feed-column 'face 'elfeed-search-feed-face) " ") + (insert (propertize tag-column 'face 'elfeed-search-tag-face) " ") + (insert (propertize title 'face title-faces 'kbd-help title)))) + + (defun +rss/elfeed-show-refresh--better-style () + "Update the buffer to match the selected entry, using a mail-style." + (interactive) + (let* ((inhibit-read-only t) + (title (elfeed-entry-title elfeed-show-entry)) + (date (seconds-to-time (elfeed-entry-date elfeed-show-entry))) + (author (elfeed-meta elfeed-show-entry :author)) + (link (elfeed-entry-link elfeed-show-entry)) + (tags (elfeed-entry-tags elfeed-show-entry)) + (tagsstr (mapconcat #'symbol-name tags ", ")) + (nicedate (format-time-string "%a, %e %b %Y %T %Z" date)) + (content (elfeed-deref (elfeed-entry-content elfeed-show-entry))) + (type (elfeed-entry-content-type elfeed-show-entry)) + (feed (elfeed-entry-feed elfeed-show-entry)) + (feed-title (elfeed-feed-title feed)) + (base (and feed (elfeed-compute-base (elfeed-feed-url feed))))) + (erase-buffer) + (insert "\n") + (insert (format "%s\n\n" (propertize title 'face 'elfeed-show-title-face))) + (insert (format "%s\t" (propertize feed-title 'face 'elfeed-search-feed-face))) + (when (and author elfeed-show-entry-author) + (insert (format "%s\n" (propertize author 'face 'elfeed-show-author-face)))) + (insert (format "%s\n\n" (propertize nicedate 'face 'elfeed-log-date-face))) + (when tags + (insert (format "%s\n" + (propertize tagsstr 'face 'elfeed-search-tag-face)))) + ;; (insert (propertize "Link: " 'face 'message-header-name)) + ;; (elfeed-insert-link link link) + ;; (insert "\n") + (cl-loop for enclosure in (elfeed-entry-enclosures elfeed-show-entry) + do (insert (propertize "Enclosure: " 'face 'message-header-name)) + do (elfeed-insert-link (car enclosure)) + do (insert "\n")) + (insert "\n") + (if content + (if (eq type 'html) + (elfeed-insert-html content base) + (insert content)) + (insert (propertize "(empty)\n" 'face 'italic))) + (goto-char (point-min))))) + +(after! elfeed-show + (require 'url) + + (defvar elfeed-pdf-dir + (expand-file-name "pdfs/" + (file-name-directory (directory-file-name elfeed-enclosure-default-dir)))) + + (defvar elfeed-link-pdfs + '(("https://www.jstatsoft.org/index.php/jss/article/view/v0\\([^/]+\\)" . "https://www.jstatsoft.org/index.php/jss/article/view/v0\\1/v\\1.pdf") + ("http://arxiv.org/abs/\\([^/]+\\)" . "https://arxiv.org/pdf/\\1.pdf")) + "List of alists of the form (REGEX-FOR-LINK . FORM-FOR-PDF)") + + (defun elfeed-show-pdf (entry) + (interactive + (list (or elfeed-show-entry (elfeed-search-selected :ignore-region)))) + (let ((link (elfeed-entry-link entry)) + (feed-name (plist-get (elfeed-feed-meta (elfeed-entry-feed entry)) :title)) + (title (elfeed-entry-title entry)) + (file-view-function + (lambda (f) + (when elfeed-show-entry + (elfeed-kill-buffer)) + (pop-to-buffer (find-file-noselect f)))) + pdf) + + (let ((file (expand-file-name + (concat (subst-char-in-string ?/ ?, title) ".pdf") + (expand-file-name (subst-char-in-string ?/ ?, feed-name) + elfeed-pdf-dir)))) + (if (file-exists-p file) + (funcall file-view-function file) + (dolist (link-pdf elfeed-link-pdfs) + (when (and (string-match-p (car link-pdf) link) + (not pdf)) + (setq pdf (replace-regexp-in-string (car link-pdf) (cdr link-pdf) link)))) + (if (not pdf) + (message "No associated PDF for entry") + (message "Fetching %s" pdf) + (unless (file-exists-p (file-name-directory file)) + (make-directory (file-name-directory file) t)) + (url-copy-file pdf file) + (funcall file-view-function file))))))) +#+end_src + +** COMMENT Ebooks +[[xkcd:548]] + +To actually read the ebooks we use =nov=. +#+begin_src emacs-lisp +(use-package! nov + :mode ("\\.epub\\'" . nov-mode) + :config + (map! :map nov-mode-map + :n "RET" #'nov-scroll-up) + + (advice-add 'nov-render-title :override #'ignore) + (defun +nov-mode-setup () + (face-remap-add-relative 'default :height 1.3) + (setq-local next-screen-context-lines 4 + shr-use-colors nil) + (require 'visual-fill-column nil t) + (setq-local visual-fill-column-center-text t + visual-fill-column-width 81 + nov-text-width 80) + (visual-fill-column-mode 1) + (add-to-list '+lookup-definition-functions #'+lookup/dictionary-definition) + (add-hook 'nov-mode-hook #'+nov-mode-setup))) +#+end_src + + + +* Org +** Org-Mode +I really like org mode, I've given some thought to why, and below is the result. +#+attr_latex: :align *{8}{p{0.105\linewidth}} :font \small +| Format | Fine-grained control | Initial ease of use | Syntax simplicity | Editor Support | Integrations | Ease-of-referencing | Versatility | +|-------------------+----------------------+---------------------+-------------------+----------------+--------------+---------------------+-------------| +| Word | 2 | 4 | 4 | 2 | 3 | 2 | 2 | +| LaTeX | 4 | 1 | 1 | 3 | 2 | 4 | 3 | +| Org Mode | 4 | 2 | 3.5 | 1 | 4 | 4 | 4 | +| Markdown | 1 | 3 | 3 | 4 | 3 | 3 | 1 | +| Markdown + Pandoc | 2.5 | 2.5 | 2.5 | 3 | 3 | 3 | 2 | + + +Beyond the elegance in the markup language, tremendously rich integrations with +Emacs allow for some fantastic [[https://orgmode.org/features.html][features]], such as what seems to be the best +support for [[https://en.wikipedia.org/wiki/Literate_programming][literate programming]] of any currently available technology. + +I prefer /org as my directory. Lets change some other defaults too +#+begin_src emacs-lisp +(after! org + (setq org-directory "~/org" ; let's put files here + org-ellipsis " ﬋" ; cute icon for folded org blocks + org-list-allow-alphabetical t ; have a. A. a) A) list bullets + org-use-property-inheritance t ; it's convenient to have properties inherited + org-catch-invisible-edits 'smart ; try not to accidently do weird stuff in invisible regions + org-log-done 'time ; having the time a item is done sounds convenient + org-roam-directory "~/org/roam/")) ; same thing, for roam +#+end_src + +And some extra fontification doesn't hurt +#+begin_src emacs-lisp +(after! org + (setq org-src-fontify-natively t + org-fontify-whole-heading-line t + org-inline-src-prettify-results '("⟨" . "⟩") + org-fontify-done-headline t + org-fontify-quote-and-verse-blocks t)) +#+end_src + +I want to slightly change the default args for babel +#+begin_src emacs-lisp +(after! org + (setq org-babel-default-header-args + '((:session . "none") + (:results . "replace") + (:exports . "code") + (:cache . "no") + (:noweb . "no") + (:hlines . "no") + (:tangle . "no") + (:comments . "link")))) +#+end_src + +I also want to change the order of bullets +#+begin_src emacs-lisp +(after! org + (setq org-list-demote-modify-bullet '(("+" . "-") ("-" . "+") ("*" . "+") ("1." . "a.")))) +#+end_src + +And the default dashes and =+= signs just don't cut it anymore. Lets make them fancy bullets instead +#+begin_src emacs-lisp +(font-lock-add-keywords 'org-mode + '(("^ *\\([-]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))) +(font-lock-add-keywords 'org-mode + '(("^ *\\([+]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "◦")))))) +#+end_src + +The =[[yt:...]]= links preview nicely, but don’t export nicely. Thankfully, we can fix that. +#+begin_src emacs-lisp +(after! ox + (org-link-set-parameters "yt" :export #'+org-export-yt) + (defun +org-export-yt (path desc backend _com) + (cond ((org-export-derived-backend-p backend 'html) + (format "" path (or "" desc))) + ((org-export-derived-backend-p backend 'latex) + (format "\\href{https://youtu.be/%s}{%s}" path (or desc "youtube"))) + (t (format "https://youtu.be/%s" path))))) +#+end_src + +*** HTML export +Inspired by Tecosaur's amazing org-css, I wanted to make my own, but with fewer features and slightly cleaner overall. +#+begin_src emacs-lisp +(defun org-inline-css-hook (exporter) + "Insert custom inline css" + (when (eq exporter 'html) + (let* ((dir (ignore-errors (file-name-directory (buffer-file-name)))) + (path (concat dir "style.css")) + (homestyle (or (null dir) (null (file-exists-p path)))) + (final (if homestyle (expand-file-name "misc/org-css/style.css" doom-private-dir) path))) + (setq org-html-head-include-default-style nil) + (setq org-html-head (concat + "\n"))))) + +(defun org-inline-js-hook (exporter) + "Insert custom inline css" + (when (eq exporter 'html) + (let* ((dir (ignore-errors (file-name-directory (buffer-file-name)))) + (path (concat dir "style.js")) + (homestyle (or (null dir) (null (file-exists-p path)))) + (final (if homestyle (expand-file-name "misc/org-css/style.js" doom-private-dir) path))) + (setq org-html-head-include-default-style nil) + (setq org-html-head (concat + "\n"))))) + +(defun org-inline-html-hook (exporter) + "Insert custom inline css" + (when (eq exporter 'html) + (let* ((dir (ignore-errors (file-name-directory (buffer-file-name)))) + (path (concat dir "style.html")) + (homestyle (or (null dir) (null (file-exists-p path)))) + (final (if homestyle (expand-file-name "misc/org-css/style.html" doom-private-dir) path))) + (setq org-html-head-include-default-style nil) + (setq org-html-head (concat + (with-temp-buffer + (insert-file-contents final) + (buffer-string)) + "\n"))))) + +(add-hook 'org-export-before-processing-hook 'org-inline-css-hook) +(add-hook 'org-export-before-processing-hook 'org-inline-js-hook) +(add-hook 'org-export-before-processing-hook 'org-inline-html-hook) +#+end_src + +If MathJax is used, we want to use version 3 instead of the default version 2. +Looking at a [[https://www.intmath.com/cg5/katex-mathjax-comparison.php][comparison]] we seem to find that it is ~5 times as fast, uses a +single file instead of multiple, but seems to be a bit bigger unfortunately. +Thankfully this can be mitigated my adding the ~async~ attribute to defer loading. + +#+begin_src emacs-lisp +(after! ox-html + (setq org-html-mathjax-options + '((path "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" ) + (scale "1") + (autonumber "ams") + (multlinewidth "85%") + (tagindent ".8em") + (tagside "right"))) + + (setq org-html-mathjax-template + " + ")) +#+end_src + +And now to preview that export live +#+begin_src emacs-lisp +(use-package! org-preview-html + :commands org-preview-html-mode + :config + (setq org-preview-html-refresh-configuration 'save + org-preview-html-viewer 'xwidget)) +#+end_src + +I like to preview images inline too +#+begin_src emacs-lisp +(setq org-startup-with-inline-images t) +#+end_src + +** COMMENT Org-Roam +Lets set up =org-roam-ui= +#+begin_src emacs-lisp +(use-package! websocket + :after org-roam) + +(use-package! org-roam-ui + :after org-roam + :commands org-roam-ui-open + :config + (setq org-roam-ui-sync-theme t + org-roam-ui-follow t + org-roam-ui-update-on-save t + org-roam-ui-open-on-start t)) +#+end_src + +Now, I want to replace the org-roam buffer with org-roam-ui, to do that, we need +to disable the regular buffer +#+begin_src emacs-lisp +(after! org-roam + (setq +org-roam-open-buffer-on-find-file nil)) +#+end_src + +** COMMENT Org-Agenda +Set the directory +#+begin_src emacs-lisp +(after! org-agenda + (setq org-agenda-files (list "~/org/school.org" + "~/org/todo.org")) + (setq org-agenda-window-setup 'current-window + org-agenda-restore-windows-after-quit t + org-agenda-show-all-dates nil + org-agenda-time-in-grid t + org-agenda-show-current-time-in-grid t + org-agenda-start-on-weekday 1 + org-agenda-span 7 + org-agenda-tags-column 0 + org-agenda-block-separator nil + org-agenda-category-icon-alist nil + org-agenda-sticky t) + (setq org-agenda-prefix-format + '((agenda . "%i %?-12t%s") + (todo . "%i") + (tags . "%i") + (search . "%i"))) + (setq org-agenda-sorting-strategy + '((agenda deadline-down scheduled-down todo-state-up time-up + habit-down priority-down category-keep) + (todo priority-down category-keep) + (tags timestamp-up priority-down category-keep) + (search category-keep)))) +#+end_src + +** COMMENT Font Display +It seems reasonable to have deadlines in the error face when they're passed. +#+begin_src emacs-lisp +(after! org + (setq org-agenda-deadline-faces + '((1.0 . error) + (1.0 . org-warning) + (0.5 . org-upcoming-deadline) + (0.0 . org-upcoming-distant-deadline)))) +#+end_src + +And lets conceal *those* /syntax/ +markers+. +#+begin_src emacs-lisp +(use-package! org-appear + :after org + :hook (org-mode . org-appear-mode) + :config + (setq org-appear-autoemphasis t + org-appear-autolinks t + org-appear-autosubmarkers t)) +#+end_src + +*** (sub|super)script characters +Annoying having to gate these, so let's fix that +#+begin_src emacs-lisp +(setq org-export-with-sub-superscripts '{}) +#+end_src + +*** Make verbatim different to code +Since have just gone to so much effort above let's make the most of it by making +=verbatim= use ~verb~ instead of ~protectedtexttt~ (default). +#+begin_src emacs-lisp +(after! org + (setq org-latex-text-markup-alist + '((bold . "\\textbf{%s}") + (code . protectedtexttt) + (italic . "\\emph{%s}") + (strike-through . "\\sout{%s}") + (underline . "\\uline{%s}") + (verbatim . verb)))) +#+end_src + +** COMMENT XKCD +[[xkcd:446]] + +#+begin_quote +Relevent XKCD: +#+end_quote + +I link to xkcd's so much that its better to just have a configuration for them +We want to set this up so it loads nicely in org. +#+begin_src emacs-lisp +(use-package! xkcd + :commands (xkcd-get-json + xkcd-download xkcd-get + ;; now for funcs from my extension of this pkg + +xkcd-find-and-copy +xkcd-find-and-view + +xkcd-fetch-info +xkcd-select) + :config + (setq xkcd-cache-dir (expand-file-name "xkcd/" doom-cache-dir) + xkcd-cache-latest (concat xkcd-cache-dir "latest")) + (unless (file-exists-p xkcd-cache-dir) + (make-directory xkcd-cache-dir)) + :general (:states 'normal + :keymaps 'xkcd-mode-map + "" #'xkcd-next + "n" #'xkcd-next + "" #'xkcd-prev + "N" #'xkcd-prev + "r" #'xkcd-rand + "a" #'xkcd-rand ; because image-rotate can interfere + "t" #'xkcd-alt-text + "q" #'xkcd-kill-buffer + "o" #'xkcd-open-browser + "e" #'xkcd-open-explanation-browser + ;; extras + "s" #'+xkcd-find-and-view + "/" #'+xkcd-find-and-view + "y" #'+xkcd-copy)) +#+end_src + +Let's also extend the functionality a whole bunch. +#+begin_src emacs-lisp +(after! xkcd + (require 'emacsql-sqlite) + + (defun +xkcd-select () + "Prompt the user for an xkcd using `completing-read' and `+xkcd-select-format'. Return the xkcd number or nil" + (let* (prompt-lines + (-dummy (maphash (lambda (key xkcd-info) + (push (+xkcd-select-format xkcd-info) prompt-lines)) + +xkcd-stored-info)) + (num (completing-read (format "xkcd (%s): " xkcd-latest) prompt-lines))) + (if (equal "" num) xkcd-latest + (string-to-number (replace-regexp-in-string "\\([0-9]+\\).*" "\\1" num))))) + + (defun +xkcd-select-format (xkcd-info) + "Creates each completing-read line from an xkcd info plist. Must start with the xkcd number" + (format "%-4s %-30s %s" + (propertize (number-to-string (plist-get xkcd-info :num)) + 'face 'counsel-key-binding) + (plist-get xkcd-info :title) + (propertize (plist-get xkcd-info :alt) + 'face '(variable-pitch font-lock-comment-face)))) + + (defun +xkcd-fetch-info (&optional num) + "Fetch the parsed json info for comic NUM. Fetches latest when omitted or 0" + (require 'xkcd) + (when (or (not num) (= num 0)) + (+xkcd-check-latest) + (setq num xkcd-latest)) + (let ((res (or (gethash num +xkcd-stored-info) + (puthash num (+xkcd-db-read num) +xkcd-stored-info)))) + (unless res + (+xkcd-db-write + (let* ((url (format "https://xkcd.com/%d/info.0.json" num)) + (json-assoc + (if (gethash num +xkcd-stored-info) + (gethash num +xkcd-stored-info) + (json-read-from-string (xkcd-get-json url num))))) + json-assoc)) + (setq res (+xkcd-db-read num))) + res)) + + ;; since we've done this, we may as well go one little step further + (defun +xkcd-find-and-copy () + "Prompt for an xkcd using `+xkcd-select' and copy url to clipboard" + (interactive) + (+xkcd-copy (+xkcd-select))) + + (defun +xkcd-copy (&optional num) + "Copy a url to xkcd NUM to the clipboard" + (interactive "i") + (let ((num (or num xkcd-cur))) + (gui-select-text (format "https://xkcd.com/%d" num)) + (message "xkcd.com/%d copied to clipboard" num))) + + (defun +xkcd-find-and-view () + "Prompt for an xkcd using `+xkcd-select' and view it" + (interactive) + (xkcd-get (+xkcd-select)) + (switch-to-buffer "*xkcd*")) + + (defvar +xkcd-latest-max-age (* 60 60) ; 1 hour + "Time after which xkcd-latest should be refreshed, in seconds") + + ;; initialise `xkcd-latest' and `+xkcd-stored-info' with latest xkcd + (add-transient-hook! '+xkcd-select + (require 'xkcd) + (+xkcd-fetch-info xkcd-latest) + (setq +xkcd-stored-info (+xkcd-db-read-all))) + + (add-transient-hook! '+xkcd-fetch-info + (xkcd-update-latest)) + + (defun +xkcd-check-latest () + "Use value in `xkcd-cache-latest' as long as it isn't older thabn `+xkcd-latest-max-age'" + (unless (and (file-exists-p xkcd-cache-latest) + (< (- (time-to-seconds (current-time)) + (time-to-seconds (file-attribute-modification-time (file-attributes xkcd-cache-latest)))) + +xkcd-latest-max-age)) + (let* ((out (xkcd-get-json "http://xkcd.com/info.0.json" 0)) + (json-assoc (json-read-from-string out)) + (latest (cdr (assoc 'num json-assoc)))) + (when (/= xkcd-latest latest) + (+xkcd-db-write json-assoc) + (with-current-buffer (find-file xkcd-cache-latest) + (setq xkcd-latest latest) + (erase-buffer) + (insert (number-to-string latest)) + (save-buffer) + (kill-buffer (current-buffer))))) + (shell-command (format "touch %s" xkcd-cache-latest)))) + + (defvar +xkcd-stored-info (make-hash-table :test 'eql) + "Basic info on downloaded xkcds, in the form of a hashtable") + + (defadvice! xkcd-get-json--and-cache (url &optional num) + "Fetch the Json coming from URL. +If the file NUM.json exists, use it instead. +If NUM is 0, always download from URL. +The return value is a string." + :override #'xkcd-get-json + (let* ((file (format "%s%d.json" xkcd-cache-dir num)) + (cached (and (file-exists-p file) (not (eq num 0)))) + (out (with-current-buffer (if cached + (find-file file) + (url-retrieve-synchronously url)) + (goto-char (point-min)) + (unless cached (re-search-forward "^$")) + (prog1 + (buffer-substring-no-properties (point) (point-max)) + (kill-buffer (current-buffer)))))) + (unless (or cached (eq num 0)) + (xkcd-cache-json num out)) + out)) + + (defadvice! +xkcd-get (num) + "Get the xkcd number NUM." + :override 'xkcd-get + (interactive "nEnter comic number: ") + (xkcd-update-latest) + (get-buffer-create "*xkcd*") + (switch-to-buffer "*xkcd*") + (xkcd-mode) + (let (buffer-read-only) + (erase-buffer) + (setq xkcd-cur num) + (let* ((xkcd-data (+xkcd-fetch-info num)) + (num (plist-get xkcd-data :num)) + (img (plist-get xkcd-data :img)) + (safe-title (plist-get xkcd-data :safe-title)) + (alt (plist-get xkcd-data :alt)) + title file) + (message "Getting comic...") + (setq file (xkcd-download img num)) + (setq title (format "%d: %s" num safe-title)) + (insert (propertize title + 'face 'outline-1)) + (center-line) + (insert "\n") + (xkcd-insert-image file num) + (if (eq xkcd-cur 0) + (setq xkcd-cur num)) + (setq xkcd-alt alt) + (message "%s" title)))) + + (defconst +xkcd-db--sqlite-available-p + (with-demoted-errors "+org-xkcd initialization: %S" + (emacsql-sqlite-ensure-binary) + t)) + + (defvar +xkcd-db--connection (make-hash-table :test #'equal) + "Database connection to +org-xkcd database.") + + (defun +xkcd-db--get () + "Return the sqlite db file." + (expand-file-name "xkcd.db" xkcd-cache-dir)) + + (defun +xkcd-db--get-connection () + "Return the database connection, if any." + (gethash (file-truename xkcd-cache-dir) + +xkcd-db--connection)) + + (defconst +xkcd-db--table-schema + '((xkcds + [(num integer :unique :primary-key) + (year :not-null) + (month :not-null) + (link :not-null) + (news :not-null) + (safe_title :not-null) + (title :not-null) + (transcript :not-null) + (alt :not-null) + (img :not-null)]))) + + (defun +xkcd-db--init (db) + "Initialize database DB with the correct schema and user version." + (emacsql-with-transaction db + (pcase-dolist (`(,table . ,schema) +xkcd-db--table-schema) + (emacsql db [:create-table $i1 $S2] table schema)))) + + (defun +xkcd-db () + "Entrypoint to the +org-xkcd sqlite database. +Initializes and stores the database, and the database connection. +Performs a database upgrade when required." + (unless (and (+xkcd-db--get-connection) + (emacsql-live-p (+xkcd-db--get-connection))) + (let* ((db-file (+xkcd-db--get)) + (init-db (not (file-exists-p db-file)))) + (make-directory (file-name-directory db-file) t) + (let ((conn (emacsql-sqlite db-file))) + (set-process-query-on-exit-flag (emacsql-process conn) nil) + (puthash (file-truename xkcd-cache-dir) + conn + +xkcd-db--connection) + (when init-db + (+xkcd-db--init conn))))) + (+xkcd-db--get-connection)) + + (defun +xkcd-db-query (sql &rest args) + "Run SQL query on +org-xkcd database with ARGS. +SQL can be either the emacsql vector representation, or a string." + (if (stringp sql) + (emacsql (+xkcd-db) (apply #'format sql args)) + (apply #'emacsql (+xkcd-db) sql args))) + + (defun +xkcd-db-read (num) + (when-let ((res + (car (+xkcd-db-query [:select * :from xkcds + :where (= num $s1)] + num + :limit 1)))) + (+xkcd-db-list-to-plist res))) + + (defun +xkcd-db-read-all () + (let ((xkcd-table (make-hash-table :test 'eql :size 4000))) + (mapcar (lambda (xkcd-info-list) + (puthash (car xkcd-info-list) (+xkcd-db-list-to-plist xkcd-info-list) xkcd-table)) + (+xkcd-db-query [:select * :from xkcds])) + xkcd-table)) + + (defun +xkcd-db-list-to-plist (xkcd-datalist) + `(:num ,(nth 0 xkcd-datalist) + :year ,(nth 1 xkcd-datalist) + :month ,(nth 2 xkcd-datalist) + :link ,(nth 3 xkcd-datalist) + :news ,(nth 4 xkcd-datalist) + :safe-title ,(nth 5 xkcd-datalist) + :title ,(nth 6 xkcd-datalist) + :transcript ,(nth 7 xkcd-datalist) + :alt ,(nth 8 xkcd-datalist) + :img ,(nth 9 xkcd-datalist))) + + (defun +xkcd-db-write (data) + (+xkcd-db-query [:insert-into xkcds + :values $v1] + (list (vector + (cdr (assoc 'num data)) + (cdr (assoc 'year data)) + (cdr (assoc 'month data)) + (cdr (assoc 'link data)) + (cdr (assoc 'news data)) + (cdr (assoc 'safe_title data)) + (cdr (assoc 'title data)) + (cdr (assoc 'transcript data)) + (cdr (assoc 'alt data)) + (cdr (assoc 'img data))))))) +#+end_src + +Now to just have this register with org +#+begin_src emacs-lisp +(after! org + (org-link-set-parameters "xkcd" + :image-data-fun #'+org-xkcd-image-fn + :follow #'+org-xkcd-open-fn + :export #'+org-xkcd-export + :complete #'+org-xkcd-complete) + + (defun +org-xkcd-open-fn (link) + (+org-xkcd-image-fn nil link nil)) + + (defun +org-xkcd-image-fn (protocol link description) + "Get image data for xkcd num LINK" + (let* ((xkcd-info (+xkcd-fetch-info (string-to-number link))) + (img (plist-get xkcd-info :img)) + (alt (plist-get xkcd-info :alt))) + (message alt) + (+org-image-file-data-fn protocol (xkcd-download img (string-to-number link)) description))) + + (defun +org-xkcd-export (num desc backend _com) + "Convert xkcd to html/LaTeX form" + (let* ((xkcd-info (+xkcd-fetch-info (string-to-number num))) + (img (plist-get xkcd-info :img)) + (alt (plist-get xkcd-info :alt)) + (title (plist-get xkcd-info :title)) + (file (xkcd-download img (string-to-number num)))) + (cond ((org-export-derived-backend-p backend 'html) + (format "%s" img (subst-char-in-string ?\" ?“ alt) title)) + ((org-export-derived-backend-p backend 'latex) + (format "\\begin{figure}[!htb] + \\centering + \\includegraphics[scale=0.4]{%s}%s + \\end{figure}" file (if (equal desc (format "xkcd:%s" num)) "" + (format "\n \\caption*{\\label{xkcd:%s} %s}" + num + (or desc + (format "\\textbf{%s} %s" title alt)))))) + (t (format "https://xkcd.com/%s" num))))) + + (defun +org-xkcd-complete (&optional arg) + "Complete xkcd using `+xkcd-stored-info'" + (format "xkcd:%d" (+xkcd-select)))) +#+end_src + +** COMMENT Calc +Embedded calc is a lovely feature which let's us use calc to operate on LaTeX +maths expressions. The standard keybinding is a bit janky however (=C-x * e=), so +we'll add a localleader-based alternative. + +#+begin_src emacs-lisp +(map! :map calc-mode-map + :after calc + :localleader + :desc "Embedded calc (toggle)" "e" #'calc-embedded) +(map! :map org-mode-map + :after org + :localleader + :desc "Embedded calc (toggle)" "E" #'calc-embedded) +(map! :map latex-mode-map + :after latex + :localleader + :desc "Embedded calc (toggle)" "e" #'calc-embedded) +#+end_src + +Unfortunately this operates without the (rather informative) calculator and +trail buffers, but we can advice it that we would rather like those in a side +panel. + +#+begin_src emacs-lisp +(defvar calc-embedded-trail-window nil) +(defvar calc-embedded-calculator-window nil) + +(defadvice! calc-embedded-with-side-pannel (&rest _) + :after #'calc-do-embedded + (when calc-embedded-trail-window + (ignore-errors + (delete-window calc-embedded-trail-window)) + (setq calc-embedded-trail-window nil)) + (when calc-embedded-calculator-window + (ignore-errors + (delete-window calc-embedded-calculator-window)) + (setq calc-embedded-calculator-window nil)) + (when (and calc-embedded-info + (> (* (window-width) (window-height)) 1200)) + (let ((main-window (selected-window)) + (vertical-p (> (window-width) 80))) + (select-window + (setq calc-embedded-trail-window + (if vertical-p + (split-window-horizontally (- (max 30 (/ (window-width) 3)))) + (split-window-vertically (- (max 8 (/ (window-height) 4))))))) + (switch-to-buffer "*Calc Trail*") + (select-window + (setq calc-embedded-calculator-window + (if vertical-p + (split-window-vertically -6) + (split-window-horizontally (- (/ (window-width) 2)))))) + (switch-to-buffer "*Calculator*") + (select-window main-window)))) +#+end_src + +*** Dictionaries +On every system I use (I have a lot of systems) the dictionary results in doom/emacs are different, and that gets annoying. Lets use lexic + stardict, instead of the default dictionaries. +#+begin_src emacs-lisp +(use-package! lexic + :commands lexic-search lexic-list-dictionary + :config + (map! :map lexic-mode-map + :n "q" #'lexic-return-from-lexic + :nv "RET" #'lexic-search-word-at-point + :n "a" #'outline-show-all + :n "h" (cmd! (outline-hide-sublevels 3)) + :n "o" #'lexic-toggle-entry + :n "n" #'lexic-next-entry + :n "N" (cmd! (lexic-next-entry t)) + :n "p" #'lexic-previous-entry + :n "P" (cmd! (lexic-previous-entry t)) + :n "E" (cmd! (lexic-return-from-lexic) ; expand + (switch-to-buffer (lexic-get-buffer))) + :n "M" (cmd! (lexic-return-from-lexic) ; minimise + (lexic-goto-lexic)) + :n "C-p" #'lexic-search-history-backwards + :n "C-n" #'lexic-search-history-forwards + :n "/" (cmd! (call-interactively #'lexic-search)))) + +(defadvice! +lookup/dictionary-definition-lexic (identifier &optional arg) + "Look up the definition of the word at point (or selection) using `lexic-search'." + :override #'+lookup/dictionary-definition + (interactive + (list (or (doom-thing-at-point-or-region 'word) + (read-string "Look up in dictionary: ")) + current-prefix-arg)) + (lexic-search identifier nil nil t)) +#+end_src + +* COMMENT LaTeX +Note that this \(\LaTeX\) export configuration is largely borrowed from Tecosaur and Elken, and just adjusted to fit my needs. Big thanks to them for their excellent configs. +** PDF-Tools +DocView gives me a headache, but pdf-tools can be improved, lets configure it a little more +#+begin_src emacs-lisp +(use-package! pdf-view + :hook (pdf-tools-enabled . pdf-view-themed-minor-mode) + :config + (setq pdf-view-use-scaling t + pdf-view-use-imagemagick nil + pdf-view-display-size 'fit-page)) +#+end_src + +*** View Exported File +I have to export files pretty often, lets setup some keybindings to make it easier +#+begin_src emacs-lisp +(map! :map org-mode-map + :localleader + :desc "View exported file" "v" #'org-view-output-file) + +(defun org-view-output-file (&optional org-file-path) + "Visit buffer open on the first output file (if any) found, using `org-view-output-file-extensions'" + (interactive) + (let* ((org-file-path (or org-file-path (buffer-file-name) "")) + (dir (file-name-directory org-file-path)) + (basename (file-name-base org-file-path)) + (output-file nil)) + (dolist (ext org-view-output-file-extensions) + (unless output-file + (when (file-exists-p + (concat dir basename "." ext)) + (setq output-file (concat dir basename "." ext))))) + (if output-file + (if (member (file-name-extension output-file) org-view-external-file-extensions) + (browse-url-xdg-open output-file) + (pop-to-bufferpop-to-buffer (or (find-buffer-visiting output-file) + (find-file-noselect output-file)))) + (message "No exported file found")))) + +(defvar org-view-output-file-extensions '("pdf" "md" "rst" "txt" "tex" "html") + "Search for output files with these extensions, in order, viewing the first that matches") +(defvar org-view-external-file-extensions '("html") + "File formats that should be opened externally.") +#+end_src + +** \(\LaTeX\) highlighting in Org-mode +The default inline latex highlighting is a bit bland. Normally this would be fixed with the =+pretty= flag, but that has its own issues. Lets just stick to enabling it manually. +#+begin_src emacs-lisp +(after! org + (setq org-highlight-latex-and-related '(native script entities)) + (add-to-list 'org-src-block-faces '("latex" (:inherit default :extend t)))) +#+end_src + +Our org-mode config gets a bit expensive though. Lets make a small mode with just the basics, for exporting +#+begin_src emacs-lisp +(defun +org-mode--fontlock-only-mode () + "Just apply org-mode's font-lock once." + (let (org-mode-hook + org-hide-leading-stars + org-hide-emphasis-markers) + (org-set-font-lock-defaults) + (font-lock-ensure)) + (setq-local major-mode #'fundamental-mode)) + +(defun +org-export-babel-mask-org-config (_backend) + "Use `+org-mode--fontlock-only-mode' instead of `org-mode'." + (setq-local org-src-lang-modes + (append org-src-lang-modes + (list (cons "org" #'+org-mode--fontlock-only))))) + +(add-hook 'org-export-before-processing-hook #'+org-export-babel-mask-org-config) +#+end_src + +** Tectonic +Tectonic is the hot new thing, which also means I can get rid of my tex installation. +#+begin_src emacs-lisp +(after! org + (setq-default org-latex-pdf-process '("tectonic -Z shell-escape --outdir=%o %f"))) +#+end_src + +Looks crisp! +\begin{align*} + f(x) &= x^2\\ + g(x) &= \frac{1}{x}\\ + F(x) &= \int^a_b \frac{1}{3}x^3 +\end{align*} + +** Preambles +Various preamble setups to improve the overall look of several items +#+begin_src emacs-lisp +(defvar org-latex-caption-preamble " +\\usepackage{subcaption} +\\usepackage[hypcap=true]{caption} +\\setkomafont{caption}{\\sffamily\\small} +\\setkomafont{captionlabel}{\\upshape\\bfseries} +\\captionsetup{justification=raggedright,singlelinecheck=true} +\\usepackage{capt-of} % required by Org +" + "Preamble that improves captions.") + +(defvar org-latex-checkbox-preamble " +\\newcommand{\\checkboxUnchecked}{$\\square$} +\\newcommand{\\checkboxTransitive}{\\rlap{\\raisebox{-0.1ex}{\\hspace{0.35ex}\\Large\\textbf -}}$\\square$} +\\newcommand{\\checkboxChecked}{\\rlap{\\raisebox{0.2ex}{\\hspace{0.35ex}\\scriptsize \\ding{52}}}$\\square$} +" + "Preamble that improves checkboxes.") + +(defvar org-latex-box-preamble " +% args = #1 Name, #2 Colour, #3 Ding, #4 Label +\\newcommand{\\defsimplebox}[4]{% + \\definecolor{#1}{HTML}{#2} + \\newenvironment{#1}[1][] + {% + \\par\\vspace{-0.7\\baselineskip}% + \\textcolor{#1}{#3} \\textcolor{#1}{\\textbf{\\def\\temp{##1}\\ifx\\temp\\empty#4\\else##1\\fi}}% + \\vspace{-0.8\\baselineskip} + \\begin{addmargin}[1em]{1em} + }{% + \\end{addmargin} + \\vspace{-0.5\\baselineskip} + }% +} +" + "Preamble that provides a macro for custom boxes.") +#+end_src + +** Conditional features +Don't always need everything in LaTeX, so only add it what we need when we need it. +#+begin_src emacs-lisp +(defvar org-latex-italic-quotes t + "Make \"quote\" environments italic.") +(defvar org-latex-par-sep t + "Vertically seperate paragraphs, and remove indentation.") + +(defvar org-latex-conditional-features + '(("\\[\\[\\(?:file\\|https?\\):\\(?:[^]]\\|\\\\\\]\\)+?\\.\\(?:eps\\|pdf\\|png\\|jpeg\\|jpg\\|jbig2\\)\\]\\]" . image) + ("\\[\\[\\(?:file\\|https?\\):\\(?:[^]]+?\\|\\\\\\]\\)\\.svg\\]\\]\\|\\\\includesvg" . svg) + ("^[ \t]*|" . table) + ("cref:\\|\\cref{\\|\\[\\[[^\\]]+\\]\\]" . cleveref) + ("[;\\\\]?\\b[A-Z][A-Z]+s?[^A-Za-z]" . acronym) + ("\\+[^ ].*[^ ]\\+\\|_[^ ].*[^ ]_\\|\\\\uu?line\\|\\\\uwave\\|\\\\sout\\|\\\\xout\\|\\\\dashuline\\|\\dotuline\\|\\markoverwith" . underline) + (":float wrap" . float-wrap) + (":float sideways" . rotate) + ("^[ \t]*#\\+caption:\\|\\\\caption" . caption) + ("\\[\\[xkcd:" . (image caption)) + ((and org-latex-italic-quotes "^[ \t]*#\\+begin_quote\\|\\\\begin{quote}") . italic-quotes) + (org-latex-par-sep . par-sep) + ("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\|[A-Za-z]+[.)]\\) \\[[ -X]\\]" . checkbox) + ("^[ \t]*#\\+begin_warning\\|\\\\begin{warning}" . box-warning) + ("^[ \t]*#\\+begin_info\\|\\\\begin{info}" . box-info) + ("^[ \t]*#\\+begin_success\\|\\\\begin{success}" . box-success) + ("^[ \t]*#\\+begin_error\\|\\\\begin{error}" . box-error)) + "Org feature tests and associated LaTeX feature flags. + +Alist where the car is a test for the presense of the feature, +and the cdr is either a single feature symbol or list of feature symbols. + +When a string, it is used as a regex search in the buffer. +The feature is registered as present when there is a match. + +The car can also be a +- symbol, the value of which is fetched +- function, which is called with info as an argument +- list, which is `eval'uated + +If the symbol, function, or list produces a string: that is used as a regex +search in the buffer. Otherwise any non-nil return value will indicate the +existance of the feature.") + +(defvar org-latex-feature-implementations + '((image :snippet "\\usepackage{graphicx}" :order 2) + (svg :snippet "\\usepackage{svg}" :order 2) + (table :snippet "\\usepackage{longtable}\n\\usepackage{booktabs}" :order 2) + (cleveref :snippet "\\usepackage[capitalize]{cleveref}" :order 1) + (underline :snippet "\\usepackage[normalem]{ulem}" :order 0.5) + (float-wrap :snippet "\\usepackage{wrapfig}" :order 2) + (rotate :snippet "\\usepackage{rotating}" :order 2) + (caption :snippet org-latex-caption-preamble :order 2.1) + (acronym :snippet "\\newcommand{\\acr}[1]{\\protect\\textls*[110]{\\scshape #1}}\n\\newcommand{\\acrs}{\\protect\\scalebox{.91}[.84]{\\hspace{0.15ex}s}}" :order 0.4) + (italic-quotes :snippet "\\renewcommand{\\quote}{\\list{}{\\rightmargin\\leftmargin}\\item\\relax\\em}\n" :order 0.5) + (par-sep :snippet "\\setlength{\\parskip}{\\baselineskip}\n\\setlength{\\parindent}{0pt}\n" :order 0.5) + (.pifont :snippet "\\usepackage{pifont}") + (checkbox :requires .pifont :order 3 + :snippet (concat (unless (memq 'maths features) + "\\usepackage{amssymb} % provides \\square") + org-latex-checkbox-preamble)) + (.fancy-box :requires .pifont :snippet org-latex-box-preamble :order 3.9) + (box-warning :requires .fancy-box :snippet "\\defsimplebox{warning}{e66100}{\\ding{68}}{Warning}" :order 4) + (box-info :requires .fancy-box :snippet "\\defsimplebox{info}{3584e4}{\\ding{68}}{Information}" :order 4) + (box-success :requires .fancy-box :snippet "\\defsimplebox{success}{26a269}{\\ding{68}}{\\vspace{-\\baselineskip}}" :order 4) + (box-error :requires .fancy-box :snippet "\\defsimplebox{error}{c01c28}{\\ding{68}}{Important}" :order 4)) + "LaTeX features and details required to implement them. + +List where the car is the feature symbol, and the rest forms a plist with the +following keys: +- :snippet, which may be either + - a string which should be included in the preamble + - a symbol, the value of which is included in the preamble + - a function, which is evaluated with the list of feature flags as its + single argument. The result of which is included in the preamble + - a list, which is passed to `eval', with a list of feature flags available + as \"features\" + +- :requires, a feature or list of features that must be available +- :when, a feature or list of features that when all available should cause this + to be automatically enabled. +- :prevents, a feature or list of features that should be masked +- :order, for when ordering is important. Lower values appear first. + The default is 0. + +Features that start with ! will be eagerly loaded, i.e. without being detected.") +#+end_src + +First, we need to detect which features we actually need + +#+begin_src emacs-lisp +(defun org-latex-detect-features (&optional buffer info) + "List features from `org-latex-conditional-features' detected in BUFFER." + (let ((case-fold-search nil)) + (with-current-buffer (or buffer (current-buffer)) + (delete-dups + (mapcan (lambda (construct-feature) + (when (let ((out (pcase (car construct-feature) + ((pred stringp) (car construct-feature)) + ((pred functionp) (funcall (car construct-feature) info)) + ((pred listp) (eval (car construct-feature))) + ((pred symbolp) (symbol-value (car construct-feature))) + (_ (user-error "org-latex-conditional-features key %s unable to be used" (car construct-feature)))))) + (if (stringp out) + (save-excursion + (goto-char (point-min)) + (re-search-forward out nil t)) + out)) + (if (listp (cdr construct-feature)) (cdr construct-feature) (list (cdr construct-feature))))) + org-latex-conditional-features))))) +#+end_src + +Then we need to expand them and sort them according to the above definitions + +#+begin_src emacs-lisp +(defun org-latex-expand-features (features) + "For each feature in FEATURES process :requires, :when, and :prevents keywords and sort according to :order." + (dolist (feature features) + (unless (assoc feature org-latex-feature-implementations) + (error "Feature %s not provided in org-latex-feature-implementations" feature))) + (setq current features) + (while current + (when-let ((requirements (plist-get (cdr (assq (car current) org-latex-feature-implementations)) :requires))) + (setcdr current (if (listp requirements) + (append requirements (cdr current)) + (cons requirements (cdr current))))) + (setq current (cdr current))) + (dolist (potential-feature + (append features (delq nil (mapcar (lambda (feat) + (when (plist-get (cdr feat) :eager) + (car feat))) + org-latex-feature-implementations)))) + (when-let ((prerequisites (plist-get (cdr (assoc potential-feature org-latex-feature-implementations)) :when))) + (setf features (if (if (listp prerequisites) + (cl-every (lambda (preq) (memq preq features)) prerequisites) + (memq prerequisites features)) + (append (list potential-feature) features) + (delq potential-feature features))))) + (dolist (feature features) + (when-let ((prevents (plist-get (cdr (assoc feature org-latex-feature-implementations)) :prevents))) + (setf features (cl-set-difference features (if (listp prevents) prevents (list prevents)))))) + (sort (delete-dups features) + (lambda (feat1 feat2) + (if (< (or (plist-get (cdr (assoc feat1 org-latex-feature-implementations)) :order) 1) + (or (plist-get (cdr (assoc feat2 org-latex-feature-implementations)) :order) 1)) + t nil)))) +#+end_src + +Finally, we can create the preamble to be inserted + +#+begin_src emacs-lisp +(defun org-latex-generate-features-preamble (features) + "Generate the LaTeX preamble content required to provide FEATURES. +This is done according to `org-latex-feature-implementations'" + (let ((expanded-features (org-latex-expand-features features))) + (concat + (format "\n%% features: %s\n" expanded-features) + (mapconcat (lambda (feature) + (when-let ((snippet (plist-get (cdr (assoc feature org-latex-feature-implementations)) :snippet))) + (concat + (pcase snippet + ((pred stringp) snippet) + ((pred functionp) (funcall snippet features)) + ((pred listp) (eval `(let ((features ',features)) (,@snippet)))) + ((pred symbolp) (symbol-value snippet)) + (_ (user-error "org-latex-feature-implementations :snippet value %s unable to be used" snippet))) + "\n"))) + expanded-features + "") + "% end features\n"))) +#+end_src + +Last step, some advice to hook in all of the above to work +#+begin_src emacs-lisp +(defvar info--tmp nil) + +(defadvice! org-latex-save-info (info &optional t_ s_) + :before #'org-latex-make-preamble + (setq info--tmp info)) + +(defadvice! org-splice-latex-header-and-generated-preamble-a (orig-fn tpl def-pkg pkg snippets-p &optional extra) + "Dynamically insert preamble content based on `org-latex-conditional-preambles'." + :around #'org-splice-latex-header + (let ((header (funcall orig-fn tpl def-pkg pkg snippets-p extra))) + (if snippets-p header + (concat header + (org-latex-generate-features-preamble (org-latex-detect-features nil info--tmp)) + "\n")))) +#+end_src + +** Class templates +I really like the KOMA bundle. It provides a set of mechanisms to tweak document +styling which is both easy to use, and quite comprehensive. +For example, I rather like section numbers in the margin, which can be +accomplished with +#+begin_src emacs-lisp +(after! ox-latex + (let* ((article-sections '(("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + (book-sections (append '(("\\chapter{%s}" . "\\chapter*{%s}")) + article-sections)) + (hanging-secnum-preamble " +\\renewcommand\\sectionformat{\\llap{\\thesection\\autodot\\enskip}} +\\renewcommand\\subsectionformat{\\llap{\\thesubsection\\autodot\\enskip}} +\\renewcommand\\subsubsectionformat{\\llap{\\thesubsubsection\\autodot\\enskip}} +") + (big-chap-preamble " +\\RedeclareSectionCommand[afterindent=false, beforeskip=0pt, afterskip=0pt, innerskip=0pt]{chapter} +\\setkomafont{chapter}{\\normalfont\\Huge} +\\renewcommand*{\\chapterheadstartvskip}{\\vspace*{0\\baselineskip}} +\\renewcommand*{\\chapterheadendvskip}{\\vspace*{0\\baselineskip}} +\\renewcommand*{\\chapterformat}{% + \\fontsize{60}{30}\\selectfont\\rlap{\\hspace{6pt}\\thechapter}} +\\renewcommand*\\chapterlinesformat[3]{% + \\parbox[b]{\\dimexpr\\textwidth-0.5em\\relax}{% + \\raggedleft{{\\large\\scshape\\bfseries\\chapapp}\\vspace{-0.5ex}\\par\\Huge#3}}% + \\hfill\\makebox[0pt][l]{#2}} +")) + (setcdr (assoc "article" org-latex-classes) + `(,(concat "\\documentclass{scrartcl}" hanging-secnum-preamble) + ,@article-sections)) + (add-to-list 'org-latex-classes + `("report" ,(concat "\\documentclass{scrartcl}" hanging-secnum-preamble) + ,@article-sections)) + (add-to-list 'org-latex-classes + `("book" ,(concat "\\documentclass[twoside=false]{scrbook}" + big-chap-preamble hanging-secnum-preamble) + ,@book-sections)) + (add-to-list 'org-latex-classes + `("blank" "[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n[EXTRA]" + ,@article-sections)) + (add-to-list 'org-latex-classes + `("bmc-article" "\\documentclass[article,code,maths]{bmc}\n[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n[EXTRA]" + ,@article-sections)) + (add-to-list 'org-latex-classes + `("bmc" "\\documentclass[code,maths]{bmc}\n[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n[EXTRA]" + ,@book-sections)))) + +(after! ox-latex + (setq org-latex-tables-booktabs t + org-latex-hyperref-template "\\colorlet{greenyblue}{blue!70!green} +\\colorlet{blueygreen}{blue!40!green} +\\providecolor{link}{named}{greenyblue} +\\providecolor{cite}{named}{blueygreen} +\\hypersetup{ + pdfauthor={%a}, + pdftitle={%t}, + pdfkeywords={%k}, + pdfsubject={%d}, + pdfcreator={%c}, + pdflang={%L}, + breaklinks=true, + colorlinks=true, + linkcolor=, + urlcolor=link, + citecolor=cite\n} +\\urlstyle{same} +" + org-latex-reference-command "\\cref{%s}")) +#+end_src + +** Adjust default packages +Thanks to our additions, we can remove a few packages from +~org-latex-default-packages-alist~. + +There are also some obsolete entries in the default value, specifically +- =grffile='s capabilities are built into the current version of =graphicx= +- =textcomp='s functionality has been included in LaTeX's core for a while now + +#+begin_src emacs-lisp +(after! org + (setq org-latex-default-packages-alist + '(("AUTO" "inputenc" t ("pdflatex")) + ("T1" "fontenc" t ("pdflatex")) + ("" "fontspec" t) + ("" "xcolor" nil) + ("" "hyperref" nil) + ("" "firamath-otf" t) + "\\setmonofont{Liga SFMono Nerd Font}" + "\\setmainfont{IBM Plex Sans}"))) +#+end_src + +** Cover page +To make a nice cover page, a simple method that comes to mind is just redefining +=\maketitle=. To get precise control over the positioning we'll use the =tikz= +package, and then add in the Tikz libraries =calc= and =shapes.geometric= to make +some nice decorations for the background. + +I'll start off by setting up the required additions to the preamble. +This will accomplish the following: +- Load the required packages +- Redefine =\maketitle= +- Draw an Org icon with Tikz to use in the cover page (it's a little easter egg) +- Start a new page after the table of contents by redefining =\tableofcontents= + +Now we've got a nice cover page to work with, we just need to use it every now +and then. Adding this to =#+options= feels most appropriate. +Let's have the =coverpage= option accept =auto= as a value and then decide whether +or not a cover page should be used based on the word count --- I'll have this be +the global default. Then we just want to insert a LaTeX snippet tweak the +subtitle format to use the cover page. +#+begin_src emacs-lisp +(after! org + (defvar org-latex-cover-page 'auto + "When t, use a cover page by default. + When auto, use a cover page when the document's wordcount exceeds + `org-latex-cover-page-wordcount-threshold'. + + Set with #+option: coverpage:{yes,auto,no} in org buffers.") + (defvar org-latex-cover-page-wordcount-threshold 5000 + "Document word count at which a cover page will be used automatically. + This condition is applied when cover page option is set to auto.") + (defvar org-latex-subtitle-coverpage-format "\\\\\\bigskip\n\\LARGE\\mdseries\\itshape\\color{black!80} %s\\par" + "Variant of `org-latex-subtitle-format' to use with the cover page.") + (defvar org-latex-cover-page-maketitle " +\\usepackage{tikz} +\\usetikzlibrary{shapes.geometric} +\\usetikzlibrary{calc} + +\\newsavebox\\orgicon +\\begin{lrbox}{\\orgicon} + \\begin{tikzpicture}[y=0.80pt, x=0.80pt, inner sep=0pt, outer sep=0pt] + \\path[fill=black!6] (16.15,24.00) .. controls (15.58,24.00) and (13.99,20.69) .. (12.77,18.06)arc(215.55:180.20:2.19) .. controls (12.33,19.91) and (11.27,19.09) .. (11.43,18.05) .. controls (11.36,18.09) and (10.17,17.83) .. (10.17,17.82) .. controls (9.94,18.75) and (9.37,19.44) .. (9.02,18.39) .. controls (8.32,16.72) and (8.14,15.40) .. (9.13,13.80) .. controls (8.22,9.74) and (2.18,7.75) .. (2.81,4.47) .. controls (2.99,4.47) and (4.45,0.99) .. (9.15,2.41) .. controls (14.71,3.99) and (17.77,0.30) .. (18.13,0.04) .. controls (18.65,-0.49) and (16.78,4.61) .. (12.83,6.90) .. controls (10.49,8.18) and (11.96,10.38) .. (12.12,11.15) .. controls (12.12,11.15) and (14.00,9.84) .. (15.36,11.85) .. controls (16.58,11.53) and (17.40,12.07) .. (18.46,11.69) .. controls (19.10,11.41) and (21.79,11.58) .. (20.79,13.08) .. controls (20.79,13.08) and (21.71,13.90) .. (21.80,13.99) .. controls (21.97,14.75) and (21.59,14.91) .. (21.47,15.12) .. controls (21.44,15.60) and (21.04,15.79) .. (20.55,15.44) .. controls (19.45,15.64) and (18.36,15.55) .. (17.83,15.59) .. controls (16.65,15.76) and (15.67,16.38) .. (15.67,16.38) .. controls (15.40,17.19) and (14.82,17.01) .. (14.09,17.32) .. controls (14.70,18.69) and (14.76,19.32) .. (15.50,21.32) .. controls (15.76,22.37) and (16.54,24.00) .. (16.15,24.00) -- cycle(7.83,16.74) .. controls (6.83,15.71) and (5.72,15.70) .. (4.05,15.42) .. controls (2.75,15.19) and (0.39,12.97) .. (0.02,10.68) .. controls (-0.02,10.07) and (-0.06,8.50) .. (0.45,7.18) .. controls (0.94,6.05) and (1.27,5.45) .. (2.29,4.85) .. controls (1.41,8.02) and (7.59,10.18) .. (8.55,13.80) -- (8.55,13.80) .. controls (7.73,15.00) and (7.80,15.64) .. (7.83,16.74) -- cycle; + \\end{tikzpicture} +\\end{lrbox} + +\\makeatletter +\\g@addto@macro\\tableofcontents{\\clearpage} +\\renewcommand\\maketitle{ + \\thispagestyle{empty} + \\hyphenpenalty=10000 % hyphens look bad in titles + \\renewcommand{\\baselinestretch}{1.1} + \\let\\oldtoday\\today + \\renewcommand{\\today}{\\LARGE\\number\\year\\\\\\large% + \\ifcase \\month \\or Jan\\or Feb\\or Mar\\or Apr\\or May \\or Jun\\or Jul\\or Aug\\or Sep\\or Oct\\or Nov\\or Dec\\fi + ~\\number\\day} + \\begin{tikzpicture}[remember picture,overlay] + %% Background Polygons %% + \\foreach \\i in {2.5,...,22} % bottom left + {\\node[rounded corners,black!3.5,draw,regular polygon,regular polygon sides=6, minimum size=\\i cm,ultra thick] at ($(current page.west)+(2.5,-4.2)$) {} ;} + \\foreach \\i in {0.5,...,22} % top left + {\\node[rounded corners,black!5,draw,regular polygon,regular polygon sides=6, minimum size=\\i cm,ultra thick] at ($(current page.north west)+(2.5,2)$) {} ;} + \\node[rounded corners,fill=black!4,regular polygon,regular polygon sides=6, minimum size=5.5 cm,ultra thick] at ($(current page.north west)+(2.5,2)$) {}; + \\foreach \\i in {0.5,...,24} % top right + {\\node[rounded corners,black!2,draw,regular polygon,regular polygon sides=6, minimum size=\\i cm,ultra thick] at ($(current page.north east)+(0,-8.5)$) {} ;} + \\node[fill=black!3,rounded corners,regular polygon,regular polygon sides=6, minimum size=2.5 cm,ultra thick] at ($(current page.north east)+(0,-8.5)$) {}; + \\foreach \\i in {21,...,3} % bottom right + {\\node[black!3,rounded corners,draw,regular polygon,regular polygon sides=6, minimum size=\\i cm,ultra thick] at ($(current page.south east)+(-1.5,0.75)$) {} ;} + \\node[fill=black!3,rounded corners,regular polygon,regular polygon sides=6, minimum size=2 cm,ultra thick] at ($(current page.south east)+(-1.5,0.75)$) {}; + \\node[align=center, scale=1.4] at ($(current page.south east)+(-1.5,0.75)$) {\\usebox\\orgicon}; + %% Text %% + \\node[left, align=right, black, text width=0.8\\paperwidth, minimum height=3cm, rounded corners,font=\\Huge\\bfseries] at ($(current page.north east)+(-2,-8.5)$) + {\\@title}; + \\node[left, align=right, black, text width=0.8\\paperwidth, minimum height=2cm, rounded corners, font=\\Large] at ($(current page.north east)+(-2,-11.8)$) + {\\scshape \\@author}; + \\renewcommand{\\baselinestretch}{0.75} + \\node[align=center,rounded corners,fill=black!3,text=black,regular polygon,regular polygon sides=6, minimum size=2.5 cm,inner sep=0, font=\\Large\\bfseries ] at ($(current page.west)+(2.5,-4.2)$) + {\\@date}; + \\end{tikzpicture} + \\let\\today\\oldtoday + \\clearpage} +\\makeatother + " + "LaTeX snippet for the preamble that sets \\maketitle to produce a cover page.") + (after! ox + (eval '(cl-pushnew '(:latex-cover-page nil "coverpage" org-latex-cover-page) + (org-export-backend-options (org-export-get-backend 'latex))))) + + (defun org-latex-cover-page-p () + "Whether a cover page should be used when exporting this Org file." + (pcase (or (car + (delq nil + (mapcar + (lambda (opt-line) + (plist-get (org-export--parse-option-keyword opt-line 'latex) :latex-cover-page)) + (cdar (org-collect-keywords '("OPTIONS")))))) + org-latex-cover-page) + ((or 't 'yes) t) + ('auto (when (> (count-words (point-min) (point-max)) org-latex-cover-page-wordcount-threshold) t)) + (_ nil))) + + (defadvice! org-latex-set-coverpage-subtitle-format-a (contents info) + "Set the subtitle format when a cover page is being used." + :before #'org-latex-template + (when (org-latex-cover-page-p) + (setf info (plist-put info :latex-subtitle-format org-latex-subtitle-coverpage-format)))) + + (add-to-list 'org-latex-feature-implementations '(cover-page :snippet org-latex-cover-page-maketitle :order 9) t) + (add-to-list 'org-latex-conditional-features '((org-latex-cover-page-p) . cover-page) t)) +#+end_src + +** Condensed lists +LaTeX is generally pretty good by default, but it's /really/ generous with how +much space it puts between list items by default. I'm generally not a fan. + +Thankfully this is easy to correct with a small snippet: +#+begin_src emacs-lisp +(after! org + (defvar org-latex-condense-lists t + "Reduce the space between list items.") + (defvar org-latex-condensed-lists " +\\newcommand{\\setuplistspacing}{\\setlength{\\itemsep}{-0.5ex}\\setlength{\\parskip}{1.5ex}\\setlength{\\parsep}{0pt}} +\\let\\olditem\\itemize\\renewcommand{\\itemize}{\\olditem\\setuplistspacing} +\\let\\oldenum\\enumerate\\renewcommand{\\enumerate}{\\oldenum\\setuplistspacing} +\\let\\olddesc\\description\\renewcommand{\\description}{\\olddesc\\setuplistspacing} + ") + + (add-to-list 'org-latex-conditional-features '((and org-latex-condense-lists "^[ \t]*[-+]\\|^[ \t]*[1Aa][.)] ") . condensed-lists) t) + (add-to-list 'org-latex-feature-implementations '(condensed-lists :snippet org-latex-condensed-lists :order 0.7) t)) +#+end_src + +** Pretty code blocks +Ripped this off of Teco, thanks mate! +#+begin_src emacs-lisp +(use-package! engrave-faces-latex + :after ox-latex + :config + (setq org-latex-listings 'engraved)) +#+end_src + +#+begin_src emacs-lisp +(defvar-local org-export-has-code-p nil) + +(defadvice! org-export-expect-no-code (&rest _) + :before #'org-export-as + (setq org-export-has-code-p nil)) + +(defadvice! org-export-register-code (&rest _) + :after #'org-latex-src-block + :after #'org-latex-inline-src-block-engraved + (setq org-export-has-code-p t)) + +(defadvice! org-latex-example-block-engraved (orig-fn example-block contents info) + "Like `org-latex-example-block', but supporting an engraved backend" + :around #'org-latex-example-block + (let ((output-block (funcall orig-fn example-block contents info))) + (if (eq 'engraved (plist-get info :latex-listings)) + (format "\\begin{Code}[alt]\n%s\n\\end{Code}" output-block) + output-block))) +#+end_src + +andn addition to the vastly superior visual output, this should also be much +faster to compile for code-heavy documents (like this config). + +Performing a little benchmark with this document, I find that this is indeed the +case. + +| LaTeX syntax highlighting backend | Compile time | Overhead | Overhead ratio | +|-----------------------------------+--------------+----------+----------------| +| verbatim | 12 s | 0 | 0.0 | +| lstlistings | 15 s | 3 s | 0.2 | +| Engrave | 34 s | 22 s | 1.8 | +| Pygments (Minted) | 184 s | 172 s | 14.3 | +#+TBLFM: $3=$2-@2$2::$4=$3 / @2$2;%.1f + +Treating the verbatim (no syntax highlighting) result as a baseline; this +rudimentary test suggest that =engrave-faces= is around eight times faster than +=pygments=, and takes three times as long as no syntax highlighting (verbatim). + +** Ox-chameleon +Match export with current emacs theme +#+begin_src emacs-lisp +(use-package! ox-chameleon + :after ox) +#+end_src + +** Support images from URLs +You can link to remote images easily, and they work nicely with HTML-based +exports. However, LaTeX can only include local files, and so the current +behaviour of =org-latex-link= is just to insert a URL to the image. + +We can do better than that by downloading the image to a predictable location, +and using that. By making the filename predictable as opposed to just another +tempfile, this can provide a caching mechanism. + +#+begin_src emacs-lisp +(after! org + (defadvice! +org-latex-link (orig-fn link desc info) + "Acts as `org-latex-link', but supports remote images." + :around #'org-latex-link + (setq o-link link + o-desc desc + o-info info) + (if (and (member (plist-get (cadr link) :type) '("http" "https")) + (member (file-name-extension (plist-get (cadr link) :path)) + '("png" "jpg" "jpeg" "pdf" "svg"))) + (org-latex-link--remote link desc info) + (funcall orig-fn link desc info))) + + (defun org-latex-link--remote (link _desc info) + (let* ((url (plist-get (cadr link) :raw-link)) + (ext (file-name-extension url)) + (target (format "%s%s.%s" + (temporary-file-directory) + (replace-regexp-in-string "[./]" "-" + (file-name-sans-extension (substring (plist-get (cadr link) :path) 2))) + ext))) + (unless (file-exists-p target) + (url-copy-file url target)) + (setcdr link (--> (cadr link) + (plist-put it :type "file") + (plist-put it :path target) + (plist-put it :raw-link (concat "file:" target)) + (list it))) + (concat "% fetched from " url "\n" + (org-latex--inline-image link info))))) +#+end_src + +** Beamer Exports +I've also recently got into presenting more and more often, so its nice to have beamer do everything for us +#+begin_src emacs-lisp +(setq org-beamer-theme "[progressbar=foot]metropolis" + org-beamer-frame-level 2) + +(defun org-beamer-p (info) + (eq 'beamer (and (plist-get info :back-end) + (org-export-backend-name (plist-get info :back-end))))) + +(defvar org-beamer-metropolis-tweaks " +\\NewCommandCopy{\\moldusetheme}{\\usetheme} +\\renewcommand*{\\usetheme}[2][]{\\moldusetheme[#1]{#2} + \\setbeamertemplate{items}{$\\bullet$} + \\setbeamerfont{block title}{size=\\normalsize, series=\\bfseries\\parbox{0pt}{\\rule{0pt}{4ex}}}} + +\\makeatletter +\\newcommand{\\setmetropolislinewidth}{ + \\setlength{\\metropolis@progressinheadfoot@linewidth}{1.2px}} +\\makeatother + +\\usepackage{etoolbox} +\\AtEndPreamble{\\setmetropolislinewidth} +") + +(add-to-list 'org-latex-conditional-features '(org-beamer-p . beamer) t) +(add-to-list 'org-latex-feature-implementations '(beamer :requires .missing-koma :prevents (italic-quotes condensed-lists)) t) +(add-to-list 'org-latex-feature-implementations '(.missing-koma :snippet "\\usepackage{scrextend}" :order 2) t) +(add-to-list 'org-latex-conditional-features '((lambda (info) (and (org-beamer-p info) (string-match-p "metropolis$" org-beamer-theme))) . beamer-metropolis) t) +(add-to-list 'org-latex-feature-implementations '(beamer-metropolis :requires beamer :snippet org-beamer-metropolis-tweaks :order 3) t) +#+end_src diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..743c414 --- /dev/null +++ b/flake.lock @@ -0,0 +1,97 @@ +{ + "nodes": { + "doom-emacs": { + "flake": false, + "locked": { + "lastModified": 1653613980, + "narHash": "sha256-PWG81Jfcyq21qCrjSsPNK9B9383O/6WmNwVVY9KuRYg=", + "owner": "hlissner", + "repo": "doom-emacs", + "rev": "1b8f46c7c5893d63e4bcebc203c0d28df9f5981b", + "type": "github" + }, + "original": { + "owner": "hlissner", + "repo": "doom-emacs", + "type": "github" + } + }, + "emacs": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1653852240, + "narHash": "sha256-VmAbVC5s8OgNJ2GoSmdccMTDDRFtezo5sH+R4vcV7r0=", + "owner": "nix-community", + "repo": "emacs-overlay", + "rev": "8d1ee06daa51522db5efd5308d85106197f6ffb0", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "emacs-overlay", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1652776076, + "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1652776076, + "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1653738054, + "narHash": "sha256-IaR8iLN4Ms3f5EjU1CJkXSc49ZzyS5qv03DtVAti6/s=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "17b62c338f2a0862a58bb6951556beecd98ccda9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "doom-emacs": "doom-emacs", + "emacs": "emacs", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f57213c --- /dev/null +++ b/flake.nix @@ -0,0 +1,29 @@ +{ + description = "Shuarya Singh's Doom-emacs config"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils = { + url = "github:numtide/flake-utils"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + emacs = { + url = "github:nix-community/emacs-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + doom-emacs.url = "github:hlissner/doom-emacs"; + doom-emacs.flake = false; + }; + + outputs = { self, nixpkgs, flake-utils, emacs, doom-emacs }: + flake-utils.lib.simpleFlake { + inherit self nixpkgs; + name = "doom-emacs"; + preOverlays = [ + emacs.overlay + (final: prev: { doomEmacsRevision = doom-emacs.rev; }) + ]; + shell = ./shell.nix; + systems = [ "aarch64-darwin" ]; + }; +} diff --git a/init.el b/init.el new file mode 100644 index 0000000..9246aa1 --- /dev/null +++ b/init.el @@ -0,0 +1,151 @@ +;;; init.el -*- lexical-binding: t; -*- + +;; This file controls what Doom modules are enabled and what order they load in. +;; Press 'K' on a module to view its documentation, and 'gd' to browse its directory. + +(doom! :completion + (company ; the ultimate code completion backend + +childframe) ; ... when your children are better than you + (vertico +icons) ; the search engine of the future + + :ui + doom-dashboard ; a nifty splash screen for Emacs + doom-quit ; DOOM quit-message prompts when you quit Emacs + (ligatures ; ligatures and symbols to make your code pnoretty again + +extra) ; for those who dislike letters + minimap ; show a map of the code on the side + ophints ; highlight the region an operation acts on + (popup ; tame sudden yet inevitable temporary windows + +all ; catch all popups that start with an asterix + +defaults) ; default popup rules + vc-gutter ; vcs diff in the fringe + workspaces ; tab emulation, persistence & separate workspaces + zen ; distraction-free coding or writing + + :editor + (evil +everywhere) ; come to the dark side, we have cookies + format ; automated prettiness + + :emacs + (dired +icons) ; making dired pretty [functional] + electric ; smarter, keyword-based electric-indent + (ibuffer +icons) ; interactive buffer management + undo ; persistent, smarter undo for your inevitable mistakes + vc ; version-control and Emacs, sitting in a tree + + :term + vterm ; the best terminal emulation in Emacs + + :checkers + syntax ; tasing you for every semicolon you forget + (:if (executable-find "aspell") spell) ; tasing you for misspelling mispelling + (:if (executable-find "languagetool") grammar) ; tasing grammar mistake every you make + + :tools + biblio ; Writes a PhD for you (citation needed) + (debugger +lsp) ; FIXME stepping through code, to help you add bugs + (eval +overlay) ; run code, run (also, repls) + (lookup ; helps you navigate your code and documentation + +dictionary ; dictionary/thesaurus is nice + +docsets) ; ...or in Dash docsets locally + lsp ; Language Server Protocol + (magit ; a git porcelain for Emacs + +forge) ; interface with git forges + pdf ; pdf enhancements + rgb ; creating color strings + tree-sitter ; Syntax and Parsing sitting in a tree + + :os + (:if IS-MAC macos) ; improve compatibility with macOS + + :lang + ;;agda ; types of types of types of types... + ;;beancount ; mind the GAAP + (cc +lsp +tree-sitter) ; C/C++/Obj-C madness + (clojure +lsp) ; java with a lisp + ;;common-lisp ; if you've seen one lisp, you've seen them all + ;;coq ; proofs-as-programs + ;;crystal ; ruby at the speed of c + ;;csharp ; unity, .NET, and mono shenanigans + ;;data ; config/data formats + ;;(dart +flutter) ; paint ui and not much else + ;;dhall ; JSON with FP sprinkles + ;;elixir ; erlang done right + ;;elm ; care for a cup of TEA? + emacs-lisp ; drown in parentheses + ;;erlang ; an elegant language for a more civilized age + ;;ess ; emacs speaks statistics + ;;faust ; dsp, but you get to keep your soul + ;;fsharp ; ML stands for Microsoft's Language + ;;fstar ; (dependent) types and (monadic) effects and Z3 + ;;gdscript ; the language you waited for + ;;(go +lsp) ; the hipster dialect + ;;(haskell +lsp) ; a language that's lazier than I am + ;;hy ; readability of scheme w/ speed of python + ;;idris ; + ;;json ; At least it ain't XML + ;;(java +lsp) ; the poster child for carpal tunnel syndrome + ;;(javascript +lsp) ; all(hope(abandon(ye(who(enter(here)))))) + ;;(julia +lsp) ; Python, R, and MATLAB in a blender + ;;(kotlin +lsp) ; a better, slicker Java(Script) + (latex ; writing papers in Emacs has never been so fun + ;;+fold ; fold the clutter away nicities + +latexmk ; modern latex plz + ;;+cdlatex ; quick maths symbols + +lsp) + ;;lean ; proof that mathematicians need help + ;;factor ; for when scripts are stacked against you + ;;ledger ; an accounting system in Emacs + (lua +lsp +fennel) ; one-based indices? one-based indices + (markdown +grip) ; writing docs for people to ignore + ;;nim ; python + lisp at the speed of c + (nix +tree-sitter) ; I hereby declare "nix geht mehr!" + ;;ocaml ; an objective camel + (org ; organize your plain life in plain text + ;;+pretty ; yessss my pretties! (nice unicode symbols) + ;;+dragndrop ; drag & drop files/images into org buffers + ;;+hugo ; use Emacs for hugo blogging + +noter ; enhanced PDF notetaking + +jupyter ; ipython/jupyter support for babel + +pandoc ; export-with-pandoc support + +gnuplot ; who doesn't like pretty pictures + +pomodoro ; be fruitful with the tomato technique + +present ; using org-mode for presentations + +roam2) ; wander around notes + ;;php ; perl's insecure younger brother + ;;plantuml ; diagrams for confusing people more + ;;purescript ; javascript, but functional + (python ; beautiful is better than ugly + +lsp + +pyright + +tree-sitter + +conda) + ;;qt ; the 'cutest' gui framework ever + ;;racket ; a DSL for DSLs + ;;raku ; the artist formerly known as perl6 + ;;(rust + ;; +lsp + ;; +tree-sitter) ; Fe2O3.unwrap().unwrap().unwrap() + ;;scala ; java, but good + ;;scheme ; a fully conniving family of lisps + ;;(sh +lsp +fish +tree-sitter) ; she sells {ba,z,fi}sh shells on the C xor + ;;sml ; no, the /other/ ML + ;;solidity ; do you need a blockchain? No. + ;;swift ; who asked for emoji variables? + ;;terra ; Earth and Moon in alignment for performance. + ;;(web +lsp) ; the tubes + ;;yaml ; JSON, but readable + ;;zig ; C, but simpler + + :email + ;; (:if (executable-find "mu") (mu4e +org +gmail)) + + :app + ;;calendar ; A dated approach to timetabling + ;;emms ; Multimedia in Emacs is music to my ears + ;;everywhere ; *leave* Emacs!? You must be joking. + ;; (rss +org) ; emacs as an RSS reader + + :config + literate + (default +bindings +smartparens)) diff --git a/misc/org-css/style.css b/misc/org-css/style.css new file mode 100644 index 0000000..ba45652 --- /dev/null +++ b/misc/org-css/style.css @@ -0,0 +1,261 @@ +@charset "UTF-8"; +@import url('https://fonts.googleapis.com/css?family=IBM Plex Sans:300,350,400'); +@import url('https://fonts.googleapis.com/css?family=Roboto Mono:300,340,380'); +@import url('https://fonts.googleapis.com/css?family=IBM Plex Sans Condensed:300,350,400'); + +body { + font-family: "IBM Plex Sans", sans; + font-size: 16px; + font-weight: 350; + line-height: 1.35em; + background-color: #FFFFFF; + color: #37474F; +} + +#content { + margin: 0 auto; + max-width: 720px; + margin-top: 5em; + margin-bottom: 5em; +} + +b { + color: #FFAB91; + font-weight: 400; +} + +a { + color: #673AB7; + font-weight: 400; + text-decoration: none; +} + +h1, h2, h3 { + font-family: "IBM Plex Sans Condensed", serif; + font-weight: 400; +} + +h1.title { + font-weight: 400; + line-height: 1em; + padding-top: 1.em; + padding-bottom: 0.5em; +} +h1 span.subtitle { + font-size: 16px; + font-weight: 350; +} +h2 { + clear: both; + padding-top: 1em; + padding-bottom: 0em; +} + + +p { + text-align: justify; + text-justify: inter-word; + hyphens: auto; +} + +div.abstract { + background: #ECEFF1; + padding: .75em 1em .75em 1em; + line-height: 1.25em; + font-family: "IBM Plex Sans Condensed", sans-serif; + padding-bottom: 0.25em; + border-bottom: 4px solid #673AB7; +} +div.abstract p { + column-count: 1; + margin: 0 0 0.5em 0; +} + +div.figure { + padding: 0.50em .00em 0.75em .00em; +} +div.figure p { + column-count: 1; + line-height: 1.2em; + font-family: "IBM Plex Sans Condensed", sans-serif; +} +div.sidefig::after { + display: block; + content: ""; + clear: both; +} +div.sidefig div.figure p:nth-of-type(1) { + width: 60%; + float: left; +} +div.sidefig div.figure p:nth-of-type(2) { + font-size: 95%; + background-color:#ECEFF1; + padding: 1em; +} +div.sidefig div.figure img { + width: 100%; +} + +div.figure img { + width: 100%; +} +span.figure-number { + font-weight: 500; +} + +/* --- Footnote ------------------------------------------------------------ */ +div.footpara { + display: inline-block; +} +h2.footnotes { + font-size: 16px; + width: 50%; + border-bottom: 4px solid #90A4AE; +} +p.footpara { + column-count: 1; + line-height: 1.25em; + font-family: "IBM Plex Sans Condensed", sans-serif; + margin: 0; +} +sup { + font-size: 0.75em; + vertical-align: top; + position: relative; top: -0.5em; +} + +/* --- Block quote --------------------------------------------------------- */ +blockquote p { + font-family: "IBM Plex Sans Condensed", sans-serif; + font-size: 95%; + line-height: 1.15em; + column-count: 1; + padding-top: 1em; + padding-bottom: 1.5em; + padding: 0.50em 1.00em 0.75em 1.00em; + background-color: #FAFAFA; + margin-bottom: 0.5em; + border-left: 4px solid #ECEFF1; +} + +/* --- Source blocks ------------------------------------------------------- */ +code { + font-family: "Roboto Mono", sans-serif; + font-weight: 300; +} +pre.example::before { + display: block; + background-color: #37474F; + content: "Output"; + font-family: "Roboto Mono", sans-serif; + font-weight: 400; + padding-bottom: 0.25em; +} + +pre.example { + font-size: 95%; + background-color: #FAFAFA; + line-height: 1.4em; + font-family: "Roboto Mono", sans-serif; + font-weight: 300; + padding: 0.5em 1em 0.5em 1em; + border-left: 4px solid #90A4AE; +} + +pre.src { + font-size: 95%; + line-height: 1.4em; + font-family: "Roboto Mono", sans-serif; + font-weight: 300; + padding: 0; + margin: 0; + overflow-x: visible; + white-space: pre-wrap; +} +div.org-src-container { + border-bottom: 4px solid #ECEFF1; + padding: 0.50em 1.00em 0.75em 1.00em; + background-color: #FAFAFA; + margin-top: 0.25em; + margin-bottom: 0.75em; +} +label.org-src-name { + display: block; + font-family: "Roboto Mono", sans-serif; + padding-bottom: .25em; +} +span.listing-number { + font-weight: 500; +} + +/* TOC */ +@media (min-width: 1280px) { + body { + padding-left: 25em; + } + #table-of-contents { + position: fixed; + width: 18rem; + left: 1rem; + top: 0; + padding: 1em; + line-height: 1.5; } + #table-of-contents h2 { + margin-top: 0; } + #table-of-contents #text-table-of-contents { + position: relative; } + #table-of-contents #text-table-of-contents::before, #table-of-contents #text-table-of-contents::after { + position: absolute; + content: ''; + width: calc(100% - 10px); + height: 0.7rem; + left: 0; + z-index: 1; } + #table-of-contents #text-table-of-contents > ul { + list-style: none; + padding: 0; + margin: 0; + max-height: calc(100vh - 5rem - 50px); + overflow-y: auto; + overflow-x: hidden; + scrollbar-width: thin; } + #table-of-contents #text-table-of-contents > ul ul { + padding-left: 2em; } + #table-of-contents #text-table-of-contents > ul ul.active { + display: inline-block; } + #table-of-contents #text-table-of-contents > ul li.active > ul { + display: inline-block; } + #table-of-contents #text-table-of-contents > ul li.active > label a, #table-of-contents #text-table-of-contents > ul li.active > a { + color: #263238; } + #table-of-contents #text-table-of-contents > ul li.active > input:not(:checked) ~ label::after { + transform: rotate(90deg); + top: 5px; + opacity: 0.35; } + #table-of-contents #text-table-of-contents > ul > li:last-child { + margin-bottom: 2rem; } } + +/* top bar */ +.topnav { + overflow: hidden; + background-color: #FAFAFA; +} + +.topnav a { + float: left; + color: #37474F; + text-align: center; + padding: 14px 16px; + text-decoration: none; + font-size: 17px; +} + +.topnav a:hover { + background-color: #ECEFF1; + color: #37474F; +} + +.topnav a.active { + background-color: #FAFAFA; + color: #37474F; +} diff --git a/misc/org-css/style.html b/misc/org-css/style.html new file mode 100644 index 0000000..e69de29 diff --git a/misc/org-css/style.js b/misc/org-css/style.js new file mode 100644 index 0000000..e69de29 diff --git a/misc/showcase/gura.png b/misc/showcase/gura.png new file mode 100644 index 0000000..1f75066 Binary files /dev/null and b/misc/showcase/gura.png differ diff --git a/misc/showcase/org.png b/misc/showcase/org.png new file mode 100644 index 0000000..75e9e4b Binary files /dev/null and b/misc/showcase/org.png differ diff --git a/misc/showcase/vertico.png b/misc/showcase/vertico.png new file mode 100644 index 0000000..bf08dfd Binary files /dev/null and b/misc/showcase/vertico.png differ diff --git a/misc/splash-images/fennel.png b/misc/splash-images/fennel.png new file mode 100644 index 0000000..e38dbab Binary files /dev/null and b/misc/splash-images/fennel.png differ diff --git a/misc/splash-images/ibm.png b/misc/splash-images/ibm.png new file mode 100644 index 0000000..28d84bc Binary files /dev/null and b/misc/splash-images/ibm.png differ diff --git a/misc/splash-images/kaori.png b/misc/splash-images/kaori.png new file mode 100644 index 0000000..b92b006 Binary files /dev/null and b/misc/splash-images/kaori.png differ diff --git a/misc/splash-phrases/corperate-bs-1-adverbs.txt b/misc/splash-phrases/corperate-bs-1-adverbs.txt new file mode 100644 index 0000000..ba7f627 --- /dev/null +++ b/misc/splash-phrases/corperate-bs-1-adverbs.txt @@ -0,0 +1,32 @@ +Appropriately +Assertively +Authoritatively +Collaboratively +Compellingly +Competently +Completely +Continually +Conveniently +Credibly +Distinctively +Dramatically +Dynamically +Efficiently +Energistically +Enthusiastically +Globally +Holistically +Interactively +Intrinsically +Monotonectally +Objectively +Phosfluorescently +Proactively +Professionally +Progressively +Quickly +Rapidiously +Seamlessly +Synergistically +Uniquely +Fungibly diff --git a/misc/splash-phrases/corperate-bs-2-verbs.txt b/misc/splash-phrases/corperate-bs-2-verbs.txt new file mode 100644 index 0000000..88ff3f9 --- /dev/null +++ b/misc/splash-phrases/corperate-bs-2-verbs.txt @@ -0,0 +1,99 @@ +actualise +administrate +aggregate +architect +benchmark +brand +build +communicate +conceptualise +coordinate +create +cultivate +customise +deliver +deploy +develop +disintermediate +disseminate +drive +embrace +e-enable +empower +enable +engage +engineer +enhance +envisioneer +evisculate +evolve +expedite +exploit +extend +fabricate +facilitate +fashion +formulate +foster +generate +grow +harness +impact +implement +incentivise +incubate +initiate +innovate +integrate +iterate +leverage existing +leverage other's +maintain +matrix +maximise +mesh +monetise +morph +myocardinate +negotiate +network +optimise +orchestrate +parallel task +plagiarise +pontificate +predominate +procrastinate +productivate +productize +promote +provide access to +pursue +recaptiualize +reconceptualize +redefine +re-engineer +reintermediate +reinvent +repurpose +restore +revolutionize +scale +seize +simplify +strategize +streamline +supply +syndicate +synergize +synthesize +target +transform +transition +underwhelm +unleash +utilize +visualize +whiteboard +cloudify +right-shore diff --git a/misc/splash-phrases/corperate-bs-3-adjuctives.txt b/misc/splash-phrases/corperate-bs-3-adjuctives.txt new file mode 100644 index 0000000..eba728d --- /dev/null +++ b/misc/splash-phrases/corperate-bs-3-adjuctives.txt @@ -0,0 +1,162 @@ +24/7 +24/365 +accurate +adaptive +alternative +an expanded array of +B2B +B2C +backend +backward-compatible +best-of-breed +bleeding-edge +bricks-and-clicks +business +clicks-and-mortar +client-based +client-centred +client-centric +client-focused +collaborative +compelling +competitive +cooperative +corporate +cost effective +covalent +cross functional +cross-media +cross-platform +cross-unit +customer directed +customised +cutting-edge +distinctive +distributed +diverse +dynamic +e-business +economically sound +effective +efficient +emerging +empowered +enabled +end-to-end +enterprise +enterprise-wide +equity invested +error-free +ethical +excellent +exceptional +extensible +extensive +flexible +focused +frictionless +front-end +fully researched +fully tested +functional +functionalised +future-proof +global +go forward +goal-oriented +granular +high standards in +high-payoff +high-quality +highly efficient +holistic +impactful +inexpensive +innovative +installed base +integrated +interactive +interdependent +intermandated +interoperable +intuitive +just in time +leading-edge +leveraged +long-term high-impact +low-risk high-yield +magnetic +maintainable +market positioning +market-driven +mission-critical +multidisciplinary +multifunctional +multimedia based +next-generation +one-to-one +open-source +optimal +orthogonal +out-of-the-box +pandemic +parallel +performance based +plug-and-play +premier +premium +principle-centred +proactive +process-centric +professional +progressive +prospective +quality +real-time +reliable +resource-sucking +resource-maximising +resource-levelling +revolutionary +robust +scalable +seamless +stand-alone +standardised +standards compliant +state of the art +sticky +strategic +superior +sustainable +synergistic +tactical +team building +team driven +technically sound +timely +top-line +transparent +turnkey +ubiquitous +unique +user-centric +user friendly +value-added +vertical +viral +virtual +visionary +web-enabled +wireless +world-class +worldwide +fungible +cloud-ready +elastic +hyper-scale +on-demand +cloud-based +cloud-centric +cloudified +agile diff --git a/misc/splash-phrases/corperate-bs-4-nouns.txt b/misc/splash-phrases/corperate-bs-4-nouns.txt new file mode 100644 index 0000000..826f6b7 --- /dev/null +++ b/misc/splash-phrases/corperate-bs-4-nouns.txt @@ -0,0 +1,93 @@ +action items +alignments +applications +architectures +bandwidth +benefits +best practices +catalysts for change +channels +collaboration and idea-sharing +communities +content +convergence +core competencies +customer service +data +deliverables +e-business +e-commerce +e-markets +e-tailers +e-services +experiences +expertise +functionalities +growth strategies +human capital +ideas +imperatives +infomediaries +information +infrastructures +initiatives +innovation +intellectual capital +interfaces +internal or "organic" sources +leadership +leadership skills +manufactured products +markets +materials +meta-services +methodologies +methods of empowerment +metrics +mindshare +models +networks +niches +niche markets +opportunities +"outside the box" thinking +outsourcing +paradigms +partnerships +platforms +portals +potentialities +process improvements +processes +products +quality vectors +relationships +resources +results +ROI +scenarios +schemas +services +solutions +sources +strategic theme areas +supply chains +synergy +systems +technologies +technology +testing procedures +total linkage +users +value +vortals +web-readiness +web services +fungibility +clouds +nosql +storage +virtualisation +scrums +sprints +wins diff --git a/misc/splash-phrases/dev-excuses.txt b/misc/splash-phrases/dev-excuses.txt new file mode 100644 index 0000000..b4340be --- /dev/null +++ b/misc/splash-phrases/dev-excuses.txt @@ -0,0 +1,125 @@ +Actually, that’s a feature. +Did you check for a virus on your system? +Even though it doesn’t work, how does it feel? +Everything looks fine on my end. +How is that possible? +I broke that deliberately to do some testing. +I can’t make that a priority right now. +I can’t test everything. +I couldn’t find any examples of how that can be done anywhere online. +I couldn’t find any library that can even do that. +I did a quick fix last time but it broke when we rebooted. +I didn’t anticipate that I would make any errors. +I didn’t create that part of the program. +I didn’t receive a ticket for it. +I forgot to commit the code that fixes that. +I have never seen that before in my life. +I have too many other high priority things to do right now. +I haven’t been able to reproduce that. +I haven’t had a chance to run that code yet. +I haven’t had any experience with that before. +I haven’t touched that code in weeks. +I heard there was a solar flare today. +I must have been stress-testing our production server. +I must not have understood what you were asking for. +I thought I finished that. +I thought he knew the context of what I was talking about. +I thought you signed off on that. +I told you yesterday it would be done by the end of today. +I usually get a notification when that happens. +I was just fixing that. +I was told to stop working on that when something important came up. +In the interest of efficiency I only check my email for that on a Friday. +It can’t be broken, it passes all unit tests. +It must be a hardware problem. +It must be because of a leap year. +It probably won’t happen again. +It was working in my head. +It works for me. +It works, but it’s not been tested. +It would have taken twice as long to build it properly. +It would take too long to rewrite the code from scratch. +It’s a browser compatibility issue. +It’s a character encoding issue. +It’s a compatibility issue. +It’s a known bug with the programming language. +It’s a remote vendor issue. +It’s always been like that. +It’s an unexpected emergent behaviour of several last minute abstractions. +It’s just some unlucky coincidence. +It’s never done that before. +It’s never shown unexpected behavior like this before. +It’s not a code problem — our users need more training. +I’ll have to fix that at a later date. +I’m not familiar with it so I didn’t fix it in case I made it worse. +I’m not getting any error codes. +I’m not sure as I’ve never had a look at how that works before. +I’m still working on that as we speak. +I’m surprised it was working at all. +I’m surprised it works as well as it does. +Management insisted we wouldn’t need to waste our time writing unit tests. +Maybe somebody forgot to pay our hosting company. +My time was split in a way that meant I couldn’t do either project properly +No one told me so I was forced to assume which way to do that. +Nobody asked me how long it would actually take. +Nobody has ever complained about it. +Oh, that was just a temporary fix. +Oh, that was only supposed to be a placeholder. +Oh, you said you DIDN’T want that to happen? +Our code quality is no worse than anyone else in the industry. +Our hardware is too slow to cope with demand. +Our internet connection must not be working. +Our redundant systems must have failed as well. +Please ignore that, it’s for debugging +Somebody must have changed my code. +THIS can’t be the source of THAT. +That behaviour is in the original specification. +That code seemed so simple I didn’t think it needed testing. +That error means it was successful. +That feature was slated for phase two. +That feature would be outside the scope. +That important email must have been marked as spam. +That isn’t covered by my job description. +That process requires human oversight that nobody was providing. +That was literally a one in a million error. +That wasn’t in the original specification. +That worked perfectly when I developed it. +That wouldn’t be economically feasible. +That’s already fixed, it just hasn’t taken effect yet. +That’s interesting, how did you manage to make it do that? +That’s not a bug it’s a configuration issue. +That’s the fault of the graphic designer. +The accounting department must have cancelled that subscription. +The client must have been hacked. +The client wanted it changed at the last minute. +The code is compiling. +The DNS hasn’t propagated yet. +The download must have been corrupted. +The existing design makes it difficult to do the right thing. +The marketing department made us put that there. +The person responsible doesn’t work here anymore. +The problem seems to be with our legacy software. +The program has never collected that information. +The project manager said no one would want that feature +The project manager told me to do it that way. +The request must have dropped some packets. +The specifications were ambiguous. +The third party documentation doesn’t exist. +The user must not know how to use it. +There must be something strange in your data. +There was too little data to bother with the extra functionality at the time. +There’s currently a problem with our hosting company. +This code was not supposed to go in to production yet. +This is a previously known bug you told me not to work on yet. +We didn’t have enough time to peer review the final changes. +Well done, you found my easter egg! +Well, at least it displays a very pretty error. +Well, at least we know not to try that again. +Well, that’s a first. +What did I tell you about using parts of the system you don’t understand? +What did you type in wrong to get it to crash? +Where were you when the program blew up? +Why do you want to do it that way? +You must have done something wrong. +You’re doing it wrong. +You must have the wrong version. diff --git a/misc/splash-phrases/useless-facts.txt b/misc/splash-phrases/useless-facts.txt new file mode 100644 index 0000000..4dc33c3 --- /dev/null +++ b/misc/splash-phrases/useless-facts.txt @@ -0,0 +1,579 @@ +Most American car horns honk in the key of F. +The name Wendy was made up for the book 'Peter Pan.'Barbie's full name is Barbara Millicent Roberts.Every time you lick a stamp, you consume 1/10 of a calorie. +The average person falls asleep in seven minutes. +Studies show that if a cat falls off the seventh floor of a building it has about thirty percent less chance of surviving than a cat that falls off the twentieth floor. It supposedly takes about eight floors for the cat to realize what is occurring, relax and correct itself.Your stomach has to produce a new layer of mucus every 2 weeks otherwise it will digest itself. +The citrus soda 7-UP was created in 1929; '7' was selected after the original 7-ounce containers and 'UP' for the direction of the bubbles. +101 Dalmatians, Peter Pan, Lady and the Tramp, and Mulan are the only Disney cartoons where both parents are present and don't die throughout the movie. +A pig's orgasm lasts for 30 minutes.'Stewardesses' is the longest word that is typed with only the left hand.To escape the grip of a crocodile's jaws, push your thumbs into its eyeballs - it will let you go instantly. +Reindeer like to eat bananas. +No word in the English language rhymes with month, orange, silver and purple. +The word 'samba' means 'to rub navels together.'Mel Blanc (the voice of Bugs Bunny) was allergic to carrots. +The electric chair was invented by a dentist.The very first bomb dropped by the Allies on Berlin during World War II Killed the only elephant in the Berlin Zoo. +More people are killed annually by donkeys than airplane crashes.A 'jiffy' is a unit of time for 1/100th of a second. +A whale's penis is called a dork.Because of the rotation of the earth, an object can be thrown farther if it is thrown west. +The average person spends 6 months of their life sitting at red lights.In 1912 a law passed in Nebraska where drivers in the country at night were required to stop every 150 yards, send up a skyrocket, wait eight minutes for the road to clear before proceeding cautiously, all the while blowing their horn and shooting off flares. +More Monopoly money is printed in a year, than real money throughout the world. +Caesar salad has nothing to do with any of the Caesars. It was first concocted in a bar in Tijuana, Mexico, in the 1920's.One quarter of the bones in your body are in your feet. +Crocodiles and alligators are surprisingly fast on land. Although they are rapid, they are not agile. So, if being chased by one, run in a zigzag line to lose him or her. +Seattle’s Fremont Bridge rises up and down more than any drawbridge in the world. +Right-handed people live, on average; nine years longer than left handed people. +Ten percent of the Russian government's income comes from the sale of vodka.In the United States, a pound of potato chips costs two hundred times more than a pound of potatoes. +A giraffe can go without water longer than a camel. +A person cannot taste food unless it is mixed with saliva. For example, if a strong-tasting substance like salt is placed on a dry tongue, the taste buds will not be able to taste it. As soon as a drop of saliva is added and the salt is dissolved, however, a definite taste sensation results. This is true for all foods.Nearly 80% of all animals on earth have six legs. +In the marriage ceremony of the ancient Inca Indians of Peru, the couple was considered officially wed when they took off their sandals and handed them to each other. +Ninety percent of all species that have become extinct have been birds. +There is approximately one chicken for every human being in the world. +Most collect calls are made on father's day. +The first automobile race ever seen in the United States was held in Chicago in 1895. The track ran from Chicago to Evanston, Illinois. The winner was J. Frank Duryea, whose average speed was 71/2 miles per hour. +Each of us generates about 3.5 pounds of rubbish a day, most of it paper. +Women manage the money and pay the bills in 75% of all Americans households. +A rainbow can be seen only in the morning or late afternoon. It can occur only when the sun is 40 degrees or less above the horizon. +It has NEVER rained in Calama, a town in the Atacama Desert of Chile. +It costs more to buy a new car today in the United States than it cost Christopher Columbus to equip and undertake three voyages to and from the New World. +The plastic things on the end of shoelaces are called aglets. +An eighteenth-century German named Matthew Birchinger, known as 'the little man of Nuremberg,' played four musical instruments including the bagpipes, was an expert calligrapher, and was the most famous stage magician of his day. He performed tricks with the cup and balls that have never been explained. Yet Birchinger had no hands, legs, or thighs, and was less than 29 inches tall. +Daylight Saving Time is not observed in most of the state of Arizona and parts of Indiana. +Ants closely resemble human manners: When they wake, they stretch & appear to yawn in a human manner before taking up the tasks of the day. +Bees have 5 eyes. There are 3 small eyes on the top of a bee's head and 2 larger ones in front. +Count the number of cricket chirps in a 15-second period, add 37 to the total, and your result will be very close to the actual outdoor Fahrenheit temperature. +One-fourth of the world's population lives on less than $200 a year. Ninety million people survive on less than $75 a year. +Butterflies taste with their hind feet. +Only female mosquito’s' bite and most are attracted to the color blue twice as much as to any other color. +If one places a tiny amount of liquor on a scorpion, it will instantly go mad and sting itself to death. +It is illegal to hunt camels in the state of Arizona. +In eighteenth-century English gambling dens, there was an employee whose only job was to swallow the dice if there was a police raid. +There are no clocks in Las Vegas gambling casinos. +The human tongue tastes bitter things with the taste buds toward the back. Salty and pungent flavors are tasted in the middle of the tongue, sweet flavors at the tip! +The first product to have a bar code was Wrigley’s gum. +When you sneeze, air and particles travel through the nostrils at speeds over100 mph. During this time, all bodily functions stop, including your heart, contributing to the impossibility of keeping one's eyes open during a sneeze. +Annual growth of WWW traffic is 314,000% +%60 of all people using the Internet, use it for pornography. +In 1778, fashionable women of Paris never went out in blustery weather without a lightning rod attached to their hats. +Sex burns 360 calories per hour. +A raisin dropped in a glass of fresh champagne will bounce up and down continually from the bottom of the glass to the top. +Celery has negative calories! It takes more calories to eat a piece of celery than the celery has in it. +The average lead pencil will draw a line 35 miles long or write approximately 50,000 English words. More than 2 billion pencils are manufactured each year in the United States. If these were laid end to end they would circle the world nine times. +The pop you hear when you crack your knuckles is actually a bubble of gas burning. +A literal translation of a standard traffic sign in China: 'Give large space to the festive dog that makes sport in the roadway.' +You burn more calories sleeping than you do watching TV. +Larry Lewis ran the 100-yard dash in 17.8 seconds in 1969, thereby setting a new world's record for runners in the 100-years-or-older class. He was 101. +In a lifetime the average human produces enough quarts of spit to fill 2 swimming pools. +It's against the law to doze off under a hair dryer in Florida/against the law to slap an old friend on the back in Georgia/against the law to Play hopscotch on a Sunday in Missouri. +Barbie's measurements, if she were life-size, would be 39-29-33. +The human heart creates enough pressure to squirt blood 30ft. +One third of all cancers are sun related. +THE MOST UNUSUAL CANNONBALL: On two occasions, Miss 'Rita Thunderbird' remained inside the cannon despite a lot of gunpowder encouragement to do otherwise. She performed in a gold lamé bikini and on one of the two occasions (1977) Miss Thunderbird remained lodged in the cannon, while her bra was shot across the Thames River. +It has been estimated that humans use only 10% of their brain. +Valentine Tapley from Pike County, Missouri grew chin whiskers attaining a length of twelve feet six inches from 1860 until his death 1910, protesting Abraham Lincoln's election to the presidency. +Most Egyptians died by the time they were 30 about 300 years ago, +For some time Frederic Chopin, the composer and pianist, wore a beard on only one side of his face, explaining: 'It does not matter, my audience sees only my right side.' +1 in every 4 Americans has appeared someway or another on television. +1 in 8 Americans has worked at a McDonalds restaurant. +70% of all boats sold are used for fishing. +Studies have shown that children laugh an average of 300 times/day and adults 17 times/day, making the average child more optimistic, curious, and creative than the adult. +A pregnant goldfish is called a twit. +The shortest war in history was between Zanzibar and England in 1896. Zanzibar surrendered after 38 minutes. +You were born with 300 bones, but by the time you are an adult you will only have 206. +If you go blind in one eye you only lose about one fifth of your vision but all your sense of depth. +Women blink nearly twice as much as men. +The strongest muscle (Relative to size) in the body is the tongue. +A Boeing 747's wingspan is longer than the Wright brother's first flight. +American Airlines saved $40,000 in 1987 by eliminating one olive from each salad served in first-class. +Average life span of a major league baseball: 7 pitches. +A palindrome is a sentence or group of sentences that reads the same backwards as it does forward: Ex: 'Red rum, sir, is murder.' 'Ma is as selfless as I am.' 'Nurse, I spy gypsies. Run!' 'A man, a plan, a canal - Panama.' 'He lived as a devil, eh?' +The first CD pressed in the US was Bruce Springsteen's 'Born in the USA' +In 1986 Congress & President Ronald Reagan signed Public Law 99-359, which changed Daylight Saving Time from the last Sunday in April to the first Sunday in April. It was estimated to save the nation about 300,000 barrels of oil each year by adding most of the month April to D.S.T. +The thumbnail grows the slowest, the middle nail the fastest, nearly 4 times faster than toenails. +The Human eyes never grow, but nose and ears never stop growing. +The 57 on Heinz ketchup bottles represents the number of varieties of pickles the company once had. +Tom Sawyer was the first novel written on a typewriter. +If Texas were a country, its GNP would be the fifth largest of any country in the world. +There are 1 million ants for every human in the world. +Odds of being killed by lightening? 1 in 2million/killed in a car crash? 1 in 5,000/killed by falling out of bed? 1 in 2million/killed in a plane crash? 1 in 25 million. +Since 1978, 37 people have died by Vending Machine's falling on them. 13 people are killed annually. All this while trying to shake merchandise out of them. 113 people have been injured. +Half the foods eaten throughout the world today were developed by farmers in the Andes Mountains (including potatoes, maize, sweet potatoes, squash, all varieties of beans, peanuts, manioc, papayas, strawberries, mulberries and many others). +The 'Golden Arches' of fast food chain McDonalds is more recognized worldwide than the religious cross of Christianity. +Former basketball superstar Michael Jordan is the most recognized face in the world, more than the pope himself. +The average talker sprays about 300 microscopic saliva droplets per minute, about 2.5 droplets per word. +The Earth experiences 50,000 Earth quakes per year and is hit by Lightning 100 times a second. +Every year 11,000 Americans injure themselves while trying out bizarre sexual positions. +If we had the same mortality rate now as in 1900, more than half the people in the world today would not be alive. +On average, Americans eat 18 acres of pizza everyday. +Researchers at the Texas Department of Highways in Fort Worth determined the cow population of the U.S. burps some 50 million tons of valuable hydrocarbons into the atmosphere each year. The accumulated burps of ten average cows could keep a small house adequately heated and its stove operating for a year. +During a severe windstorm or rainstorm the Empire State Building sways several feet to either side. +In the last 3,500 years, there have been approximately 230 years of peace throughout the civilized world. +The Black Death reduced the population of Europe by one third in the period from 1347 to 1351. +The average person spends about two years on the phone in a lifetime. +Length of beard an average man would grow if he never shaved 27.5 feet +Over 60% of all those who marry get divorced. +400-quarter pounders can be made from 1 cow. +A full-loaded supertanker traveling at normal speed takes at least 20 minutes to stop. +Coca-Cola was originally green. +Men can read smaller print than women; women can hear better. +Hong Kong holds the most Rolls Royce’s per capita. +Average number of days a West German goes without washing his underwear: 7 +WWII fighter pilots in the South Pacific armed their airplanes while stationed with .50 caliber machine gun ammo belts measuring 27 feet before being loaded into the fuselage. If the pilots fired all their ammo at a target, he went through 'the whole 9 yards', hence the term. +Average number of people airborne over the US any given hour: 61,000. +Intelligent people have more zinc and copper in their hair. +Iceland consumes more Coca-Cola per capita than any other nation. +In the early 1940s, the FCC assigned television's Channel 1 to mobile services (like two-way radios in taxis) but did not re-number the other channel assignments. +The San Francisco Cable cars are the only mobile National Monuments. +Firehouses have circular stairways originating from the old days when the engines were pulled by horses. The horses were stabled on the ground floor and figured out how to walk up straight staircases. +The Main Library at Indiana University sinks over an inch every year because when it was built, engineers failed to take into account the weight of all the books that would occupy the building. +111,111,111 x 111,111,111 = 12,345,678,987,654,321 +Statues in parks: If the horse has both front legs in the air, the person died in battle; if the horse has one front leg in the air, the person died as a result of wounds received in battle; if the horse has all four legs on the ground, the person died of natural causes. +The expression 'to get fired' comes from long ago Clans that wanted to get rid of unwanted people, so they would burn their houses instead of killing them, creating the term 'Got fired'. +'I am.' is the shortest complete sentence in the English language. +Hershey's Kisses are called that because the machine that makes them looks like it's kissing the conveyor belt. +The phrase 'rule of thumb' is derived from an old English law, which stated that you couldn't beat your wife with anything wider than your thumb. +The longest recorded flight of a chicken is thirteen seconds. +The Eisenhower interstate system requires that one mile in every five must be straight in case of war or emergency, they could be used as airstrips. +The name Jeep came from the abbreviation used in the army. G.P. for 'General Purpose' vehicle. +The Pentagon, in Arlington, Virginia, has twice as many bathrooms as is necessary, because when it was built in the 1940s, the state of Virginia still had segregation laws requiring separate toilet facilities for blacks and whites. +The cruise liner, Queen Elizabeth II, moves only six inches for each gallon of diesel that it burns. +If you have three quarters, four dimes, and four pennies, you have $1.19, the largest amount of money in coins without being able to make change for a dollar. +In Aspen Colorado, you can have a maximum income of $104,000 and still receive government subsidized housing. +Honking of car horns for a couple that just got married is an old superstition to insure great sex. +Dr. Kellogg introduced Kellogg's Corn Flakes in hopes that it would reduce masturbation. +The sperm of a mouse is actually longer than the sperm of an elephant. +In medieval France, unfaithful wives were made to chase a chicken through town naked. +The Black Widow spider eats her mate during or after sex. +Napoleon's penis was sold to an American Urologist for $40,000. +Eating the heart of a male Partridge was the cure for impotence in ancient Babylon. +A bull can inseminate 300 cows from one single ejaculation. +When a Hawaiian woman wears a flower over her left ear, it means that she is not available. +The 'save' icon on Microsoft Word shows a floppy disk with the shutter on backwards. +The only nation whose name begins with an 'A', but doesn't end in an 'A' is Afghanistan. +The following sentence: 'A rough-coated, dough-faced, thoughtful ploughman strode through the streets of Scarborough; after falling into a slough, he coughed and hiccoughed.' Contains the nine different pronunciations of 'ough' in the English Language. +The verb 'cleave' is the only English word with two synonyms which are antonyms of each other: adhere and separate. +The only 15-letter word that can be spelled without repeating a letter is uncopyrightable. +The shape of plant collenchyma’s cells and the shape of the bubbles in beer foam are the same - they are orthotetrachidecahedrons. +Emus and kangaroos cannot walk backwards, and are on the Australian coat of arms for that reason. +Cats have over one hundred vocal sounds, while dogs only have about ten. +Blueberry Jelly Bellies were created especially for Ronald Reagan. +PEZ candy even comes in a Coffee flavor. +The first song played on Armed Forces Radio during operation Desert Shield was 'Rock the Casba' by the Clash. +Non-dairy creamer is flammable. +The airplane Buddy Holly died in was the 'American Pie.' (Thus the name of the Don McLean song.) +Each king in a deck of playing cards represents a great king from history. Spades - King David, Clubs - Alexander the Great, Hearts - Charlemagne, and Diamonds - Julius Caesar. +Golf courses cover 4% of North America. +The average person will accidentally eat just under a pound of insects every year. +Until 1994, world maps and globes sold in Albania only had Albania on them. +The value of Pi will be officially 'rounded down' to 3.14 from 3.14159265359 on December 31, 1999. +The Great Wall of China is the only man-made structure visible from space. +A piece of paper can be folded no more then 9 times. +The amount of computer Memory required to run WordPerfect for Win95 is 8 times the amount needed aboard the space shuttle. +The average North American will eat 35,000 cookies during their life span. +Between 25% and 33% of the population sneeze when exposed to light. +The most common name in world is Mohammed. +Mount Olympus Mons on Mars is three times the size of Mount Everest. +Most toilets flush in E flat. +2,000 pounds of space dust and other space debris fall on the Earth every day. +Each month, there is at least one report of UFOs from each province of Canada. +40,000 Americans are injured by toilets each year. +You can be fined up to $1,000 for whistling on Sunday in Salt Lake City, Utah. +It takes about 142.18 licks to reach the center of a Tootsie pop. +The serial number of the first MAC ever produced was 2001. +It is illegal to eat oranges while bathing in California. +If done perfectly, a rubix cube combination can be solved in 17 turns. +The average American butt is 14.9 inches long. +More bullets were fired in 'Starship Troopers' than any other movie ever made. +60% of electrocutions occur while talking on the telephone during a thunderstorm. +The name of the girl on the statue of liberty is Mother of Exiles. +3.6 cans of Spam are consumed each second. +There's a systematic lull in conversation every 7 minutes. +The buzz from an electric razor in America plays in the key of B flat; Key of G in England. +There are 1,575 steps from the ground floor to the top of the Empire State building. +The world's record for keeping a Lifesaver in the mouth with the hole intact is 7 hrs 10 min. +There are 293 ways to make change for a dollar. +The world record for spitting a watermelon seed is 65 feet 4 inches. +In the Philippine jungle, the yo-yo was first used as a weapon. +Dueling is legal in Paraguay as long as both parties are registered blood donors. +Texas is also the only state that is allowed to fly its state flag at the same height as the U.S. flag. +The three most recognized Western names in China are Jesus Christ, Richard Nixon, & Elvis Presley. +There is a town in Newfoundland, Canada called Dildo. +The Boston University Bridge (on Commonwealth Avenue, Boston, Massachusetts) is the only place in the world where a boat can sail under a train driving under a car driving under an airplane. +All 50 states are listed across the top of the Lincoln Memorial on the back of the $5 bill. +In space, astronauts are unable to cry, because there is no gravity and the tears won't flow. +Chewing gum while peeling onions will keep you from crying. +There are more plastic flamingos in the U.S that there are real ones. +The crack of a whip is actually a tiny sonic boom, since the tip breaks the sound barrier. +Jupiter is bigger than all the other planets in our solar system combined. +Hot water is heavier than cold. +The common idea that only 10% of the brain is used it not true as it is impossible to determine the actual percentage because of the complexity of the brain. +Lawn darts are illegal in Canada. +There are more psychoanalysts per capita in Buenos Aires than any other place in the world. +Between 2 and 3 jockeys are killed each year in horse racing. +5,840 people with pillow related injuries checked into U.S. emergency rooms in 1992. +The average woman consumes 6 lbs of lipstick in her lifetime. +Some individuals express concern sharing their soap, rightly so, considering 75% of all people wash from top to bottom. +Conception occurs most in the month of December. +CBS' '60 Minutes' is the only TV show without a theme song/music. +Half of all Americans live within 50 miles of their birthplace. +'Obsession' is the most popular boat name. +On average, Americans' favorite smell is banana. +If one spells out numbers, they would have to count to One Thousand before coming across the letter 'A'. +Honey is the only food which does not spoil. +3.9% of all women do not wear underwear. +This common everyday occurrence composed of 59% nitrogen, 21% hydrogen, and 9% dioxide is called a 'fart'. +'Evaluation and Parameterization of Stability and Safety Performance Characteristics of Two and Three Wheeled Vehicular Toys for Riding.' Title of a $230,000 research project proposed by the Department of Health, Education and Welfare, to study the various ways children fall off bicycles. +Babies are born without kneecaps. They don't appear until the child reaches 2-6 years of age. +Meteorologists claim they're right 85% of the time (think about that one!) +In 1980, a Las Vegas hospital suspended workers for betting on when patients would die. +Los Angeles' full name 'El Pueblo de Nuestra Senora la Reina de Los Angeles de Porciuncula' is reduced to 3.63% of its size in the abbreviation 'L.A.'. +If you went out into space, you would explode before you suffocated because there's no air pressure. +The only real person to ever to appear on a pez dispenser was Betsy Ross. +Mike Nesmith's (the guitarist of The Monkeys) mom invented White Out. +Only 6 people in the whole world have died from moshing. +241. In a test performed by Canadian scientists, using various different styles of music, it was determined that chickens lay the most eggs when pop music was played. +The storage capacity of human brain exceeds 4 Terabytes. +In Vermont, the ratio of cows to people is 10:1 +Any free-moving liquid in outer space will form itself into a sphere, because of its surface tension. +The average American looks at eight houses before buying one. +In the average lifetime, a person will walk the equivalent of 5 times around the equator. +Koala is Aboriginal for 'no drink'. +Shakespeare spelled his OWN name several different ways. +The first contraceptive was crocodile dung used by the ancient Egyptians. +A signature is called a John Hancock because he signed the Declaration of Independence. Only 2 people signed the declaration of independence on July 4. The Last person signed 2 years later. +Arnold Schonberg suffered from triskaidecaphobia, the fear of the number 13. He died at 13 minutes from midnight on Friday the 13th. +Mozart wrote the nursery rhyme 'twinkle, twinkle, little star' at the age of 5. +Weatherman Willard Scott was the first original Ronald McDonald. +Virginia Woolf wrote all her books standing. +Einstein couldn't speak fluently until after his ninth birthday. His parents thought he was mentally retarded. +Al Capone's business card said he was a used furniture dealer. +Deborah Winger did the voice of E.T. +Kelsey Grammar sings and plays the piano for the theme song of Fraiser. +Thomas Edison, acclaimed inventor of the light bulb, was afraid of the dark. +In England, the Speaker of the House is not allowed to speak. +You can sail all the way around the world at latitude 60 degrees south. +The earth weighs around 6,588,000,000,000,000,000,000,000,000 tons. +Peanuts are one of the ingredients of dynamite. +Porcupines can float in water. +The average person's left hand does 56% of the typing. +A shark is the only fish that can blink with both eyes. +The longest one-syllable word in the English language is 'screeched.' +All of the clocks in the movie 'Pulp Fiction' are stuck on 4:20, a national pot-smokers hour. +'Dreamt' is the only English word that ends in the letters 'mt.' +Almonds are a member of the peach family. +Winston Churchill was born in a ladies' room during a dance. +Maine is the only state whose name is just one syllable. +There are only four words in the English language which end in 'dous': tremendous, horrendous, stupendous, and hazardous. +Tigers not only have striped fur, they have striped skin! +In most advertisements, including newspapers, the time displayed on a watch is 10:10. +On the ground, a group of geese is a gaggle, in the sky it is a skein. +To Ensure Promptness, one is expected to pay beyond the value of service – hence the later abbreviation: T.I.P. +When the University of Nebraska Cornhuskers play football at home, the stadium becomes the state's third largest city. +The characters Bert and Ernie on Sesame Street were named after Bert the cop and Ernie the taxi driver in Frank Capra's 'Its A Wonderful Life.' +A dragonfly has a lifespan of 24 hours. +A dime has 118 ridges around the edge. +On an American one-dollar bill, there is an owl in the upper left-hand corner of the '1'encased in the 'shield' and a spider hidden in the front upper right-hand corner. +The name for Oz in the 'Wizard of Oz' was thought up when the creator, Frank Baum, looked at his filing cabinet and saw A-N, and O-Z; hence the name 'OZ.' +The microwave was invented after a researcher walked by a radar tube and a chocolate bar melted in his pocket. +Mr. Rogers is an ordained minister. +John Lennon's first girlfriend was named Thelma Pickles. +There are 336 dimples on a regulation golf ball. +The scene where Indiana Jones shoots the swordsman in Raider’s of the Lost Ark was Harrison Ford's idea so that he could take a bathroom break. +A crocodile cannot stick its tongue out. +A snail can sleep for three years. +All polar bears are left-handed. +China has more English speakers than the United States. +Elephants are the only animals that can't jump. +February 1865 is the only month in recorded history not to have a full moon. +If the population of China walked past you in single file, the line would never end because of the rate of reproduction. +If you yelled for 8 years, 7 months and 6 days, you will have produced enough sound energy to heat one cup of coffee. +In the last 4000 years, no new animals have been domesticated. +Leonardo Da Vinci invented the scissors. +The word 'set' has more definitions than any other word in the English language. +Nutmeg is extremely poisonous if injected intravenously. +On average, people fear spiders more than they do death. +One of the reasons marijuana is illegal today is because cotton growers in the 1930s lobbied against hemp farmers they saw it as competition. +Shakespeare invented the word 'assassination' and 'bump'. +Some lions mate over 50 times a day. +Starfish haven't got brains. +The ant always falls over on its right side when intoxicated. +The name of all continents in the world end with the same letter that they start with. +There are two credit cards for every person in the United States. +The longest word comprised of one row on the keyboard is: TYPEWRITER +You can't kill yourself by holding your breath. +The average person spends 12 weeks a year 'looking for things'. +The symbol on the 'pound' key (#) is called an octothorpe.. +The dot over the letter 'i' is called a tittle. +Ingrown toenails are hereditary. +'Underground' is the only word in the English language that begins and ends with the letters 'und' +The longest word in the English language, according to the Oxford English Dictionary, is: pneumonoultramicroscopicsilicovolcanoconiosis.. +The longest place-name still in use is: Taumatawhakatangihangakoauauotamateaturipukakapikimaungahoronukupokaiakitnatahu, a New Zealand hill. +An ostrich's eye is bigger than its brain. +Alfred Hitchcock didn't have a belly button. It was eliminated when he was sewn up after surgery. +Telly Savalas and Louis Armstrong died on their birthdays. +Donald Duck's middle name is Fauntleroy. +The muzzle of a lion is like a fingerprint - no two lions have the same pattern of whiskers. +Steely Dan got their name from a sexual device depicted in the book 'The Naked Lunch'. +The Ramses brand condom is named after the great pharoh Ramses II who fathered over 160 children. +There is a seven letter word in the English language that contains ten words without rearranging any of its letters, 'therein': the, there, he, in, rein, her, here, ere, therein, herein. +A goldfish has a memory span of three seconds. +Cranberries are sorted for ripeness by bouncing them; a fully ripened cranberry can be dribbled like a basketball. +The male gypsy moth can 'smell' the virgin female gypsy moth from 1.8 miles away. +The letters KGB stand for Komitet Gosudarstvennoy Bezopasnosti. +The word 'dexter' whose meaning refers to the right hand is typed with only the left hand. +To 'testify' was based on men in the Roman court swearing to a statement made by swearing on their testicles. +Facetious and abstemious contain all the vowels in the correct order, as does arsenious, meaning 'containing arsenic.' +The word 'Checkmate' in chess comes from the Persian phrase 'Shah Mat,' which means 'the king is dead.' +The first episode of 'Joanie Loves Chachi' was the highest rated American program in the history of Korean television, a country where 'Chachi' translates to 'penis'. +Rubber bands last longer when refrigerated. +The national anthem of Greece has 158 verses. No one in Greece has memorized all 158 verses. +Two-thirds of the world's eggplant is grown in New Jersey. +The giant squid has the largest eyes in the world. +Giraffes have no vocal cords. +The pupils of a goat's eyes are square. +Van Gogh only sold one painting when he was alive. +A standard slinky measures 87 feet when stretched out. +The highest per capita Jell-O comsumption in the US is Des Moines. +If a rooster can't fully extend its neck, it can't crow. +There were always 56 curls in Shirley Temple's hair. +The eyes of a donkey are positioned so that it can see all four feet at all times. +Worcestershire sauce in essentially an Anchovy Ketchup. +Rhode Island is the only state which the hammer throw is a legal high school sport. +The average lifespan of an eyelash is five months. +A spider has transparent blood. +Every acre of American crops harvested contains 100 pounds of insects. +Prince Charles is an avid collecter of toilet seats. +The most common street name in the U.S. is Second Street. +Tehran is the most expensive city on earth. +The sweat drops drawn in cartoon comic strips are called pleuts. +Babies are most likely to be born on Tuesdays. +The HyperMart outside of Garland Texas has 58 check-outs. +The Minneapolis phone book has 21 pages of Andersons. +In the 1980's American migraines increased by 60%. +Poland is the 'stolen car capital of the world'. +Jefferson invented the dumbwaiter, the monetary system, and the folding attic ladder. +The S in Harry S. Truman did not stand for anything. +In Miconesia, coins are 12 feet across. +A horse can look forward with one eye and back with the other. +Shakespeare is quoted 33,150 times in the Oxford English dictionary. +The word Pennsylvania is misspelled on the Liberty Bell. +NBA superstar Michael Jordan was originally cut from his high school basketball team. +You spend 7 years of your life in the bathroom. +A family of 26 could go to the movies in Mexico city for the price of one in Tokyo. +10,000 Dutch cows pass through the Amsterdam airport each year. +Approximately every seven minutes of every day, someone in an aerobics class pulls their hamstring. +Simplistic passwords contribute to over 80% of all computer password break-ins. +The top 3 health-related searches on the Internet are (in this order): Depression, Allergies, & Cancer. +Dentists have recommended that a toothbrush be kept at least 6 feet away from a toilet to avoid airborne particles resulting from the flush. +Most dust particles in your house are made from dead skin. +Venus is the only planet that rotates clockwise. +Oak trees do not produce acorns until they are fifty years of age or older. +The first owner of the Marlboro company died of lung cancer. +All US Presidents have worn glasses; some just didn't like being seen wearing them in public. +Mosquito repellents don't repel. They hide you. The spray blocks the mosquito's sensors so they don't know you're there. +Walt Disney was afraid of mice. +The site with the highest number of women visitors between the age of 35 and 44 years old: Alka-Seltzer.com +The king of hearts is the only king without a mustache. +Pearls melt in vinegar. +It takes 3,000 cows to supply the NFL with enough leather for a year's supply of footballs. +Thirty-five percent of people who use personal ads for dating are already married. +The 3 most valuable brand names on earth are Marlboro, Coca-Cola, and Budweiser (in that order). +Humans are the only primates that don't have pigment in the palms of their hands. +Months that begin on a Sunday will always have a 'Friday the 13th'. +The fingerprints of koala bears are virtually indistinguishable from those of humans, so much so that they can be easily confused at a crime scene. +The mask worn by Michael Myers in the original 'Halloween' was actually a Captain Kirk mask painted white. +The only two days of the year in which there are no professional sports games--MLB, NBA, NHL, or NFL--are the day before and the day after the Major League All-Star Game. +Only one person in two billion will live to be 116 or older. +When the French Academy was preparing its first dictionary, it defined 'crab' as, 'A small red fish, which walks backwards.' This definition was sent with a number of others to the naturalist Cuvier for his approval. The scientist wrote back, 'Your definition, gentlemen, would be perfect, only for three exceptions. The crab is not a fish, it is not red and it does not walk backwards.' +Dr. Jack Kevorkian first patient has Alzheimer's disease. +Fictional/horror writer Stephen King sleeps with a nearby light on to calm his fear of the dark. +It's possible to lead a cow upstairs but not downstairs. +It was discovered on a space mission that a frog can throw up. The frog throws up its stomach first, so the stomach is dangling out of its mouth. Then the frog uses its forearms to dig out all of the stomach's contents and then swallows the stomach back down. +The very first song played on MTV was 'Video Killed The Radio Star' by the Buggles. +William Marston engineered one of the earliest forms of the polygraph in the early 1900's. Later he went on to create the comic strip Wonder Woman, a story about a displaced Amazon princess who forces anyone caught in her magic lasso to tell the truth +Americans travel 1,144,721,000 miles by air every day +The the U.S. you dial '911'. In Stockholm, Sweden you dial 90000 +38% of American men say they love their cars more than women +The U.S. military operates 234 golf courses +100% of lottery winners do gain weight +Bullet proof vests, fire escapes, windshield wipers, and laser printers were all invented by women +A cat has 32 muscles in each ear. +A duck's quack doesn't echo, and no one knows why. +Cats urine glows under a black light. +In every episode of Seinfeld there is a Superman somewhere. +Lorne Greene had one of his nipples bitten off by an alligator while he was host of 'Lorne Greene's Wild Kingdom.' +Pamela Anderson Lee is Canada's Centennial Baby, being the first baby born on the centennial anniversary of Canada's independence. +Pinocchio is Italian for 'pine head.' +When possums are playing 'possum', they are not 'playing.' They actually pass out from sheer terror. +Who's that playing the piano on the 'Mad About You' theme? Paul Reiser himself. +Winston Churchill was born in a ladies' room during a dance. +Most lipstick contains fish scales! +Donald Duck comics were banned from Finland because he doesn't wear pants! +There are more than 10 million bricks in the Empire State Building! +Camels have three eyelids to protect themselves from blowing sand! +The placement of a donkey's eyes in its' heads enables it to see all four feet at all times! +The average American/Canadian will eat about 11.9 pounds of cereal per year! +Over 1000 birds a year die from smashing into windows! +The state of Florida is bigger than England! +Dolphins sleep with one eye open! +In the White House, there are 13,092 knives, forks and spoons! +Recycling one glass jar, saves enough energy to watch T.V for 3 hours! +Owls are one of the only birds who can see the color blue! +Honeybees have a type of hair on their eyes! +A jellyfish is 95 percent water! +In Bangladesh, kids as young as 15 can be jailed for cheating on their finals! +The katydid bug hears through holes in its hind legs! +Q is the only letter in the alphabet that does not appear in the name of any of the United States! +166,875,000,000 pieces of mail are delivered each year in the US +Bats always turn left when exiting a cave +The praying mantis is the only insect that can turn its head +Daffy Duck's middle name is 'Dumas' +In Disney's Fantasia, the Sorcerer's name is 'Yensid' (Disney backwards.) +In The Empire Strikes Back there is a potato hidden in the asteroid field +Walt Disney holds the world record for the most Academy Awards won by one person, he has won twenty statuettes, and twelve other plaques and certificates +James Bond's car had three different license plates in Goldfinger +Canada makes up 6.67 percent of the Earth's land area +South Dakota is the only U.S state which shares no letters with the name of it's capital +The KGB is headquartered at No. 2 Felix Dzerzhinsky Square, Moscow +The Vatican city registered 0 births in 1983 +Spain leads the world in cork production +There are 1,792 steps in the Eiffel Tower +There are 269 steps to the top of the Leaning Tower of Pisa +Leonardo da Vinci could write with one hand while drawing with the other +Rubber bands last longer when refrigerated. +Peanuts are one of the ingredients of dynamite. +The national anthem of Greece has 158 verses. No one in Greece has memorized all 158 verses. +There are 293 ways to make change for a dollar. +The average secretary’s left hand does 56% of the typing. +A shark is the only fish that can blink with both eyes. +There are more chickens than people in the world (at least before that chicken-flu thing). +Two-thirds of the world’s eggplant is grown in New Jersey. +The longest one-syllable word in the English language is 'screeched.' +All of the clocks in the movie Pulp Fiction are stuck on 4:20. +No word in the English language rhymes with month, orange, silver or purple. +'Dreamt' is the only English word that ends in the letters 'mt'. +All 50 states are listed across the top of the Lincoln Memorial on the back of the $5 bill. +Almonds are members of the peach family. +Winston Churchill was born in a ladies’ room during a dance. +Maine is the only state whose name is just one syllable. +There are only four words in the English language which end in 'dous': tremendous, horrendous, stupendous, and hazardous. +Los Angeles’s full name is 'El Pueblo de Nuestra Senora la Reina de los Angeles de Porciuncula'. And can be abbreviated to 3.63% of its size, 'L.A.' +A cat has 32 muscles in each ear. +An ostrich’s eye is bigger than it’s brain. +Tigers have striped skin, not just striped fur. +In most advertisements, including newspapers, the time displayed on a watch is 10:10. +Al Capone’s business card said he was a used furniture dealer. +The only real person to be a Pez head was Betsy Ross. +When the University of Nebraska Cornhuskers plays football at home, the stadium becomes the state’s third largest city. +The characters Bert and Ernie on Sesame Street were named after Bert the cop and Ernie the taxi driver in Frank Capra’s 'Its A Wonderful Life' +A dragonfly has a lifespan of 24 hours. +A goldfish has a memory span of three seconds. +A goldfish has a memory span of three seconds. +A dime has 118 ridges around the edge. +On an American one-dollar bill, there is an owl in the upper left-hand corner of the '1' encased in the 'shield' and a spider hidden in the front upper right-hand corner. +It’s impossible to sneeze with your eyes open. +The giant squid has the largest eyes in the world. +Who’s that playing the piano on the 'Mad About You' theme? Paul Reiser himself. +The male gypsy moth can 'smell' the virgin female gypsy moth from 1.8 miles away (pretty good trick). +In England, the Speaker of the House is not allowed to speak. +The name for Oz in the 'Wizard of Oz' was thought up when the creator, Frank Baum, looked at his filing cabinet and saw A-N, and O-Z, hence 'Oz.' +The microwave was invented after a researcher walked by a radar tube and a chocolate bar melted in his pocket. +Mr. Rogers is an ordained minister. +John Lennon’s first girlfriend was named Thelma Pickles. +The average person falls asleep in seven minutes. +There are 336 dimples on a regulation golf ball. +'Stewardesses' is the longest word that is typed with only the left hand. +The 'pound' key on your keyboard (#) is called an octotroph. +The only domestic animal not mentioned in the Bible is the cat. +The 'dot' over the letter 'i' is called a tittle. +Table tennis balls have been known to travel off the paddle at speeds up to 160 km/hr. +Pepsi originally contained pepsin, thus the name. +The original story from 'Tales of 1001 Arabian Nights' begins, 'Aladdin was a little Chinese boy.' +Nutmeg is extremely poisonous if injected intravenously. +Honey is the only natural food that is made without destroying any kind of life. What about milk you say? A cow has to eat grass to produce milk and grass are living. +Hawaiian alphabet only has 12 letters: A, E, I, O, U, H, K, L, M, N, P, W +Honey is the only food that does not spoil. +And one single teaspoon of honey represents the life work of 12 bees. +Flamingos only can eat with their heads upside down. +Lighter was invented ten years before the match was. +It’s physically impossible for a pig to look up at the sky. +The first internet domain name to ever be registered is Symbolics.com on March 15th, 1985. +Humans are born with 350 bones in their body, but when reaching adulthood, we only 260. +There are 150 verses in Greek national anthem which making it the longest national anthem in the world. +This is impossible to tickle yourself. +A typical pencil can draw a line that is 35 miles long. +Astronauts get taller in space due to the lack of gravity. +The total surface area of human lungs is 750 square feet. That’s roughly the same area as on-side of a tennis court. +Mosquitos have contributed to more deaths than any animals on earth. +An octopus has 3 hearts, 9 brains & blue blood. +The hair on a polar bear is actually not white but clear. They appear white because it reflects light. +A chameleon can move its eyes in two different directions at the same time. +Buttermilk does not contain any butter and actually low in fat. +A giraffe can go longer without water than a camel can. +Australia has the biggest camel population in the world. +Snails can sleep up to 3 years. +Methane gases produced by cow products as much pollution as cars do. +The majority of the duct in your house is made up from your own dead skin. +Most lipstick contains fish scales. +Most ice-cream contains pig skins (Gelatin). +The Philippine island of Luzon contains a lake that contains an island that contains a lake that contains another island. +Hudson Bay Area in Canada had less gravity than rest of the world and scientists do not know why. +Only one to two percent of the entire world population are natural redheads. +Sloppy handwriting has doctors kills more than 7,000 people and injures more than 1.5million people annually due to getting the wrong medication. +Putting sugar on a wound or cut will greatly reduce pain and shorten healing process. +Real diamonds do not show up in X-ray. +Due to extreme pressure and weather conditions, it literally rains diamonds on Neptune and Uranus. +There are 7 different kinds of twins: Identical, Fraternal, Half-Identical, Mirror Image Twins, Mixed Chromosome Twins, Superfecundation and Superfetation. +Before the 17th century, carrots were actually purple. They didn’t get their orange color until mutation occupied. +If the sun is scaled down to the size of a white blood cell, the Milky Way would be equal the size of the United States. +A grammatical pedantry syndrome is a form of OCD in which suffers feel the need to correct every grammatical error that they see. +Scorpions can hold their breath underwater for up to 6 days. +In zero gravity, a candle’s flame is round and blue. +Only 8 percent of the world’s money exists in physical form, the rest is in computers. +Crows are able to recognize human faces and even hold grudges against ones that they don’t like. +Your cellphone carries up to ten times more bacteria than a toilet seat. +Humans and bananas share about 50 percent of the same DNA. +Humans have fewer chromosomes than a potato. +An American Pharmacist named John Pemberton invented Coca-Cola who advertises it as a nerve tonic for curing headaches and fatigue. +Statistically, you are more likely to die on the way to buy a lottery ticket than you are to win the lottery itself. +The word checkmate comes from the Arabic which means 'the king is dead.' +Hot water turns to ice faster than cool water. This is known as the Mpemba effect. +Apollo 7 Mission was the first 'astronaut ice cream' flew in space. However, it was so unpopular among astronauts and was retired from the menu after only one trip into space. +Apollo 8 astronauts were the first to celebrate Christmas in space. +IV Is The Roman Numeral designation for 4 everywhere. However, on the clock face, 4 is displayed as 'IIII'. +The Apple Macintosh had the signatures Of its design team engraved inside its case. +Japan has the most vending machines per capita, a staggering 1:23. +A study by University Chicago in 1915, it concluded that the easiest color to spot at a distance is the color yellow. Which is why the most popular color for taxi cabs are yellow. +Japanese police declare murders that they cannot solve as suicides, in order to save faces and keep crime rate artificially low. +The smallest poisonous frogs only 10 millimeters (0.393701 inch) in length. +Farting helps to reduce blood pressure and is good for your overall health. +In 1994, the US Air Force did research on creating a gay bomb (are informal names for theoretical non-lethal chemical weapon) which is a non-lethal bomb containing very strong human sexual pheromones that would make the enemy forces attracted to each other. +There are around 1,584 people in the United States named 'Seven'. +The classic heart shape that we all know was meant to be two hearts fused together. +The water we drink is older than the sun. The sun is 4.6 billion years old. +The water on our planet is very old. The water we have now is the same water that existed hundreds of millions of year ago. The next time you drink a glass of water, you could be about to sip on dinosaur pee. +Meanwhile, about 40% of Americans think humans and dinosaurs existed at the same time. +Nobody knows who named our planet 'Earth'. +Michael Nicholson from Michigan. He has one bachelor’s degree, two associate’s degrees, 22 master’s degrees, three specialist degrees and one doctoral degree, making him the most credentialed person in history. +Practicing a kill in your head will make you better at it, but only if you’re already good at it. +If two identical twins have children with another pair of identical twins, then their children will genetically be full siblings. +In Biertan village (located in Transylvania, Romania) the church had a 'divorce-reconciliation room.' Couples that wanted to get a divorce had to live in a room for two weeks with one small bed, one chair, one table, one plate and one spoon. In 300 years, they only had one divorce. +Killing a panda in China is a seriously crime. It is punishable by death. +December 4th is the National Cookie Day! +Beards can slow the aging process by stopping water from leaving the skin, keeping it moisturized. +A survey found that 33% of men and 43% of women claimed that they had fallen in love with someone they did not initially find attractive. +Most people dream in color, but those who grow up watching television in black and white are more likely to dream in black and white. +Mixing your drinks with diet soda can get you drunk about 18% faster than regular soda. Hummm… +The number of H2O molecules in 10 drops of water is roughly equal to the total amount of stars in the universe. +Octopuses have copper-based blood instead of iron-based blood, which is why their blood is blue rather than red. +Also, they have three hearts and nine brains +The hormones responsible for your growth are only produced when you sleep. +You touch your face an average of once every three minutes. And you properly touched your face after you read it. +People who sleep less than six hours a night are 4.2 times more likely to catch a cold compared those who get more than seven hours of sleep. +Dogs can make about 100 different facial expressions. +Iceland has no army as is often recognized as the most peaceful country in the world. +Shigeru Miyamoto – maker of Super Mario Bros. and Donkey Kong – is not allowed to bike to work because his safety is too important to Nintendo. +Every year, women lose approximately 1.73 billion bobby pins. +Dolphins give each other 'names' – Specific sounds that they use to call friends and family. +Chimpanzee babies like to play with dolls – They’ll make dolls out of sticks and rocks for themselves. +Squirrels plant thousands of trees every year, simply by forgetting where they put their acorns. +Koalas can sleep for up to 20 hours a day. +The average woman will spend one full year of her life trying to decide what to wear. +The average woman owns eight times more makeup than she actually uses. +Rainbows that appear at night are called 'moonbows.' +100 million years ago, crocodiles had long legs and could gallop after their prey. +The real Top Gun school give a $5 fine to any staff member that quotes the movie. diff --git a/packages.el b/packages.el new file mode 100644 index 0000000..e303765 --- /dev/null +++ b/packages.el @@ -0,0 +1,41 @@ +;; -*- no-byte-compile: t; -*- +;;; $DOOMDIR/packages.el + +;;org +(package! doct) +(package! websocket) +(package! org-appear) +(package! org-roam-ui) +(package! org-preview-html) + +;;latex +(package! aas) +(package! laas) +(package! engrave-faces) +(package! ox-chameleon + :recipe (:host github :repo "tecosaur/ox-chameleon")) + +;;looks +(package! focus) +(package! dimmer) +(package! minions) +(package! mini-frame) +(package! solaire-mode :disable t) + +;; nano stuff +(package! nano-theme) +(package! svg-tag-mode) +;; (package! nano-modeline) + +;;emacs additions +(package! nov) +(package! lexic) +(package! info-colors) +(package! magit-delta :recipe (:host github :repo "dandavison/magit-delta")) + +;;fun +(package! xkcd) +(package! md4rd) +(package! smudge) +(package! elcord) +(package! monkeytype) diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..1426eaa --- /dev/null +++ b/shell.nix @@ -0,0 +1,43 @@ +{ pkgs ? import { + overlays = [ + (import (builtins.fetchTarball { + url = "https://github.com/nix-community/emacs-overlay/archive/master.tar.gz"; + })) + ]; +} }: +with pkgs; +mkShell { + buildInputs = [ + # use emacs29 + emacsGit + # :completion vertico + (ripgrep.override { withPCRE2 = true; }) + sqlite + # :lang org + tectonic + ## +gnuplot + gnuplot + ## +pandoc + pandoc + ## +jupyter + (python39.withPackages(ps: with ps; [jupyter])) + # :checkers spell + (aspellWithDicts (ds: with ds; [ en en-computers en-science ])) + sdcv + # :checkers grammar + languagetool + # :app mu4e + ## mu + ## isync + ]; + shellHook = '' + if [ ! -d $HOME/.config/emacs/.git ]; then + mkdir -p $HOME/.config/emacs + git -C $HOME/.config/emacs init + fi + if [ $(git -C $HOME/.config/emacs rev-parse HEAD) != ${pkgs.doomEmacsRevision} ]; then + git -C $HOME/.config/emacs fetch https://github.com/hlissner/doom-emacs.git || true + git -C $HOME/.config/emacs checkout ${pkgs.doomEmacsRevision} || true + fi + ''; +}