louietan / anki-editor

Emacs minor mode for making Anki cards with Org
699 stars 87 forks source link

Shorter possibility to set Front and Back #59

Open leoc opened 4 years ago

leoc commented 4 years ago

Default Front to note name if the Front field is not defined.

That way we could write:

* How much is the fish?
** Front
How much is the fish?
** Back
This much!

as

* How much is the fish?
** Back
This much.

Much love. I will try to look into this this weekend. But maybe this functionality exists already.

Cheers!

leoc commented 4 years ago

Yesterday I have played around a bit:

(setq anki-editor-quick-field-mapping '(("Basic" . ("Front" . nil))))

(defun anki-editor-get-quick-fields ()
  ""
  (interactive)
  (let* (quick-fields
         (note-heading (org-element-at-point))
         (note-title (org-element-property :title note-heading))
         (note-type (org-element-property :ANKI_NOTE_TYPE note-heading))
         (quick-field-mapping (alist-get note-type anki-editor-quick-field-mapping 'equal))
         (title-field (car quick-field-mapping))
         (contents-field (cdr quick-field-mapping))
         (contents-begin (org-element-property :contents-begin note-heading))
         (contents-end (org-element-property :contents-end note-heading))
     (point-of-first-child (- (save-excursion
                    (if (org-goto-first-child)
                    (point)
                      (point-max)))
                  1)))
    (when title-field
      (map-put quick-fields
           title-field
           (org-export-string-as note-title
                                     anki-editor--ox-anki-html-backend
                                     t
                                     anki-editor--ox-export-ext-plist)
           'equal))
    (when contents-field
      (map-put quick-fields
           contents-field
           (cond
                ((and contents-begin contents-end)
                 (org-export-string-as
                  (buffer-substring
                   contents-begin
                   ;; in case the buffer is narrowed,
                   ;; e.g. by `org-map-entries' when
                   ;; scope is `tree'
                   (min (point-max) contents-end point-of-first-child))
                  anki-editor--ox-anki-html-backend
                  t
                  anki-editor--ox-export-ext-plist))
                (t ""))
           'equal))
    quick-fields))

(defun anki-editor--build-fields ()
  "Build a list of fields from subheadings of current heading, each element of which is a cons cell, the car of which is field name and the cdr of which is field content."
  (save-excursion
    (let ((fields (anki-editor-get-quick-fields))
          (point-of-last-child (point)))
      (when (org-goto-first-child)
        (while (/= point-of-last-child (point))
          (setq point-of-last-child (point))
          (let* ((inhibit-message t)  ;; suppress echo message from `org-babel-exp-src-block'
                 (field-heading (org-element-at-point))
                 (field-name (substring-no-properties
                              (org-element-property
                               :raw-value
                               field-heading)))
                 (contents-begin (org-element-property :contents-begin field-heading))
                 (contents-end (org-element-property :contents-end field-heading)))

            (map-put fields
             field-name
             (cond
                      ((and contents-begin contents-end) (or (org-export-string-as
                                                              (buffer-substring
                                                               contents-begin
                                                               ;; in case the buffer is narrowed,
                                                               ;; e.g. by `org-map-entries' when
                                                               ;; scope is `tree'
                                                               (min (point-max) contents-end))
                                                              anki-editor--ox-anki-html-backend
                                                              t
                                                              anki-editor--ox-export-ext-plist)

                                                             ;; 8.2.10 version of
                                                             ;; `org-export-filter-apply-functions'
                                                             ;; returns nil for an input of empty string,
                                                             ;; which will cause AnkiConnect to fail
                                                             ""))
                      (t ""))
             'equal)
            (org-forward-heading-same-level nil t))))
      (reverse fields))))

I tried to allow the contents of the heading to be associated with the Back field via:

(setq anki-editor-quick-field-mapping '(("Basic" . ("Front" . "Back"))))

But I do not know yet, how to export the contents of the heading without the properties drawer. Maybe you have an idea.

Maybe you have some hints. I will create a pull request after I played around a bit.

Edit: Nice! I found that

(setq anki-editor--ox-export-ext-plist '(:with-toc nil :anki-editor-mode t :with-drawers nil))

Hides the drawers correctly. I will prepare a pull request as soon as I can.

matiya commented 4 years ago

Yes please! I would also use something like this.

louietan commented 4 years ago

Sorry for the delay. I was focusing on my personal stuff last few months.

I would say this is really a good idea. I always find it's tricky to come up with a name for every note and sometimes I have to write the same content in heading and front field, so I was also thinking about a solution to this.

Your experimentation looks good, but it requires configuration for mapping between fields and note types. An alternative I prefer is just comparing the number of expected fields with the actual number of subtrees under the note to find out the missing field and use note heading as that field. I have implemented the idea in the develop branch, go check it out to see if that works for you.

leoc commented 4 years ago

Thanks @louietan

This means that I would still have to keep a Back heading for each card? How would anki-editor know which is Front and which is Back?

I think your solution is okay for cards with more than two fields, because then we can check the missing field name. For two fields we still need configurability, no?

My solution allows to write:

* My question for the Front field
My content for the Back field
wedens commented 4 years ago

I agree that it'd be great to be able to use heading as "front" and content under the heading as "back".

I have a lot of .org files that I can't use in either anki-editor or org-drill because they require structural changes :/

memeplex commented 2 years ago

Why not just:

* Front
Back