Allow updating of deck, add support for omitting a field
Also fix some bugs and add `anki-editor-push-note-at-point'.
This commit is contained in:
parent
8aa42d9435
commit
ccd7f77322
1 changed files with 78 additions and 14 deletions
|
@ -7,7 +7,7 @@
|
||||||
;; Version: 0.3.3
|
;; Version: 0.3.3
|
||||||
;; Package-Requires: ((emacs "25.1"))
|
;; Package-Requires: ((emacs "25.1"))
|
||||||
;; URL: https://github.com/louietan/anki-editor
|
;; URL: https://github.com/louietan/anki-editor
|
||||||
;;
|
;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
@ -513,12 +513,17 @@ Where the subtree is created depends on PREFIX."
|
||||||
(anki-editor--set-note-id)))
|
(anki-editor--set-note-id)))
|
||||||
|
|
||||||
(defun anki-editor--update-note (note)
|
(defun anki-editor--update-note (note)
|
||||||
"Request AnkiConnect for updating fields and tags of NOTE."
|
"Request AnkiConnect for updating fields, deck, and tags of NOTE."
|
||||||
(let* ((oldnote (caar (anki-editor-api-with-multi
|
(let* ((oldnote (caar (anki-editor-api-with-multi
|
||||||
(anki-editor-api-enqueue 'notesInfo
|
(anki-editor-api-enqueue 'notesInfo
|
||||||
:notes (list (anki-editor-note-id note)))
|
:notes (list (string-to-number
|
||||||
|
(anki-editor-note-id note))))
|
||||||
(anki-editor-api-enqueue 'updateNoteFields
|
(anki-editor-api-enqueue 'updateNoteFields
|
||||||
:note (anki-editor-api--note note)))))
|
:note (anki-editor-api--note note))
|
||||||
|
(anki-editor-api-enqueue 'changeDeck
|
||||||
|
:cards (list (string-to-number (anki-editor-note-id note)))
|
||||||
|
:deck (anki-editor-note-deck note))
|
||||||
|
)))
|
||||||
(tagsadd (cl-set-difference (anki-editor-note-tags note)
|
(tagsadd (cl-set-difference (anki-editor-note-tags note)
|
||||||
(alist-get 'tags oldnote)
|
(alist-get 'tags oldnote)
|
||||||
:test 'string=))
|
:test 'string=))
|
||||||
|
@ -528,11 +533,13 @@ Where the subtree is created depends on PREFIX."
|
||||||
(anki-editor-api-with-multi
|
(anki-editor-api-with-multi
|
||||||
(when tagsadd
|
(when tagsadd
|
||||||
(anki-editor-api-enqueue 'addTags
|
(anki-editor-api-enqueue 'addTags
|
||||||
:notes (list (anki-editor-note-id note))
|
:notes (list (string-to-number
|
||||||
|
(anki-editor-note-id note)))
|
||||||
:tags (mapconcat #'identity tagsadd " ")))
|
:tags (mapconcat #'identity tagsadd " ")))
|
||||||
(when tagsdel
|
(when tagsdel
|
||||||
(anki-editor-api-enqueue 'removeTags
|
(anki-editor-api-enqueue 'removeTags
|
||||||
:notes (list (anki-editor-note-id note))
|
:notes (list (string-to-number
|
||||||
|
(anki-editor-note-id note)))
|
||||||
:tags (mapconcat #'identity tagsdel " "))))))
|
:tags (mapconcat #'identity tagsdel " "))))))
|
||||||
|
|
||||||
(defun anki-editor--set-failure-reason (reason)
|
(defun anki-editor--set-failure-reason (reason)
|
||||||
|
@ -610,19 +617,72 @@ Where the subtree is created depends on PREFIX."
|
||||||
(tags (cl-set-difference (anki-editor--get-tags)
|
(tags (cl-set-difference (anki-editor--get-tags)
|
||||||
anki-editor-ignored-org-tags
|
anki-editor-ignored-org-tags
|
||||||
:test #'string=))
|
:test #'string=))
|
||||||
(fields (anki-editor--build-fields)))
|
(fields (anki-editor--build-fields))
|
||||||
|
(content-before-subheading)
|
||||||
|
(content-before-subheading-raw))
|
||||||
|
|
||||||
|
;; get contents before first subheading (skipping drawers and planning)
|
||||||
|
;; FIXME refactor
|
||||||
|
(save-excursion
|
||||||
|
(let* ((begin (cl-loop for eoh = (org-element-property :contents-begin (org-element-at-point))
|
||||||
|
then (org-element-property :end subelem)
|
||||||
|
for subelem = (progn
|
||||||
|
(goto-char eoh)
|
||||||
|
(org-element-context))
|
||||||
|
while (memq (org-element-type subelem)
|
||||||
|
'(drawer planning property-drawer))
|
||||||
|
finally return (org-element-property :begin subelem)))
|
||||||
|
(end (cl-loop for eoh = (org-element-property :end (org-element-at-point))
|
||||||
|
then (org-element-property :end nextelem)
|
||||||
|
for nextelem = (progn
|
||||||
|
(goto-char eoh)
|
||||||
|
(org-element-at-point))
|
||||||
|
while (not (memq (org-element-type nextelem) '(headline)))
|
||||||
|
finally return (org-element-property :begin nextelem)
|
||||||
|
))
|
||||||
|
(raw (or (and begin
|
||||||
|
end
|
||||||
|
(buffer-substring-no-properties
|
||||||
|
begin
|
||||||
|
;; in case the buffer is narrowed,
|
||||||
|
;; e.g. by `org-map-entries' when
|
||||||
|
;; scope is `tree'
|
||||||
|
(min (point-max) end)))
|
||||||
|
""))
|
||||||
|
(content (anki-editor--export-string raw (anki-editor-entry-format))))
|
||||||
|
|
||||||
|
(setq content-before-subheading content)
|
||||||
|
(setq content-before-subheading-raw (string-trim raw))
|
||||||
|
))
|
||||||
|
|
||||||
(anki-editor--with-collection-data-updated
|
(anki-editor--with-collection-data-updated
|
||||||
(when-let ((missing (cl-set-difference
|
(when-let ((missing (cl-set-difference
|
||||||
(alist-get note-type anki-editor--model-fields nil nil #'string=)
|
(alist-get note-type anki-editor--model-fields nil nil #'string=)
|
||||||
(mapcar #'car fields)
|
(mapcar #'car fields)
|
||||||
:test #'string=)))
|
:test #'string=)))
|
||||||
;; use heading as the missing field
|
;; use heading and/or text before subheading for the missing field(s)
|
||||||
(push (cons (car missing)
|
;; FIXME refactor
|
||||||
(anki-editor--export-string
|
(if (and (equal 1 (length missing))
|
||||||
(substring-no-properties (org-get-heading t t t))
|
(equal "" content-before-subheading-raw))
|
||||||
format))
|
(push (cons (car missing)
|
||||||
fields)))
|
(anki-editor--export-string
|
||||||
|
(substring-no-properties (org-get-heading t t t))
|
||||||
|
format))
|
||||||
|
fields)
|
||||||
|
(if (equal 1 (length missing))
|
||||||
|
(push (cons (car missing)
|
||||||
|
content-before-subheading)
|
||||||
|
fields)
|
||||||
|
(progn
|
||||||
|
(push (cons (nth 1 missing)
|
||||||
|
content-before-subheading)
|
||||||
|
fields)
|
||||||
|
(push (cons (car missing)
|
||||||
|
(anki-editor--export-string
|
||||||
|
(substring-no-properties (org-get-heading t t t))
|
||||||
|
format))
|
||||||
|
fields))))))
|
||||||
|
|
||||||
|
|
||||||
(unless deck (error "Missing deck"))
|
(unless deck (error "Missing deck"))
|
||||||
(unless note-type (error "Missing note type"))
|
(unless note-type (error "Missing note type"))
|
||||||
|
@ -650,7 +710,7 @@ Where the subtree is created depends on PREFIX."
|
||||||
(defun anki-editor--build-fields ()
|
(defun anki-editor--build-fields ()
|
||||||
"Build a list of fields from subheadings of current heading.
|
"Build a list of fields from subheadings of current heading.
|
||||||
|
|
||||||
Return a list of cons of (FIELD-NAME . FIELD-CONTENT)."
|
Return a list of cons of (FIELD-NAME . FIELD-CONTENT)."
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(cl-loop with inhibit-message = t ; suppress echo message from `org-babel-exp-src-block'
|
(cl-loop with inhibit-message = t ; suppress echo message from `org-babel-exp-src-block'
|
||||||
initially (unless (org-goto-first-child)
|
initially (unless (org-goto-first-child)
|
||||||
|
@ -813,6 +873,10 @@ When you have fixed those issues, try re-push the failed ones with `anki-editor-
|
||||||
do (set-marker m nil)
|
do (set-marker m nil)
|
||||||
finally do (setq anki-editor--note-markers nil))))
|
finally do (setq anki-editor--note-markers nil))))
|
||||||
|
|
||||||
|
(defun anki-editor-push-note-at-point ()
|
||||||
|
(interactive)
|
||||||
|
(anki-editor--push-note (anki-editor-note-at-point)))
|
||||||
|
|
||||||
(defun anki-editor-push-new-notes (&optional scope)
|
(defun anki-editor-push-new-notes (&optional scope)
|
||||||
"Push note entries without ANKI_NOTE_ID in SCOPE to Anki."
|
"Push note entries without ANKI_NOTE_ID in SCOPE to Anki."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
|
Loading…
Reference in a new issue