diff options
author | Thanos Apollo <[email protected]> | 2025-01-03 19:44:39 +0200 |
---|---|---|
committer | Thanos Apollo <[email protected]> | 2025-01-03 19:44:39 +0200 |
commit | 66021690ff2a36f663dc92fac81c278d9986fbf4 (patch) | |
tree | 9ef71fa3f96757a85f529c84c2d4cc1657513908 | |
parent | afe753051e0a1c3ef6ad08e27ae5179624e54c51 (diff) |
Rewrite gnosis-org module.
* This module provides parsing of org-mode buffers.
-rw-r--r-- | gnosis-org.el | 140 |
1 files changed, 116 insertions, 24 deletions
diff --git a/gnosis-org.el b/gnosis-org.el index e977083..e50d95c 100644 --- a/gnosis-org.el +++ b/gnosis-org.el @@ -24,7 +24,7 @@ ;;; Commentary: -;; Under development. +;; This module provides parsing of org-mode buffers for gnosis. ;;; Code: @@ -64,29 +64,121 @@ BUFFER defaults to the current buffer if not specified." (if results (reverse results) (message "No custom properties found for %s" property) nil)))) -;; TODO: Add support for tags. -(cl-defun gnosis-org-insert-heading (&key main id answer type) - "Insert an Org heading in current buffer. - -- MAIN as the title. -- ID as GNOSIS_ID. -- ANSWER as the subheading. -- TYPE as the note type. - -If BUFFER is not specified, defaults to the current buffer." - (cl-assert (stringp main) nil "MAIN must be a string representing the heading title.") - (cl-assert (stringp id) nil "ID must be a string representing the GNOSIS_ID.") - (cl-assert (stringp type) nil "TYPE must be a string representing the TYPE property.") - (let ((main (if (string-match-p "\n" main) (replace-regexp-in-string "\n" "\\\\n" main) main)) - (answer (cond ((stringp answer) - answer) - ((numberp answer) - (number-to-string answer)) - (t (mapconcat 'identity answer ", "))))) - (goto-char (point-max)) ;; Ensure we're at the end of the buffer - (insert (format "* %s\n:PROPERTIES:\n:GNOSIS_ID: %s\n:TYPE: %s\n:END:\n** %s\n" - main id type answer)) - (message "Inserted heading: %s with GNOSIS_ID %s and TYPE %s" main id type))) + +(defun gnosis-org--insert-read-only (string) + "Insert STRING as read-only." + (let ((start (point))) + (insert string) + ;; Set the just inserted string as read-only + (add-text-properties start (point) '(read-only t)) + ;; Since the space is inserted outside of the read-only region, it's editable + (let ((inhibit-read-only t)) + (insert " ")))) + +(defun gnosis-org-make-read-only (&rest values) + "Make the provided VALUES read-only in the whole buffer." + (goto-char (point-min)) + (dolist (value values) + (while (search-forward value nil t) + (put-text-property (match-beginning 0) (match-end 0) 'read-only t))) + (goto-char (point-min))) + +(cl-defun gnosis-org--insert-thema (id type &optional keimenon hypothesis apocalypse parathema tags example) + "Insert thema for note ID. + +TYPE: Thema type, refer to `gnosis-thema-types' +KEIMENON: Text user is first presented with. +HYPOTHESIS: Hypothesis for what the APOCALYPSE is +APOCALYPSE: The revelation after KEIMENON +PARATHEMA: The text where THEMA is derived from. +TAGS: List of THEMA tags +EXAMPLE: Boolean value, if non-nil do not add properties for thema." + (let ((components `(("** Keimenon" . ,keimenon) + ("** Hypothesis" . ,hypothesis) + ("** Apocalypse" . ,apocalypse) + ("** Parathema" . ,parathema)))) + (insert "\n* Thema") + (org-set-tags tags) + (unless example + (org-set-property "GNOSIS_ID" id) + (org-set-property "GNOSIS_TYPE" type) + (gnosis-org-make-read-only ":PROPERTIES:" + (format "GNOSIS_ID: %s" id) + (format "GNOSIS_TYPE: %s" type) + ":END:")) + (dolist (comp components) + (goto-char (point-max)) + (gnosis-org--insert-read-only (car comp)) + (insert "\n" (or (cdr comp) "") "\n\n")))) + +(defun gnosis-org-parse--deck-name (&optional parsed-data) + "Retrieve deck name from PARSED-DATA." + (let* ((parsed-data (or parsed-data (org-element-parse-buffer))) + (title (org-element-map parsed-data 'keyword + (lambda (kw) + (when (string= (org-element-property :key kw) "DECK") + (org-element-property :value kw))) + nil t))) + title)) + +(defun gnosis-org-parse-themas () + "Extract content for each level-2 heading for thema headings with a GNOSIS_ID." + (let (results) + (org-element-map (org-element-parse-buffer) 'headline + (lambda (headline) + (let* ((level (org-element-property :level headline)) + (gnosis-id (org-element-property :GNOSIS_ID headline)) + (gnosis-type (org-element-property :GNOSIS_TYPE headline)) + (tags (org-element-property :tags headline))) + (when (and (= level 1) gnosis-id gnosis-type) + (let (entry) + (push gnosis-id entry) + (push gnosis-type entry) + (dolist (child (org-element-contents headline)) + (when (eq 'headline (org-element-type child)) + (let ((child-text (org-element-interpret-data (org-element-contents child)))) + (setq child-text (string-trim child-text)) + (if (string-empty-p child-text) + (push nil entry) ; Push nil if the content is empty + (push (substring-no-properties child-text) entry))))) + (push tags entry) ;; Add tags last + (push (nreverse entry) results))))) + nil nil) + results)) + +;;;; TODO: Rewrite function that export deck without read-only values. +;;;; Make them only with built-in to work with async.el +;; (defun gnosis-org-export-deck (deck) +;; "Export DECK in an org file." +;; (interactive (list (gnosis--get-deck-id))) +;; ;; (find-file (read-file-name "File: ")) +;; ;; TODO: Retrieve all values instead of just ids and then insert them async +;; (let* ((notes (append (gnosis-select '[type keimenon hypothesis apocalypse tags] 'notes `(= deck-id ,deck)) +;; ;; (gnosis-select 'parathema 'extras `(= deck-id ,deck) t) +;; nil)) +;; (deck-name (car (gnosis-select 'name 'decks `(= id ,deck) t)))) +;; (async-start +;; (lambda () (let ((inhibit-read-only 1)) +;; (find-file (format "/tmp/%s.org" (downcase deck-name))) +;; (erase-buffer) +;; (org-mode) +;; (insert "#+DECK: " deck-name "\n\n") +;; (cl-loop for note in notes +;; do +;; (insert "\n* Thema") +;; (insert "\n** Keimenon\n") +;; (insert (format "\n%s\n" (nth 1 note)))) +;; (save-buffer))) +;; ;; (let ((inhibit-read-only 1)) +;; ;; (erase-buffer)) +;; ;; (org-mode) +;; ;; (insert "#+DECK: " deck-name) +;; ;; (org-set-property "GNOSIS_DECK" (number-to-string deck)) +;; ;; (goto-char (point-max)) +;; ;; (cl-loop for note in notes +;; ;; do (gnosis-export-note note)) +;; ;; (save-buffer) +;; ))) (provide 'gnosis-org) ;;; gnosis-org.el ends here. |