summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2022-12-24 11:49:44 +0000
committerYann Herklotz <git@yannherklotz.com>2022-12-24 11:49:44 +0000
commita96d758daa28fa375dad4617e53ea2713aa7eb45 (patch)
tree8596c072e6291bc752afc244479039aef1b7fa7d
parentd1309fe7f770a865441b91c1c8327036c307ef54 (diff)
downloadorg-zettelkasten-a96d758daa28fa375dad4617e53ea2713aa7eb45.tar.gz
org-zettelkasten-a96d758daa28fa375dad4617e53ea2713aa7eb45.zip
Remove support for zettelkasten.el and fork repository
-rw-r--r--README.md161
-rw-r--r--README.org35
-rw-r--r--org-zettelkasten-consult.el42
-rw-r--r--org-zettelkasten-counsel.el42
-rw-r--r--zettelkasten.el503
5 files changed, 119 insertions, 664 deletions
diff --git a/README.md b/README.md
deleted file mode 100644
index d1b4dac..0000000
--- a/README.md
+++ /dev/null
@@ -1,161 +0,0 @@
-# Zettelkasten mode for Emacs
-
-[![melpazoid](https://github.com/ymherklotz/emacs-zettelkasten/actions/workflows/melpazoid.yml/badge.svg)](https://github.com/ymherklotz/emacs-zettelkasten/actions/workflows/melpazoid.yml)
-
-| Package | Melpa |
-|---|---|
-| `org-zettelkasten` | [![MELPA](https://melpa.org/packages/org-zettelkasten-badge.svg)](https://melpa.org/#/org-zettelkasten) |
-| `zettelkasten` | [![MELPA](https://melpa.org/packages/zettelkasten-badge.svg)](https://melpa.org/#/zettelkasten) |
-
-[Zettelkasten](https://zettelkasten.de/) is a note-taking technique designed to keep, and create new
-links between all the notes as they are written. This allows them to develop over time, link to
-various different topics and allow the notes to grow into a network over time. This helps draw
-connections between different fields.
-
-The idea of this mode is to integrate fully into Emacs Org mode, trying to leverage most of its
-preexisting features. It is split into two modes, the main one being `org-zettelkasten`, and a
-secondary standalone mode called `zettelkasten` which is a minimal implementation of existing
-Zettelkasten modes.
-
-## `org-zettelkasten` and `zettelkasten`
-
-This repository contains two packages which are also on Melpa, and are separate from each other,
-giving two different ways to use the Zettelkasten method in Emacs. One (`org-zettelkasten`)
-leverages emacs' [`org-mode`](https://orgmode.org/), and the other (`zettelkasten`) is an
-implementation from scratch, which can either use `org-mode` files or markdown files as a base.
-
-## How to use `org-zettelkasten`
-
-The method implemented in `org-zettelkasten` has been described in detail in a [blog
-article](https://yannherklotz.com/blog/2020-12-21-introduction-to-luhmanns-zettelkasten.html). It
-leverages `org-mode` features such as `CUSTOM_ID`,
-
-**Manual Installation**
-
-``` emacs-lisp
-(add-to-list 'load-path "/path/to/org-zettelkasten.el")
-(require 'org-zettelkasten)
-(add-hook 'org-mode-hook #'org-zettelkasten-mode)
-```
-
-**`use-package` from Melpa**
-
-``` emacs-lisp
-(use-package org-zettelkasten
- :ensure t
- :config
- (add-hook 'org-mode-hook #'org-zettelkasten-mode))
-```
-
-### Tag search
-
-Tag search can be implemented using your favourite completion framework. These will use the `ID` at
-the current heading and will look for any other notes that reference this heading (i.e. it will find
-all the back links of the current heading).
-
-#### Tag search with counsel
-
-``` emacs-lisp
-(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: ")))
-```
-
-#### Tag search with consult
-
-``` emacs-lisp
-(defun org-zettelkasten-search-current-id ()
- "Use `consult-ripgrep' to search for the current ID in all files."
- (interactive)
- (let ((current-id (org-entry-get nil "CUSTOM_ID")))
- (consult-ripgrep org-zettelkasten-directory (concat "[\\[:]." current-id "\\]#"))))
-```
-
-#### Add search to keymap
-
-``` emacs-lisp
-(define-key org-zettelkasten-mode-map (kbd "s") #'org-zettelkasten-search-current-id)
-```
-
-## How to use `zettelkasten`
-
-To use Zettelkasten, first create a directory which will contain all your notes. This will be a flat
-directory, as tags are used to place notes into specific categories.
-
-``` shell
-mkdir ~/zettelkasten
-```
-
-Then, you can activate the mode as follows:
-
-**Manual Installation**
-
-```emacs-lisp
-(add-to-list 'load-path "/path/to/zettelkasten.el")
-(require 'zettelkasten)
-(zettelkasten-mode t)
-```
-
-**`use-package` from Melpa**
-
-``` emacs-lisp
-(use-package zettelkasten
- :ensure t
- :config
- (zettelkasten-mode t))
-```
-
-### Creating new notes
-
-A new note can be created using
-
-``` text
-M-x zettelkasten-create-new-note
-```
-
-### Linking to a note
-
-To link to a note from the current note, use the following command:
-
-``` text
-M-x zettelkasten-insert-link
-```
-
-which will open a list of available notes which you can choose to link to.
-
-### Opening a parent note
-
-To open a parent note of the current note, the following command can be used:
-
-``` text
-M-x zettelkasten-find-parent
-```
-
-This opens the chosen parent note from a list of available notes. This is bound to `C-c k p` by
-default.
-
-### Default bindings
-
-The default keymap for the mode is `C-c k`, this can easily be changed though by editing
-`zettelkasten-prefix`.
-
-| Function | Key | Description |
-|---|---|---|
-| `zettelkasten-create-new-note` | `n` | Create a new note and optionally link it to a parent. This can be disabled by using a prefix argument. |
-| `zettelkasten-insert-link` | `i` | Insert a link to a note. |
-| `zettelkasten-find-parent` | `p` | Choose from a list of parents of the current note and open the note. |
-| `zettelkasten-open-note` | `o` | Open a note from anywhere, using auto complete on the ID or TITLE of the note. |
-| `zettelkasten-open-note-by-tag` | `t` | Open a note using a tag as the first identifier. |
-
-## Alternatives
-
-An alternative to use Zettelkasten in emacs is [Zetteldeft](https://github.com/EFLS/zetteldeft),
-which uses Deft as a backend to search files.
-
-Another beefier alternative is [org-roam](https://github.com/jethrokuan/org-roam/), which is a fully
-integrated note taking system based on a wiki-system.
-
-Finally, [org-brain](https://github.com/Kungsgeten/org-brain) is a similar note-taking system that
-is meant for concept mapping in Emacs.
diff --git a/README.org b/README.org
new file mode 100644
index 0000000..8eadc73
--- /dev/null
+++ b/README.org
@@ -0,0 +1,35 @@
+#+title: Zettelkasten for Org
+#+author: Yann Herklotz
+
+[[https://zettelkasten.de/][Zettelkasten]] is a note-taking technique designed to keep, and create new links
+between all the notes as they are written. This allows them to develop over
+time, link to various different topics and allow the notes to grow into a
+network over time. This helps draw connections between different fields.
+
+The idea of this mode is to integrate fully into Emacs Org mode, trying to
+leverage most of its preexisting features. It is split into two modes, the main
+one being `org-zettelkasten`, and a secondary standalone mode called
+`zettelkasten` which is a minimal implementation of existing Zettelkasten modes.
+
+* How to use `org-zettelkasten`
+
+The method implemented in `org-zettelkasten` has been described in detail in a [blog
+article](https://yannherklotz.com/blog/2020-12-21-introduction-to-luhmanns-zettelkasten.html). It
+leverages `org-mode` features such as `CUSTOM_ID`,
+
+*Manual Installation*
+
+#+begin_src emacs-lisp
+ (add-to-list 'load-path "/path/to/org-zettelkasten.el")
+ (require 'org-zettelkasten)
+ (add-hook 'org-mode-hook #'org-zettelkasten-mode)
+#+end_src
+
+*~use-package~ from Melpa*
+
+#+begin_src emacs-lisp
+ (use-package org-zettelkasten
+ :ensure t
+ :config
+ (add-hook 'org-mode-hook #'org-zettelkasten-mode))
+#+end_src
diff --git a/org-zettelkasten-consult.el b/org-zettelkasten-consult.el
new file mode 100644
index 0000000..85ec6d1
--- /dev/null
+++ b/org-zettelkasten-consult.el
@@ -0,0 +1,42 @@
+;;; org-zettelkasten-consult.el --- Helper functions to use Zettelkasten in org-mode -*- lexical-binding: t; -*-
+
+;; Author: Yann Herklotz <yann@ymhg.org>
+;; Created: 2022
+;; Version: 0.3.0
+;; Package-Requires: ((emacs "24.3") (consult "0.20"))
+;; Keywords: files, hypermedia, Org, notes
+;; Homepage: https://github.com/ymherklotz/emacs-zettelkasten
+
+;; 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/>.
+
+;;; 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.
+
+;;; Code:
+
+(require 'consult)
+
+(defun org-zettelkasten-consult-search-current-id ()
+ "Use `consult-ripgrep' to search for the current ID in all files."
+ (interactive)
+ (let ((current-id (org-entry-get nil "CUSTOM_ID")))
+ (consult-ripgrep org-zettelkasten-directory (concat "[\\[:]." current-id "\\]#"))))
+
+(provide 'org-zettelkasten-consult)
+
+;;; org-zettelkasten-consult.el ends here
diff --git a/org-zettelkasten-counsel.el b/org-zettelkasten-counsel.el
new file mode 100644
index 0000000..5c48074
--- /dev/null
+++ b/org-zettelkasten-counsel.el
@@ -0,0 +1,42 @@
+;;; org-zettelkasten-counsel.el --- Helper functions to use Zettelkasten in org-mode -*- lexical-binding: t; -*-
+
+;; Author: Yann Herklotz <yann@ymhg.org>
+;; Created: 2022
+;; Version: 0.3.0
+;; Package-Requires: ((emacs "24.3") (consult "0.20"))
+;; Keywords: files, hypermedia, Org, notes
+;; Homepage: https://github.com/ymherklotz/emacs-zettelkasten
+
+;; 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/>.
+
+;;; 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.
+
+;;; Code:
+
+(require 'counsel)
+
+(defun org-zettelkasten-counsel-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: ")))
+
+(provide 'org-zettelkasten-counsel)
+
+;;; org-zettelkasten-counsel.el ends here
diff --git a/zettelkasten.el b/zettelkasten.el
deleted file mode 100644
index 6acb90d..0000000
--- a/zettelkasten.el
+++ /dev/null
@@ -1,503 +0,0 @@
-;;; zettelkasten.el --- Helper functions to organise notes in a Zettelkasten style -*- lexical-binding: t; -*-
-
-;; Author: Yann Herklotz <yann@ymhg.org>
-;; URL: https://github.com/ymherklotz/emacs-zettelkasten
-;; Version: 0.3.0
-;; Package-Requires: ((emacs "25.1") (s "1.10.0"))
-;; Keywords: files, hypermedia, notes
-
-;;; Commentary:
-
-;; Used to organise notes using the Zettelkasten method.
-
-;;; License:
-
-;; Copyright (C) 2020-2022 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 'cl-lib)
-(require 's)
-
-(defgroup zettelkasten nil
- "Helper to work with zettelkasten notes."
- :group 'applications)
-
-(defcustom zettelkasten-prefix [(control ?c) ?k]
- "Prefix key to use for Zettelkasten commands in Zettelkasten minor mode.
-The value of this variable is checked as part of loading Zettelkasten mode.
-After that, changing the prefix key requires manipulating keymaps."
- :type 'key-sequence
- :group 'zettelkasten)
-
-(defcustom zettelkasten-directory (expand-file-name "~/zettelkasten")
- "Main zettelkasten directory."
- :type 'string
- :group 'zettelkasten)
-
-(defcustom zettelkasten-file-format "%y%W%u%%02d"
- "Format for new zettelkasten files.
-
-For supported options, please consult `format-time-string'."
- :type 'string
- :group 'zettelkasten)
-
-(defcustom zettelkasten-link-format "[[./%2$s.%3$s][%1$s]]"
- "Zettelkasten link format."
- :type 'string
- :group 'zettelkasten)
-
-(defcustom zettelkasten-extension "org"
- "Default extension for notes."
- :type 'string
- :group 'zettelkasten)
-
-(defcustom zettelkasten-id-regexp "[0-9]+"
- "Regexp for IDs."
- :type 'string
- :group 'zettelkasten)
-
-;;; -----------------------------
-;;; HELPER FUNCTIONS FOR NOTE IDs
-;;; -----------------------------
-
-(defun zettelkasten--make-filename (note)
- "Make a filename using the default directory and the NOTE passed to it."
- (expand-file-name (concat zettelkasten-directory "/"
- note "." zettelkasten-extension)))
-
-(defun zettelkasten--filename-to-id (filename)
- "Convert FILENAME to id."
- (string-match
- (format "\\(%s\\)\\.%s\\'" zettelkasten-id-regexp zettelkasten-extension)
- filename)
- (match-string 1 filename))
-
-(defun zettelkasten--display-for-search (note)
- "Dispaly the NOTE's title and id.
-
-Meant for displaying when searching."
- (format "%s: %s" note (zettelkasten--get-note-title note)))
-
-(defun zettelkasten--get-id (note)
- "Return the id for a NOTE.
-
-The note may be formatted with some title, which this function
-aims to remove."
- (string-match (format "[^0-9]*\\(%s\\)" zettelkasten-id-regexp) note)
- (match-string 1 note))
-
-(defun zettelkasten--format-link (note &optional link-text)
- "Format a LINK-TEXT to a NOTE."
- (format zettelkasten-link-format
- (or link-text (zettelkasten--get-note-title note))
- (zettelkasten--get-id note)
- zettelkasten-extension))
-
-;;; ---------------------------
-;;; LISTING AND SEARCHING NOTES
-;;; ---------------------------
-
-(defun zettelkasten--note-regexp (note regexp &optional num)
- "Return the REGEXP first match in the NOTE.
-
-Return the NUMth match. If NUM is nil, return the 0th match."
- (with-temp-buffer
- (insert-file-contents-literally
- (zettelkasten--make-filename note))
- (when (re-search-forward regexp nil t)
- (match-string (if num num 0)))))
-
-(defun zettelkasten--note-regexp-multiple (note regexp &optional num)
- "Return the REGEXP matched in the NOTE.
-
-Return the NUMth match. If NUM is nil, return the 0th match."
- (with-temp-buffer
- (insert-file-contents-literally
- (zettelkasten--make-filename note))
- (let (match-list)
- (while (re-search-forward regexp nil t)
- (setq match-list (append match-list (list (match-string (if num num 0))))))
- match-list)))
-
-(defun zettelkasten--match-link (current note)
- "Return the note if the link to CURRENT is in the NOTE."
- (when (zettelkasten--note-regexp
- note
- (let ((zk-link-format (replace-regexp-in-string
- "\\\\\\$" "$"
- (regexp-quote zettelkasten-link-format))))
- (format zk-link-format
- ".*" current
- zettelkasten-extension)))
- note))
-
-(defun zettelkasten--list-notes-by-id ()
- "Return all the ids that are currently available."
- (mapcar #'zettelkasten--filename-to-id
- (directory-files
- (expand-file-name zettelkasten-directory) nil
- (format "%s\\.%s$" zettelkasten-id-regexp zettelkasten-extension) t)))
-
-(defun zettelkasten--list-notes-grep ()
- "Return all the ids and titles of notes in the `zettelkasten-directory'.
-
-This is deprecated in favour for `zettelkasten-list-notes'."
- (shell-command (concat "grep -i \"#+TITLE:\" " zettelkasten-directory "/*"))
- (let (match-list morelines current-string matched-string)
- (with-current-buffer "*Shell Command Output*"
- (set-buffer "*Shell Command Output*")
- (setq morelines t)
- (goto-char 1)
- (while morelines
- (setq current-string
- (buffer-substring-no-properties
- (line-beginning-position)
- (line-end-position)))
- (when (string-match
- (format "\\(%s\\)\\.%s:#\\+TITLE: \\(.*\\)"
- zettelkasten-id-regexp zettelkasten-extension)
- current-string)
- (setq matched-string (concat (match-string 1 current-string) ": "
- (match-string 2 current-string)))
- (setq match-list (append match-list (list matched-string))))
- (setq morelines (= 0 (forward-line 1)))))
- (kill-buffer "*Shell Command Output*")
- match-list))
-
-(defun zettelkasten--list-notes ()
- "Return all the ids and titles of notes in the `zettelkasten-directory'."
- (mapcar #'zettelkasten--display-for-search
- (zettelkasten--list-notes-by-id)))
-
-(defun zettelkasten--list-links (note)
- "List all notes that the current NOTE links to."
- (sort
- (cl-remove-duplicates
- (mapcar #'zettelkasten--get-id
- (zettelkasten--note-regexp-multiple
- note
- (let ((zk-link-format (replace-regexp-in-string
- "\\\\\\$" "$"
- (regexp-quote zettelkasten-link-format))))
- (format zk-link-format
- ".*" ".*"
- zettelkasten-extension))))) #'string<))
-
-;;; ------------------
-;;; CREATING NEW NOTES
-;;; ------------------
-
-(defun zettelkasten--find-new-note-name (note)
- "Iterate on ITERATION until a usable file based on NOTE is found."
- (let ((iteration 0)
- (maxcount 10000))
- (while (and (< iteration maxcount)
- (file-exists-p
- (zettelkasten--make-filename (format note iteration))))
- (setq iteration (+ iteration 1)))
- (format note iteration)))
-
-(defun zettelkasten--add-link-to-parent (note parent)
- "Add a link to NOTE from a PARENT."
- (with-temp-file (zettelkasten--make-filename parent)
- (insert-file-contents-literally (zettelkasten--make-filename parent))
- (goto-char (point-max))
- (insert "\n" (zettelkasten--format-link note))))
-
-(defun zettelkasten--create-new-note-ni (title &optional parent custom-id)
- "Create a new note based on the TITLE and it's optional PARENT note.
-
-If PARENT is nil, it will not add a link from a PARENT.
-
-If CUSTOM-ID is not nil, will not generate a time-based ID but
-will use that instead."
- (let* ((note (zettelkasten--find-new-note-name
- (or custom-id (format-time-string zettelkasten-file-format))))
- (filename (zettelkasten--make-filename note)))
- (with-temp-buffer
- (set-visited-file-name filename)
- (set-buffer-file-coding-system 'utf-8)
- (insert "#+TITLE: " title
- (format-time-string "\n#+DATE: %c\n#+TAGS:\n\n"))
- (save-buffer))
- (when parent
- (zettelkasten--add-link-to-parent note (zettelkasten--get-id parent)))
- (find-file filename)))
-
-(defun zettelkasten--find-parents (note)
- "Find the parents of the NOTE."
- (delete
- nil
- (mapcar (lambda (el) (zettelkasten--match-link
- note el))
- (zettelkasten--list-notes-by-id))))
-
-(defun zettelkasten--get-note-title (note)
- "Return the title of the NOTE."
- (zettelkasten--note-regexp note "#\\+TITLE: \\(.*\\)" 1))
-
-;;; -----------------
-;;; DEALING WITH TAGS
-;;; -----------------
-
-(defun zettelkasten--get-tags (note)
- "Get all the tags for a specific NOTE."
- (let ((tags (zettelkasten--note-regexp
- note "#\\+TAGS: \\(.*\\)" 1)))
- (when tags
- (mapcar #'s-trim (s-split "," tags)))))
-
-(defun zettelkasten--get-tags-and-ids ()
- "Return a mapping from TAGS to ids for NOTE."
- (let ((tags nil)
- (onlytags nil))
- (mapc
- (lambda (note)
- (mapc
- (lambda (el)
- (when el
- (let* ((ismember (member el tags))
- (currlist (cdr ismember)))
- (if ismember
- (setcar currlist (append (car currlist) (list note)))
- (progn
- (setq tags (append (list el (list note)) tags))
- (push el onlytags))))))
- (zettelkasten--get-tags note)))
- (zettelkasten--list-notes-by-id))
- (append (list onlytags) tags)))
-
-;;; -------------------------------
-;;; HELPER FUNCTIONS FOR `org-mode'
-;;; -------------------------------
-
-(defun zettelkasten--indent (amount str-list)
- "Indent STR-LIST by some AMOUNT."
- (mapcar (lambda (n) (concat (make-string amount ?\s) n)) str-list))
-
-(defun zettelkasten--generate-list-for-note-nc (notes)
- "Generate a list of NOTES."
- (if notes
- (apply #'append
- (mapcar (lambda (n)
- (cons (concat "- " (zettelkasten--format-link n) "\n")
- (zettelkasten--indent
- 2 (zettelkasten--generate-list-for-note-nc
- (zettelkasten--list-links n)))))
- notes)) ""))
-
-(defun zettelkasten--generate-list-for-note (note)
- "Generate a list of links for NOTE."
- (zettelkasten--generate-list-for-note-nc (zettelkasten--list-links note)))
-
-(defun zettelkasten--list-notes-without-parents ()
- "List all the notes that do not have any parents."
- (delete nil (mapcar (lambda (n)
- (if (zettelkasten--find-parents n) nil n))
- (zettelkasten--list-notes-by-id))))
-
-(defun zettelkasten-generate-site-map (title _)
- "Generate the site map for the Zettelkasten using TITLE."
- (let* ((ti (zettelkasten--get-tags-and-ids))
- (tags (sort (car ti) #'string<)))
- (concat
- "#+TITLE: " title "\n\n"
- (apply
- #'concat
- (mapcar
- (lambda (tag)
- (concat "[[#" tag "][" tag "]] \| "))
- tags))
- "\n\n* Index\n\n"
- (apply
- #'concat
- (zettelkasten--generate-list-for-note-nc (sort (zettelkasten--list-notes-without-parents) #'string>)))
- "\n* Tags\n\n"
- (apply
- #'concat
- (mapcar
- (lambda (tag)
- (let* ((ismember (member tag ti))
- (currlist (car (cdr ismember))))
- (with-temp-buffer
- (set-visited-file-name (concat tag ".org"))
- (set-buffer-file-coding-system 'utf-8)
- (insert "#+TITLE: " (capitalize tag) "\n\n"
- (apply
- #'concat
- (mapcar
- (lambda (note)
- (concat "- " (zettelkasten--format-link note) "\n"))
- currlist)))
- (save-buffer))
- (concat "** " (capitalize tag) "\n :PROPERTIES:\n :CUSTOM_ID: " tag "\n :END:\n\n"
- (apply
- #'concat
- (mapcar
- (lambda (note)
- (concat "- " (zettelkasten--format-link note) "\n"))
- currlist))
- "\n")))
- tags)))))
-
-(defun zettelkasten-org-export-preprocessor (_)
- "A preprocessor for Zettelkasten directories.
-
-Adds information such as backlinks to the `org-mode' files before
-publishing."
- (unless (string= (zettelkasten--filename-to-id (buffer-file-name)) "")
- (let ((notes (zettelkasten--find-parents
- (zettelkasten--filename-to-id (buffer-file-name))))
- (tags (zettelkasten--get-tags
- (zettelkasten--filename-to-id (buffer-file-name)))))
- (save-excursion
- (when tags
- (goto-char (point-min))
- (insert
- "#+begin_export html\n<div class=\"tags\"><ul>\n"
- (mapconcat (lambda (el) (concat "<li><a href=\"" el
- ".html\">" el "</a></li>\n")) tags "")
- "</ul></div>\n#+end_export\n"))
- (when notes
- (goto-char (point-max))
- (insert
- (mapconcat #'identity (append
- '("\n* Backlinks\n")
- (mapcar
- (lambda
- (el)
- (concat "- " (zettelkasten--format-link el) "\n"))
- notes)) "")))))))
-
-;;; ---------------------
-;;; INTERACTIVE FUNCTIONS
-;;; ---------------------
-
-(defun zettelkasten-insert-link (note)
- "Insert a link to another NOTE in the current note.
-if region is active use that as link text"
- (interactive
- (list (completing-read "Notes: "
- (zettelkasten--list-notes) nil 'match)))
- (let ((region-text (when (use-region-p)
- (prog1 (buffer-substring-no-properties (region-beginning)
- (region-end))
- (delete-region (region-beginning) (region-end))))))
- (insert (zettelkasten--format-link (zettelkasten--get-id note) region-text))))
-
-(defun zettelkasten-create-new-note (prefix)
- "Create a new zettelkasten.
-
-If PREFIX is used, or if the `zettelkasten-directory' is empty,
-does not create a parent.
-
-Also see `zettelkasten--create-new-note-ni' for more information."
- (interactive "P")
- (let ((title (read-string "Note title: "))
- (notes (zettelkasten--list-notes)))
- (zettelkasten--create-new-note-ni
- title
- (unless (or prefix (not notes))
- (completing-read "Parent note: " notes nil 'match)))))
-
-(defun zettelkasten-create-new-custom-note (prefix)
- "Create a new zettelkasten.
-
-If PREFIX is used, or if the `zettelkasten-directory' is empty,
-does not create a parent.
-
-Also see `zettelkasten--create-new-note-ni' for more information."
- (interactive "P")
- (let ((title (read-string "Note title: "))
- (notes (zettelkasten--list-notes)))
- (zettelkasten--create-new-note-ni
- title
- (unless (or prefix (not notes))
- (completing-read "Parent note: " notes nil 'match))
- (let ((id (read-string "Note ID: ")))
- (if (string= id "") nil id)))))
-
-(defun zettelkasten-open-parent (&optional note)
- "Find the parent notes to the NOTE that is given.
-
-The format of the NOTE is anything that can be ready by
- `zettelkasten--get-id'."
- (interactive)
- (let* ((act-note
- (if note (zettelkasten--get-id note)
- (zettelkasten--filename-to-id (buffer-file-name))))
- (selected (completing-read
- "Notes: "
- (mapcar #'zettelkasten--display-for-search
- (zettelkasten--find-parents act-note))
- nil 'match)))
- (find-file (zettelkasten--make-filename (zettelkasten--get-id selected)))))
-
-(defun zettelkasten-open-note (note)
- "Open an existing NOTE, searching by title and id."
- (interactive
- (list (completing-read "Notes: "
- (zettelkasten--list-notes) nil 'match)))
- (find-file (zettelkasten--make-filename (zettelkasten--get-id note))))
-
-(defun zettelkasten-open-note-by-tag ()
- "Open a note by filtering on tags."
- (interactive)
- (let* ((all (zettelkasten--get-tags-and-ids))
- (onlytags (car all))
- (tags (cdr all))
- (chosentag (completing-read
- "Tags: "
- onlytags
- nil 'match))
- (chosennote
- (let ((ismember (member chosentag tags)))
- (completing-read
- "Note: "
- (mapcar #'zettelkasten--display-for-search (car (cdr ismember)))
- nil 'match))))
- (find-file (zettelkasten--make-filename (zettelkasten--get-id chosennote)))))
-
-;;; ---------------------------------
-;;; FUNCTIONS FOR `zettelkasten-mode'
-;;; ---------------------------------
-
-(defvar zettelkasten-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "i" #'zettelkasten-insert-link)
- (define-key map "n" #'zettelkasten-create-new-note)
- (define-key map "p" #'zettelkasten-open-parent)
- (define-key map "o" #'zettelkasten-open-note)
- (define-key map "t" #'zettelkasten-open-note-by-tag)
- map))
-
-(defvar zettelkasten-minor-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map zettelkasten-prefix zettelkasten-mode-map)
- map)
- "Keymap used for binding footnote minor mode.")
-
-;;;###autoload
-(define-minor-mode zettelkasten-mode
- "Enable the keymaps to be used with zettelkasten."
- :lighter " zettelkasten"
- :keymap zettelkasten-minor-mode-map
- :global t)
-
-(provide 'zettelkasten)
-
-;;; zettelkasten.el ends here