54 KiB
Phil's Doom Emacs Literate Config
- Intro
- Header
- config.el
- custom.el
- init.el
- packages.el
Intro
This is my personal Doom Emacs config. The important bit is that I have some additional keybinds. This file is a catch-all for all the files in $DOOMDIR - you can use org-babel-tangle
to tangle them into their respective files.
Some of the comments are from the default config.el file that ships with Doom Emacs.
You can extract all the source/ config files from here by running Emacs and hitting C-c C-v t
.
A lot of these are swiped from DT's Configuring Emacs config files, as well as Karl Voit's Emacs config.
Header
This will generate a header, clarifying that the resulting Doom Emacs config.el
is not to be modified directly.
;; -*- lexical-binding: t -*-
;; DO NOT EDIT THIS FILE
;; This file was generated from the .config/doom/README.org file
;; in the following repo: https://git.bajsicki.com/phil/dot/
config.el
Basic settings
Author/ personal info
(setq user-full-name "Phil Bajsicki")
Global settings
backup-inhibited
is true because I use git for the vast majority of my work.global-auto-revert-mode
is true because I sometimes use external tools on my org-files, and don't want to have to manuallyrevert-buffer
when these changes happen. Mild inconvenience but it's nice to have.indent-tabs-mode
because that's what tabs are for.
(setq-default backup-inhibited t)
(setq global-auto-revert-mode t)
(setq-default indent-tabs-mode t)
Ensure visited files are called by their true names. Kinda insignificant but nice.
(setq find-file-visit-truename t)
Auth
(setq auth-sources '("~/.authinfo"))
Locale
(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-clipboard-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
Langtool
Note that for this functionality you do need some resources, namely:
- some kind of Java runtime (OpenJRE for instance)
- LanguageTool
This command only sets up the path to your java runtime binary.
(setq langtool-java-bin "/usr/bin/java")
Theming and prettifying
(after! counsel
(setq counsel-outline-display-style 'title))
Doom Theme
¯\_(ツ)_/¯
(load-theme 'doom-one t)
(doom-themes-neotree-config)
(doom-themes-org-config)
org-modern
Just some bits here that affect the entirety of Emacs; the parts relevant to org-mode specifically are in org's appearance section.
This part removes all the unnecessary bits that take up screen space and add clutter.
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
Then fixing up some borders and dividers. It's a very clean look, imo.
(modify-all-frames-parameters
'((right-divider-width . 0)
(internal-border-width . 0)))
(dolist (face '(window-divider
window-divider-first-pixel
window-divider-last-pixel))
(face-spec-reset-face face)
(set-face-foreground face (face-attribute 'default :background)))
(set-face-background 'fringe (face-attribute 'default :background))
Transparency
¯\_(ツ)_/¯
(set-frame-parameter nil 'alpha-background 85)
(add-to-list 'default-frame-alist '(alpha-background . 85))
Fonts
To be entirely fair, I pretty much exclusively use Iosevka. Such a good font.
(setq doom-themes-enable-bold t
doom-themes-enable-italic t
doom-font (font-spec :family "Iosevka" :size 14)
doom-big-font (font-spec :family "Iosevka" :size 16)
;; doom-variable-pitch-font (font-spec :family "Iosevka" :size 14)
doom-unicode-font (font-spec :family "Iosevka"))
;; doom-serif-font (font-spec :family "IBM Plex Mono" :size 10 :weight 'light))
;; (set-face-attribute 'default nil :family "Iosevka")
;; (set-face-attribute 'variable-pitch nil :family "Iosevka Aile")
;; (set-face-attribute 'org-modern-symbol nil :family "Iosevka")
Font Family List
This is a simple command that outputs the fonts you have available in Emacs. Not really a config thing, but it's useful when trying to find out why that one specific thing isn't showing correctly.
(print (font-family-list))
Ligature.el
(ligature-set-ligatures 't '("www"))
;; Enable traditional ligature support in eww-mode, if the
;; `variable-pitch' face supports it
(ligature-set-ligatures 'eww-mode '("ff" "fi" "ffi"))
;; Enable all Cascadia Code ligatures in programming modes
(ligature-set-ligatures 'org-mode '("|||>" "<|||" "<==>" "<!--" "####" "~~>" "***" "||=" "||>"
":::" "::=" "=:=" "===" "==>" "=!=" "=>>" "=<<" "=/=" "!=="
"!!." ">=>" ">>=" ">>>" ">>-" ">->" "->>" "-->" "---" "-<<"
"<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->"
"<--" "<-<" "<<=" "<<-" "<<<" "<+>" "</>" "###" "#_(" "..<"
"..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~="
"~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|"
"[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:"
">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:"
"<$" "<=" "<>" "<-" "<<" "<+" "</" "#{" "#[" "#:" "#=" "#!"
"##" "#(" "#?" "#_" "%%" ".=" ".-" ".." ".?" "+>" "++" "?:"
"?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)"
"\\\\" "://"))
;; Enables ligature checks globally in all buffers. You can also do it
;; per mode with `ligature-mode'.
(global-ligature-mode t)
Helpers for text editing
(setq display-line-numbers-type 'relative) ;; best honestly
(setq-default global-visual-line-mode t)
(setq column-number-mode t)
(setq next-screen-context-lines 4)
(setq x-stretch-cursor t)
Global Keybinds
Setting this here because I experiment with these occasionally and want them reset properly eaach time.
(global-set-key "\C-g" 'keyboard-quit)
(global-set-key "\C-cu" 'browse-url-chrome)
Package settings
Straight
Living on the edge. Honestly I probably should not… but then I do find joy in fixing up my config…
(setq straight-repository-branch "develop")
org-mode
I am including pretty much everything here, mostly sorted by package, but I'm keeping org-mode and org-agenda together since they're virtually inseparable in my mind.
Basic settings
;; must be set before `org` is loaded
(add-to-list 'auto-mode-alist
'("\\.org\\'" . org-mode))
(setq-default calendar-week-start-day 1)
Basic directory set-up for org-mode
(setq org-contacts-files '("~/enc/org/people.org"))
(setq org-directory "~/enc/org/")
Agenda files
(setq org-agenda-files (directory-files-recursively "~/enc/org/" ".org$"))1
org-refile
targets. I just want to see nearly everything. If something is more
than 9 levels deep then I should start questioning my sanity. I do want to go
step by step on these (org-outline-path-complete-in-steps
controls this), since
I have a lot of information collected.
(setq org-refile-targets '((nil :maxlevel . 9)
(org-agenda-files :maxlevel . 9)))
(setq org-outline-path-complete-in-steps nil)
(setq org-refile-use-outline-path 'file)
Keeps images contained on the screen.
(setq org-image-actual-width '(0.8))
Footnote positioning and style.
(setq org-footnote-auto-adjust t)
(setq org-footnote-define-inline t)
Pretty!
(setq org-superstar-headline-bullets-list
'("⁖" "◉" "○" "✸" "✿")
org-hide-emphasis-markers t
org-pretty-entities t
org-fontify-todo-headline t
org-hide-leading-stars t)
Code highlighting in code blocks!
(setq org-src-fontify-natively t)
Naturally, I prefer to have a consistent look in my numbers.
(setq org-table-duration-hour-zero-padding t)
Tags flush right to the 80th column, and realign them when the length/ indentation of the heading changes.
(setq org-tags-column -80
org-auto-align-tags t)
And, enable org-modern-mode by default, since it's nice.
(global-org-modern-mode)
It's preferable to have org guess dates in the future when scheduling.
(setq org-read-date-prefer-future t)
This makes the notes I take read like a book. I can imagine there's folks who enjoy reversing their notes and having the most recent at the top but… no. Just no.
(setq org-reverse-note-order nil)
This one really annoyed me for a long time, until I just gave up. There is no better way to have more vertical space in my files than by just… not wasting more space between headings and list items.
(setq org-blank-before-new-entry (quote ((heading . nil)
(plain-list-item . nil))))
This is something I struggled with, particularly when dealing with lots of nested headings; ultimately I have settled on 'smart' as 'good enough'. May move to 'nil' at some point?
(setq org-catch-invisible-edits "smart")
Special functions for headings.
(setq org-special-ctrl-a/e t)
(setq org-special-ctrl-k t)
This fits the yanked subtree into the appropriate level in the structure it's yanked into.
(setq org-yank-adjusted-subtrees t)
I like being able to split lines sometimes, especially when cleaning up large pieces of text.
(setq org-M-RET-may-split-line '((headline . t)
(item . t)
(default . nil)))
This ensures that I can insert my headings anywhere without having to consider structure; particularly useful when I'm breaking large pieces of text into headings, and don't want to jiggle things around much.
(setq org-insert-heading-respect-content nil)
Keep the footnotes per heading, instead of per file; when t
, it'll create a
footnote heading at the end of the file and that's a pain when dealing with
large files.
(setq org-footnote-section nil)
Logging into a drawer.
(setq org-log-done (quote time)
org-log-into-drawer t
org-clock-into-drawer t)
Do not log inserting the TODO heading for the first time; only when further changes are made to the heading.
(setq org-treat-insert-todo-heading-as-state-change nil)
Property inheritance is… difficult. I don't believe it has a place in my world, but I can see specific scenarios where it would. Haven't found one myself yet, despite experimenting.
(setq org-use-property-inheritance nil)
;;(setq org-use-property-inheritance '(category columns archive logging))
Forcing myself to acknowledge and address dependencies has been of great help for me, especially on more involved projects; I am occasionally prone to being lazy and leaving tasks I set for myself unaddressed, but these little settings have really helped me maintain my files over time.
(setq-default org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
I want to know when my deadlines are approaching.
(setq org-deadline-warning-days 7)
I like my statistics.
(setq org-provide-todo-statistics t
org-hierarchical-todo-statistics t)
(setq org-todo-repeat-to-state "LOOP")
I got these from… I frankly don't even know where. They're not bad, imo.
(setq org-todo-keywords
'((sequence
"INBOX(i!)"
"TASK(t!)" ; A task that needs doing & is ready to do
"PROJ(p!)" ; A project, which usually contains other tasks
"LOOP(r!)" ; A recurring task
"WAIT(w!)" ; Something external is holding up this task
"HOLD(h!)" ; This task is paused/on hold because of me
"|"
"DONE(d!@)" ; Task successfully completed
"KILL(k!@)") ; Task was cancelled, aborted or is no longer applicable
(sequence
"DECIDE()" ; for making decisions
"|"
"OKAY(o!)" ; okay as-is
"YES(y!)" ; take action
"NO(n!)")) ; don't take action
org-todo-keyword-faces
'(
("INBOX" :foreground "cyan" :weight bold)
("TASK" :foreground "purple" :weight bold)
("PROJ" :foreground "violet" :weight bold)
("LOOP" :foreground "magenta" :weight bold)
("WAIT" :foreground "yellow" :weight bold)
("HOLD" :foreground "orange" :weight bold)
("DONE" :foreground "green" :weight bold)
("KILL" :foreground "grey" :weight bold)))
Change font for DONE tasks
(setq org-fontify-done-headline t)
(custom-set-faces
'(org-done ((t (:foreground "PaleGreen"
:weight normal
:strike-through t))))
'(org-headline-done
((((class color) (min-colors 16) (background dark))
(:foreground "LightSalmon" :strike-through t)))))
Capture templates
(setq org-capture-templates '(("t" "inbox" entry (file+headline "~/enc/org/agenda.org" "Inbox") "* %i%?")
("i" "idea" entry (file+headline "~/enc/org/agenda.org" "Ideas") "* %?")
("d" "reminder" entry (file+headline "~/enc/org/agenda.org" "Reminders") "* %i%? \n %U")
("p" "person" entry (file+headline "~/enc/org/people.org" "Sort")
"* %(org-contacts-template-name)
:PROPERTIES:
:EMAIL: %(org-contacts-template-email)
:PHONE:
:ALIAS:
:NICKNAME:
:IGNORE:
:ICON:
:NOTE:
:ADDRESS:
:BIRTHDAY:
:END:")))
t | inbox | entry | (file+headline ~/enc/org/agenda.org Inbox) | * %i%? |
i | idea | entry | (file+headline ~/enc/org/agenda.org Ideas) | * %? |
d | reminder | entry | (file+headline ~/enc/org/agenda.org Reminders) | * %i%? |
Keybinds
Pretty self-explanatory.
(global-set-key "\C-cl" 'org-store-link)
(global-set-key "\C-cnn" 'org-capture)
Timestamp keybinds
Inserts timestamps in the proper format. '(16)
stands for two universal arguments, keeping the command from prompting for the time. Two keybinds here, which insert an active or inactive timestamp.
(global-set-key "\C-cia" '(lambda ()(interactive)
(org-time-stamp '(16))))
(global-set-key "\C-cii" '(lambda () (interactive)
(org-time-stamp-inactive '(16))))
org-roam
(setq org-roam-v2-ack t)
(setq org-roam-completion-everywhere t)
(setq org-roam-directory
(file-truename "~/enc/org/roam"))
(org-roam-db-autosync-mode)
(org-roam-db-autosync-enable)
Capture templates
(setq org-roam-capture-templates
'(("n" "default" plain
"%?"
:if-new (file+head "${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: \n")
:empty-lines 1
:unnarrowed t)
("t" "Therapy" plain
"#+title: ${title}\n"
:if-new (file+head "therapy/therapy-${slug}.org" "#+title: ${title}\n#+category: 📗 ${title}\n#+filetags: 📗\n")
:empty-lines 1
:unnarrowed)))
Keybinds
(define-prefix-command 'org-roam-map)
(global-set-key "\C-r" 'org-roam-map)
(define-key org-roam-map "o" 'org-roam-buffer-toggle)
(define-key org-roam-map "f" 'org-roam-node-find)
(define-key org-roam-map "i" 'org-roam-node-insert)
(define-key org-roam-map "n" 'org-roam-capture)
Functions
my-id-get-or-generate
Straight from Karl Voit's config.
(defun my-id-get-or-generate()
"Returns the ID property if set or generates and returns a new one if not set.
The generated ID is stripped off potential progress indicator cookies and
sanitized to get a slug. Furthermore, it is prepended with an ISO date-stamp
if none was found before."
(interactive)
(when (not (org-id-get))
(progn
(let* (
(my-heading-text (nth 4 (org-heading-components)));; retrieve heading string
(my-heading-text (replace-regexp-in-string "\\(\\[[0-9]+%\\]\\)" "" my-heading-text));; remove progress indicators like "[25%]"
(my-heading-text (replace-regexp-in-string "\\(\\[[0-9]+/[0-9]+\\]\\)" "" my-heading-text));; remove progress indicators like "[2/7]"
(my-heading-text (replace-regexp-in-string "\\(\\[#[ABC]\\]\\)" "" my-heading-text));; remove priority indicators like "[#A]"
(my-heading-text (replace-regexp-in-string "\\[\\[\\(.+?\\)\\]\\[" "" my-heading-text t));; removes links, keeps their description and ending brackets
;; (my-heading-text (replace-regexp-in-string "[<\\[][12][0-9]\\{3\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\( .*?\\)[>\\]]" "" my-heading-text t));; removes day of week and time from date- and time-stamps (doesn't work somehow)
(my-heading-text (replace-regexp-in-string "<[12][0-9]\\{3\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\( .*?\\)>" "" my-heading-text t));; removes day of week and time from active date- and time-stamps
(my-heading-text (replace-regexp-in-string "\\[[12][0-9]\\{3\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\( .*?\\)\\]" "" my-heading-text t));; removes day of week and time from inactive date- and time-stamps
(new-id (my-generate-sanitized-alnum-dash-string my-heading-text));; get slug from heading text
(my-created-property (assoc "CREATED" (org-entry-properties))) ;; nil or content of CREATED time-stamp
)
(when (not (string-match "[12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9]-.+" new-id))
;; only if no ISO date-stamp is found at the beginning of the new id:
(if my-created-property (progn
;; prefer date-stamp of CREATED property (if found):
(setq my-created-datestamp (substring (org-entry-get nil "CREATED" nil) 1 11)) ;; returns "2021-12-16" or nil (if no CREATED property)
(setq new-id (concat my-created-datestamp "-" new-id))
)
;; use today's date-stamp if no CREATED property is found:
(setq new-id (concat (format-time-string "%Y-%m-%d-") new-id))))
(org-set-property "ID" new-id)
)
)
)
(kill-new (concat "id:" (org-id-get)));; put ID in kill-ring
(org-id-get);; retrieve the current ID in any case as return value
)
Directory to org
Frankly I don't know where I got this from, it's been a long time, and I don't recall ever using it but… it's so nice that I don't dare remove this just in case I need it at some point in the future.
(defun my-dir-to-org (dir org-file)
"Create a file ORG-FILE which has all txt files in DIR as linked headlines
and the contents of the files below the headlines."
(interactive "DDirectory to convert: \nFFilename: ")
(let ((files (directory-files
dir t ".*\\.txt\\'")))
(with-temp-file org-file
(dolist (file files)
(insert (concat "* " (file-name-nondirectory file) "\n\n"))
(insert-file-contents file)
(goto-char (point-max))
(insert "\n")))))
(defun my-dir-to-org-with-links (dir org-file)
"Create a file ORG-FILE which has all txt files in DIR as linked headlines
and the contents of the files below the headlines."
(interactive "DDirectory to convert: \nFFilename: ")
(let ((files (directory-files
dir t ".*\\.txt\\'")))
(with-temp-file org-file
(dolist (file files)
(insert (concat "* " "[[" file "][" (file-name-nondirectory file) "]]\n\n"))
(insert-file-contents file)
(goto-char (point-max))
(insert "\n")))))
(defun my-mass-conversion (source-dir target-dir)
"Create one org file per directory of SOURCE-DIR inside TARGET-DIR."
(interactive "DDirectory to convert: \nDTarget Directory:")
(let ((dirs-full
(remove-if-not #'file-directory-p
(directory-files
source-dir t
directory-files-no-dot-files-regexp))))
(mapc (lambda (dir)
(my-dir-to-org dir
(concat target-dir
(file-name-base dir) ".org")))
dirs-full)))
my-org-tree-to-indirect-buffer
This beautiful piece of code was done by alphapapa and published on reddit. Its purpose is to provide more than one indirect buffer when using
org-tree-to-indirect-buffer()
(viaC-c C-x b
). Further more, it has a different way of naming these buffers.Using an advice, the original function gets overwritten.
–Karl Voit
(defun my-org-tree-to-indirect-buffer (&optional arg)
"Create indirect buffer and narrow it to current subtree.
The buffer is named after the subtree heading, with the filename
appended. If a buffer by that name already exists, it is
selected instead of creating a new buffer."
(interactive "P")
(let* ((new-buffer-p)
(pos (point))
w (buffer-name (let* ((heading (org-get-heading t t))
(level (org-outline-level))
(face (intern (concat "outline-" (number-to-string level))))
(heading-string (propertize (org-link-display-format heading)
'face face)))
(concat heading-string "::" (buffer-name))))
(new-buffer (or (get-buffer buffer-name)
(prog1 (condition-case nil
(make-indirect-buffer (current-buffer) buffer-name 'clone)
(error (make-indirect-buffer (current-buffer) buffer-name)))
(setq new-buffer-p t)))))
(switch-to-buffer new-buffer)
(when new-buffer-p
;; I don't understand why setting the point again is necessary, but it is.
(goto-char pos)
(rename-buffer buffer-name)
(org-narrow-to-subtree))))
(advice-add 'org-tree-to-indirect-buffer :override 'my-org-tree-to-indirect-buffer)
preserving all heading levels when archiving
Preserve the hierarchy when archiving: blog article, source code (GitHub gist) –Karl Voit
(setq org-archive-default-command #'org-archive-subtree-hierarchically)
(defun org-archive-subtree-hierarchically (&optional prefix)
(interactive "P")
(let* ((fix-archive-p (and (not prefix)
(not (use-region-p))))
(afile (car (org-archive--compute-location
(or (org-entry-get nil "ARCHIVE" 'inherit) org-archive-location))))
(buffer (or (find-buffer-visiting afile) (find-file-noselect afile))))
(org-archive-subtree prefix)
(when fix-archive-p
(with-current-buffer buffer
(goto-char (point-max))
(while (org-up-heading-safe))
(let* ((olpath (org-entry-get (point) "ARCHIVE_OLPATH"))
(path (and olpath (split-string olpath "/")))
(level 1)
tree-text)
(when olpath
(org-mark-subtree)
(setq tree-text (buffer-substring (region-beginning) (region-end)))
(let (this-command (inhibit-message t)) (org-cut-subtree)) ; we don’t want to see "Cut subtree" messages
(goto-char (point-min))
(save-restriction
(widen)
(-each path
(lambda (heading)
(if (re-search-forward
(rx-to-string
`(: bol (repeat ,level "*") (1+ " ") ,heading)) nil t)
(org-narrow-to-subtree)
(goto-char (point-max))
(unless (looking-at "^")
(insert "\n"))
(insert (make-string level ?*)
" "
heading
"\n"))
(cl-incf level)))
(widen)
(org-end-of-subtree t t)
(org-paste-subtree level tree-text))))))))
my-dired-insert-lfile-link-list-to-other-org-window()
2022-06-20 I had this idea and implemented it Development task: id:2022-06-20-implement-add-lfile-links-to-buffer-with-marked-dired-files
This stackexchange snippet had the almost exactly perfect code which I adapted.
The idea of the process is:
- I have an Org-mode buffer and a dired buffer side-by-side (which is my usual setup).
- I place the cursor in the Org-mode buffer so that I may add a list.
- I switch to the dired buffer and mark one or more files.
- I invoke this function.
This results in a list that gets added to the Org-mode buffer similar to:
- [[lfile:This is an example.odt][This is an example.odt]] - [[lfile:2022-06-20 an image.png][2022-06-20 an image.png]]
(defun my-dired-insert-lfile-link-list-to-other-org-window (files)
;; adapted by Karl Voit from https://emacs.stackexchange.com/a/60369
(interactive
(list (dired-get-marked-files)))
(unless (eq major-mode 'dired-mode)
(user-error "This command must be triggered in a dired buffer"))
(let ((dired-win (selected-window))
(orgmode-win
(get-window-with-predicate
(lambda (window)
(with-current-buffer (window-buffer window)
(eq major-mode 'org-mode))))))
(unless orgmode-win
(user-error
"Can't attach to subtree. No window displaying an Org buffer"))
(select-window orgmode-win)
(dolist (file files)
(let* ((fname (file-name-nondirectory file))
(link (format "lfile:%s" fname))
(desc fname))
;;(push (list link desc) org-stored-links) ;; original idea was to insert to this buffer in order to paste via C-c C-l
(insert (format "%s" (concat "- [[" link "][" desc "]]\n")))
))
(select-window dired-win)))
org-agenda
These are settings specifically for org-agenda, that don't overlap with any other settings.
(setq org-agenda-start-day nil)
(setq org-agenda-start-on-weekday nil)
(setq org-agenda-span 'day)
Dim blocked tasks to clearly see that their prerequisites are not met. Make the agenda blocks more compact by skipping certain elements.
(setq org-agenda-dim-blocked-tasks t)
(setq org-agenda-compact-blocks t)
Non-nil means skip timestamp line if same entry shows because of deadline.
(setq org-agenda-skip-timestamp-if-deadline-is-shown t)
Remove completed deadline and scheduled tasks from the agenda view
(setq org-agenda-skip-deadline-if-done t)
(setq org-agenda-skip-scheduled-if-done t)
Remove completed items from search results
(setq org-agenda-skip-timestamp-if-done t)
Include agenda archive files when searching for things
(setq org-agenda-text-search-extra-files (quote (agenda-archives)))
Do not search for time in heading when displaying a date-stamp
(setq org-agenda-search-headline-for-time nil)
Show all agenda dates - even if they are empty
(setq org-agenda-show-all-dates t)
Show the following items in log mode.
(setq org-agenda-log-mode-items '(closed clock state))
(setq org-agenda-sorting-strategy
(quote ((agenda time-up user-defined-up priority-down category-keep)
(todo priority-down category-keep)
(tags priority-down category-keep)
(search category-keep))))
Ensuring that tag inheritance is applied in the agenda view.
(setq org-agenda-use-tag-inheritance (quote (agenda)))
Agenda prefixes and org-modern agenda styling.
(setq org-agenda-prefix-format '((agenda . " %l %i %c %s %t")
(todo . " %i %-12:c")
(tags . " %i $-12:c")
(search . " %i %-12:c")))
(setq org-agenda-tags-column -80
org-agenda-block-separator ?─
org-agenda-current-time-string "◀── now ─────────────────────────────────────────────────")
Two to choose from, I'm not sure which one is better here. I don't know where I got this one from.
(setq org-agenda-time-grid
'((daily today remove-match)
(800 1000 1200 1400 1600 1800 2000)
" ┄┄┄┄┄ "
"┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄"))
Add hook into the agenda mode for highlighting.
(add-hook 'org-agenda-mode-hook '(lambda () (hl-line-mode 1)))
org-habits
I try to run a reasonable routine, and it doesn't always work. This helps me review if I'm sticking to it well (or, reasonably well) over time.
(add-to-list 'org-modules 'habit)
(setq org-habit-following-days 2
org-habit-preceding-days 7
org-habit-show-all-today nil
org-habit-show-habits-only-for-today t
org-habit-show-habits t)
Some keybinds and a hook.
(define-key org-mode-map (kbd "C-c h") 'org-habit-stats-view-habit-at-point)
(add-hook 'org-after-todo-state-change-hook 'org-habit-stats-update-properties)
multiple-cursors
I rarely use these, since I don't edit much structured data, and when I do it's less like this and more like massive articles or books or whatnot. Still, it does come in handy occasionally.
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
[disabled] copilot.el
;; accept completion from copilot and fallback to company
(use-package! copilot
:hook (prog-mode . copilot-mode)
:bind (:map copilot-completion-map
("<tab>" . 'copilot-accept-completion)
("TAB" . 'copilot-accept-completion)
("C-TAB" . 'copilot-accept-completion-by-word)
("C-<tab>" . 'copilot-accept-completion-by-word)))
Hooks
org-auto-tangle
By adding #+auto_tangle: t
to the frontmatter of an org-mode file, this enables
automatic tangling upon the file being saved.
(require 'org-auto-tangle)
(add-hook 'org-mode-hook 'org-auto-tangle-mode)
Automated timestamps in headings
I need this because hitting the timestamp keybinds is tedious.
For the files whose paths match the strings in the function, it will advise the org-insert-heading function to insert an inactive timestamp into the new heading.
This turns making new entries from C-<return> C-i i
into just C-<return>
. Much easier, and I don't have to think about this any more.
Additionally, outside of the structured files where I am tracking time linearly, I want org-expiry-insert-created
, which fits in neatly into this little hook, thus allowing me to inspect my workflows more carefully.
(use-package! org-expiry)
(after! org
(add-hook! 'org-insert-heading-hook
(if (or
(string-match-p "journal.org" buffer-file-name)
(string-match-p "money.org" buffer-file-name)
(string-match-p "therapy.org" buffer-file-name))
(progn
(org-time-stamp-inactive '(16))
(newline))
(org-expiry-insert-created))))
org-mode expansions
org-babel
This is really important for me since I tend to use PlantUML to generate charts, graphs and diagrams.
(add-hook 'org-babel-after-execute-hook 'org-display-inline-images)
org-crypt
This is nice, since it lets me easily encrypt parts of my notes using my GPG key, which I have set up with my NitroKey. It's some really really cool tech.
(require 'org-crypt)
(require 'epa-file)
(epa-file-enable)
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance (quote ("crypt")))
(setq org-crypt-key "phil@bajsicki.com")
(setenv "GPG_AGENT_INFO" nil)
org-export
Just a catch-all category for this… I honestly should split things up better instead of this, but it is what it is.
LaTeX
Adding the tufte-handout and the memoir classes.
(with-eval-after-load 'ox-latex
(add-to-list 'org-latex-classes
'("tufte-handout"
"\\documentclass[nobib]{tufte-handout}
\\usepackage{nicefrac}
\\usepackage{units}
[NO-DEFAULT-PACKAGES]
[EXTRA]"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
'("memoir"
"\\documentclass{memoir}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))
Testing function, not tangled.
(print org-latex-classes)
I have not settled on this. Meh.
(setq org-latex-default-class "tufte-handout"
org-latex-pdf-process '("latexmk -pdf -bibtex-cond -f -outdir=%o %f"))
ox-hugo
(use-package! ox-hugo
:ensure t
:after ox)
org-transclusion
I don't use this enough, and hopefully I'll find happiness with this if I do end up working on larger projects.
(use-package! org-transclusion
:after org
:init
(map!
:map global-map "<f12>" #'org-transclusion-add
:leader
:prefix "n"
:desc "Org Transclusion Mode" "t" #'org-transclusion-mode))
Org-wild-notifier
This lets me get desktop notifications for TODO items.
(org-wild-notifier-mode)
(setq alert-default-style 'libnotify
org-wild-notifier-alert-time '(0 5 15 60)
org-wild-notifier-keyword-whitelist nil
;; good for testing
org-wild-notifier--alert-severity 'high
alert-fade-time 50)
mu4e
Email in Emacs… what more can a man want?
(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e/")
(setq mu4e-change-filenames-when-moving t)
(setq mu4e-update-interval (* 10 60))
(setq mu4e-get-mail-command "mbsync -a")
(setq mu4e-maildir "~/enc/.mail")
(setq mu4e-drafts-folder "/Drafts")
(setq mu4e-sent-folder "/Sent")
(setq mu4e-refile-folder "/Refile")
(setq mu4e-trash-folder "/Trash")
(mu4e t)
circe
Doesn't work very well. I guess it "works", but I still need to auth manually; not sure what the issue is - my best guess is that my passwords use unusual unicode characters and that screws with the (read)
instruction.
(setq my-credentials-file "~/enc/keys/emacs/circe.el")
(defun my-nickserv-password (server)
(with-temp-buffer
(insert-file-contents-literally my-credentials-file)
(plist-get (read (buffer-string)) :nickserv-password)))
(setq circe-network-options
'(("Libera Chat"
:nick "phil_bb"
:channels ("#emacs" "#emacs-circe")
:nickserv-password my-nickserv-password)))
pdf-tools
Gotta read in Emacs, sometimes. Usually in the browser, but when I have to take notes there's nothing more convenient.
(use-package! pdf-tools
:defer t
:commands (pdf-loader-install)
:mode "\\.pdf\\'"
:bind (:map pdf-view-mode-map
("n" . pdf-view-next-line-or-next-page)
("p" . pdf-view-previous-line-or-previous-page)
("C-=" . pdf-view-enlarge)
("C--" . pdf-view-shrink))
:init (pdf-loader-install)
:config (add-to-list 'revert-without-query ".pdf"))
(add-hook 'pdf-view-mode-hook #'(lambda () (interactive (display-line-numbers-mode))))
yasnippets
(setq doom-snippets-enable-short-helpers t)
csv-mode
Just making sure it loads when I load up csv files.
(add-to-list 'auto-mode-alist '("\\.[Cc][Ss][Vv]\\'" . csv-mode))
(autoload 'csv-mode "csv-mode"
"Major mode for editing comma-separated value files." t)
sly
Basic settings for Common Lisp development.
;; (load (expand-file-name "~/.roswell/helper.el"))
(setq inferior-lisp-program "sbcl --dynamic-space-size 8192 -Q -l ~/.sbclrc")
gptel
This is exclusively local, as I am not entirely comfortable letting third parties into my journals and personal notes. I usually run LLMs as they come, using them largely for brainstorming when I'm trying to plan out projects or consider my habits.
With their context size only increasing as time goes by, this is turning into a very easy way to get feedback on the ideas I have.
(use-package! gptel)
(gptel-make-openai "ooba" ;Any name
:key "thisisanapikey"
:stream t ;Stream responses
:protocol "http"
:host "localhost:6666" ;Llama.cpp server location
:models '("model")) ;Any names, doesn't matter for Llama
(gptel-make-openai "OpenRouter"
:host "openrouter.ai"
:endpoint "/api/v1/chat/completions"
:key (getenv "GPTEL_OPENROUTER_API")
:stream t ;Stream responses
:models '(qwen/qwen-2.5-coder-32b-instruct))
(setq gptel--debug t)
elfeed
RSS is not dead. RSS is not dead. RSS is not dead.
(setq-default elfeed-search-filter "@1-week-ago +unread ")
custom.el
Custom variables. Note that this file is generally set up automatically by Emacs" so I'm not exporting this block. I'm keeping the default warning comments in just for completion here.
(custom-set-variables)
;; custom-set-variables was added by Custom.
;; If you edit it by hand" you could mess it up" so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one" they won't work right.
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand" you could mess it up" so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one" they won't work right.
)
init.el
;;; init.el -*- lexical-binding: t; -*-
;; This file controls what Doom modules are enabled and what order they load
;; in. Remember to run 'doom sync' after modifying it!
;; NOTE Press 'SPC h d h' (or 'C-h d h' for non-vim users) to access Doom's
;; documentation. There you'll find a link to Doom's Module Index where all
;; of our modules are listed" including what flags they support.
;; NOTE Move your cursor over a module's name (or its flags) and press 'K' (or
;; 'C-c c k' for non-vim users) to view its documentation. This works on
;; flags as well (those symbols that start with a plus).
;;
;; Alternatively" press 'gd' (or 'C-c c d') on a module to browse its
;; directory (for easy access to its source code).
(doom! :input
;;bidi ; (tfel ot) thgir etirw uoy gnipleh
;;chinese
;;japanese
;;layout ; auie" ctsrnm is the superior home row
:completion
(company +childframe) ; the ultimate code completion backend
;;helm ; the *other* search engine for love and life
;;ido ; the other *other* search engine...
;;ivy ; a search engine for love and life
vertico ; the search engine of the future
:ui
;;deft ; notational velocity for Emacs
doom ; what makes DOOM look the way it does
doom-dashboard ; a nifty splash screen for Emacs
doom-quit ; DOOM quit-message prompts when you quit Emacs
(emoji +unicode) ; 🙂
;;hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW
hydra
indent-guides ; highlighted indent columns
(ligatures +iosevka +extra) ; ligatures and symbols to make your code pretty again
minimap ; show a map of the code on the side
modeline ; snazzy" Atom-inspired modeline" plus API
nav-flash ; blink cursor line after big motions
;;neotree ; a project drawer" like NERDTree for vim
ophints ; highlight the region an operation acts on
(popup +defaults) ; tame sudden yet inevitable temporary windows
;;tabs ; a tab bar for Emacs
treemacs ; a project drawer" like neotree but cooler
unicode ; extended unicode support for various languages
(vc-gutter +pretty) ; vcs diff in the fringe
vi-tilde-fringe ; fringe tildes to mark beyond EOB
;;window-select ; visually switch windows
workspaces ; tab emulation" persistence & separate workspaces
;;zen ; distraction-free coding or writing
:editor
;;(evil +everywhere); come to the dark side" we have cookies
file-templates ; auto-snippets for empty files
fold ; (nigh) universal code folding
(format +onsave) ; automated prettiness
;;god ; run Emacs commands without modifier keys
;;lispy ; vim for lisp" for people who don't like vim
;;multiple-cursors ; editing in many places at once
;;objed ; text object editing for the innocent
;;parinfer ; turn lisp into python" sort of
;;rotate-text ; cycle region at point between text candidates
snippets ; my elves. They type so I don't have to
word-wrap ; soft wrapping with language-aware indent
:emacs
dired ; making dired pretty [functional]
electric ; smarter" keyword-based electric-indent
;;ibuffer ; interactive buffer management
(undo +tree) ; persistent" smarter undo for your inevitable mistakes
vc ; version-control and Emacs" sitting in a tree
:term
;;eshell ; the elisp shell that works everywhere
;;shell ; simple shell REPL for Emacs
;;term ; basic terminal emulator for Emacs
vterm ; the best terminal emulation in Emacs
:checkers
syntax ; tasing you for every semicolon you forget
(spell +flyspell) ; tasing you for misspelling mispelling
;;grammar ; tasing grammar mistake every you make
:tools
ansible
;;biblio ; Writes a PhD for you (citation needed)
debugger ; FIXME stepping through code" to help you add bugs
;;direnv
docker
editorconfig ; let someone else argue about tabs vs spaces
;;ein ; tame Jupyter notebooks with emacs
(eval +overlay) ; run code" run (also" repls)
;;gist ; interacting with github gists
lookup ; navigate your code and its documentation
lsp ; M-x vscode
magit ; a git porcelain for Emacs
;;make ; run make tasks from Emacs
;;pass ; password manager for nerds
pdf ; pdf enhancements
;;prodigy ; FIXME managing external services & code builders
rgb ; creating color strings
;;taskrunner ; taskrunner for all your projects
terraform ; infrastructure as code
;;tmux ; an API for interacting with tmux
;;upload ; map local to remote projects via ssh/ftp
:os
(:if IS-MAC macos) ; improve compatibility with macOS
;;tty ; improve the terminal Emacs experience
:lang
;;agda ; types of types of types of types...
;;beancount ; mind the GAAP
(cc +lsp) ; C > C++ == 1
;;(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
;;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
;;factor
;;faust ; dsp" but you get to keep your soul
;;fortran ; in FORTRAN" GOD is REAL (unless declared INTEGER)
;;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
;;(graphql +lsp) ; Give queries a REST
(haskell +lsp) ; a language that's lazier than I am
;;hy ; readability of scheme w/ speed of python
;;idris ; a language you can depend on
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) ; a better" faster MATLAB
;;kotlin ; a better" slicker Java(Script)
latex ; writing papers in Emacs has never been so fun
;;lean ; for folks with too much to prove
;;ledger ; be audit you can be
;;lua ; one-based indices? one-based indices
markdown ; writing docs for people to ignore
;;nim ; python + lisp at the speed of c
;;nix ; I hereby declare "nix geht mehr!"
;;ocaml ; an objective camel
(org +dragndrop +pandoc +pretty +gnuplot +roam2) ; organize your plain life in plain text
;;php ; perl's insecure younger brother
plantuml ; diagrams for confusing people more
;;purescript ; javascript" but functional
(python +lsp) ; beautiful is better than ugly
;;qt ; the 'cutest' gui framework ever
;;racket ; a DSL for DSLs
;;raku ; the artist formerly known as perl6
;;rest ; Emacs as a REST client
;;rst ; ReST in peace
;;(ruby +rails) ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
;;(rust +lsp) ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
;;scala ; java" but good
;;(scheme +guile) ; a fully conniving family of lisps
(sh +lsp) ; she sells {ba" z" fi}sh shells on the C xor
;;sml
;;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 +lsp) ; C" but simpler
:email
(mu4e +org +gmail)
;;notmuch
;;(wanderlust +gmail)
:app
calendar
emms
everywhere ; *leave* Emacs!? You must be joking
irc ; how neckbeards socialize
(rss +org) ; emacs as an RSS reader
;;twitter ; twitter client https://twitter.com/vnought
:config
;;literate
(default +bindings))
packages.el
Core
;; -*- no-byte-compile: t; -*-
;;; $DOOMDIR/packages.el
(unpin! straight)
(package! beacon)
(package! counsel)
(package! deft)
Themes
(package! all-the-icons)
(package! all-the-icons-dired)
(package! doom-themes)
Modes:
(package! battle-haxe)
(package! fish-mode)
(package! typescript-mode)
(package! terraform-mode)
(package! wc-mode)
(package! plantuml-mode)
(package! csv-mode)
dired
(package! dired-open)
pdf-tools
(package! pdf-tools)
Org
;; Fix for org-roam link issue
(package! org-auto-tangle)
(package! ox-slack)
(package! ox-tufte)
(package! ox-hugo)
(package! ox-gemini
:recipe (
:host sourcehut
:repo "abrahms/ox-gemini"))
(package! org-special-block-extras)
(package! org-transclusion)
(package! org-modern)
(package! org-ql)
(package! org-sidebar
:recipe (
:host github
:repo "alphapapa/org-sidebar"
))
(package! org-contacts)
(package! org-bullets)
(package! org-download)
(package! org-cliplink)
(package! org-roam)
;; (package! org-super-agenda)
(package! org-wild-notifier)
(package! org-habit-stats)
org-contrib
(package! org-contrib
:recipe (:host sourcehut :type git
:repo "~bzg/org-contrib"
:files ("lisp/*.el")))
LLM
Some packages for dealing with LLM integrations.
copilot.el
(package! copilot
:recipe (:host github :repo "zerolfx/copilot.el" :files ("*.el" "dist")))
gptel
I mostly use this for my locally hosted LLM solutions. It's pretty neat since large-context models are coming out at an increasing pace.
(package! gptel
:recipe (:host github
:repo "karthink/gptel"
:files ("*.el")))
Better Internet
elpher
Gopher and Gemini browser in Emacs!
(package! elpher)