Fast fuzzy search for Zotero using fzf

fzf is a command line tool that offers very fast and incremental fuzzy search.

You can enter characters one at a time, and fzf will interactively find entries that match these characters.

For example, both "tom c" or "c tom" will find entries containing "Clancy, Tom".
"clancy" will find all lines containing the characters c,l,a,n,c, (including "The c language reference"), but lines with better matches are prioritized.
A single quote, like 'clancy, will limit the search to full words.

More details and installation instructions can be found at https://github.com/junegunn/fzf

Using the steps below Zotero can be searched with fzf.

This is but a quick, inelegant, hack, but it might be useful to others.
Improvements are welcome.

0. Install fzf

1. Install the BetterBibTeX plugin for Zotero

2. In the Zotero settings, add an export postscript to add itemIDs to the links, more info at https://forums.zotero.org/discussion/101535/betterbibtex-export-itemids-to-bib-file :


if (Translator.BetterBibLaTeX) {
tex.add({ name: 'zoteroselect', value: zotero.uri.replace(/http:\/\/zotero.org\/users\/\d+\/items\/(\w+)/, 'zotero://select/library/items/$1')});
}


3. Export your library using BetterBibLatex to a file with the name "My Library.bib".
Each item should now have a "zoteroselect" entry.

4. Convert the bib file to a txt file with one entry per line. The zotero://select link is the last item, separated by a |.


import bibtexparser

bibtex_file = r"path\to\My Library.bib"
outputFile_full = "zoterodb.txt"

parser = bibtexparser.bparser.BibTexParser()
parser.ignore_nonstandard_types = False
parser.homogenize_fields = False
parser.common_strings = False
bib_database:bibtexparser.bibdatabase.BibDatabase = bibtexparser.load(open(bibtex_file, 'r', encoding='utf-8'), parser=parser)

with open(outputFile_full, 'w', encoding='utf-8') as f_full:
for n, entry in enumerate(bib_database.entries):
# Export other fields if desired
f_full.write(f"{entry.get('author', '')} | {entry.get('title', '')} | {entry.get('file', '')} | {entry.get('zoteroselect', '')}\n")

print(f"exported {n} entries to {outputFile_full}")



5. Create a shim file fzfsearch.py that takes the line returned by fzf, finds the select link, and opens the link in Zotero:


import sys
import webbrowser

if __name__=='__main__':
print("test", str(sys.argv))
selectlink = sys.argv[1].rsplit("|")[-1].strip()
#os.system(f'start /b \"\" {selectlink} ') # Windows only
webbrowser.open(selectlink) # should work everywhere


6. Search through your library using fzf, F1 opens the item in Zotero. fzf can stay open in the terminal.

cat .\zoterodb.txt | fzf --bind 'f1:execute-silent(python.exe fzfsearch.py {})'



Some terminals can show hyperlinks. Windows Terminal has support for automatic detection of URLs, but it doesn't work for zotero:// links. If anyone knows how to set this up, please post.
Sign In or Register to comment.