Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor cache architecture #628

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions CONTRIBUTING.org
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,49 @@

If you would like to contribute, details:

- For more signifiant potential changes, file an issue first to get feedback on the basic idea.
- For more significant potential changes, file an issue first to get feedback on the basic idea.
- If you do submit a PR, follow the [[https://github.com/bbatsov/emacs-lisp-style-guide][elisp style guide]], and [[https://cbea.ms/git-commit/][these suggestions]] on git commit messages.
- For working on lists and such, we primarily use the =seq= functions, and occassionally ~dolist~.

** Basic Architecture

Citar has two primary caches, each of which store the data in hash tables:

- bibliographic :: keys are citekeys, values are alists of entry fields
- completion :: keys are completion strings, values are citekeys

The =citar--ref-completion-table= function returns a hash table from the bibliographic cache, and ~citar--get-entry~ and ~-citar--get-value~ provide access to those data.
Most user-accessible citar functions take an argument ~key~ or ~keys~.
Some functions also take an ~entry~ argument, and ~citar--get-value~ takes either.
When using these functions, you should keep in mind that unless you pass an entry alist to ~citar--get-value~, and instead use a key, each call to that function will query the cache.
This, therefore, is a better pattern to use:

#+begin_src emacs-lisp

(let* ((entry (citar--get-entry key))
(title (citar--get-value entry "title")))
(message title))

#+end_src


** Extending citar

Most user-accessible citar functions take an argument ~key-entry~ or ~keys-entries~.
These expect, respectively, a cons cell of a citation key (a string like "SmithWritingHistory1987") and the corresponding bibliography entry for that citation, or a list of such cons cells.
If you wish to extend citar at the user-action level, perhaps by adding a function to one of the embark keymaps, you will find it easiest to reproduce this pattern.
If you need to build the cons cells manually, this can be accomplished via ~citar--get-entry~.
So, for example, to insert the annotations from a pdf into a buffer, the following pair of functions might be used:
You can use ~citar-select-ref~ or ~citar-select-refs~ to write custom commands.
An example:

#+begin_src emacs-lisp


(defun my/citar-insert-annots (keys-entries)
(defun my/citar-insert-annots (keys)
"insert annotations as org text from KEYS-ENTRIES"
(interactive (list (citar-select-refs
:rebuild-cache current-prefix-arg)))
(interactive (list (citar-select-refs)))
(let* ((files
(seq-mapcat (lambda (key-entry)
(seq-mapcat (lambda (key)
(citar-file--files-for-entry
(car key-entry) (cdr key-entry)
key (citar--get-entry key)
'("/") '("pdf")))
keys-entries ))
keys ))
(output (seq-map
(lambda (file)
(pdf-annot-markups-as-org-text ;; you'll still need to write this function!
Expand All @@ -44,8 +62,7 @@ So, for example, to insert the annotations from a pdf into a buffer, the followi

(defun my/independent-insert-annots (key)
"helper function to insert annotations without the bibtex-actins apparatus"
(let ((key-entry (cons key (citar--get-entry key))))
(my/citar-insert-annots (list key-entry))))
(my/citar-insert-annots (list key)))


#+end_src
Expand Down
37 changes: 9 additions & 28 deletions citar-file.el
Original file line number Diff line number Diff line change
Expand Up @@ -233,31 +233,6 @@ need to scan the contents of DIRS in this case."
(puthash key (nreverse filelist) files))
files))))

(defun citar-file--has-file-notes-hash ()
"Return a hash of keys and file paths for notes."
(citar-file--directory-files
citar-notes-paths nil citar-file-note-extensions
citar-file-additional-files-separator))

(defun citar-file--has-library-files-hash ()
"Return a hash of keys and file paths for library files."
(citar-file--directory-files
citar-library-paths nil citar-library-file-extensions
citar-file-additional-files-separator))

(defun citar-file--keys-with-file-notes ()
"Return a list of keys with file notes."
(hash-table-keys (citar-file--has-file-notes-hash)))

(defun citar-file--keys-with-library-files ()
"Return a list of keys with file notes."
(hash-table-keys (citar-file--has-library-files-hash)))

(defun citar-file-has-notes ()
"Return a predicate testing whether a reference has associated notes."
(citar-file--has-file citar-notes-paths
citar-file-note-extensions))

(defun citar-file--has-file (dirs extensions &optional entry-field)
"Return predicate testing whether a key and entry have associated files.

Expand All @@ -277,8 +252,9 @@ once per command; the function it returns can be called
repeatedly."
(let ((files (citar-file--directory-files dirs nil extensions
citar-file-additional-files-separator)))
(lambda (key entry)
(let* ((xref (citar--get-value "crossref" entry))
(lambda (key &optional entry)
(let* ((nentry (or entry (citar--get-entry key)))
(xref (citar--get-value "crossref" nentry))
(cached (if (and xref
(not (eq 'unknown (gethash xref files 'unknown))))
(gethash xref files 'unknown)
Expand All @@ -292,7 +268,7 @@ repeatedly."
(puthash key
(seq-some
#'file-exists-p
(citar-file--parse-file-field entry entry-field dirs extensions))
(citar-file--parse-file-field nentry entry-field dirs extensions))
files))))))

(defun citar-file--files-for-entry (key entry dirs extensions)
Expand Down Expand Up @@ -351,6 +327,11 @@ of files found in two ways:
nil 0 nil
file)))

(defun citar-file-has-notes ()
"Return a predicate testing whether a reference has associated notes."
(citar-file--has-file citar-notes-paths
citar-file-note-extensions))

(defun citar-file--open-note (key entry)
"Open a note file from KEY and ENTRY."
(if-let* ((file (citar-file--get-note-filename key
Expand Down
Loading