aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2021-01-22 10:31:36 +0000
committerYann Herklotz <git@yannherklotz.com>2021-01-22 10:31:36 +0000
commit96a000fb27a5e8726f23423e970c6eb99f3575fe (patch)
treefcdae46de23035fef2947dc08cb0a8a125717088
parentcf7056e3ae22cdbfcb215697f0add017052564e6 (diff)
downloademacs-zettelkasten-96a000fb27a5e8726f23423e970c6eb99f3575fe.tar.gz
emacs-zettelkasten-96a000fb27a5e8726f23423e970c6eb99f3575fe.zip
Add org-zettelkastenv0.2.0
-rw-r--r--CHANGELOG4
-rw-r--r--org-zettelkasten.el116
2 files changed, 120 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG
index dbf52e7..d158c2c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+2021-01-22 Yann Herklotz <git@ymhg.org>
+
+ * v0.2.0: Add org-zettelkasten, a different mode which adds helper functions to org-mode to use it as a Zettelkasten.
+
2020-12-08 Yann Herklotz <git@ymhg.org>
* v0.1.1: Release the first stable version of Zettelkasten.
diff --git a/org-zettelkasten.el b/org-zettelkasten.el
new file mode 100644
index 0000000..f343a9f
--- /dev/null
+++ b/org-zettelkasten.el
@@ -0,0 +1,116 @@
+;;; org-zettelkasten.el --- Helper functions to use Zettelkasten in Org.
+
+;; Author: Yann Herklotz
+;; Keywords: notes
+;; Package-Requires: ((emacs "24.1"))
+;; Version: 1.0.0
+
+;;; Commentary:
+
+;; These functions allow for the use of the zettelkasten method in org-mode.
+;;
+;; It uses the CUSTOM_ID property to store a permanent ID to the note,
+;; which are organised in the same fashion as the notes by Luhmann.
+;;
+;; Copyright (C) 2020 Yann Herklotz
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'org)
+(require 'counsel)
+
+(defgroup org-zettelkasten nil
+ "Helper to work with zettelkasten notes."
+ :group 'applications)
+
+(defcustom org-zettelkasten-directory "~/Dropbox/zk"
+ "Main zettelkasten directory."
+ :type 'string
+ :group 'org-zettelkasten)
+
+(defun ymhg/incr-id (ident)
+ "Simple function to increment any IDENT.
+
+This might result in duplicate IDs though."
+ (let* ((ident-list (append nil ident nil))
+ (last-ident (last ident-list)))
+ (setcar last-ident (+ (car last-ident) 1))
+ (concat ident-list)))
+
+(defun ymhg/incr-id-total (ident)
+ "A better way to incement numerical IDENT.
+
+This might still result in duplicate IDENTs for an IDENT that
+ends with a letter."
+ (if (string-match-p "\\(.*[a-z]\\)\\([0-9]+\\)$" ident)
+ (progn
+ (string-match "\\(.*[a-z]\\)\\([0-9]+\\)$" ident)
+ (let ((pre (match-string 1 ident))
+ (post (match-string 2 ident)))
+ (concat pre (number-to-string (+ 1 (string-to-number post))))))
+ (ymhg/incr-id ident)))
+
+(defun ymhg/branch-id (ident)
+ "Create a branch ID from IDENT."
+ (if (string-match-p ".*[0-9]$" ident)
+ (concat ident "a")
+ (concat ident "1")))
+
+(defun ymhg/org-zettelkasten-create (incr newheading)
+ "Creat a new heading according to INCR and NEWHEADING.
+
+INCR: function to increment the ID by.
+NEWHEADING: function used to create the heading and set the current
+ POINT to it."
+ (let* ((current-id (org-entry-get nil "CUSTOM_ID"))
+ (next-id (funcall incr current-id)))
+ (funcall newheading)
+ (org-set-property "CUSTOM_ID" next-id)))
+
+(defun org-zettelkasten-create-next ()
+ "Create a heading at the same level as the current one."
+ (ymhg/org-zettelkasten-create
+ 'ymhg/incr-id 'org-insert-heading))
+
+(defun org-zettelkasten-create-branch ()
+ "Create a branching heading at a level lower than the current."
+ (ymhg/org-zettelkasten-create
+ 'ymhg/branch-id '(lambda () (org-insert-subheading ""))))
+
+(defun org-zettelkasten-create-dwim ()
+ "Create the right type of heading based on current position."
+ (interactive)
+ (let ((current-point (save-excursion
+ (org-back-to-heading)
+ (point)))
+ (next-point (save-excursion
+ (org-forward-heading-same-level 1 t)
+ (point))))
+ (if (= current-point next-point)
+ (org-zettelkasten-create-next)
+ (org-zettelkasten-create-branch))))
+
+(defun org-zettelkasten-search-current-id ()
+ "Use counsel-rg to search for the current ID in all files."
+ (interactive)
+ (let ((current-id (org-entry-get nil "CUSTOM_ID")))
+ (counsel-rg (concat "#" current-id) org-zettelkasten-directory "-g *.org" "ID: ")))
+
+(define-key org-mode-map (kbd "C-c y n") #'org-zettelkasten-create-dwim)
+(define-key org-mode-map (kbd "C-c y s") #'org-zettelkasten-search-current-id)
+
+(provide 'org-zettelkasten)
+;;; org-zettelkasten.el ends here