Jump to content

Bookends Tools — A curated toolset for Bookends reference manager


Recommended Posts

Bookends is an excellent bibliographic/research manager for macOS. This Alfred workflow curates 11 tools together in one interface to interact with Bookends and other apps. You can use Alfred keywords (be…) and/or bind your preferred key combination to trigger these directly. It has been designed for Alfred 3, and should keep itself up-to-date using OneUpdater.

 

More Information…      —<>—     Download Directly…

 

workflow.png

 

key: ?: select some text in another app then trigger tool — ?: select reference(s) within Bookends then trigger tool — : trigger tool and enter some text in Alfred

 

  1. beidsearch ? — Find a selected uniqueID in Bookends. For example, if you have a temporary citation like {Koffka, 1922, #6475} in your word-processor, double-click select the Bookends ID `6475`, then trigger this workflow and it will find the reference in Bookends for you.
  2.  bebrowser ? — Search selected text in Bookends browser. For the Pubmed interface you should select this manually in the bookends browser. Because this uses `System Events`, sometimes the automatic paste into the search field fails, in which case you need to manually press ⌘V and ⌅ (enter) to trigger the search.
  3. berefsearch ? — Take some selected text like "(Doe et al., 2005)" citation, clean it up become "Doe 2005" and send it to Bookend's quick search. This is great because you can take a formatted ref in a text document and search for the first author/year, then quickly paste back (⌘Y for Scrivener) the Bookends style temporary citation in its place!
  4. bequickadd ? — Take a text selected DOI / PMID / ISBN or JSTOR identifier in any app and use Quick Add (feature added in Bookends 13.0.3+) to quickly add this reference to the database.
  5. betoopml ? — Select multiple references within Bookends, then run this to create an OPML file which you can import into Scrivener or other OPML-aware tool. This will contain the abstract and notes which is very useful for research. It contains links back to the Bookends reference. You can configure the export path in the workflow variables (default Desktop/).
  6. bescopus ? — Select a reference (with a DOI) in Bookends, then trigger this to search Scopus with the DOI.  It will return an inline results list for the Scopus entry AND the Cited-by page. Select an entry to go to that page. It will also append these Scopus URLs in the Notes field for future reference. You can enter your Scopus API key in the workflow variables. 
  7. betobibtex  — You enter the name of a Bookends static/smart group name and this will create a BibTeX bibliography file for those particular groups. Very useful for Pandoc and/or LaTeX workflows. You can optionally generate JSON instead of BIB (faster if use pandoc-citeproc). You can configure the export path in the workflow variables (default Desktop/). 
  8. becite  — You enter author or editor name{s} along with an optional YEAR (case insensitive REGEX), and get an inline results list. You can [enter] to paste this as a temporary citation (or use: ⌘ pastes Pandoc style, ⌥ pastes MMD style, ⌃ pastes formatted ref, ⇧ opens ref in Bookends, [space] quicklooks attachment).  
  9. betitle — You enter word{s} in the title or keyworkds , along with an optional YEAR (case insensitive REGEX), and get an inline results list. You can then paste this as a temporary citation (or use: ⌘ pastes Pandoc style, ⌥ pastes MMD style, ⌃ pastes formatted ref, ⇧ opens ref in Bookends, [space] quicklooks attachment).
  10. beall — You enter word in any field (case insensitive REGEX), and get an inline results list. You can then paste this as a temporary citation (or use: ⌘ pastes Pandoc style, ⌥ pastes MMD style, ⌃ pastes formatted ref, ⇧ opens ref in Bookends, [space] quicklooks attachment).
  11. bebib — You enter an author / editor name, and get an inline results list. You can [enter] to paste this as a formatted reference (or use: ⌘ pastes MMD style, ⌥ pastes Pandoc style).

 

becite, betitle, beall and bebib were inspired by the tool by Eggman which I've rewritten in Ruby to be faster and more flexible.

 

Changelog

1.2.9 — add a new workflow variable `tempCitationStyle` that sets the default temporary citation format for becite / betitle / beall. When unset it will be the Bookends standard, but you can set the variable to `Pandoc` / `MMD` / `LaTeX` to paste the citation in a different format (`[@key]` / `[#key]` / `\\cite[]{key}`). Also if the authors field is empty for a reference, we now try to use editor names instead in the Alfred results list.

1.2.8 — add phrase search, so for example 'cartesian theatre' 2016 will find papers that use that exact phrase rather than before where cartesian and theatre were searched irrespective of their location.

1.2.5 — becite/betitle/beall first AND last author names with initials are now shown, and if an attachment is present you can Quicklook it directly from Alfred without losing focus (press shift or ⌘Y)!

1.2.4 — becite/betitle/beall now show if a reference has an attachment, and for BE13 users use the new applescript events that are slightly more efficienct.
1.2.3 — small change to open the attachment when you use becite with [fn].
1.2.2 — update the Scopus search tool to the newest API changes (https by default and httpAccept is required)

1.2.1 — rewrote the becite, bebib and betitle tools to perform a mutliple item search (i.e author1 + author2) and you can add an optional YEAR to refine the search. So for example [Zipser Lamme 1998] searches for references by authors (or editors) Zipser and Lamme published in 1998. Also optimised the search code (rewritten in Ruby) so now it takes much less time for large results sets. Because it is so much faster, add a new [beall] tool like betitle but to search in all database fields. For becite/betitle/beall you can now use SHIFT to open ref directly in Bookends.

1.1.0 — option to use RTF for becite/betitle temporary citations to enable bookends links copied into RTF comments/annotation aware apps like Scrivener. Added Workflow env variables citeUsesRTF to enable/disable this feature (default is disabled). Note it cannot match your font on paste of RTF, this is a limitation of RTF.
1.0.9 — V1.0.9 add new bequickadd Quick Add tool, needs BE 13.0.3+

1.0.8 — allow author name OR editor name search for becite; better chinese author fix.
1.0.7 — try to get becite search for chinese authors to work.

1.0.6 — add betitle that searches within the reference title for a word.

1.0.5 — add ⌥ to bebib to paste pandoc footnote format. bebib formatted ref now pastes in the target app. Add environment variable to control the bibliography format for bebib.

Edited by iandol
update for V1.2.9
Link to comment
  • 1 month later...

Thank you for this really cool Workflow! If I may add a feature request: I’d like to search for an Author or Title and have the option to pass the page to cite to alfred. For my MMD to LaTeX Workflow I cite like this: [11][#Hagner2001;] - I already changed the Applescipt so I can paste the second part of the citation, [#Hagner2001;] but I’m really missing the option to define a page ?

 

Would be great if you would consider adding this!

 

 

Link to comment

This is for tool 7 (becite)? At the moment it takes the entry name and searches immediately, I'm not sure how to add a page number without interfering with the initial search. So I wonder whether I can add a (key modifier) trigger when you select an item to bring up Alfred again to enter the page number, I'll have a think about it over the weekend, any other ideas welcome :)

Link to comment
  • 1 month later...

That was easy , new tool is called betitle in V1.0.6, does a case insensitive search (needs to be > 2 characters) within the title field. I have ~3800 references and it searches quickly even when it returns around 30 or 40 search hits to populate the Alfred results list…

Link to comment
39 minutes ago, iandol said:

That was easy , new tool is called betitle in V1.0.6, does a case insensitive search (needs to be > 2 characters) within the title field. I have ~3800 references and it searches quickly even when it returns around 30 or 40 search hits to populate the Alfred results list…

 

Great! Gonna test it right away :)

Link to comment

Hm, that's weird. Eggman's script (which I slightly modified) should work with english names (it does for me and I assume everyone else). The first line of the applescript converts the input from Alfred into UTF-8:

 

set query to (do shell script "echo " & argv & " | iconv -s -f UTF-8-Mac -t UTF-8") as Unicode text

 

and so it should work at input. Bookends should be UTF-8 aware, if you do a SQL search (⇧⌘S) directly in Bookends, it seems to work:

 

Sample:  & 照山 (2017) “This is a test article” Neuron 23(4) p.1–5 

 

SQL REGEX: authors REGEX '王'

 

One potential problem is for speed I do not use single character search (if you search for "s" you basically block the applescript, which means chinese characters may never trigger the search...

Link to comment

You can test this by modifying the findReferences.applescript if...end if block on line 9 to send some debugging output to the desktop:

 

		if length of query is greater than 1 then --no point in searching for <=2 letter fragments
			set AppleScript's text item delimiters to {return}
			set searchString to "authors REGEX '(?i)" & query as string & "'"
			set refList to text items of («event ToySSQLS» searchString)
			do shell script "echo " & quoted form of (searchString as string) & " >> ~/Desktop/becite.txt"
			do shell script "echo " & quoted form of (refList as string) & " >> ~/Desktop/becite.txt"
			set AppleScript's text item delimiters to {","}
		end if

 

This shows the output for english names but not Chinese characters. If I remove the "if length..." check then the script blocks taking ages for searching each single character. The solution would be to check if this is a particular range of unicode, and if it was standard latin then enforce the length check, otherwise don't. but how one does that in Applescript I don't know, so one would have to do it in the shell? 

 

If I set length to 0 then the script works:

 

?  osascript findReferences.applescript 王   
{"items": [    

{
	"uid": "38685",
	"arg": "38685",
	"title": "王 2017",
	"subtitle": "This is a test article",
	"icon": {"path": "file.png"}
}
]}

So the issue really is to be able to check if the Alfred input is chinese or not in the Applescript. Any ideas welcome!

 

EDIT: one way is to use the shell test command and check if the input is greater than a latin extended character (binary value of the string value is used): if [[ '王' > 'ž' ]] then; echo "YES!"; fi

Edited by iandol
one possible solution?
Link to comment

I've added a new tool, bequickadd that lets you select a DOI/PMID/ISBN/JSTOR tag in any app/broswer and pass it to BE's new Quick Add feature, which automatically adds that reference to the database. This nice feature is new to BE 13.0.3...

Edited by iandol
Link to comment

chaxu443: for single authors this is possible, not for multiple authors; but I'd suggest to use Live Search in Bookends directly as it is much more powerful (combine author and year or keywords etc.). You can trigger Live search from Alfred by using tool [3] berefsearch without a text selection then type authors years or whatever else you like.

Edited by iandol
Link to comment
  • 2 weeks later...

iandol: these are fantastic, however using v.1.1.0 (the latest I think),  when doing a very few certain author and title searches that should return a lot of results (and do in Bookends live search) i get nothing at all. Any thoughts on what might be going wrong?

Link to comment

@w.yaqoob — does this depend on particular characters, like accents in author names? how big is your database? if you could find some references that reliably don't get found, you could make a small database and I can test... Did this get worse recently or it has never worked for you?

 

@swilcox — I just downloaded 13.0.5, and becite seems to be working for me...

 

 

Toy you BOTH: If you have some terminal skills, you can test the script itself by downloading https://github.com/iandol/bookends-tools/raw/master/source/findReferences.applescript and running it directly from the command line; make it executable then run it: 

 

osascript -s ho ./findReferences.applescript AUTHORNAME

 

I may make a version that has a debug mode to try to make it easier to test it. There are a couple of lines 21/22 that start --do shell script "echo — if you remove the -- this will copy the SQL search text and results to a text file on the desktop which may help to determine what may be wrong.

 

GENERAL: I am going to update becite / betitle to do a multi author / word search, and in the case of authors you can put an additional year to narrow the search further. It will be quite easy to update the script, but I just need to find time to do it; but I think it will make the search more useful...

Edited by iandol
Link to comment

If it helps, here is the debug report from the workflow of a becite for "Langacker" (no quotes in the original search). It looks like it's doing the search but then running into a problem. And it seems to only fail on this particular search, so I guess it's relating to one of the returned entries.

 

Starting debug for 'Bookends Tools'

[2018-01-29 19:22:35][ERROR: input.scriptfilter] JSON error: Unescaped control character around character 7145. in JSON:
{"items": [    

{
    "uid": "57630",
    "arg": "57630",
    "title": "Casad 1985",
    "subtitle": "Inside' and 'Outside' in Cora Grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "3324",
    "arg": "3324",
    "title": "Thompson 2013",
    "subtitle": "The eyes don’t point: Understanding language universals through person marking in American Signed Language",
    "icon": {"path": "file.png"}
},

{
    "uid": "41918",
    "arg": "41918",
    "title": "Varriano 2006",
    "subtitle": "Caravaggio : the art of realism",
    "icon": {"path": "file.png"}
},

{
    "uid": "67373",
    "arg": "67373",
    "title": "Langacker 1972",
    "subtitle": "Fundamentals of linguistic analysis",
    "icon": {"path": "file.png"}
},

{
    "uid": "36784",
    "arg": "36784",
    "title": "Langacker 1979",
    "subtitle": "Grammar as image",
    "icon": {"path": "file.png"}
},

{
    "uid": "45299",
    "arg": "45299",
    "title": "Langacker 1985",
    "subtitle": "Observations and speculations on subjectivity",
    "icon": {"path": "file.png"}
},

{
    "uid": "69761",
    "arg": "69761",
    "title": "Langacker 1986",
    "subtitle": "An introduction to cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "64871",
    "arg": "64871",
    "title": "Langacker 1987",
    "subtitle": "Foundations of cognitive grammar: Volume I, Theoretical foundations",
    "icon": {"path": "file.png"}
},

{
    "uid": "78109",
    "arg": "78109",
    "title": "Langacker 1987",
    "subtitle": "Nouns and verbs",
    "icon": {"path": "file.png"}
},

{
    "uid": "74243",
    "arg": "74243",
    "title": "Langacker 1988",
    "subtitle": "An overview of cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "87204",
    "arg": "87204",
    "title": "Langacker 1988",
    "subtitle": "An overview of cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "54196",
    "arg": "54196",
    "title": "Langacker 1990",
    "subtitle": "Subjectification",
    "icon": {"path": "file.png"}
},

{
    "uid": "75988",
    "arg": "75988",
    "title": "Langacker 1991",
    "subtitle": "Concept, image, and symbol: The cognitive basis of grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "37148",
    "arg": "37148",
    "title": "Langacker 1991",
    "subtitle": "Foundations of cognitive grammar. Volume II, Descriptive application",
    "icon": {"path": "file.png"}
},

{
    "uid": "56899",
    "arg": "56899",
    "title": "Langacker 1993",
    "subtitle": "Reference-point constructions",
    "icon": {"path": "file.png"}
},

{
    "uid": "80541",
    "arg": "80541",
    "title": "Langacker 1998",
    "subtitle": "Conceptualization, symbolization and grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "13027",
    "arg": "13027",
    "title": "Langacker 2000",
    "subtitle": "Grammar and conceptualization",
    "icon": {"path": "file.png"}
},

{
    "uid": "65327",
    "arg": "65327",
    "title": "Langacker 2000",
    "subtitle": "Grammar and Conceptualization (Cognitive Linguistics Research, 14)",
    "icon": {"path": "file.png"}
},

{
    "uid": "77272",
    "arg": "77272",
    "title": "Langacker 2000",
    "subtitle": "A Dynamic Usage-Based Model",
    "icon": {"path": "file.png"}
},

{
    "uid": "74925",
    "arg": "74925",
    "title": "Langacker 2001",
    "subtitle": "Dynamicity in grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "51758",
    "arg": "51758",
    "title": "Langacker 2001",
    "subtitle": "Discourse in cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "71541",
    "arg": "71541",
    "title": "Langacker 2003",
    "subtitle": "Construction grammars: Cognitive, radical, and less so.",
    "icon": {"path": "file.png"}
},

{
    "uid": "8594",
    "arg": "8594",
    "title": "Langacker 2006",
    "subtitle": "Subjectification, grammaticization, and conceptual archetypes",
    "icon": {"path": "file.png"}
},

{
    "uid": "33122",
    "arg": "33122",
    "title": "Langacker 2007",
    "subtitle": "Constructing the meanings of personal pronouns",
    "icon": {"path": "file.png"}
},

{
    "uid": "36662",
    "arg": "36662",
    "title": "Langacker 2008",
    "subtitle": "Cognitive grammar: A basic introduction",
    "icon": {"path": "file.png"}
},

{
    "uid": "10627",
    "arg": "10627",
    "title": "Langacker 2009",
    "subtitle": "Investigations in cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "12027",
    "arg": "12027",
    "title": "Langacker 2013",
    "subtitle": "Interactive cognition: Toward a unified account of structure, processing, and discourse",
    "icon": {"path": "file.png"}
},

{
    "uid": "48775",
    "arg": "48775",
    "title": "Romaine 2008",
    "subtitle": "The use of like as a marker of reported speech and thought: A case of grammaticalization in progress",
    "icon": {"path": "file.png"}
},

{
    "uid": "29435",
    "arg": "29435",
    "title": "Young 2012",
    "subtitle": "He Said What?!\": Constructed Dialogue in Various Interface Modes",
    "icon": {"path": "file.png"}
},

{
    "uid": "30960",
    "arg": "30960",
    "title": "Langacker 1975",
    "subtitle": "Functional stratigraphy",
    "icon": {"path": "file.png"}
},

{
    "uid": "57482",
    "arg": "57482",
    "title": "Langacker 2009",
    "subtitle": "Cognitive (Construction) Grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "87618",
    "arg": "87618",
    "title": "Langacker 1999",
    "subtitle": "Double-subject constructions",
    "icon": {"path": "file.png"}
},

{
    "uid": "40329",
    "arg": "40329",
    "title": "Langacker 2005",
    "subtitle": "Integration, Grammaticization, and Constructional Meaning",
    "icon": {"path": "file.png"}
},

{
    "uid": "103209",
    "arg": "103209",
    "title": "Langacker 2017",
    "subtitle": "Evidentiality in cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "38907",
    "arg": "38907",
    "title": "Langacker 2016",
    "subtitle": "Baseline and elaboration",
    "icon": {"path": "file.png"}
},

{
    "uid": "46835",
    "arg": "46835",
    "title": "Langacker 2013",
    "subtitle": "Modals: Striving for control",
    "icon": {"path": "file.png"}
},

{
    "uid": "99130",
    "arg": "99130",
    "title": "Langacker 2016",
    "subtitle": "Nominal structure in cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "24297",
    "arg": "24297",
    "title": "Langacker 2016",
    "subtitle": "Working toward a synthesis",
    "icon": {"path": "file.png"}
},

{
    "uid": "96826",
    "arg": "96826",
    "title": "Langacker 2016",
    "subtitle": "Nominal grounding and English quantifiers",
    "icon": {"path": "file.png"}
},

{
    "uid": "78385",
    "arg": "78385",
    "title": "Langacker 2009",
    "subtitle": "A dynamic view of usage and language acquisition",
    "icon": {"path": "file.png"}
},

{
    "uid": "88601",
    "arg": "88601",
    "title": "Langacker 2005",
    "subtitle": "Dynamicity, fictivity, and scanning",
    "icon": {"path": "file.png"}
},

{
    "uid": "38850",
    "arg": "38850",
    "title": "Chen 2017",
    "subtitle": "A rating of perceived exertion scale using facial expressions for conveying exercise intensity for children and young adults",
    "icon": {"path": "file.png"}
},

{
    "uid": "51190",
    "arg": "51190",
    "title": "Huang 2014",
    "subtitle": "Frowning and jaw clenching muscle activity reflects the perception of effort during incremental workload cycling",
    "icon": {"path": "file.png"}
},

{
    "uid": "65172",
    "arg": "65172",
    "title": "Langacker 1999",
    "subtitle": "Losing control: grammaticization, subjectification",
    "icon": {"path": "file.png"}
},

{
    "uid": "70801",
    "arg": "70801",
    "title": "Langacker 2003
",
    "subtitle": "Extreme subjectification: English tense and modals",
    "icon": {"path": "file.png"}
},

{
    "uid": "47149",
    "arg": "47149",
    "title": "Langacker 2011",
    "subtitle": "The English present: Temporal coincidence vs. epistemic immediacy",
    "icon": {"path": "file.png"}
},

{
    "uid": "79954",
    "arg": "79954",
    "title": "Huang 2017",
    "subtitle": "The Design Features of Pictorial Face Design for Facilitating Exertion Perception",
    "icon": {"path": "file.png"}
},

{
    "uid": "24906",
    "arg": "24906",
    "title": "Langacker 1987",
    "subtitle": "Nouns and verbs",
    "icon": {"path": "file.png"}
},

{
    "uid": "89596",
    "arg": "89596",
    "title": "Langacker 1995",
    "subtitle": "Raising and transparency",
    "icon": {"path": "file.png"}
},

{
    "uid": "29780",
    "arg": "29780",
    "title": "Langacker 2011",
    "subtitle": "Grammaticalization and cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "1442",
    "arg": "1442",
    "title": "Langacker 2003",
    "subtitle": "Constructions in cognitive grammar",
    "icon": {"path": "file.png"}
},

{
    "uid": "10410",
    "arg": "10410",
    "title": "Langacker 2001",
    "subtitle": "Topic, subject, and possessor",
    "icon": {"path": "file.png"}
}
]}

 

Link to comment

I've added my Powerpack email.

@iandol I have around 7000 references. I can only isolate one author, it turns out, for which the author search simply doesn’t work (i.e. returns no results). 'Arendt, Hannah', with no accents or diacritics. But I have a lot of references attached to her (she's the subject of a book I'm finishing): 290. I made a small test database with all those references, and with one reference from one other author, and the same problem occurs: here is the test DB: https://www.dropbox.com/s/b64xxbe5f8g2oel/Test.bdb?dl=0. When I remove say 200 of those references, the search works. So perhaps it's the sheer number of results returned that is the problem?

I'm afraid I don't have any terminal skills else I'd love to help with the other request.

The possibility of inputting the year to narrow the search further would be wonderful: I'm sorry I don't have any skills of use, but if there's any testing I could do please let me know.

Link to comment
1 hour ago, taja said:

So perhaps it's the sheer number of results returned that is the problem?

 

I bet it's not.

 

The problem is almost certainly the one I described in the post above yours: there's something about your dataset that the naïve, string-smushing JSON-generation code in the workflow can't handle.

 

If you open Alfred's debugger, set Log to "All Information", run your non-working search, and then paste the JSON into a JSON validator, I bet you it's not valid.

 

The problem isn't with your data, it's with the workflow. The proper fix is to remove the ad-hoc JSON generation from the workflow and use a proper JSON library instead.

 

Link to comment

deanishe is bang on the money (i.e. correct)! I inherited this Applescript which string constructed the results list, and it is vulnerable to stray characters like the Langacker 2003 reference above; the datefield has a newline in it. Your Arendt database also contains a malformed date in ref Arendt #76260 — you can find these in your database by using an SQL search (⌘⇧S) in Bookends with a query string: thedate REGEX '\n' — the date field in Bookends is not so easy to parse as you can put in a mix of month day year in any order but there is no need for a newline there. If you want to sort on date, you should always put year first...

 

Anyway, in the interim, I have fixed this so the newline or other stray characters are removed from the date field. You can redownload the workflow V1.1.1 or wait for the auto-updater to kick in. At least with your Arendt database it now works (takes about 4 seconds to parse all the Arendt refs into Alfred)

 

I planned to rewrite this script in Ruby, although I worry about the performance hit as it has to call many applescript events to pull data from Bookends. To stick to Applescript I don't want any external dependencies and I only found https://github.com/mgax/applescript-json  - @deanishe do you have any advice for a better JSON solution in Applescript?

Edited by iandol
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...