Reduce duplication in latex functions

This commit is contained in:
louie 2019-11-03 17:24:00 +08:00 committed by louie
parent df2a90c9b8
commit 1feb3becc3

View file

@ -64,19 +64,6 @@
(require 'ox) (require 'ox)
(require 'ox-html) (require 'ox-html)
(defconst anki-editor-prop-note-type "ANKI_NOTE_TYPE")
(defconst anki-editor-prop-note-id "ANKI_NOTE_ID")
(defconst anki-editor-prop-exporter "ANKI_EXPORTER")
(defconst anki-editor-prop-deck "ANKI_DECK")
(defconst anki-editor-prop-tags "ANKI_TAGS")
(defconst anki-editor-prop-tags-plus (concat anki-editor-prop-tags "+"))
(defconst anki-editor-prop-failure-reason "ANKI_FAILURE_REASON")
(defconst anki-editor-buffer-html-output "*AnkiEditor HTML Output*")
(defconst anki-editor-org-tag-regexp "^\\([[:alnum:]_@#%]+\\)+$")
(defconst anki-editor-exporter-raw "raw")
(defconst anki-editor-exporter-default "default")
(defconst anki-editor-api-version 5)
(defgroup anki-editor nil (defgroup anki-editor nil
"Customizations for anki-editor." "Customizations for anki-editor."
:group 'org) :group 'org)
@ -117,6 +104,8 @@ form entries."
;;; AnkiConnect ;;; AnkiConnect
(defconst anki-editor-api-version 5)
(cl-defun anki-editor--fetch (url (cl-defun anki-editor--fetch (url
&rest settings &rest settings
&key type data success error parser &key type data success error parser
@ -246,95 +235,68 @@ The result is the path to the newly stored media file."
media-file-name)) media-file-name))
;;; Org Export Backend ;;; Org export backend
(defconst anki-editor--ox-anki-html-backend (defconst anki-editor--ox-anki-html-backend
(if anki-editor-use-math-jax
(org-export-create-backend
:parent 'html
:transcoders '((latex-fragment . anki-editor--ox-latex-for-mathjax)
(latex-environment . anki-editor--ox-latex-for-mathjax)))
(org-export-create-backend (org-export-create-backend
:parent 'html :parent 'html
:transcoders '((latex-fragment . anki-editor--ox-latex) :transcoders '((latex-fragment . anki-editor--ox-latex)
(latex-environment . anki-editor--ox-latex))))) (latex-environment . anki-editor--ox-latex))))
(defconst anki-editor--ox-export-ext-plist (defconst anki-editor--ox-export-ext-plist
'(:with-toc nil :anki-editor-mode t)) '(:with-toc nil :anki-editor-mode t))
(defun anki-editor--translate-latex-delimiters (latex-code) (cl-macrolet ((with-table (table)
(catch 'done `(cl-loop for delims in ,table
(let ((delimiter-map (list (list (cons (format "^%s" (regexp-quote "$$")) "[$$]") collect
(cons (format "%s$" (regexp-quote "$$")) "[/$$]")) (list (concat "^" (regexp-quote (cl-first delims)))
(list (cons (format "^%s" (regexp-quote "$")) "[$]") (cl-second delims)
(cons (format "%s$" (regexp-quote "$")) "[/$]")) (concat (regexp-quote (cl-third delims)) "$")
(list (cons (format "^%s" (regexp-quote "\\(")) "[$]") (cl-fourth delims)))))
(cons (format "%s$" (regexp-quote "\\)")) "[/$]"))
(list (cons (format "^%s" (regexp-quote "\\[")) "[$$]")
(cons (format "%s$" (regexp-quote "\\]")) "[/$$]"))))
(matched nil))
(save-match-data
(dolist (pair delimiter-map)
(dolist (delimiter pair)
(when (setq matched (string-match (car delimiter) latex-code))
(setq latex-code (replace-match (cdr delimiter) t t latex-code))))
(when matched (throw 'done latex-code)))))
latex-code))
(defun anki-editor--translate-latex-delimiters-to-anki-mathjax-delimiters (latex-code) (defconst anki-editor--native-latex-delimiters
(catch 'done (with-table '(("$$" "[$$]"
(let ((delimiter-map (list (list (cons (format "^%s" (regexp-quote "$$")) "\\[") "$$" "[/$$]")
(cons (format "%s$" (regexp-quote "$$")) "\\]")) ("$" "[$]"
(list (cons (format "^%s" (regexp-quote "$")) "\\(") "$" "[/$]")
(cons (format "%s$" (regexp-quote "$")) "\\)")))) ("\\(" "[$]"
(matched nil)) "\\)" "[/$]")
(save-match-data ("\\[" "[$$]"
(dolist (pair delimiter-map) "\\]" "[/$$]"))))
(dolist (delimiter pair)
(when (setq matched (string-match (car delimiter) latex-code))
(setq latex-code (replace-match (cdr delimiter) t t latex-code))))
(when matched (throw 'done latex-code)))))
latex-code))
(defun anki-editor--wrap-latex (content) (defconst anki-editor--mathjax-delimiters
"Wrap CONTENT with Anki-style latex markers." (with-table '(("$$" "\\["
(format "<p><div>[latex]</div>%s<div>[/latex]</div></p>" content)) "$$" "\\]")
("$" "\\("
"$" "\\)")))))
(defun anki-editor--wrap-latex-for-mathjax (content) (defun anki-editor--translate-latex-fragment (latex-code)
"Wrap CONTENT for Anki's native MathJax support." (let ((table (if anki-editor-use-math-jax
(format "<p>%s</p>" content)) anki-editor--mathjax-delimiters
anki-editor--native-latex-delimiters)))
(cl-loop for delims in table
for matches = (string-match (cl-first delims) latex-code)
when matches
do
(setq latex-code (replace-match (cl-second delims) t t latex-code))
(string-match (cl-third delims) latex-code)
(setq latex-code (replace-match (cl-fourth delims) t t latex-code))
until matches
finally return latex-code)))
(defun anki-editor--wrap-div (content) (defun anki-editor--translate-latex-env (latex-code)
(format "<div>%s</div>" content)) (setq latex-code (replace-regexp-in-string "\n" "<br>" (org-html-encode-plain-text latex-code)))
(if anki-editor-use-math-jax
(concat "\\[<br>" latex-code "\\]")
(concat "[latex]<br>" latex-code "[/latex]")))
(defun anki-editor--ox-latex (latex _contents _info) (defun anki-editor--ox-latex (latex _contents _info)
"Transcode LATEX from Org to HTML. "Transcode LATEX from Org to HTML.
CONTENTS is nil. INFO is a plist holding contextual information." CONTENTS is nil. INFO is a plist holding contextual information."
(let ((code (org-remove-indentation (org-element-property :value latex)))) (let ((code (org-remove-indentation (org-element-property :value latex))))
(setq code (setq code (cl-ecase (org-element-type latex)
(pcase (org-element-type latex) (latex-fragment (anki-editor--translate-latex-fragment code))
('latex-fragment (anki-editor--translate-latex-delimiters code)) (latex-environment (anki-editor--translate-latex-env code))))
('latex-environment (anki-editor--wrap-latex
(mapconcat #'anki-editor--wrap-div
(split-string (org-html-encode-plain-text code) "\n")
"")))))
(if anki-editor-break-consecutive-braces-in-latex
(replace-regexp-in-string "}}" "} } " code)
code)))
(defun anki-editor--ox-latex-for-mathjax (latex _contents _info)
"Transcode LATEX from Org to HTML.
CONTENTS is nil. INFO is a plist holding contextual information."
(let ((code (org-remove-indentation (org-element-property :value latex))))
(setq code
(pcase (org-element-type latex)
('latex-fragment (anki-editor--translate-latex-delimiters-to-anki-mathjax-delimiters code))
('latex-environment (anki-editor--wrap-latex-for-mathjax
(mapconcat #'anki-editor--wrap-div
(split-string (org-html-encode-plain-text code) "\n")
"")))))
(if anki-editor-break-consecutive-braces-in-latex (if anki-editor-break-consecutive-braces-in-latex
(replace-regexp-in-string "}}" "} } " code) (replace-regexp-in-string "}}" "} } " code)
code))) code)))
@ -342,7 +304,6 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(defun anki-editor--ox-html-link (oldfun link desc info) (defun anki-editor--ox-html-link (oldfun link desc info)
"When LINK is a link to local file, transcodes it to html and stores the target file to Anki, otherwise calls OLDFUN for help. "When LINK is a link to local file, transcodes it to html and stores the target file to Anki, otherwise calls OLDFUN for help.
The implementation is borrowed and simplified from ox-html." The implementation is borrowed and simplified from ox-html."
(or (catch 'giveup (or (catch 'giveup
(unless (plist-get info :anki-editor-mode) (unless (plist-get info :anki-editor-mode)
(throw 'giveup nil)) (throw 'giveup nil))
@ -405,7 +366,18 @@ The implementation is borrowed and simplified from ox-html."
(funcall oldfun link desc info))) (funcall oldfun link desc info)))
;;; Core Functions ;;; Core primitives
(defconst anki-editor-prop-note-type "ANKI_NOTE_TYPE")
(defconst anki-editor-prop-note-id "ANKI_NOTE_ID")
(defconst anki-editor-prop-exporter "ANKI_EXPORTER")
(defconst anki-editor-prop-deck "ANKI_DECK")
(defconst anki-editor-prop-tags "ANKI_TAGS")
(defconst anki-editor-prop-tags-plus (concat anki-editor-prop-tags "+"))
(defconst anki-editor-prop-failure-reason "ANKI_FAILURE_REASON")
(defconst anki-editor-org-tag-regexp "^\\([[:alnum:]_@#%]+\\)+$")
(defconst anki-editor-exporter-raw "raw")
(defconst anki-editor-exporter-default "default")
(cl-defstruct anki-editor-note (cl-defstruct anki-editor-note
id model deck fields tags) id model deck fields tags)
@ -812,7 +784,7 @@ same as how it is used by `M-RET'(org-insert-heading)."
(interactive) (interactive)
(org-export-to-buffer (org-export-to-buffer
anki-editor--ox-anki-html-backend anki-editor--ox-anki-html-backend
anki-editor-buffer-html-output nil t nil t anki-editor--ox-export-ext-plist #'html-mode)) "*AnkiEditor HTML Output*" nil t nil t anki-editor--ox-export-ext-plist #'html-mode))
(defun anki-editor-convert-region-to-html () (defun anki-editor-convert-region-to-html ()
"Convert and replace region to HTML." "Convert and replace region to HTML."