summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2023-04-23 17:55:50 +0100
committerYann Herklotz <git@yannherklotz.com>2023-04-23 17:56:59 +0100
commitcf96c303c1feeb3821a20077bb6ffb80085ccc4e (patch)
treed3d1c6f41912f85a76137c44c9b3663cf89e4a47
parent50c092f0a22981e2e447dd421aa474fbc9b384ba (diff)
downloadorg-zettelkasten-cf96c303c1feeb3821a20077bb6ffb80085ccc4e.tar.gz
org-zettelkasten-cf96c303c1feeb3821a20077bb6ffb80085ccc4e.zip
Add introduction guide and persistent mapping index
-rw-r--r--CHANGELOG.org2
-rw-r--r--doc/org-zettelkasten-manual.org42
-rw-r--r--org-zettelkasten.el87
3 files changed, 120 insertions, 11 deletions
diff --git a/CHANGELOG.org b/CHANGELOG.org
index 1ebca95..edec80f 100644
--- a/CHANGELOG.org
+++ b/CHANGELOG.org
@@ -6,6 +6,8 @@
- Added =org-zettelkasten-new-topic= to create a new topic file in the current
Zettelkasten.
+- Added persistent storage for =org-zettelkasten--mapping= in
+ =org-zettelkasten-mapping-file=.
* Org Zettelkasten 0.7.0 (2022-12-27)
diff --git a/doc/org-zettelkasten-manual.org b/doc/org-zettelkasten-manual.org
index 18fd15d..61befd5 100644
--- a/doc/org-zettelkasten-manual.org
+++ b/doc/org-zettelkasten-manual.org
@@ -117,6 +117,48 @@ cannot keep track of all the possible links.
- =org-zettelkasten-counsel-search-current-id= :: Alternative to
=org-zettelkasten-search-current-id= using Ripgrep integration with Counsel.
+* Getting Started
+:PROPERTIES:
+:DESCRIPTION: Functions used and provided to navigate org-zettelkasten links.
+:END:
+#+cindex: getting-started
+
+To install =org-zettelkasten=, first make sure that you have the melpa
+repository set-up properly. Then, the following =use-package= declaration will
+set-up =org-zettelkasten= including useful hooks to activate it when it enters a
+zettelkasten file.
+
+#+begin_src emacs-lisp
+ (use-package org-zettelkasten
+ :after org
+ :config
+ (org-zettelkasten-setup))
+#+end_src
+
+Once =org-zettelkasten= is installed properly, then you can run
+=org-zettelkasten-new-topic= to create your first topic file. Make sure that
+the folder in =org-zettelkasten-directory= exists, which is set to
+=~/org-zettelkasten= by default.
+
+This should open a new file with the name that was given in the prompt, and it
+should to start experimenting with adding new notes. In the current file there
+should already be a heading with an ID:
+
+#+begin_src org-mode
+ #+title:
+
+ * First Note
+ :PROPERTIES:
+ :CUSTOM_ID: 1a
+ :END:
+#+end_src
+
+Placing the point anywhere underneath the heading =* First Note=, and pressing
+=C-c y n= will create a next note with a new ID, and jump to it. Going back to
+=* First Note= and pressing the keybinding again will create another note, but
+this time it is nested in the current note (branching) because there is already
+a next note present.
+
* GNU Free Documentation License
:PROPERTIES:
:APPENDIX: t
diff --git a/org-zettelkasten.el b/org-zettelkasten.el
index 68582ae..30632ef 100644
--- a/org-zettelkasten.el
+++ b/org-zettelkasten.el
@@ -43,12 +43,6 @@
:type 'string
:group 'org-zettelkasten)
-(defcustom org-zettelkasten-mapping nil
- "Main zettelkasten directory."
- :type '(alist :key-type (natnum :tag "Value")
- :value-type (string :tag "File name"))
- :group 'org-zettelkasten)
-
(defcustom org-zettelkasten-prefix [(control ?c) ?y]
"Prefix key to use for Zettelkasten commands in Zettelkasten minor mode.
The value of this variable is checked as part of loading Zettelkasten mode.
@@ -56,6 +50,70 @@ After that, changing the prefix key requires manipulating keymaps."
:type 'key-sequence
:group 'org-zettelkasten)
+(defcustom org-zettelkasten-mapping-file
+ (expand-file-name "org-zettelkasten-index" org-zettelkasten-directory)
+ "The file which contains mappings from indices to file-names."
+ :type 'string
+ :group 'org-zettelkasten)
+
+(defvar org-zettelkasten--mapping :unset
+ "Main mapping from indices to filenames in the Zettelkasten directory.")
+
+(defun org-zettelkasten--read-mapping ()
+ "Initialize `org-zettelkasten--mapping' using the contents of
+`org-zettelkasten-mapping-file'."
+ (let ((filename org-zettelkasten-mapping-file))
+ (setq org-zettelkasten--mapping
+ (when (file-exists-p filename)
+ (with-temp-buffer
+ (insert-file-contents filename)
+ (read (current-buffer)))))
+ (unless
+ (seq-every-p
+ (lambda (elt)
+ (and (numberp (car-safe elt)) (stringp (cdr-safe elt))))
+ org-zettelkasten--mapping)
+ (warn "Contents of %s are in wrong format, resetting" filename)
+ (setq org-zettelkasten--mapping :unset))))
+
+(defun org-zettelkasten--ensure-read-mapping ()
+ "Initialise `org-zettelkasten--mapping' if it is not yet initialised."
+ (when (eq org-zettelkasten--mapping :unset)
+ (org-zettelkasten--read-mapping)))
+
+(defun org-zettelkasten--write-mapping ()
+ "Save `org-zettelkasten--mapping' in `org-zettelkasten-mapping-file'."
+ (let ((filename org-zettelkasten-mapping-file))
+ (with-temp-buffer
+ (insert ";;; -*- lisp-data -*-\n")
+ (let ((print-length nil)
+ (print-level nil))
+ (pp org-zettelkasten--mapping (current-buffer)))
+ (write-region nil nil filename nil 'silent))))
+
+(defun org-zettelkasten--add-topic (index file-name &optional no-write)
+ "Add a topic to `org-zettelkasten--mapping' and optionally save it to disk.
+INDEX is the new index of the topic, it should not appear in
+`org-zettelkasten--mapping' yet. FILE-NAME is the file name of
+the topic to be added. NO-WRITE is an optional flag to to
+control whether the mapping should be saved to the file."
+ (org-zettelkasten--ensure-read-mapping)
+ (if (and (numberp index) (stringp file-name))
+ (add-to-list 'org-zettelkasten--mapping `(,index . ,file-name))
+ (warn "Adding topics in wrong format"))
+ (unless no-write
+ (org-zettelkasten--write-mapping)))
+
+(defun org-zettelkasten--remove-topic (index &optional no-write)
+ "Remove a topic from `org-zettelkasten--mapping' given by INDEX.
+Optionally, if NO-WRITE is set, write the new mapping to the
+file."
+ (org-zettelkasten--ensure-read-mapping)
+ (setq org-zettelkasten--mapping
+ (assq-delete-all index org-zettelkasten--mapping))
+ (unless no-write
+ (org-zettelkasten--write-mapping)))
+
(defun org-zettelkasten--abs-file (file)
"Return FILE name relative to `org-zettelkasten-directory'."
(expand-file-name file org-zettelkasten-directory))
@@ -67,11 +125,13 @@ This function assumes that IDs will start with a number."
(when (string-match "^\\([0-9]*\\)" ident)
(string-to-number (match-string 1 ident))))
+;;;###autoload
(defun org-zettelkasten-goto-id (id)
"Go to an ID automatically."
(interactive "sID: #")
+ (org-zettelkasten--ensure-read-mapping)
(let ((file (alist-get (org-zettelkasten--ident-prefix id)
- org-zettelkasten-mapping)))
+ org-zettelkasten--mapping)))
(org-link-open-from-string
(concat "[[file:" (org-zettelkasten--abs-file file)
"::#" id "]]"))))
@@ -153,8 +213,9 @@ NEWHEADING: function used to create the heading and set the current POINT to
(defun org-zettelkasten--all-files ()
"Return all files in the Zettelkasten with full path."
+ (org-zettelkasten--ensure-read-mapping)
(mapcar #'org-zettelkasten--abs-file
- (mapcar #'cdr org-zettelkasten-mapping)))
+ (mapcar #'cdr org-zettelkasten--mapping)))
(defun org-zettelkasten-buffer ()
"Check if the current buffer belongs to the Zettelkasten."
@@ -175,27 +236,31 @@ adds `org-zettelkasten--update-modified' to buffer local
nil 'local)
(org-zettelkasten-mode)))))
+;;;###autoload
(defun org-zettelkasten-search-current-id ()
"Search for references to ID in `org-zettelkasten-directory'."
(interactive)
(let ((current-id (org-entry-get nil "CUSTOM_ID")))
(lgrep (concat "[:[]." current-id "]") "*.org" org-zettelkasten-directory)))
+;;;###autoload
(defun org-zettelkasten-agenda-search-view ()
"Search for text using Org agenda in Zettelkasten files."
(interactive)
(let ((org-agenda-files (org-zettelkasten--all-files)))
(org-search-view)))
+;;;###autoload
(defun org-zettelkasten-new-topic (file-name)
"Create a new topic in a file named FILE-NAME."
(interactive "sNew Topic Filename: ")
+ (org-zettelkasten--ensure-read-mapping)
(let ((new-id
- (if org-zettelkasten-mapping
+ (if org-zettelkasten--mapping
(1+ (apply #'max (mapcar (lambda (val) (car val))
- org-zettelkasten-mapping)))
+ org-zettelkasten--mapping)))
1)))
- (add-to-list 'org-zettelkasten-mapping `(,new-id . ,file-name))
+ (org-zettelkasten--add-topic new-id file-name)
(find-file file-name)
(insert (format "#+title: