Doc stuff
This commit is contained in:
parent
b6065cd2f7
commit
b8f6986ab9
2 changed files with 84 additions and 94 deletions
98
README.org
98
README.org
|
@ -1,40 +1,40 @@
|
|||
[[http://melpa.org/#/anki-editor][file:http://melpa.org/packages/anki-editor-badge.svg]]
|
||||
|
||||
anki-editor -- Emacs minor mode for making Anki cards with Org
|
||||
anki-editor -- An Emacs minor mode for making Anki cards with Org
|
||||
|
||||
/Since I'm not a native English speaker, feel free to correct me if
|
||||
there were any ambiguity or grammatical mistakes ;-)/
|
||||
there are any ambiguity or grammatical mistakes ;-)/
|
||||
|
||||
* Installation
|
||||
|
||||
*Requirements*
|
||||
- [[https://github.com/FooSoft/anki-connect#installation][anki-connect]],
|
||||
an Anki add-on required by this package to interact with Anki.
|
||||
- [[https://github.com/FooSoft/anki-connect#installation][AnkiConnect]],
|
||||
an Anki add-on required by this package to interact with Anki
|
||||
- curl
|
||||
|
||||
If you have [[http://melpa.org/][MELPA]] in your =package-archives=,
|
||||
just =M-x package-install RET anki-editor RET=, or install it
|
||||
If you have [[http://melpa.org/][MELPA]] in your ~package-archives~,
|
||||
just ~M-x package-install RET anki-editor RET~, or install it
|
||||
manually by downloading and visiting [[./anki-editor.el][anki-editor.el]] in your
|
||||
emacs buffer, and =M-x package-install-from-buffer RET=.
|
||||
emacs buffer, and ~M-x package-install-from-buffer RET~.
|
||||
|
||||
* Usage
|
||||
|
||||
** The Layout of Notes
|
||||
|
||||
Now you can compose Anki notes in Org syntax, e.g. lists, code
|
||||
examples, tables, embedded latex, when being submitted to Anki,
|
||||
they will be converted to HTML by Org-mode's HTML backend with
|
||||
specific markers (e.g. latex) translated to Anki style.
|
||||
The power of this mode comes from the builtin HTML export backend
|
||||
provided by Org, which enables you to use almost all the Org
|
||||
constructs for writing Anki notes: lists, code blocks, tables,
|
||||
latex and so on.
|
||||
|
||||
The structure of a note is as follow, which is inspired by
|
||||
=org-drill=. More examples can be found in [[./examples.org][examples.org]].
|
||||
The structure of a note is as follows, which is inspired by
|
||||
~org-drill~. Check out [[./examples.org][examples.org]] for more examples.
|
||||
|
||||
#+BEGIN_SRC org
|
||||
,* Idiom :vocab:idioms:
|
||||
,* Raining :vocab:idioms:
|
||||
:PROPERTIES:
|
||||
:ANKI_DECK: English
|
||||
:ANKI_NOTE_TYPE: Basic (and reversed card)
|
||||
:ANKI_TAGS: languages european_languages
|
||||
:ANKI_TAGS: vocab idioms
|
||||
:END:
|
||||
,** Front
|
||||
(it's) raining cats and dogs
|
||||
|
@ -42,35 +42,41 @@ there were any ambiguity or grammatical mistakes ;-)/
|
|||
it's raining very hard
|
||||
#+END_SRC
|
||||
|
||||
- An Anki note is an Org entry with =ANKI_NOTE_TYPE= property
|
||||
- Anki tags can be set in two ways
|
||||
1. With "ANKI_TAGS" property, multiple tags are separated with space
|
||||
2. With Org tags [fn:1], this could be turned off if you would like to keep Org tags separated from Anki tags
|
||||
- Other necessary information (e.g. deck, note type) of a note is
|
||||
put in the property drawer of the entry
|
||||
- As the value of =ANKI_DECK= is retrieved with inheritance, you
|
||||
don't have to set it per note, instead, you could create a deck
|
||||
entry with this property set and put note entries under it, or
|
||||
set it per file by ~#+PROPERTY: ANKI_DECK YourDeck~
|
||||
- Child entries of a note entry are fields
|
||||
- Anki deck is provided by ~ANKI_DECK~ property. This property is
|
||||
retrieved with inheritance, that is to say, it can be put in any
|
||||
ancestor entries or at top of the file by ~#+PROPERTY: ANKI_DECK
|
||||
DeckName~.
|
||||
- ~ANKI_NOTE_TYPE~ property is to specify the Anki note type of a
|
||||
note and is also required for identifying an Anki note entry.
|
||||
- Anki tags can be provided in two ways:
|
||||
1. With a ~ANKI_TAGS~ property, multiple tags are separated by spaces
|
||||
2. With Org tags [fn:1], this could be turned off if you would
|
||||
like to keep Org tags separated from Anki tags
|
||||
- Child entries of a note entry are fields.
|
||||
|
||||
Typing all these information by hand could be inefficient and prone
|
||||
to errors, so this package provides an interactive command
|
||||
~anki-editor-insert-note~ to help with this and hooks up
|
||||
auto-completions for decks, note types and tags etc.
|
||||
|
||||
** Commands
|
||||
|
||||
| Command | Brief Description |
|
||||
|------------------------------------+--------------------------------------------------------------------------------------|
|
||||
| anki-editor-push-notes | Push notes to Anki. Additional arguments can be used to restrict the range of notes. |
|
||||
| anki-editor-retry-failure-notes | Same as above, except that it only pushes notes that have =ANKI_FAILURE_REASON=. |
|
||||
| anki-editor-insert-note | Insert a note entry like =M-RET=, interactively. |
|
||||
| anki-editor-cloze-region | Create a cloze deletion from region. |
|
||||
| anki-editor-export-subtree-to-html | Export the subtree at point to HTML. |
|
||||
| anki-editor-convert-region-to-html | Convert and replace region to HTML. |
|
||||
|
||||
** Functions
|
||||
|
||||
| Name | Description |
|
||||
|------------------------------+------------------------------------------------------------|
|
||||
| anki-editor-map-note-entries | Simple wrapper that calls =org-map-entries=. |
|
||||
| anki-editor-note-at-point | Construct an alist representing a note from current entry. |
|
||||
| Command | Description |
|
||||
|------------------------------------+---------------------------------------------------------------------------------------------------|
|
||||
| anki-editor-mode | Toggle this minor mode. |
|
||||
| anki-editor-push-notes | Push notes to Anki. Additional arguments can be used to restrict the range of notes. |
|
||||
| anki-editor-push-new-notes | Similar to ~anki-editor-push-notes~, but push those that are without ~ANKI_NOTE_ID~. |
|
||||
| anki-editor-retry-failed-notes | Similar to ~anki-editor-push-notes~, except that it only pushes notes with ~ANKI_FAILURE_REASON~. |
|
||||
| anki-editor-insert-note | Insert a note entry like ~M-RET~, interactively. |
|
||||
| anki-editor-delete-notes | Delete notes or the note at point. |
|
||||
| anki-editor-cloze-dwim | Cloze current active region or a word the under the cursor. |
|
||||
| anki-editor-export-subtree-to-html | Export the subtree at point to HTML. |
|
||||
| anki-editor-convert-region-to-html | Convert and replace region to HTML. |
|
||||
| anki-editor-anki-connect-check | Check if correct version of AnkiConnect is running. |
|
||||
| anki-editor-anki-connect-upgrade | Upgrade AnkiConnect. |
|
||||
| anki-editor-sync-collections | Synchronize your local anki collection. |
|
||||
| anki-editor-gui-browse | Open Anki Browser with a query for current note or deck. |
|
||||
| anki-editor-gui-add-cards | Open Anki Add Cards dialog with presets from current note entry. |
|
||||
|
||||
** Variables
|
||||
|
||||
|
@ -83,6 +89,7 @@ there were any ambiguity or grammatical mistakes ;-)/
|
|||
| anki-editor-ignored-org-tags | '("export" "noexport") | A list of Org tags that are ignored when constructing notes form entries. |
|
||||
| anki-editor-org-tags-as-anki-tags | t | If nil, tags of entries wont't be counted as Anki tags. |
|
||||
| anki-editor-protected-tags | '("marked" "leech") | A list of tags that won't be deleted from Anki even though they're absent in Org entries. |
|
||||
| anki-editor-use-math-jax | nil | Use Anki's built in MathJax support instead of LaTeX. |
|
||||
|
||||
* Limitations
|
||||
|
||||
|
@ -94,15 +101,14 @@ there were any ambiguity or grammatical mistakes ;-)/
|
|||
|
||||
** Working with Anki add-ons
|
||||
|
||||
This package may not work well when you are using certain Anki
|
||||
add-ons especially those who extend the builtin Anki note editor to
|
||||
This package might not work well with certain Anki add-ons
|
||||
especially those who extend the builtin Anki note editor to
|
||||
automatically fill note field content (e.g. ~Add note id~).
|
||||
|
||||
* Troubleshooting
|
||||
|
||||
In case of a failed operation and this package doesn't provide much
|
||||
useful information, especially for note creation, don't be
|
||||
frustrated, see below for some hints.
|
||||
useful information, don't be frustrated, see below for some hints.
|
||||
|
||||
1. Decks don't exist in Anki. This package by default doesn't create
|
||||
decks for you, when trying out this package with ~examples.org~,
|
||||
|
@ -139,5 +145,5 @@ there were any ambiguity or grammatical mistakes ;-)/
|
|||
|
||||
|
||||
[fn:1] It should be noted that Org only allows letters, numbers, =_=
|
||||
and =@= in a tag but Anki allows more, so you may have to edit you
|
||||
and ~@~ in a tag but Anki allows more, so you may have to edit you
|
||||
Anki tags before they can be used in Org without any surprise.
|
||||
|
|
|
@ -11,20 +11,18 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; This package is for users of both Emacs and Anki, who'd like to
|
||||
;; make Anki cards in Org mode. With this package, Anki cards can be
|
||||
;; made from an Org buffer like below: (inspired by org-drill)
|
||||
;;
|
||||
;; This package is for people who use Anki as SRS but would like to
|
||||
;; make cards in Org-mode.
|
||||
;;
|
||||
;; With this package, you can make cards from something like:
|
||||
;; (which is inspired by `org-dirll')
|
||||
;;
|
||||
;; * Item :emacs:lisp:programming:
|
||||
;; * Sample :emacs:lisp:programming:
|
||||
;; :PROPERTIES:
|
||||
;; :ANKI_DECK: Computing
|
||||
;; :ANKI_NOTE_TYPE: Basic
|
||||
;; :END:
|
||||
;; ** Front
|
||||
;; How to hello world in elisp ?
|
||||
;; How to say "hello world" in elisp?
|
||||
;; ** Back
|
||||
;; #+BEGIN_SRC emacs-lisp
|
||||
;; (message "Hello, world!")
|
||||
|
@ -32,13 +30,13 @@
|
|||
;;
|
||||
;; This package extends Org-mode's built-in HTML backend to generate
|
||||
;; HTML for contents of note fields with specific syntax (e.g. latex)
|
||||
;; translated to Anki style, then save the note to Anki.
|
||||
;; translated to Anki style.
|
||||
;;
|
||||
;; For this package to work, you have to setup these external dependencies:
|
||||
;; - curl
|
||||
;; - AnkiConnect, an Anki addon that runs an HTTP server to expose
|
||||
;; Anki functions as RESTful APIs, see
|
||||
;; https://github.com/FooSoft/anki-connect#installation
|
||||
;; - AnkiConnect, an Anki addon that runs an RPC server over HTTP to expose
|
||||
;; Anki functions as APIs,
|
||||
;; see https://github.com/FooSoft/anki-connect#installation
|
||||
;; for installation instructions
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -93,16 +91,19 @@ See https://apps.ankiweb.net/docs/manual.html#latex-conflicts.")
|
|||
|
||||
(defcustom anki-editor-org-tags-as-anki-tags
|
||||
t
|
||||
"If nil, tags of entries wont't be counted as Anki tags.")
|
||||
"If nil, tags of entries won't be counted as Anki tags.")
|
||||
|
||||
(defcustom anki-editor-protected-tags
|
||||
'("marked" "leech")
|
||||
"A list of tags that won't be deleted from Anki even though they're absent in Org entries, such as special tags `marked', `leech'."
|
||||
"A list of tags that won't be deleted from Anki even though
|
||||
they're absent in Org entries, such as special tags `marked',
|
||||
`leech'."
|
||||
:type '(repeat string))
|
||||
|
||||
(defcustom anki-editor-ignored-org-tags
|
||||
(append org-export-select-tags org-export-exclude-tags)
|
||||
"A list of Org tags that are ignored when constructing notes form entries."
|
||||
"A list of Org tags that are ignored when constructing notes
|
||||
form entries."
|
||||
:type '(repeat string))
|
||||
|
||||
(defcustom anki-editor-anki-connect-listening-address
|
||||
|
@ -142,31 +143,23 @@ See https://apps.ankiweb.net/docs/manual.html#latex-conflicts.")
|
|||
(request-backend 'curl)
|
||||
(json-array-type 'list)
|
||||
reply err)
|
||||
|
||||
(let ((response (request (format "http://%s:%s"
|
||||
anki-editor-anki-connect-listening-address
|
||||
anki-editor-anki-connect-listening-port)
|
||||
:type "POST"
|
||||
:parser 'json-read
|
||||
:data request-body
|
||||
:success (cl-function (lambda (&key data &allow-other-keys)
|
||||
(setq reply data)))
|
||||
:error (cl-function (lambda (&key _ &key error-thrown &allow-other-keys)
|
||||
(setq err (string-trim (cdr error-thrown)))))
|
||||
:sync t)))
|
||||
|
||||
;; HACK: With sync set to t, `request' waits for curl process to
|
||||
;; exit, then response data becomes available, but callbacks
|
||||
;; might not be called right away but at a later time, that's
|
||||
;; why here we manually invoke callbacks to receive the result.
|
||||
(unless (request-response-done-p response)
|
||||
(request--curl-callback (get-buffer-process (request-response--buffer response)) "finished\n")))
|
||||
|
||||
(request (format "http://%s:%s"
|
||||
anki-editor-anki-connect-listening-address
|
||||
anki-editor-anki-connect-listening-port)
|
||||
:type "POST"
|
||||
:parser 'json-read
|
||||
:data request-body
|
||||
:success (cl-function (lambda (&key data &allow-other-keys)
|
||||
(setq reply data)))
|
||||
:error (cl-function (lambda (&key _ &key error-thrown &allow-other-keys)
|
||||
(setq err (string-trim (cdr error-thrown)))))
|
||||
:sync t)
|
||||
(when err (error "Error communicating with AnkiConnect using cURL: %s" err))
|
||||
(or reply (error "Got empty reply from AnkiConnect"))))
|
||||
|
||||
(defmacro anki-editor--anki-connect-invoke-result (&rest args)
|
||||
"Invoke AnkiConnect with ARGS, return the result from response or raise an error."
|
||||
"Invoke AnkiConnect with ARGS, return the result from response
|
||||
or raise an error."
|
||||
`(let-alist (anki-editor--anki-connect-invoke ,@args)
|
||||
(when .error (error .error))
|
||||
.result))
|
||||
|
@ -380,7 +373,8 @@ The implementation is borrowed and simplified from ox-html."
|
|||
;;; Core Functions
|
||||
|
||||
(defun anki-editor-map-note-entries (func &optional match scope &rest skip)
|
||||
"Simple wrapper that calls `org-map-entries' with `&ANKI_NOTE_TYPE<>\"\"' appended to MATCH."
|
||||
"Simple wrapper that calls `org-map-entries' with
|
||||
`&ANKI_NOTE_TYPE<>\"\"' appended to MATCH."
|
||||
;; disable property inheritance temporarily, or all subheadings of a
|
||||
;; note heading will be counted as note headings as well
|
||||
(let ((org-use-property-inheritance nil))
|
||||
|
@ -391,7 +385,6 @@ The implementation is borrowed and simplified from ox-html."
|
|||
Where the subtree is created depends on PREFIX."
|
||||
(org-insert-heading prefix)
|
||||
(insert heading)
|
||||
|
||||
(unless (save-excursion
|
||||
(org-up-heading-safe)
|
||||
;; don't insert `ANKI_DECK' if some ancestor already has
|
||||
|
@ -399,9 +392,7 @@ Where the subtree is created depends on PREFIX."
|
|||
(and (not (string-blank-p deck))
|
||||
(string= deck (org-entry-get-with-inheritance anki-editor-prop-deck))))
|
||||
(org-set-property anki-editor-prop-deck deck))
|
||||
|
||||
(org-set-property anki-editor-prop-note-type note-type)
|
||||
|
||||
(dolist (field fields)
|
||||
(save-excursion
|
||||
(org-insert-heading-respect-content)
|
||||
|
@ -426,12 +417,10 @@ Where the subtree is created depends on PREFIX."
|
|||
(funcall queue
|
||||
'createDeck
|
||||
`((deck . ,(alist-get 'deck note)))))
|
||||
|
||||
(funcall queue
|
||||
'addNote
|
||||
`((note . ,(anki-editor--anki-connect-map-note note)))
|
||||
#'anki-editor--set-note-id)
|
||||
|
||||
(funcall queue)))
|
||||
|
||||
(defun anki-editor--update-note (note)
|
||||
|
@ -440,7 +429,6 @@ Where the subtree is created depends on PREFIX."
|
|||
(funcall queue
|
||||
'updateNoteFields
|
||||
`((note . ,(anki-editor--anki-connect-map-note note))))
|
||||
|
||||
(funcall queue
|
||||
'notesInfo
|
||||
`((notes . (,(alist-get 'note-id note))))
|
||||
|
@ -454,19 +442,15 @@ Where the subtree is created depends on PREFIX."
|
|||
(alist-get 'tags note))
|
||||
anki-editor-protected-tags))
|
||||
(tag-queue (anki-editor--anki-connect-invoke-queue)))
|
||||
|
||||
(when tags-to-add
|
||||
(funcall tag-queue
|
||||
'addTags `((notes . (,(alist-get 'note-id note)))
|
||||
(tags . ,(mapconcat #'identity tags-to-add " ")))))
|
||||
|
||||
(when tags-to-remove
|
||||
(funcall tag-queue
|
||||
'removeTags `((notes . (,(alist-get 'note-id note)))
|
||||
(tags . ,(mapconcat #'identity tags-to-remove " ")))))
|
||||
|
||||
(funcall tag-queue))))
|
||||
|
||||
(funcall queue)))
|
||||
|
||||
(defun anki-editor--set-failure-reason (reason)
|
||||
|
@ -638,7 +622,7 @@ name and the cdr of which is field content."
|
|||
;;; Commands
|
||||
|
||||
(defun anki-editor-push-notes (&optional scope match)
|
||||
"Build notes from headings that can be matched by MATCH within SCOPE and push them to Anki.
|
||||
"Build notes from headings that match MATCH within SCOPE and push them to Anki.
|
||||
|
||||
The default search condition `&ANKI_NOTE_TYPE<>\"\"' will always
|
||||
be appended to MATCH.
|
||||
|
|
Loading…
Reference in a new issue