Python API¶
The supported entry point is intentionally small.
from citekeep import Citekeep
app = Citekeep.open("~/bibliography/master.bib")
results = app.search("adaptive estimation", project_bib="refs.bib")
plan = app.plan_project(".")
app.apply(plan)
Parsing, fingerprint indexes and lossless text patches are implementation modules rather than a compatibility promise. What follows is.
citekeep.app.Citekeep ¶
Configured access to one canonical BibTeX library.
open
classmethod
¶
open(library)
Open the canonical library at library, expanding ~.
Nothing is read here. Every method reads the file afresh, so an edit made in a text editor between two calls is seen.
search ¶
search(query, project_bib=None)
Search the project and the library, without touching the network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
words matched against title, authors, journal, citation key, DOI and arXiv identifier. Every word must appear. |
required |
project_bib
|
str | Path | None
|
a project bibliography to search as well. |
None
|
Returns:
| Type | Description |
|---|---|
SearchResults
|
Project hits first, since their keys are the ones valid in that |
SearchResults
|
document; library hits omit works the project already holds, so |
SearchResults
|
that nothing is offered twice. |
search_online ¶
search_online(
query, limit=10, source_modules=sources.DEFAULT
)
Search the online sources, zbMATH first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
a DOI, an arXiv identifier, or free text. |
required |
limit
|
int
|
how many results to ask the source for. |
10
|
source_modules
|
tuple
|
the sources to try, in order. |
DEFAULT
|
Returns:
| Type | Description |
|---|---|
str
|
The source that answered, and the records it returned. A source |
tuple[Record, ...]
|
with nothing to say is passed over rather than reported as a |
tuple[str, tuple[Record, ...]]
|
failure. |
verify ¶
verify(record, source_modules=sources.DEFAULT)
Ask every source about record, and report what they answer.
Nothing is written: the caller arbitrates. One service failing does not hide the evidence of the others.
plan_refresh ¶
plan_refresh(
record, candidate, mode="complete", fields=None
)
Plan an update of record from one verified candidate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
Record
|
the record as currently held. |
required |
candidate
|
SourceCandidate
|
a candidate returned by |
required |
mode
|
str
|
|
'complete'
|
fields
|
list[str] | None
|
the fields to take, when |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
the candidate identity is not trusted, or the mode is unknown. |
The local citation key and every project-only field survive all three modes; the plan is not applied here.
plan_materialize ¶
plan_materialize(master_key, project_bib)
Plan copying one library record into a project bibliography.
Raises:
| Type | Description |
|---|---|
KeyError
|
no record in the library carries |
plan_project ¶
plan_project(
root,
project_bib=None,
field_resolutions=None,
identity_resolutions=None,
)
Plan one complete synchronisation of the project under root.
Reads the \cite commands in the project's TeX files and pairs them
with the library both ways: records the document needs are copied
down, records only the project holds are offered up.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str | Path
|
the project directory. |
required |
project_bib
|
str | Path | None
|
its bibliography, when the document declares none or declares several. |
None
|
field_resolutions
|
dict | None
|
decisions on fields where a reviewed local value contradicts the library. |
None
|
identity_resolutions
|
dict | None
|
decisions on records whose identity the evidence does not settle. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
no bibliography is declared, several are, or the one given is the library itself. |
The plan records a digest of both files, so that apply can refuse
to act on a file that has changed since. Nothing is written here.
apply ¶
apply(plan)
Write a plan to disk, atomically.
Raises:
| Type | Description |
|---|---|
ValueError
|
the plan carries unresolved conflicts, or was not built against files. |
ConcurrentModification
|
the library or the project bibliography changed since the plan was made. |
Returns:
| Type | Description |
|---|---|
ProjectPlan
|
The plan that was applied. |
The editor protocol¶
The citekeep editor … command namespace is an implementation protocol for
editor extensions, not a second everyday CLI. It carries the small stdin/JSON
operations needed to materialise, add or refresh one record after an
interactive choice has been made — the choosing itself belongs to the editor.
Its JSON carries a schema_version. An extension should refuse to run against
a version it does not know, rather than misread the output; citekeep.el does
exactly that.
Building an extension for another editor¶
There is no VS Code or Neovim extension today, and the API above is what one would be built on. The shape that works, as learned from the Emacs one:
- call
searchwith what the user typed, and show project hits before library hits; - offer an explicit online action rather than searching the network implicitly;
- call
plan_materializewhen a library record is chosen, and insert the key the plan reports — not the library's key, which may differ from the project's; - never write while the user has unsaved changes in the buffer you are about to touch.