summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Meyer <kyle@kyleam.com>2014-02-02 23:50:16 -0500
committerKyle Meyer <kyle@kyleam.com>2014-02-03 00:23:31 -0500
commit2626b234016d3a826dde5b11c321512c98e12214 (patch)
tree44aa3cb09b949a637d08b8b37784f22f3f690f63
parent9fe3a4cc25190682554ccc6eef94dd19928af8b2 (diff)
downloadbog-2626b234016d3a826dde5b11c321512c98e12214.tar.gz
Add core citekey functions
-rw-r--r--bog-tests.el116
-rw-r--r--bog.el126
2 files changed, 242 insertions, 0 deletions
diff --git a/bog-tests.el b/bog-tests.el
new file mode 100644
index 0000000..e7ce2cc
--- /dev/null
+++ b/bog-tests.el
@@ -0,0 +1,116 @@
+(require 'ert)
+(require 'org)
+(require 'bog)
+
+
+;;; Citekey functions
+
+;; `bog-citekey-p'
+
+(ert-deftest bog-citekey-p ()
+ (should (bog-citekey-p "name2010word"))
+ (should (bog-citekey-p "name1900word"))
+ (should-not (bog-citekey-p "name201word")))
+
+(ert-deftest bog-citekey-p-with-hyphen-in-name ()
+ (should (bog-citekey-p "hyphen-ok2010word")))
+
+(ert-deftest bog-citekey-p-with-other-text ()
+ (should (bog-citekey-p "name2010word more text")))
+
+(ert-deftest bog-citekey-only-p ()
+ (should (bog-citekey-only-p "name2010word"))
+ (should-not (bog-citekey-only-p "name201word"))
+ (should (bog-citekey-only-p "hyphen-ok2010word"))
+ (should-not (bog-citekey-only-p "name2010word more text")))
+
+;; `bog-citekey-groups-with-delim'
+
+(ert-deftest bog-citekey-groups-with-delim ()
+ (let ((citekey "name2010word"))
+ (should (equal (bog-citekey-groups-with-delim citekey)
+ "name 2010 word"))
+ (should (equal (bog-citekey-groups-with-delim citekey ",")
+ "name,2010,word"))
+ (should (equal (bog-citekey-groups-with-delim citekey nil '(1 3))
+ "name word"))))
+
+;; `bog-citekey-at-point'
+
+(ert-deftest bog-citekey-at-point ()
+ (let ((citekey "name2010word"))
+ (with-temp-buffer
+ (insert citekey)
+ (goto-char (point-min))
+ (should (equal (bog-citekey-at-point) citekey)))))
+
+;; `bog-citekey-heading'
+
+(ert-deftest bog-citekey-heading-current-level ()
+ (let ((citekey "name2010word"))
+ (with-temp-buffer
+ (insert (format "\n* top level\n\n** %s\n\nsome text\n"
+ citekey))
+ (org-mode)
+ (show-all)
+ (should (equal (bog-citekey-heading) citekey)))))
+
+(ert-deftest bog-citekey-heading-in-parent ()
+ (let ((citekey "name2010word"))
+ (with-temp-buffer
+ (insert (format "\n* top level\n\n** %s\n\n*** subheading\n\nsome text\n"
+ citekey))
+ (org-mode)
+ (show-all)
+ (should (equal (bog-citekey-heading) citekey)))))
+
+(ert-deftest bog-citekey-heading-on-heading ()
+ (let ((citekey "name2010word"))
+ (with-temp-buffer
+ (insert (format "\n* top level\n\n** %s\n\nsome text\n"
+ citekey))
+ (org-mode)
+ (show-all)
+ (re-search-backward bog-citekey-format)
+ (should (equal (bog-citekey-heading) citekey)))))
+
+(ert-deftest bog-citekey-action-in-normal-text ()
+ (let ((citekey "name2010word"))
+ (with-temp-buffer
+ (insert (format "\n* top level\n\n** %s\n\nsome text\n"
+ citekey))
+ (org-mode)
+ (show-all)
+ (flet ((funcall (action citekey) citekey))
+ (should (equal (bog-citekey-action nil nil nil) citekey))))))
+
+;; `bog-citekey-action'
+
+(ert-deftest bog-citekey-action-on-heading ()
+ (let ((citekey "name2010word"))
+ (with-temp-buffer
+ (insert (format "\n* top level\n\n** %s\n\nsome text\n"
+ citekey))
+ (org-mode)
+ (show-all)
+ (re-search-backward bog-citekey-format)
+ (flet ((funcall (action citekey) citekey))
+ (should (equal (bog-citekey-action nil nil nil) citekey))))))
+
+(ert-deftest bog-citekey-action-on-in-text-citekey ()
+ (let ((citekey "name2010word"))
+ (with-temp-buffer
+ (insert (format "\n* top level\n\n** other2000key\n\nsome text and %s\n"
+ citekey))
+ (org-mode)
+ (show-all)
+ (re-search-backward bog-citekey-format)
+ (flet ((funcall (action citekey) citekey))
+ (should (equal (bog-citekey-action nil nil nil) citekey))))))
+
+(ert-deftest bog-citekey-action-no-citekey ()
+ (with-temp-buffer
+ (insert "\n* top level\n\n** second\n\n")
+ (org-mode)
+ (show-all)
+ (should-error (bog-citekey-action nil nil nil))))
diff --git a/bog.el b/bog.el
new file mode 100644
index 0000000..971b811
--- /dev/null
+++ b/bog.el
@@ -0,0 +1,126 @@
+;;; bog.el --- Extensions for research notes in Org mode
+
+;; Copyright (C) 2013 Kyle Meyer <kyle@kyleam.com>
+
+;; Author: Kyle Meyer <kyle@kyleam.com>
+;; URL: https://github.com/kyleam/bog
+;; Keywords: BibTeX, org-mode
+;; Version: 0.5.0
+;; Package-Requires: ((org "8.0.0") (dash "2.5.0"))
+
+;; 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, 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Bog provides a few convenience functions for taking research notes in
+;; Org mode.
+
+;;; Code:
+
+(require 'dash)
+(require 'org)
+
+
+;;; Customization
+
+(defgroup bog nil
+ "Extensions for research notes in Org mode"
+ :group 'tools
+ :group 'convenience)
+
+(defcustom bog-notes-directory "~/bib"
+ "The name of the directory that Org note are stored in."
+ :group 'bog
+ :type 'string)
+
+(defcustom bog-read-file-name 'read-file-name
+ "A function that will be used to promtp for file name.
+The function should accept one arguments, a string to use for the
+prompt. A good alternative is `ido-read-file-name'."
+ :group 'bog
+ :type 'function)
+
+(defcustom bog-completing-read 'completing-read
+ "A function that will be used for completion prompts.
+The function should accept two arguments, a string to use for the
+prompt and a list of strings to offer as choices. A good
+alternative is `ido-completing-read'."
+ :group 'bog
+ :type 'function)
+
+(defcustom bog-citekey-format
+ "\\([0-9]*[a-z]+[-a-z]*\\)\\([0-9]\\{4\\}\\)\\([a-z]+\\)"
+ "Regex used to match study citekey.
+By default, this matches any sequence of lower case
+letters (allowing hyphenation) that is followed by 4 digits and
+then lower case letters."
+ :type 'string
+ :group 'bog)
+
+
+;;; General utilities
+
+(defun bog-citekey-action (action ask-func ask-citekey)
+ "Perform ACTION on file associtated with a citekey.
+
+ASK-FUNC should be a function that queries the user for a citekey
+when ASK-CITEKEY is non-nil. Otherwise, the citekey will be taken
+from the text under point if it matches `bog-citekey-format' or
+from the first parent heading that matches `bog-citekey-format'.
+
+ACTION will be called with the resulting citekey as an argument."
+ (let* ((citekey (and ask-citekey (funcall ask-func)))
+ (citekey (or (bog-citekey-at-point)
+ (bog-citekey-heading))))
+ (funcall action citekey)))
+
+(defun bog-select-citekey (citekeys)
+ "Prompt for citekey from CITEKEYS"
+ (funcall bog-completing-read "Select citekey: " citekeys))
+
+(defun bog-citekey-at-point ()
+ (let ((maybe-citekey (thing-at-point 'word)))
+ (when (and maybe-citekey
+ (bog-citekey-only-p maybe-citekey))
+ maybe-citekey)))
+
+(defun bog-citekey-heading ()
+ "Return first org heading that matches `bog-citekey-format'."
+ (save-excursion
+ (save-restriction
+ (widen)
+ (org-back-to-heading)
+ (let ((heading (org-element-property :raw-value (org-element-at-point))))
+ (while (and (not (bog-citekey-only-p heading))
+ (org-up-heading-safe))
+ (setq heading
+ (org-element-property :raw-value (org-element-at-point))))
+ (when (not (bog-citekey-only-p heading))
+ (error "Citekey not found"))
+ heading))))
+
+(defun bog-citekey-p (text)
+ "Indicate if TEXT matches `bog-citekey-format'."
+ (when (string-match bog-citekey-format text)
+ t))
+
+(defun bog-citekey-only-p (text)
+ "Indicate if all of TEXT matches `bog-citekey-format'."
+ (string-match bog-citekey-format text)
+ (when (equal (length text) (match-end 0))
+ t))
+
+(provide 'bog)
+
+;; bog.el ends here