Merge branch 'feat/improve-insertion-cmds' into develop
This commit is contained in:
commit
338cf93f1e
2 changed files with 115 additions and 29 deletions
16
README.org
16
README.org
|
@ -51,14 +51,14 @@ anki-editor -- an Emacs package that helps you create Anki cards in Org-mode
|
||||||
|
|
||||||
** Command Cheatsheet
|
** Command Cheatsheet
|
||||||
|
|
||||||
| Command | Brief Description |
|
| Command | Brief Description |
|
||||||
|-----------------------------------------------+---------------------------------------------------------------|
|
|-----------------------------------------------+------------------------------------------------------|
|
||||||
| =anki-editor-submit= | Send notes in current buffer to Anki. |
|
| =anki-editor-submit= | Send notes in current buffer to Anki. |
|
||||||
| =anki-editor-insert-deck= | Insert a deck heading with the same level as current heading. |
|
| =anki-editor-insert-deck= | Insert a deck heading. |
|
||||||
| =anki-editor-insert-note= | Insert the skeleton of a note. |
|
| =anki-editor-insert-note= | Insert the skeleton of a note. |
|
||||||
| =anki-editor-insert-tags= | Insert a tag at point with autocompletion. |
|
| =anki-editor-insert-tags= | Insert a tag at point with autocompletion. |
|
||||||
| =anki-editor-export-heading-contents-to-html= | Export the contents of the heading at point to HTML. |
|
| =anki-editor-export-heading-contents-to-html= | Export the contents of the heading at point to HTML. |
|
||||||
| =anki-editor-convert-region-to-html= | Convert and replace region to HTML. |
|
| =anki-editor-convert-region-to-html= | Convert and replace region to HTML. |
|
||||||
|
|
||||||
|
|
||||||
*Since I'm not a native English speaker, let me know if there's any ambiguity or grammatical mistakes.*
|
*Since I'm not a native English speaker, let me know if there's any ambiguity or grammatical mistakes.*
|
||||||
|
|
128
anki-editor.el
128
anki-editor.el
|
@ -170,23 +170,46 @@ of that heading."
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun anki-editor-insert-deck (&optional prefix)
|
(defun anki-editor-insert-deck (&optional prefix)
|
||||||
"Insert a deck heading with the same level as current heading.
|
"Insert a deck heading.
|
||||||
With PREFIX, only insert the deck name."
|
With PREFIX, only insert the deck name at point."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(message "Fetching decks...")
|
(message "Fetching decks...")
|
||||||
(let ((decks (sort (anki-editor--anki-connect-invoke-result "deckNames" 5) #'string-lessp))
|
(let ((decks (sort (anki-editor--anki-connect-invoke-result "deckNames" 5) #'string-lessp))
|
||||||
deckname)
|
deckname)
|
||||||
(setq deckname (completing-read "Choose a deck: " decks))
|
(setq deckname (completing-read "Choose a deck: " decks))
|
||||||
(unless prefix (org-insert-heading-respect-content))
|
(if prefix
|
||||||
(insert deckname)
|
(insert deckname)
|
||||||
(unless prefix (anki-editor--set-tags-fix anki-editor-deck-tag))))
|
(let (inserted)
|
||||||
|
(anki-editor--visit-superior-headings
|
||||||
|
(lambda ()
|
||||||
|
(when (member anki-editor-deck-tag (org-get-tags))
|
||||||
|
(anki-editor--insert-deck-heading deckname)
|
||||||
|
(setq inserted t))))
|
||||||
|
|
||||||
|
(unless inserted
|
||||||
|
(anki-editor--insert-deck-heading deckname))))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun anki-editor-insert-note ()
|
(defun anki-editor-insert-note ()
|
||||||
"Insert the skeleton of a note.
|
"Insert the skeleton of a note.
|
||||||
|
|
||||||
The contents to be insrted are structured with a note heading
|
The contents to be insrted are structured with a note heading
|
||||||
that's one level lower to the current one as well as subheadings
|
along with subheadings that correspond to fields.
|
||||||
that correspond to fields."
|
|
||||||
|
Where the note is inserted depends on where the point is.
|
||||||
|
|
||||||
|
When the point is somewhere inside a note heading, the new note
|
||||||
|
is inserted below this note with same heading level.
|
||||||
|
|
||||||
|
Or when the point is outside any note heading but inside a
|
||||||
|
heading that isn't tagged with 'deck' but under a deck heading,
|
||||||
|
the new note is one level lower to and is inserted at the bottom
|
||||||
|
of this heading.
|
||||||
|
|
||||||
|
Or when the point is inside a deck heading, the behavior is the
|
||||||
|
same as above.
|
||||||
|
|
||||||
|
Otherwise, it's inserted at point."
|
||||||
(interactive)
|
(interactive)
|
||||||
(message "Fetching note types...")
|
(message "Fetching note types...")
|
||||||
(let ((note-types (sort (anki-editor--anki-connect-invoke-result "modelNames" 5) #'string-lessp))
|
(let ((note-types (sort (anki-editor--anki-connect-invoke-result "modelNames" 5) #'string-lessp))
|
||||||
|
@ -195,19 +218,39 @@ that correspond to fields."
|
||||||
(message "Fetching note fields...")
|
(message "Fetching note fields...")
|
||||||
(setq fields (anki-editor--anki-connect-invoke-result "modelFieldNames" 5 `((modelName . ,note-type)))
|
(setq fields (anki-editor--anki-connect-invoke-result "modelFieldNames" 5 `((modelName . ,note-type)))
|
||||||
note-heading (read-from-minibuffer "Enter the heading: " "Item"))
|
note-heading (read-from-minibuffer "Enter the heading: " "Item"))
|
||||||
(org-insert-heading-respect-content)
|
|
||||||
(org-do-demote)
|
;; find and go to the best position, then insert the note
|
||||||
(insert note-heading)
|
(let ((cur-point (point))
|
||||||
(anki-editor--set-tags-fix anki-editor-note-tag)
|
pt-of-grp
|
||||||
(org-set-property (substring (symbol-name anki-editor-prop-note-type) 1) note-type)
|
inserted)
|
||||||
(dolist (field fields)
|
(anki-editor--visit-superior-headings
|
||||||
(save-excursion
|
(lambda ()
|
||||||
(org-insert-heading-respect-content)
|
(let ((tags (org-get-tags)))
|
||||||
(org-do-demote)
|
(cond
|
||||||
(insert field)))
|
;; if runs into a note heading, inserts the note heading with
|
||||||
(org-next-visible-heading 1)
|
;; the same level
|
||||||
(end-of-line)
|
((member anki-editor-note-tag tags)
|
||||||
(newline-and-indent)))
|
(progn
|
||||||
|
(anki-editor--insert-note-skeleton note-heading note-type fields)
|
||||||
|
(setq inserted t)
|
||||||
|
t))
|
||||||
|
;; if runs into a deck heading, inserts the note heading one
|
||||||
|
;; level lower to current deck heading or to the group
|
||||||
|
;; heading that was visited before
|
||||||
|
((member anki-editor-deck-tag tags)
|
||||||
|
(progn
|
||||||
|
(when pt-of-grp (goto-char pt-of-grp))
|
||||||
|
(anki-editor--insert-note-skeleton note-heading note-type fields t)
|
||||||
|
(setq inserted t)
|
||||||
|
t))
|
||||||
|
;; otherwise, consider it as a group heading and save its
|
||||||
|
;; point for further consideration, then continue
|
||||||
|
(t (progn
|
||||||
|
(unless pt-of-grp (setq pt-of-grp (point)))
|
||||||
|
nil))))))
|
||||||
|
(unless inserted
|
||||||
|
(goto-char cur-point)
|
||||||
|
(anki-editor--insert-note-skeleton note-heading note-type fields)))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun anki-editor-insert-tags ()
|
(defun anki-editor-insert-tags ()
|
||||||
|
@ -246,7 +289,7 @@ that correspond to fields."
|
||||||
"Upgrade anki-connect to the latest version.
|
"Upgrade anki-connect to the latest version.
|
||||||
|
|
||||||
This will display a confirmation dialog box in Anki asking if you
|
This will display a confirmation dialog box in Anki asking if you
|
||||||
want to continue. The upgrading is done by downloading the latest
|
want to continue. The upgrading is done by downloading the latest
|
||||||
code in the master branch of its Github repo.
|
code in the master branch of its Github repo.
|
||||||
|
|
||||||
This is useful when new version of this package depends on the
|
This is useful when new version of this package depends on the
|
||||||
|
@ -259,6 +302,12 @@ bugfixes or new features of anki-connect."
|
||||||
|
|
||||||
;;; Core Functions
|
;;; Core Functions
|
||||||
|
|
||||||
|
(defun anki-editor--insert-deck-heading (deckname)
|
||||||
|
"Insert a deck heading with DECKNAME."
|
||||||
|
(org-insert-heading-respect-content)
|
||||||
|
(insert deckname)
|
||||||
|
(anki-editor--set-tags-fix anki-editor-deck-tag))
|
||||||
|
|
||||||
(defun anki-editor--process-note-heading (deck)
|
(defun anki-editor--process-note-heading (deck)
|
||||||
"Process note heading at point.
|
"Process note heading at point.
|
||||||
DECK is used when the action is note creation."
|
DECK is used when the action is note creation."
|
||||||
|
@ -276,6 +325,28 @@ DECK is used when the action is note creation."
|
||||||
(push `(deck . ,deck) note)
|
(push `(deck . ,deck) note)
|
||||||
(anki-editor--save-note note)))
|
(anki-editor--save-note note)))
|
||||||
|
|
||||||
|
(defun anki-editor--insert-note-skeleton (heading note-type fields &optional demote)
|
||||||
|
"Insert a note skeleton with HEADING, NOTE-TYPE and FIELDS.
|
||||||
|
If DEMOTE is t, demote the inserted note heading."
|
||||||
|
(org-insert-heading-respect-content)
|
||||||
|
(when demote (org-do-demote))
|
||||||
|
(insert heading)
|
||||||
|
(anki-editor--set-tags-fix anki-editor-note-tag)
|
||||||
|
(org-set-property (substring (symbol-name anki-editor-prop-note-type) 1) note-type)
|
||||||
|
(dolist (field fields)
|
||||||
|
(save-excursion
|
||||||
|
(org-insert-heading-respect-content)
|
||||||
|
(org-do-demote)
|
||||||
|
(insert field)))
|
||||||
|
|
||||||
|
;; TODO: Is it a good idea to automatically move to the first field
|
||||||
|
;; heading and open a new line ?
|
||||||
|
|
||||||
|
;; (org-next-visible-heading 1)
|
||||||
|
;; (end-of-line)
|
||||||
|
;; (newline-and-indent)
|
||||||
|
)
|
||||||
|
|
||||||
(defun anki-editor--save-note (note)
|
(defun anki-editor--save-note (note)
|
||||||
"Request anki-connect for updating or creating NOTE."
|
"Request anki-connect for updating or creating NOTE."
|
||||||
(if (= (alist-get 'note-id note) -1)
|
(if (= (alist-get 'note-id note) -1)
|
||||||
|
@ -446,6 +517,21 @@ DECK is used when the action is note creation."
|
||||||
(insert replacement)
|
(insert replacement)
|
||||||
(cons original replacement)))
|
(cons original replacement)))
|
||||||
|
|
||||||
|
(defun anki-editor--visit-superior-headings (visitor &optional level)
|
||||||
|
"Move point to and call VISITOR at each superior heading from point.
|
||||||
|
Don't pass LEVEL, it's only used in recursion.
|
||||||
|
Stops when VISITOR returns t or point reaches the beginning of buffer."
|
||||||
|
(let (stop)
|
||||||
|
(when (org-at-heading-p)
|
||||||
|
(let ((cur-level (car (org-heading-components))))
|
||||||
|
(when (or (null level) (< cur-level level))
|
||||||
|
(setq level cur-level
|
||||||
|
stop (funcall visitor)))))
|
||||||
|
(when (and (not stop) (/= (point) (point-min)))
|
||||||
|
(org-previous-visible-heading 1)
|
||||||
|
(anki-editor--visit-superior-headings visitor level))))
|
||||||
|
|
||||||
|
|
||||||
(provide 'anki-editor)
|
(provide 'anki-editor)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
Loading…
Reference in a new issue