Last active
January 31, 2022 23:09
-
-
Save redblobgames/3ef970bdeeef0e4a025d2981ce83ed27 to your computer and use it in GitHub Desktop.
My note taking setup in emacs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; my-notes.el --- | |
;;; Commentary: | |
;; My notes, inspired by org-roam, but built on other packages I already use. | |
;; | |
;; 1. Capture into a queue (org-capture) | |
;; 2. Review queue (org-agenda) | |
;; 3. Find note (find-file in folder). | |
;; 4. Make new note. Fill with title, date. | |
;; 5. Link to existing note. C-u C-c C-l. | |
;; Once most of my notes have titles, it would be nice to have 3 and 5 | |
;; use the note titles. It'd also be nice to be able to rename a note | |
;; title and have the filename change to match, updating links to the | |
;; file from both my notes folder and my journal folder. | |
;;; Code: | |
;; NOTE: I use ivy, counsel for some of thse but vertico, selectrum, consult probably would work too | |
(require 'hydra) | |
(require 'org) | |
(require 'org-drill) | |
(defvar my/notes-directory "~/Documents/notes") | |
(defhydra hydra-notes (:color blue) | |
("n" my/notes-new "new") | |
("o" my/notes-open "open") | |
("s" my/notes-search "search") | |
("S" my/notes-search-content "search contents") | |
("d" my/notes-directory "directory") | |
("c" (lambda () (interactive) (org-capture nil "t")) "capture") | |
("a" org-agenda "agenda review") | |
("D" my/org-drill "drill")) | |
(bind-key "H-n" 'hydra-notes/body) | |
(defun my/notes-new (title) | |
"Create a new note given a title" | |
(interactive "sTitle: ") | |
(let ((default-directory (concat my/notes-directory "/"))) | |
(find-file (concat (my/title-to-filename title) ".org")) | |
(when (= 0 (buffer-size)) | |
(insert "#+title: " title "\n" | |
"#+date: ") | |
(org-insert-time-stamp nil) | |
(insert "\n\n")))) | |
(defun my/title-to-filename (title) | |
"Convert TITLE to a reasonable filename." | |
;; Based on the slug logic in org-roam, but org-roam also uses a | |
;; timestamp, and I use only the slug. BTW "slug" comes from | |
;; <https://en.wikipedia.org/wiki/Clean_URL#Slug> | |
(setq title (s-downcase title)) | |
(setq title (s-replace-regexp "[^a-zA-Z0-9]+" "-" title)) | |
(setq title (s-replace-regexp "-+" "-" title)) | |
(setq title (s-replace-regexp "^-" "" title)) | |
(setq title (s-replace-regexp "-$" "" title)) | |
title) | |
(defun my/notes-open (filename) | |
"Open an existing note." | |
(interactive) | |
(let ((default-directory (concat my/notes-directory "/" filename ".org"))) | |
(call-interactively 'find-file))) | |
(defun my/notes-directory () | |
"Open dired with my notes files" | |
(interactive) | |
(dired my/notes-directory "-lt")) | |
(defun my/notes-search () | |
"Search my notes for words or phrases" | |
(interactive) | |
(counsel-rg nil my/notes-directory "--glob !archive/*")) | |
(defvar my/notes-search-history) | |
(defun my/notes-search-content () | |
"Full-text search using mdfind. Doesn't show the matched text." | |
(interactive) | |
(ivy-read "Search: " #'my/notes-search-function | |
:dynamic-collection t | |
:action #'find-file | |
:history 'my/notes-search-history | |
:caller 'my/notes)) | |
(defun my/notes-search-function (input) | |
(or (ivy-more-chars) | |
(progn | |
(counsel--async-command (concat "mdfind -onlyin " my/notes-directory "/ " | |
(shell-quote-argument input))) | |
'("" "searching...")))) | |
(defun my/org-drill () | |
"Open my drill file and run org-drill" | |
(interactive) | |
(find-file (concat org-directory "/drill.org")) | |
(org-drill)) | |
(provide 'my-notes) | |
;;; my-notes.el ends here | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment