1

I'm trying to use request.el but have no clue what I'm doing. What I want to do is create a request to Zotero that uses their citation picker using the to get a 'Cite As You Write' capability using the Better Bibtex For Zotero backend.

I have gotten this working with a do-applescript function, but it sporadically just stops working, and I get the error Emacs is not allows to send keystrokes. I have gone and reset the security preferences numerous times, and ensured the the Info.plist has the proper permissions, but I still get this error sporadically.

Can anyone guide me through the process of what I need to do? The relevant url to call is "/usr/bin/curl 'http://localhost:23119/better-bibtex/cayw?format=pandoc' 2>/dev/null; exit 0". I have tested it in the scratch buffer and got the popup citation picker once (see picture). However, when I selected the references it changed focus to the Zotero apps search box, and that's as far as I got.

screenshot

Subsequent requests have failed, and I get the following error:

Debugger entered--Lisp error: (void-function request)
  (request "http://localhost:23119/better-bibtex/cayw?format=pandoc 2>/dev/null; exit 0")
  eval((request "http://localhost:23119/better-bibtex/cayw?format=pandoc 2>/dev/null; exit 0") nil)
  elisp--eval-last-sexp(nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  #<subr call-interactively>(eval-last-sexp nil nil)
  apply(#<subr call-interactively> eval-last-sexp (nil nil))
  (let ((ido-cr+-current-command command)) (apply orig-fun command args))
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> eval-last-sexp nil nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (eval-last-sexp nil nil))
  call-interactively(eval-last-sexp nil nil)
  command-execute(eval-last-sexp)

I'm sorry, but this is coming across as very much a "can you do this for me" as I don't have a clue what I'm doing.


So I got it working again thanks to @lawlist, and the message I get is:

(fn &rest ARGS2)"] :url "http://localhost:23119/better-bibtex/cayw?format=pandoc 2>/dev/null; exit 0" :response #0 :encoding utf-8) #<buffer  *request curl*> nil nil ...)

Any idea how to get this working?

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Type `C-x C-b` and then navegate to the buffer `*request curl*` or the same thing, but with a leading space that makes the buffer *uninteresting* so to speak, and see if it contains what it is that you seek. Perhaps the buffer is being created with the desired data, but is simply not being displayed in the manner desired .... – lawlist Jan 16 '20 at 08:17
  • Thanks again @lawlist, but I don't see any bugger `*request curl*`... Is this was I'm supposed to see? – Atanas Janackovski Jan 16 '20 at 12:17

2 Answers2

1

Whenever an Emacs user receives an error message like void-function request, it generally means the function has not yet been defined because the library containing that function has not been loaded. If, for example, the function at issue is named request and it is defined in the library request.el, then before using the library, evaluate the following statement:

(require 'request)

That statement can also be placed inside the .emacs / init.el file if you will be using the library fairly frequently in the future.

The library request.el should be placed within a file folder in the Emacs load-path so that Emacs knows where to look for it.

lawlist
  • 18,826
  • 5
  • 37
  • 118
  • Thanks @lawlist, I got it working again in the `scratch` buffer. Sorry, so new to Emacs, still getting my head around everything. Would you have any tips on how to proceed to achieve the goal of pasting citations into a buffer via the `Zotero` citation picker? – Atanas Janackovski Jan 16 '20 at 03:18
  • In general, each thread should contain one discrete question. Your thread contains multiple questions ... a forum participant such as myself can zero in on one aspect, whereas another forum participant can zero in on another. The result is multiple answers, with neither being entirely comprehensive. .... I would need to take a look at Zotero with a cup of coffee in hand on a new date ... You can decide whether to edit the question, or launch a new question, or .... it's entirely up to you. – lawlist Jan 16 '20 at 03:58
  • Thanks @lawlist, I really am green here. I'll edit a more specific question. Cheers. – Atanas Janackovski Jan 16 '20 at 04:14
1

/usr/bin/curl 'http://localhost:23119/better-bibtex/cayw?format=pandoc' 2>/dev/null; exit 0

This is a shell command consisting two commands (curl and exit), here is another way to write it

/usr/bin/curl 'http://localhost:23119/better-bibtex/cayw?format=pandoc'
exit 0

thus the URL is http://localhost:23119/better-bibtex/cayw?format=pandoc, to fetch the URL and insert its contents into Emacs buffer, an easy way for new Emacs user is

(insert
 (shell-command-to-string
  "curl -s 'http://localhost:23119/better-bibtex/cayw?format=pandoc'"))

(The -s (or --silent) option tells curl not to print progress meter.) shell-command-to-string consumes a shell command and produces its output, for example,

(shell-command-to-string "date")
;; =>
"Thu Jan 16 20:03:09 CST 2020
"

insert consumes a string and insert it at current cursor.

If the above code works for you, then you can wrap it as an Emacs command, e.g.,

(defun zotero-cite ()
  "Insert Zotero Cite at point."
  (interactive)
  (insert
   (shell-command-to-string
    "curl -s 'http://localhost:23119/better-bibtex/cayw?format=pandoc'")))

now you can use M-x zotero-cite, you can also assign a key binding if you prefer

(global-set-key (kbd "C-c C-c") 'zotero-cite)

Instead of curl, Emacs has built HTTP client library (that is, url.el) and third part package request.el, but you need to be familiar with Emacs Lisp and HTTP in order to use them.

xuchunyang
  • 14,302
  • 1
  • 18
  • 39
  • You are a legend! That works great, thanks so much. It inserts the citations exactly as expected. However, the cursor ends up in the `Zotero` search window and `Emacs` is not the top most app. Any ideas how to return the focus back to `Emacs` prior to the function completing? – Atanas Janackovski Jan 16 '20 at 12:39
  • @AtanasJanackovski `(do-applescript "tell application \"Emacs\" to activate")` works for me, put it right after `(insert (shell-command-to-string ...))`. – xuchunyang Jan 16 '20 at 13:54
  • that is awesome and looks so simple, when you know what you're doing... Thanks so much. I cannot endorse any of these answers, but consider it answered! Is there any way to get an error message if the app isn't open or installed? – Atanas Janackovski Jan 17 '20 at 11:44