From 8de55eca2804a0d50af33c273b69bdddb5c111d5 Mon Sep 17 00:00:00 2001 From: Kyle Meyer Date: Thu, 11 Dec 2014 23:18:30 -0500 Subject: Add command to list orphan citekeys --- NEWS | 3 +++ bog-todo | 2 +- bog.el | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index dbef01f..c11a25c 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,9 @@ - New commands =bog-next-non-heading-citekey= and =bog-previous-non-heading-citekey= +- New command =bog-list-orphan-citekeys= finds citekeys that are + referred to in the notes but don't have their own heading. + ** Other changes - =bog-goto-citekey-heading-in-buffer= and diff --git a/bog-todo b/bog-todo index 785ae48..7309776 100644 --- a/bog-todo +++ b/bog-todo @@ -24,7 +24,7 @@ Perhaps use a cache file. This could be used in * Notes -** ENH Find in-text citekeys that don't have a header +** DONE Find in-text citekeys that don't have a header ** CANCELED Check for duplicate citekeys headings :LOGBOOK: diff --git a/bog.el b/bog.el index 4207855..dc4899d 100644 --- a/bog.el +++ b/bog.el @@ -345,6 +345,44 @@ word constituents." (--keep it (org-map-entries 'bog-citekey-from-heading nil 'file))) +(defun bog-non-heading-citekeys-in-file (file) + "Return all non-heading citekeys in FILE." + (let (refs + case-fold-search) + (with-temp-buffer + (org-mode) + (insert-file-contents file) + (while (re-search-forward bog-citekey-format nil t) + (unless (or (org-at-heading-p) + (org-at-property-p)) + (push (match-string-no-properties 0) refs)))) + (-distinct refs))) + +(defun bog-list-orphan-citekeys (&optional file) + "List in citekeys that appear in notes but don't have heading. +With prefix FILE, include only orphan citekeys from that file." + (interactive (list (and current-prefix-arg + (bog-read-note-file-name)))) + (let ((files (or (and file (list file)) + (bog-notes))) + (heading-cks (bog-all-heading-citekeys)) + cks) + (with-current-buffer (get-buffer-create "*Bog orphan citekeys*") + (delete-region (point-min) (point-max)) + (insert "\n") + (-each files + (lambda (f) + (setq cks + (--> (bog-non-heading-citekeys-in-file f) + (-difference it heading-cks) + (-sort (lambda (x y) (string-lessp x y)) it) + (mapconcat #'identity it "\n"))) + (unless (equal cks "") + (insert (format "* %s\n\n" (file-name-nondirectory f))) + (insert (concat cks "\n\n"))))) + (org-mode) + (show-all)))) + ;;; Citekey-associated files @@ -740,6 +778,13 @@ level `bog-refile-maxlevel' are considered." (concat (file-name-as-directory bog-note-directory) "*.org")))) +(defun bog-read-note-file-name () + (let ((nodir-files (-annotate #'file-name-nondirectory + (bog-notes)))) + (cdr (assoc (org-icompleting-read "File: " + (-map #'car nodir-files)) + nodir-files)))) + (defun bog-search-notes (&optional todo-only string) "Search notes using `org-search-view'. With prefix argument TODO-ONLY, only TODO entries are searched. -- cgit v1.2.3