org-anki icon indicating copy to clipboard operation
org-anki copied to clipboard

org-anki can't make `ANKI_NOTE_ID` property correctly with `with-current-buffer`

Open hwiorn opened this issue 2 years ago • 6 comments

  • Emacs version: 28.2
  • org version: Org mode version 9.6 (9.6-??-bed47b437)
  • org-anki version: 1.0.4 and latest (1.0.5)

test.org

#+ANKI_DECK: TestDeck
org-anki Batch Test

* Front
Back

Test code

(with-current-buffer (find-file-noselect "~/test.org")
  (org-mode)
  (save-excursion
    (goto-char (point-max))
    (org-anki-sync-entry))
  (save-buffer))

The code makes an anki card but can't make ANKI_NOTE_ID property at the heading. Emacs shows the org-fold-region: Calling ‘org-fold-core-region’ with missing SPEC error. And :PROPERTY:\n:END: is printed in the beginning of scratch buffer. I'm not sure. But My guess is that the message is that org seems to try parsing Users' current buffer which is scratch-buffer.

hwiorn avatar Nov 18 '22 15:11 hwiorn

After some digging, I found the cause of this issue is that org-anki uses anki-connect API request as asynchronous call. So, org-anki-sync-entry can't org-set-property in the buffer which is closed already.

@eyeinsky Is there any other way to solve this? emacs-request provides :sync keyword only. I feel buffer-local variable is a more reasonable option for this issue.

hwiorn avatar Nov 19 '22 13:11 hwiorn

I thought adding sync buffer-local variables fix this issue simply. But I found that org-anki is using emacs-promise as well as emacs-request.

Actually buffer-name is changed to *scratch* from test.org when then clause of promise-chain is executed.

https://github.com/eyeinsky/org-anki/blob/dda524d582d11d4f5317091da7335350d2d66640/org-anki.el#L434-L443

In addition, I found this https://github.com/chuntaro/emacs-promise/issues/13

According to the above issue, The below with-current-buffer clause has a same potential issue.

https://github.com/eyeinsky/org-anki/blob/dda524d582d11d4f5317091da7335350d2d66640/org-anki.el#L542-L548

hwiorn avatar Nov 20 '22 16:11 hwiorn

How did you come about in running in to this, do you run an elisp script to sync certain files without having the files themselves open?

I think I did manage to reproduce it by having test.org closed, then running the test code above from the M-: (eval-expression) minibuffer prompt.

eyeinsky avatar Nov 20 '22 20:11 eyeinsky

How did you come about in running in to this, do you run an elisp script to sync certain files without having the files themselves open?

Yes. I'm writing the code to generate and sync anki cards from part of my org files which have :ANKI: tag automatically without user interaction. I, sometimes, forget to sync anki after editing bunch of my prompts following org-roam backlinks. I figure out batch ankifying is really useful if prompts are prepared already in the org files. You can see the test code is just simplyfing the error case. It's not real usecase.

I think I did manage to reproduce it by having test.org closed, then running the test code above from the M-: (eval-expression) minibuffer prompt.

Yes. Ensure the test file is closed and call the test code from scratch buffer or M-x <org-anki-sync-batch>(if you defined as an interactive function).

hwiorn avatar Nov 21 '22 01:11 hwiorn

I managed to handle this. In order to solve this issue, it needs the synchronous emacs-promise and the synchronous emacs-request. sync request can be solved by #56. But emacs-promise side, it needs await of the async-await module. async-await doesn't block main thread. I think async-await can be applied into org-anki.

After applying #56, You can make an anki card using below code.

(require 'async-await)
(funcall (async-lambda () 
                      (with-current-buffer (find-file-noselect "~/test.org")
                        (org-mode)
                        (setq org-anki-sync-request t)
                          (save-excursion
                            (goto-char (point-max))
                            (await (org-anki-sync-entry)))
                          (save-buffer)
                          (kill-buffer))
                        (message "done")))

hwiorn avatar Nov 29 '22 11:11 hwiorn

I'm running into the same problem: even though calling org-anki-sync-entry succeeds and the note is created in anki, no ANKI_NOTE_ID property is created at the header.

I'm on emacs 29, org-mode 9.6-??-bed47b4

threddast avatar Jan 20 '23 11:01 threddast