tmalsburg/helm-bibtex

[Feature] Non-interactive extraction of bibkeys

Closed this issue · 22 comments

Can I use a predefined search string (as in the example with helm-bibtex-my-publications) and have that function return a list of bibkeys?

I'm not aware of a solution for but it may very well be possible. It's a question for people who know more about Helm than I do.

What I would do is the following: Get a list of all entries with (bibtex-completion-candidates). Then filter out the relevant entries yourself in a loop, similar to this.

Thanks. I was more thinking of combining the steps that I would do manually otherwise in helm-bibtex, i.e.,

  1. run something like helm-bibtex-my-publications
  2. select all entries
  3. and insert bibtex keys

Since my elisp skills are not worth writing home about I don't really see how I would do this in elisp. Any hints would be appreciated.

Ah, I see. You can use the code snippet here and replace Jane Doe by whatever your search string is. Then call this command, select all entries with M-a. Then hit the TAB key to select actions and choose "Insert BibTeX key". Done.

Thank you, that works great. And can I do that also without user interaction, by just running code?

And can I do that also without user interaction, by just running code?

Probably but I don't know how. Automating helm searches is something that other people probably tried before, so it may be worth checking on Emacs Stack Exchange.

Please let me know if you find a solution. I will include it in the documentation since it could be useful for other as well. Thanks.

I'll probably end up using a python solution that I'll be executing in org mode, i.e. bibtexparser and pymongo. John Kitchin has some nice code examples here that appear to work well. My ultimate aim is a cv + publication list in org mode that is automatically updated and built with a Makefile and then exported to LaTeX/pdf. I will post it on my github soon.

I use org for my CV, too. No python or helm-bibtex are needed for publications. Biblatex has support for filters and multiple bibliographies in one document (e.g., journal articles, conference posters, etc.). Here's my code for the section with journal articles:

** Journal articles:
\nocite{StoneEtAl2020, PaapeEtAl2020, MorganEtAl2020, MalsburgEtAl2020, SchotterEtAl2018, SchotterEtAl2018b, MalsburgAngele2016, MetznerEtAl2016, MetznerEtAl2015N400, MalsburgEtAl2015, VasishthEtAl2013, MalsburgVasishth2013, MaruschEtAl2012, MalsburgVasishth2011}
\printbibliography[keyword=article,notkeyword=submitted,keyword=own,heading=none]

Thanks, yes, I think I have a similar solution too already, where I manually add the bibkeys of my publications. But what I'm trying to do is to automatically update the publication list with items that have been added to my bibtex file, basically anything that is tagged as "first author", "last author", "coauthor". Admittedly, it is a bit of an overkill since I really don't publish all that much and could probably do this manually, but it happens occasionally that I miss a talk that I gave or a paper that I coauthored, and it would be nice to have those items added to the list automatically. Makes sense?

Or wait, is your \printbibliography already doing that, with the filters? I should probably really look into Biblatex, haven't used it before.

That does make sense and I, too, sometimes forget to add something to my publications. But are we sure there is no way to achieve this with just biblatex?

Or wait, is your \printbibliography already doing that, with the filters? I should probably really look into Biblatex, haven't used it before.

No, you still need to individually reference each publication with \nocite. The filters just make sure that this section only displays journal articles and nothing else that was referenced via \nocite elsewhere.

Unfortunately I know next to nothing about biblatex. But with this elisp code I manage to retrieve all bibkeys of my bib file, so adding some filtering would probably do the trick.

(defun get-bibtex-keys ()
  (mapcar #'(lambda (x) (cdr (assoc "=key=" x)))
  (bibtex-completion-candidates)))

Your elisp code is not too far from the solution. Recipe: First filter the entries such that you only have entries with your name in the authors string and the publication is of the desired type, then extract the BibTeX keys from the remaining entries. If I had more time I'd write it spell it out but I have to prepare lectures. Sorry.

Thanks, but for some reason I can't figure out how to do the "filter the entries" part ...

The dash.el package makes these things relatively easy. See here.

Thanks. I think I'm almost there:

(-filter (lambda(string) (string-match-p "mystring" string))
         (mapcar #'(lambda (x) (car x)) (bibtex-completion-candidates)))

I just don't see how I would apply this filter and at the same time retrieve just the keys.

Probably not very elegant but I think this works:

(defun get-bibtex-key (searchstr)
(setq key " \\(\\w*....\\)$")
(setq f (-filter (lambda(string) (string-match-p searchstr string))
         (mapcar #'(lambda (x) (car x)) (bibtex-completion-candidates))))
(setq l  (mapcar #'(lambda (x) (save-match-data
                                 (and (string-match key (format "%s" (last x)))
                                      (match-string 1 (format "%s" (last x)))))) f)))

Here you go:

(seq-map
 (lambda (entry)
   (cdr (assoc "=key=" (cdr entry))))
 (seq-filter
  (lambda (entry)
    (string-match-p "Savage" (or (cdr (assoc "author" (cdr entry))) "")))
  (bibtex-completion-candidates)))

This returns the list of all keys where the author list contains "Savage". This solution uses seq.el instead of dash.el. The former is part of recent Emacs so you don't need an extra package.

Amazing, thanks so much! I adapted it slightly to search for author and tags:

(defun get-bibkeys (searchstr)
(seq-map
 (lambda (entry)
   (cdr (assoc "=key=" (cdr entry))))
 (seq-filter
   (lambda (entry)
     (string-match-p searchstr (or (car entry) "")))
  (bibtex-completion-candidates))))

Last question (I promise): is it possible to sort the entries by year?

Last question (I promise): is it possible to sort the entries by year?

Not with my code. But it's probably easy to extend your function above with sorting.

Something like this:

(sort (bibtex-completion-candidates)
      (lambda (entry1 entry2)
        (< (string-to-number (or (cdr (assoc "year" (cdr entry1))) "0"))
           (string-to-number (or (cdr (assoc "year" (cdr entry2))) "0")))))