bir-extract.el 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. ;;; bir-extract.el --- Extracting functions for BIR -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2021 c1-g
  3. ;; Author: c1-g <char1iegordon@protonmail.com>
  4. ;; Keywords: multimedia
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;; Code:
  17. (require 'org-roam)
  18. (require 'org-fc)
  19. (defun bir-extract-region (beg end &optional text interactive)
  20. "docstring"
  21. (interactive
  22. (let ((id (org-id-get-create)))
  23. (list (region-beginning) (region-end) nil t)))
  24. (let* ((text (or text (buffer-substring beg end)))
  25. (article-title (if (= (org-outline-level) 0)
  26. (cadar (org-collect-keywords '("TITLE")))
  27. (save-excursion (while (org-up-heading-safe))
  28. (or (org-entry-get nil "title")
  29. (nth 4 (org-heading-components))))))
  30. (article-prop (org-entry-get nil bir-article-property t t))
  31. (article-id (or article-prop
  32. (plist-get (org-element--get-global-node-properties) :ID)
  33. (save-excursion (while (org-up-heading-safe))
  34. (org-id-get-create))))
  35. (article (or article-prop
  36. (org-link-make-string (concat "id:" article-id) article-title)))
  37. (parent-title (if (= (org-outline-level) 0)
  38. (cadar (org-collect-keywords '("TITLE")))
  39. (save-excursion (or (org-entry-get nil "title")
  40. (org-up-heading-safe)
  41. (nth 4 (org-heading-components))))))
  42. (parent (save-excursion
  43. (org-back-to-heading-or-point-min t)
  44. (if (string= (org-id-get) article-id)
  45. article
  46. (org-link-make-string (concat "id:" (org-id-get-create))
  47. parent-title))))
  48. (template-info nil)
  49. (node (org-roam-node-at-point))
  50. (refs (ignore-errors (org-roam-node-refs (org-roam-node-from-id article-id))))
  51. (template (org-roam-format-template
  52. (string-trim (org-capture-fill-template org-roam-extract-new-file-path))
  53. (lambda (key default-val)
  54. (let ((fn (intern key))
  55. (node-fn (intern (concat "org-roam-node-" key)))
  56. (ksym (intern (concat ":" key))))
  57. (cond
  58. ((fboundp fn)
  59. (funcall fn node))
  60. ((fboundp node-fn)
  61. (funcall node-fn node))
  62. (t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
  63. (plist-put template-info ksym r)
  64. r)))))))
  65. (file-path (expand-file-name template (file-name-as-directory org-roam-directory)))
  66. id)
  67. (when (file-exists-p file-path)
  68. (user-error "%s exists. Aborting" file-path))
  69. (with-temp-buffer
  70. (org-mode)
  71. (org-set-property bir-article-property article)
  72. (org-set-property bir-parent-property parent)
  73. (when refs (org-roam-property-add "ROAM_REFS" (concat "cite:&" (car refs))))
  74. (write-region (point-min) (point-max) file-path nil t nil t)
  75. (setq id (org-id-get-create))
  76. (if interactive
  77. (funcall (intern (format "org-fc-type-%s-init" (completing-read "Which type?: " org-fc-types))))
  78. (org-fc-type-topic-init))
  79. (goto-char (point-max))
  80. (insert "\n" text "\n")
  81. (save-buffer))
  82. (when (and (not buffer-read-only) (eq major-mode 'org-mode))
  83. (delete-region beg end)
  84. (insert (org-link-make-string (concat "extract:" id) text)))
  85. (when interactive
  86. (find-file file-path))
  87. id))
  88. (defun bir-extract-cloze (beg end &optional hint interactive)
  89. "docstring"
  90. (interactive
  91. (let ((id (org-id-get-create)))
  92. (list (region-beginning) (region-end) (read-string "Hint (optional): ") t)))
  93. (let* ((article-title (if (= (org-outline-level) 0)
  94. (org-collect-keywords '("TITLE"))
  95. (save-excursion (while (org-up-heading-safe))
  96. (or (org-entry-get nil "title")
  97. (nth 4 (org-heading-components))))))
  98. (article-prop (org-entry-get nil bir-article-property t))
  99. (article-id (or (plist-get (org-element--get-global-node-properties) :ID)
  100. (when article-prop
  101. (progn (string-match org-link-bracket-re article-prop)
  102. (substring-no-properties (match-string 1 article-prop) 3)))
  103. (save-excursion (while (org-up-heading-safe))
  104. (org-id-get-create))))
  105. (article (or (org-entry-get nil bir-article-property t t)
  106. (org-link-make-string (concat "id:" article-id) article-title)))
  107. (parent (save-excursion
  108. (org-back-to-heading-or-point-min t)
  109. (if (string= (org-id-get) article-id)
  110. article
  111. (org-link-make-string (concat "id:" (org-id-get-create))
  112. (if (org-at-heading-p)
  113. (nth 4 (org-heading-components))
  114. "")))))
  115. (template-info nil)
  116. (node (org-roam-node-at-point))
  117. (refs (ignore-errors (org-roam-node-refs (org-roam-node-from-id article-id))))
  118. (template (org-roam-format-template
  119. (string-trim (org-capture-fill-template org-roam-extract-new-file-path))
  120. (lambda (key default-val)
  121. (let ((fn (intern key))
  122. (node-fn (intern (concat "org-roam-node-" key)))
  123. (ksym (intern (concat ":" key))))
  124. (cond
  125. ((fboundp fn)
  126. (funcall fn node))
  127. ((fboundp node-fn)
  128. (funcall node-fn node))
  129. (t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
  130. (plist-put template-info ksym r)
  131. r)))))))
  132. (file-path (expand-file-name template (file-name-as-directory org-roam-directory)))
  133. (origin-file (buffer-file-name))
  134. id)
  135. (when (file-exists-p file-path)
  136. (user-error "%s exists. Aborting" file-path))
  137. (with-temp-buffer
  138. (insert-file-contents origin-file)
  139. (org-fc--region-to-cloze beg end nil hint)
  140. (org-mode)
  141. (org-with-point-at (point-min)
  142. (org-set-property bir-article-property article)
  143. (org-set-property bir-parent-property parent)
  144. (when refs (org-roam-property-add "ROAM_REFS" (concat "cite:&" (car refs)))))
  145. (org-delete-property "id")
  146. (write-region (point-min) (point-max) file-path nil t nil t)
  147. (ignore-errors (org-fc--deinit-card))
  148. (setq id (org-id-get-create))
  149. (save-buffer)
  150. (revert-buffer-quick)
  151. (if interactive
  152. (call-interactively #'org-fc-type-cloze-init)
  153. (org-fc-type-cloze-init 'deletion))
  154. (save-buffer))
  155. (when interactive
  156. (find-file file-path))
  157. id))
  158. (defun bir-extract-subtree ()
  159. "Convert current subtree at point to a node, and extract it into a new file."
  160. (save-excursion
  161. (org-id-get-create)
  162. (let* ((template-info nil)
  163. (title (org-roam-get-keyword "TITLE"))
  164. (article-prop (org-entry-get nil bir-article-property t))
  165. (article-id (or (plist-get (org-element--get-global-node-properties) :ID)
  166. (when article-prop
  167. (progn (string-match org-link-bracket-re article-prop)
  168. (substring-no-properties (match-string 1 article-prop) 3)))
  169. (save-excursion (while (org-up-heading-safe))
  170. (org-id-get-create))))
  171. (article (org-link-make-string (concat "id:" article-id) title))
  172. (parent (save-excursion
  173. (org-up-heading-safe)
  174. (if (string= (org-id-get-create) article-id)
  175. article
  176. (org-link-make-string (concat "id:" (org-id-get-create))
  177. (org-get-heading t t t t)))))
  178. (node (org-roam-node-at-point))
  179. (refs (org-roam-node-refs (org-roam-node-from-id article-id)))
  180. (template (org-roam-format-template
  181. (string-trim (org-capture-fill-template org-roam-extract-new-file-path))
  182. (lambda (key default-val)
  183. (let ((fn (intern key))
  184. (node-fn (intern (concat "org-roam-node-" key)))
  185. (ksym (intern (concat ":" key))))
  186. (cond
  187. ((fboundp fn)
  188. (funcall fn node))
  189. ((fboundp node-fn)
  190. (funcall node-fn node))
  191. (t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
  192. (plist-put template-info ksym r)
  193. r)))))))
  194. (file-path (expand-file-name template (file-name-as-directory org-roam-directory)))
  195. (id (org-id-get)))
  196. (unless (file-exists-p file-path)
  197. (let ((kill-do-not-save-duplicates t))
  198. (org-cut-subtree))
  199. (with-temp-buffer
  200. (org-set-property bir-article-property article)
  201. (org-set-property bir-parent-property parent)
  202. (when refs (org-set-property "ROAM_REFS" (concat "cite:&" (car refs))))
  203. (org-paste-subtree 1 nil nil t)
  204. (write-region (point-min) (point-max) file-path nil t)
  205. (org-fc-type-topic-init)
  206. (save-buffer)
  207. (org-roam-db-update-file)
  208. id)))))
  209. (provide 'bir-extract)
  210. ;;; bir-extract.el ends here