emacs.d/site-lisp/org-index-capture/org-index-capture.el

88 lines
3.5 KiB
EmacsLisp

;;; org-index-capture --- dynamic block example -*- lexical-binding: t; -*-
;;; Blog: https://one-octet.dev/posts/org-mode-dynamic-index.html
(require 'org)
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only keep-deferred))
(declare-function org-element-property "org-element-ast" (property node))
(defun org-index-extract-infos (file-path)
"Extract all information for an index from FILE-PATH."
(with-temp-buffer
(insert-file-contents file-path)
(append
(org-element-map (org-element-parse-buffer) 'keyword
(lambda (keyword)
(list (org-element-property :key keyword)
(org-element-property :value keyword))))
(list (list "FILE-PATH" file-path)
(list "FILE-FULL-PATH" (expand-file-name file-path))))))
(defun org-index-list-files-path (directory)
"Get the DIRECTORY based names of all `.org' files in DIRECTORY."
(mapcar (lambda (file-name)
(file-name-concat directory file-name))
(directory-files directory nil ".org$")))
(defun org-index-sort-file-alists (alists)
"Sort a list of `.org' information alists by date."
(sort alists (lambda (file-a file-b)
(string> (cadr (assoc "DATE" file-a))
(cadr (assoc "DATE" file-b))))))
(defun org-index-spec-make (alist)
"Call `format-spec-make' using an `.org' file ALIST."
(let ((author (or (cadr (assoc "AUTHOR" alist)) "NO-AUTHOR"))
(creator (or (cadr (assoc "CREATOR" alist)) "NO-CREATOR"))
(date (or (cadr (assoc "DATE" alist)) "1999.12.31"))
(description (or (cadr (assoc "DESCRIPTION" alist)) "NO-DESCRIPTION"))
(file-full-path (cadr (assoc "FILE-FULL-PATH" alist)))
(file-path (cadr (assoc "FILE-PATH" alist)))
(language (or (cadr (assoc "LANGUAGE" alist)) "NO-LANGUAGE"))
(options (or (cadr (assoc "OPTIONS" alist)) "NO-OPTIONS"))
(title (or (cadr (assoc "TITLE" alist)) "NO-TITLE")))
(format-spec-make ?a author ?c creator
?d date ?D description
?l language ?o options
?P file-full-path ?p file-path
?t title)))
(defun org-dblock-write:index (params)
"Write a directory index."
(let ((directory (or (plist-get params :directory )
(file-name-directory (buffer-file-name))))
(sort-recent (plist-get params :sort-recent))
(fmt (or (plist-get params :format) "- %d: [[file:%p][%t]]"))
(alists nil))
(if sort-recent
(setq alists (org-index-sort-file-alists
(mapcar
'org-index-extract-infos
(org-index-list-files-path directory))))
(setq alists (mapcar
'org-index-extract-infos
(org-index-list-files-path directory))))
(mapcar
(lambda (alist)
(insert (format-spec fmt (org-index-spec-make alist)) "\n"))
alists)))
;;;###autoload
(defun org-index-insert-dblock (directory)
"Create a dynamic block capturing a directory index."
(interactive
(list (string-replace
(file-name-directory (buffer-file-name))
""
(expand-file-name (read-directory-name "Directory to index: ")))))
(org-create-dblock
(list :name "index"
:directory directory)))
(org-dynamic-block-define "index" 'org-index-insert-dblock)
(provide 'org-index-capture)
;;; org-index-capture.el ends here