Calling `org-ref-open-bibtex-notes` triggers "Which function for creating the link" question

Hi all,

First, a non-perfunctory thanks to everyone contributing to this project. I’m quite new to this but so far I’m having a blast.

Whenever I try to create a new org-roam note from a .bib file, using org-ref-open-bibtex-notes, I’m asked the question “Which function for creating the link?”. The options are org-ref-bibtex-store-link and org-bibtex-store-link. Has anyone else encountered this behavior?

From what I can tell, this question is being asked by org-store-link, which is being called by orb-notes-fn at some point—org-ref-open-bibtex-notes is calling org-ref-notes-function, which org-roam-bibtex sets to orb-notes-fn. I know very little Elisp, but from going over the definitions of the relevant functions I couldn’t figure out why this choice between the two *-store-link functions is coming in. I just want to be able to answer that question once and for all.

(I tried setting up org-ref without org-roam-bibtex but I failed, so it could be that the issue has nothing to do with org-roam-bibtex, in which case I apologize.)

Hi @apc, welcome!

I cannot reproduce this behaviour. Typing M-x org-ref-open-bibtex-notes when in a record in a .bib file brings up Org Roam note creation dialog.

orb-note-fn does not call org-store-link, it calls org-ref-find-bibliography. The first thing the latter does is checking whether you are in a .bib file, and if you are, returns that filename and exits.

Are you sure you’re calling org-ref-open-bibtex-notes and not something else, for example with a default keychord that has been rebound to something else?

You can also try M-x org-ref-bibtex-hydra/body and then choose n: Open notes - it should run the same function.

Thanks!

Yes, I’m sure I’m calling org-ref-open-bibtex-notes. Running M-x org-ref-bibtex-hydra/body and then n also asks me to pick a function.

I’ve searched around my elpa dir and the only place I can find the string Which function for is inside org-plus-contrib-20200928/ol.elc.

Here’s the org-ref and org-roam related bits of my config, in case it helps:

(use-package org-ref
  :defer nil
  :config
  (setq org-ref-bibiliography-notes '("~/org/notebook/")
        org-ref-default-bibliography '("~/bib/apcmaster.bib")
        org-ref-pdf-directory "~/Document/Papers")
  )

;;;;;;; Org-roam and (Deft)

(use-package org-roam
  :hook
  (after-init . org-roam-mode)
  :custom
  (make-directory "~/org/notebook")
  (org-roam-directory "~/org/notebook")
  (org-roam-dailies-capture-templates '(("d" "daily" plain (function org-roam-capture--get-point) ""
                                         :immediate-finish t
                                         :file-name "dailies/%<%Y-%m-%d>"
                                         :head "#+TITLE: %<%Y-%m-%d>")))
  (org-roam-capture-templates
      '(("d" "default" plain (function org-roam--capture-get-point)
         "%?"
         :file-name "%<%Y%m%d%H%M%S>"
         :head "#+TITLE: ${title}\n"
         :unnarrowed t)))
  :bind (:map org-roam-mode-map
              (("C-c n l" . org-roam)
               ("C-c n r" . org-roam-find-ref)
               ("C-c n g" . org-roam-show-graph)
               ("C-c n i" . org-roam-insert)
               ("C-c n I" . org-roam-insert-immediate))
              :map org-mode-map
              (("C-c n c" . org-roam-capture)
               ("C-c n f" . org-roam-find-file)))
  )

(use-package org-roam-bibtex
  :after org-roam
  :hook (org-roam-mode . org-roam-bibtex-mode)
  :bind (:map org-mode-map
              (("C-c n a" . orb-note-actions))))

This must be it. Org Ref is a tricky package to load properly. With :defer nil you load it immediately upon Emacs startup. Org Ref requires Org and thus when it is loaded too early both the built-in Org shipped with Emacs and a newer Melpa version are loaded simultaneously leading to all kinds of issues.

Try this:

(use-package org-ref
  :after org
  ...)

Or this:

(use-package org-ref
  :hook 
  (org-load . (lambda () (require 'org-ref))  
  ...)

Note that if you compile your init file or your Emacs configuration framework such as Doom or Spacemacs does it, you will need to recompile it. Recompilation/reinstallation of Org mode, Org Ref and other Org-related packages may also be required.

To be on the safe side, you should also load Org Roam after Org:

(use-package org-roam
  :hook
  (org-load . org-roam-mode)
  ...)

Thanks again for your help. Unfortunately, this isn’t making much of a difference. I basically replaced my org-roam-bibtex related config with this, following your advice:


;;;;;;; Org-ref

(use-package org-ref
  :hook
  (org-load . (lambda () (require 'org-ref)))
  :config
  (setq org-ref-bibiliography-notes '("~/org/notebook/")
        org-ref-default-bibliography '("~/bib/apcmaster.bib")
        org-ref-pdf-directory "~/Document/Papers")
  ;; (org-ref-completion-library 'org-ref-ivy-cite-completion)
  )

;;;;;;; Org-roam and (Deft)

(use-package org-roam
  :hook
  (org-load . org-roam-mode)
  :custom
  (make-directory "~/org/notebook")
  (org-roam-directory "~/org/notebook")
  (org-roam-dailies-capture-templates '(("d" "daily" plain (function org-roam-capture--get-point) ""
                                         :immediate-finish t
                                         :file-name "dailies/%<%Y-%m-%d>"
                                         :head "#+TITLE: %<%Y-%m-%d>")))
  (org-roam-capture-templates
      '(("d" "default" plain (function org-roam--capture-get-point)
         "%?"
         :file-name "%<%Y%m%d%H%M%S>"
         :head "#+TITLE: ${title}\n"
         :unnarrowed t)))
         ;; :immediate-finish t)))
  :bind (:map org-roam-mode-map
              (("C-c n l" . org-roam)
               ("C-c n r" . org-roam-find-ref)
               ("C-c n g" . org-roam-show-graph)
               ("C-c n i" . org-roam-insert)
               ("C-c n I" . org-roam-insert-immediate))
              :map org-mode-map
              (("C-c n c" . org-roam-capture)
               ("C-c n f" . org-roam-find-file)))
  )

(use-package org-roam-bibtex
  :after org-roam
  ;; :hook org-roam-mode;; This should work instead of the code below, but it just doesn't. Weird.
  :hook (org-roam-mode . org-roam-bibtex-mode)
  :bind (:map org-mode-map
              (("C-c n a" . orb-note-actions))))

(use-package deft
      :after org
      :bind
      (:map org-mode-map ("C-c n d" . deft))
      :custom
      (deft-recursive t)
      (deft-use-filter-string-for-filename t)
      (deft-default-extension "org")
      (deft-directory  "~/org/notebook")
      (deft-strip-summary-regexp "\\([\n ]\\|^#\\+[[:upper:][:lower:]_]+:.*$\\)"))

To be safe, I then deleted everything inside my elpa directory so that all packages would be reinstalled. I still get the same behavior.

I should add that I did try to step through org-ref-open-bibtex-notes, but not knowing much about how to work with the debugger, I’m not sure if what I am pasting below is of much help.

Debugger entered--returning value: "[[file:~/Library/texmf/bibtex/bib/apc/apcmaster.bi..."
  org-store-link(nil)
  org-capture(nil "r")
  org-roam-capture--capture()
  orb-edit-notes("joyce2018")
  orb-notes-fn("joyce2018")
  #f(compiled-function () (interactive nil) #<bytecode 0x1fec9df59e61>)()
  apply(#f(compiled-function () (interactive nil) #<bytecode 0x1fec9df59e61>) nil)
* org-ref-open-bibtex-notes()
  funcall-interactively(org-ref-open-bibtex-notes)
  call-interactively(org-ref-open-bibtex-notes record nil)
  command-execute(org-ref-open-bibtex-notes record)
  counsel-M-x-action("org-ref-open-bibtex-notes")

It seems that org-store-link is being called by org-capture, which is being called by org-roam-capture--capture. It’s only when org-store-link is being called, it seems, that I’m prompted to answer the question “Which function…”.

It helps a lot actually. Your system is working properly and behaving exactly as you told it to :slight_smile:

The following is happening. orb-notes-fn does its part and happily delegates creation of your note to org-capture. Org capture is a complex process. Not only it captures what you explicitly told it to do, but also as much of the context as it can — according to its specification. Among those captured things is an Org-style link to the location context you initiated the org-capture process from. The BibTeX file in your particular case. Different location contexts have different functions for creating Org-style links associated with them, and many external packages define their own functions for their specific tasks. Usually, there is no more than one function for each context. In your runtime environment, however, there are two alternative functions, org-ref-bibtex-store-link and org-bibtex-store-link, that can be used to create an Org link to a BibTeX file. The former comes from the Org Ref package, the latter is defined in the ol-bibtex Org module. Having two functions available, org-capture cannot decide on its own which one to use and asks you to make the choice.

There are several possibilities to fix this behaviour:

  1. Don’t use the ol-bibtex module (org-ref I guess is out of question)
  2. Keep ol-bibtex and org-bibtex-store-link, advise the org-ref-generate-cite-links function not to call org-link-set-parameters. This should be done before org-ref is loaded.
  3. Advise or re-write orb-edit-fn so that it temporarily sets org-capture-link-is-already-stored to t. This must be done after org-roam-bibtex is loaded:
(defun orb-edit-fn (citekey)
  (when (require 'org-ref nil t)
    (let ((bibtex-completion-bibliography (org-ref-find-bibliography))
           ;; trick `org-capture` to believe the link is already stored
           (org-capture-link-is-already-stored t) ) 
      (orb-edit-notes citekey)))

Note that in this case you won’t be able to meaningfully use the “annotation” feature (%a and %A wildcards) of org-capture in your orb-templates because it will always return nil.

Edit:
4. According to how org-store-link works, you can also redefine either org-ref-bitex-store-link or org-bibtex-store-link to return nil:

;; keep `org-ref-bibtex-store-link'
(defun org-bibtex-store-link () nil)

;; keep `org-bibtex-store-link'
(defun org-ref-bibtex-store-link () nil)

The other function will then be used automatically.

2 Likes

Thank you! This is incredibly helpful.

I’ll go with option 4 for now, since I don’t know how to avoid loading ol-bibtex short of not loading org-plus-contrib (if you do know off the top of your head, I’d love to know!). I don’t use org-bibtex-store-link anywhere else AFAIK, so that should fix things.

Again, many thanks for your patience and your help!

1 Like

Ι’m glad to help.

It depends on how you load org-plus-contrib. It’s not a package as such but rather a collection of small packages. As far as I know, you must explicitly load its files one by one by setting the org-modules variable or simply (require ...). Could it be possible that you have org-modules loading ol-bibtex somewhere in your config?

I’m using use-package and have :ensure org-plus-contrib in my org declaration.

I thought that was what was loading ol-bibtex, since I don’t call it anywhere else on my config. But I just removed that line, manually removed org-plus-contrib from package-selected-packages, restarted Emacs, and C-h v for org-modules still includes ol-bibtex (together with a bunch of other stuff). I will try just dumping everything inside my elpa directory and try downloading all packages from scratch.

EDIT: I did just that (i.e. deleted everything inside elpa/) and I still have org-modules include ol-bibtex. I searched through my elpa/ and discovered that doi-utils.el (which comes as part of org-ref) has the following at line 60:

(or (require 'ol-bibtex nil t)
    (require 'org-bibtex)) ; org-bibtex-yank

Could this be the culprit?

Can I just manually remove ol-bibtex from the org-modules list? (Is there something that does the opposite of add-to-list?)

Thanks again!

Ahaha, that’s why I call org-ref a tricky package. Yes, this is it.

I actually can confirm it on my system as well. I must apologize because I obviously didn’t try to reproduce the issue thoroughly enough - I just ran the org-ref-open-bibtex-notes and after the filename prompt appeared, assumed I didn’t run into it.

If you have ol-bibtex in org-modules, it is there by default actually, you must remove it before loading Org like this:

(use-package 'org
  :init
  (setq org-modules (remove 'ol-bibtex org-modules))
  ...)

But this will not solve the issue because you have to deal with org-ref also requiring ol-bibtex.

Let me think it out.

That isn’t really necessary. Your system is fine.

Thanks! Could I place org-ref-open-bibtex-notes in a wrapper that uses let to temporarily set org-bibtex-store-link to nil? Seems like this would cause the least amount of interference with the functionality of org-ref

You can temporarily set to nil a variable, but org-bibtex-store-link is a function, so you must either redefine it or advise.

Advising is more flexible:


;; define a dummy function
(defun org-bibtex-store-link-return-nil ()
"Advice for `org-bibtex-store-link' to do nothing and return nil"
nil)

;; advise `org-bibtex-store-link to be overriden by `org-bibtex-store-link-return-nil
(advice-add #'org-bibtex-store-link
  :override #'org-bibtex-store-link-return-nil)

;; to remove the advice evaluate this:
(advice-remove #'org-bibtex-store-link
     :override #'org-bibtex-store-link-return-nil)

Since the issue also affects ORB users, and ORB positions itself to provide a smooth integration between BibTeX and note taking, I’m now considering to handle this in ORB. But it will have to wait a couple of days.

1 Like

Great! Thanks again. I’ll stay tuned to see what you come up with.

1 Like

@apc, you can now upgrade to the latest master. ORB handles this situation by default. You can set functions that you want to suppress in orb-ignore-bibtex-store-link-functions (org-bibtex-store-link is suppressed by default).

1 Like

Thanks for the update! Works great so far!

1 Like