Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
hwiorn opened this issue Nov 18, 2022 · 6 comments · May be fixed by #56
Open

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

hwiorn opened this issue Nov 18, 2022 · 6 comments · May be fixed by #56

Comments

@hwiorn
Copy link

hwiorn commented Nov 18, 2022

  • 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
Copy link
Author

hwiorn commented Nov 19, 2022

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
Copy link
Author

hwiorn commented Nov 20, 2022

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.

org-anki/org-anki.el

Lines 434 to 443 in dda524d

(defun org-anki--sync-notes (notes)
;; :: [Note] -> IO ()
"Syncronize NOTES."
(if notes
(promise-chain
(org-anki--existing-tags notes)
(then
(lambda (all-existing-tags)
(let*

In addition, I found this chuntaro/emacs-promise#13

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

org-anki/org-anki.el

Lines 542 to 548 in dda524d

(defun org-anki-sync-all (&optional buffer)
;; :: Maybe Buffer -> IO ()
"Syncronize all entries in optional BUFFER."
(interactive)
(with-current-buffer (or buffer (buffer-name))
(org-anki--sync-notes
(org-map-entries 'org-anki--note-at-point (org-anki--get-match) nil org-anki-skip-function))))

@eyeinsky
Copy link
Owner

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.

@hwiorn
Copy link
Author

hwiorn commented Nov 21, 2022

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 hwiorn linked a pull request Nov 29, 2022 that will close this issue
@hwiorn
Copy link
Author

hwiorn commented Nov 29, 2022

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")))

@threddast
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants