Doc stuff
This commit is contained in:
parent
b6065cd2f7
commit
b8f6986ab9
2 changed files with 84 additions and 94 deletions
92
README.org
92
README.org
|
@ -1,40 +1,40 @@
|
||||||
[[http://melpa.org/#/anki-editor][file:http://melpa.org/packages/anki-editor-badge.svg]]
|
[[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
|
/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
|
* Installation
|
||||||
|
|
||||||
*Requirements*
|
*Requirements*
|
||||||
- [[https://github.com/FooSoft/anki-connect#installation][anki-connect]],
|
- [[https://github.com/FooSoft/anki-connect#installation][AnkiConnect]],
|
||||||
an Anki add-on required by this package to interact with Anki.
|
an Anki add-on required by this package to interact with Anki
|
||||||
- curl
|
- curl
|
||||||
|
|
||||||
If you have [[http://melpa.org/][MELPA]] in your =package-archives=,
|
If you have [[http://melpa.org/][MELPA]] in your ~package-archives~,
|
||||||
just =M-x package-install RET anki-editor RET=, or install it
|
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
|
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
|
* Usage
|
||||||
|
|
||||||
** The Layout of Notes
|
** The Layout of Notes
|
||||||
|
|
||||||
Now you can compose Anki notes in Org syntax, e.g. lists, code
|
The power of this mode comes from the builtin HTML export backend
|
||||||
examples, tables, embedded latex, when being submitted to Anki,
|
provided by Org, which enables you to use almost all the Org
|
||||||
they will be converted to HTML by Org-mode's HTML backend with
|
constructs for writing Anki notes: lists, code blocks, tables,
|
||||||
specific markers (e.g. latex) translated to Anki style.
|
latex and so on.
|
||||||
|
|
||||||
The structure of a note is as follow, which is inspired by
|
The structure of a note is as follows, which is inspired by
|
||||||
=org-drill=. More examples can be found in [[./examples.org][examples.org]].
|
~org-drill~. Check out [[./examples.org][examples.org]] for more examples.
|
||||||
|
|
||||||
#+BEGIN_SRC org
|
#+BEGIN_SRC org
|
||||||
,* Idiom :vocab:idioms:
|
,* Raining :vocab:idioms:
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:ANKI_DECK: English
|
:ANKI_DECK: English
|
||||||
:ANKI_NOTE_TYPE: Basic (and reversed card)
|
:ANKI_NOTE_TYPE: Basic (and reversed card)
|
||||||
:ANKI_TAGS: languages european_languages
|
:ANKI_TAGS: vocab idioms
|
||||||
:END:
|
:END:
|
||||||
,** Front
|
,** Front
|
||||||
(it's) raining cats and dogs
|
(it's) raining cats and dogs
|
||||||
|
@ -42,35 +42,41 @@ there were any ambiguity or grammatical mistakes ;-)/
|
||||||
it's raining very hard
|
it's raining very hard
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
- An Anki note is an Org entry with =ANKI_NOTE_TYPE= property
|
- Anki deck is provided by ~ANKI_DECK~ property. This property is
|
||||||
- Anki tags can be set in two ways
|
retrieved with inheritance, that is to say, it can be put in any
|
||||||
1. With "ANKI_TAGS" property, multiple tags are separated with space
|
ancestor entries or at top of the file by ~#+PROPERTY: ANKI_DECK
|
||||||
2. With Org tags [fn:1], this could be turned off if you would like to keep Org tags separated from Anki tags
|
DeckName~.
|
||||||
- Other necessary information (e.g. deck, note type) of a note is
|
- ~ANKI_NOTE_TYPE~ property is to specify the Anki note type of a
|
||||||
put in the property drawer of the entry
|
note and is also required for identifying an Anki note entry.
|
||||||
- As the value of =ANKI_DECK= is retrieved with inheritance, you
|
- Anki tags can be provided in two ways:
|
||||||
don't have to set it per note, instead, you could create a deck
|
1. With a ~ANKI_TAGS~ property, multiple tags are separated by spaces
|
||||||
entry with this property set and put note entries under it, or
|
2. With Org tags [fn:1], this could be turned off if you would
|
||||||
set it per file by ~#+PROPERTY: ANKI_DECK YourDeck~
|
like to keep Org tags separated from Anki tags
|
||||||
- Child entries of a note entry are fields
|
- 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
|
** Commands
|
||||||
|
|
||||||
| Command | Brief Description |
|
| 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-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-push-new-notes | Similar to ~anki-editor-push-notes~, but push those that are without ~ANKI_NOTE_ID~. |
|
||||||
| anki-editor-insert-note | Insert a note entry like =M-RET=, interactively. |
|
| anki-editor-retry-failed-notes | Similar to ~anki-editor-push-notes~, except that it only pushes notes with ~ANKI_FAILURE_REASON~. |
|
||||||
| anki-editor-cloze-region | Create a cloze deletion from region. |
|
| 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-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-convert-region-to-html | Convert and replace region to HTML. |
|
||||||
|
| anki-editor-anki-connect-check | Check if correct version of AnkiConnect is running. |
|
||||||
** Functions
|
| anki-editor-anki-connect-upgrade | Upgrade AnkiConnect. |
|
||||||
|
| anki-editor-sync-collections | Synchronize your local anki collection. |
|
||||||
| Name | Description |
|
| 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. |
|
||||||
| 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. |
|
|
||||||
|
|
||||||
** Variables
|
** 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-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-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-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
|
* Limitations
|
||||||
|
|
||||||
|
@ -94,15 +101,14 @@ there were any ambiguity or grammatical mistakes ;-)/
|
||||||
|
|
||||||
** Working with Anki add-ons
|
** Working with Anki add-ons
|
||||||
|
|
||||||
This package may not work well when you are using certain Anki
|
This package might not work well with certain Anki add-ons
|
||||||
add-ons especially those who extend the builtin Anki note editor to
|
especially those who extend the builtin Anki note editor to
|
||||||
automatically fill note field content (e.g. ~Add note id~).
|
automatically fill note field content (e.g. ~Add note id~).
|
||||||
|
|
||||||
* Troubleshooting
|
* Troubleshooting
|
||||||
|
|
||||||
In case of a failed operation and this package doesn't provide much
|
In case of a failed operation and this package doesn't provide much
|
||||||
useful information, especially for note creation, don't be
|
useful information, don't be frustrated, see below for some hints.
|
||||||
frustrated, see below for some hints.
|
|
||||||
|
|
||||||
1. Decks don't exist in Anki. This package by default doesn't create
|
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~,
|
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, =_=
|
[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.
|
Anki tags before they can be used in Org without any surprise.
|
||||||
|
|
|
@ -12,19 +12,17 @@
|
||||||
;;
|
;;
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;
|
;;
|
||||||
;; This package is for people who use Anki as SRS but would like to
|
;; This package is for users of both Emacs and Anki, who'd like to
|
||||||
;; make cards in Org-mode.
|
;; make Anki cards in Org mode. With this package, Anki cards can be
|
||||||
|
;; made from an Org buffer like below: (inspired by org-drill)
|
||||||
;;
|
;;
|
||||||
;; With this package, you can make cards from something like:
|
;; * Sample :emacs:lisp:programming:
|
||||||
;; (which is inspired by `org-dirll')
|
|
||||||
;;
|
|
||||||
;; * Item :emacs:lisp:programming:
|
|
||||||
;; :PROPERTIES:
|
;; :PROPERTIES:
|
||||||
;; :ANKI_DECK: Computing
|
;; :ANKI_DECK: Computing
|
||||||
;; :ANKI_NOTE_TYPE: Basic
|
;; :ANKI_NOTE_TYPE: Basic
|
||||||
;; :END:
|
;; :END:
|
||||||
;; ** Front
|
;; ** Front
|
||||||
;; How to hello world in elisp ?
|
;; How to say "hello world" in elisp?
|
||||||
;; ** Back
|
;; ** Back
|
||||||
;; #+BEGIN_SRC emacs-lisp
|
;; #+BEGIN_SRC emacs-lisp
|
||||||
;; (message "Hello, world!")
|
;; (message "Hello, world!")
|
||||||
|
@ -32,13 +30,13 @@
|
||||||
;;
|
;;
|
||||||
;; This package extends Org-mode's built-in HTML backend to generate
|
;; This package extends Org-mode's built-in HTML backend to generate
|
||||||
;; HTML for contents of note fields with specific syntax (e.g. latex)
|
;; 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:
|
;; For this package to work, you have to setup these external dependencies:
|
||||||
;; - curl
|
;; - curl
|
||||||
;; - AnkiConnect, an Anki addon that runs an HTTP server to expose
|
;; - AnkiConnect, an Anki addon that runs an RPC server over HTTP to expose
|
||||||
;; Anki functions as RESTful APIs, see
|
;; Anki functions as APIs,
|
||||||
;; https://github.com/FooSoft/anki-connect#installation
|
;; see https://github.com/FooSoft/anki-connect#installation
|
||||||
;; for installation instructions
|
;; 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
|
(defcustom anki-editor-org-tags-as-anki-tags
|
||||||
t
|
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
|
(defcustom anki-editor-protected-tags
|
||||||
'("marked" "leech")
|
'("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))
|
:type '(repeat string))
|
||||||
|
|
||||||
(defcustom anki-editor-ignored-org-tags
|
(defcustom anki-editor-ignored-org-tags
|
||||||
(append org-export-select-tags org-export-exclude-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))
|
:type '(repeat string))
|
||||||
|
|
||||||
(defcustom anki-editor-anki-connect-listening-address
|
(defcustom anki-editor-anki-connect-listening-address
|
||||||
|
@ -142,8 +143,7 @@ See https://apps.ankiweb.net/docs/manual.html#latex-conflicts.")
|
||||||
(request-backend 'curl)
|
(request-backend 'curl)
|
||||||
(json-array-type 'list)
|
(json-array-type 'list)
|
||||||
reply err)
|
reply err)
|
||||||
|
(request (format "http://%s:%s"
|
||||||
(let ((response (request (format "http://%s:%s"
|
|
||||||
anki-editor-anki-connect-listening-address
|
anki-editor-anki-connect-listening-address
|
||||||
anki-editor-anki-connect-listening-port)
|
anki-editor-anki-connect-listening-port)
|
||||||
:type "POST"
|
:type "POST"
|
||||||
|
@ -153,20 +153,13 @@ See https://apps.ankiweb.net/docs/manual.html#latex-conflicts.")
|
||||||
(setq reply data)))
|
(setq reply data)))
|
||||||
:error (cl-function (lambda (&key _ &key error-thrown &allow-other-keys)
|
:error (cl-function (lambda (&key _ &key error-thrown &allow-other-keys)
|
||||||
(setq err (string-trim (cdr error-thrown)))))
|
(setq err (string-trim (cdr error-thrown)))))
|
||||||
:sync t)))
|
: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")))
|
|
||||||
|
|
||||||
(when err (error "Error communicating with AnkiConnect using cURL: %s" err))
|
(when err (error "Error communicating with AnkiConnect using cURL: %s" err))
|
||||||
(or reply (error "Got empty reply from AnkiConnect"))))
|
(or reply (error "Got empty reply from AnkiConnect"))))
|
||||||
|
|
||||||
(defmacro anki-editor--anki-connect-invoke-result (&rest args)
|
(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)
|
`(let-alist (anki-editor--anki-connect-invoke ,@args)
|
||||||
(when .error (error .error))
|
(when .error (error .error))
|
||||||
.result))
|
.result))
|
||||||
|
@ -380,7 +373,8 @@ The implementation is borrowed and simplified from ox-html."
|
||||||
;;; Core Functions
|
;;; Core Functions
|
||||||
|
|
||||||
(defun anki-editor-map-note-entries (func &optional match scope &rest skip)
|
(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
|
;; disable property inheritance temporarily, or all subheadings of a
|
||||||
;; note heading will be counted as note headings as well
|
;; note heading will be counted as note headings as well
|
||||||
(let ((org-use-property-inheritance nil))
|
(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."
|
Where the subtree is created depends on PREFIX."
|
||||||
(org-insert-heading prefix)
|
(org-insert-heading prefix)
|
||||||
(insert heading)
|
(insert heading)
|
||||||
|
|
||||||
(unless (save-excursion
|
(unless (save-excursion
|
||||||
(org-up-heading-safe)
|
(org-up-heading-safe)
|
||||||
;; don't insert `ANKI_DECK' if some ancestor already has
|
;; 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))
|
(and (not (string-blank-p deck))
|
||||||
(string= deck (org-entry-get-with-inheritance anki-editor-prop-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-deck deck))
|
||||||
|
|
||||||
(org-set-property anki-editor-prop-note-type note-type)
|
(org-set-property anki-editor-prop-note-type note-type)
|
||||||
|
|
||||||
(dolist (field fields)
|
(dolist (field fields)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(org-insert-heading-respect-content)
|
(org-insert-heading-respect-content)
|
||||||
|
@ -426,12 +417,10 @@ Where the subtree is created depends on PREFIX."
|
||||||
(funcall queue
|
(funcall queue
|
||||||
'createDeck
|
'createDeck
|
||||||
`((deck . ,(alist-get 'deck note)))))
|
`((deck . ,(alist-get 'deck note)))))
|
||||||
|
|
||||||
(funcall queue
|
(funcall queue
|
||||||
'addNote
|
'addNote
|
||||||
`((note . ,(anki-editor--anki-connect-map-note note)))
|
`((note . ,(anki-editor--anki-connect-map-note note)))
|
||||||
#'anki-editor--set-note-id)
|
#'anki-editor--set-note-id)
|
||||||
|
|
||||||
(funcall queue)))
|
(funcall queue)))
|
||||||
|
|
||||||
(defun anki-editor--update-note (note)
|
(defun anki-editor--update-note (note)
|
||||||
|
@ -440,7 +429,6 @@ Where the subtree is created depends on PREFIX."
|
||||||
(funcall queue
|
(funcall queue
|
||||||
'updateNoteFields
|
'updateNoteFields
|
||||||
`((note . ,(anki-editor--anki-connect-map-note note))))
|
`((note . ,(anki-editor--anki-connect-map-note note))))
|
||||||
|
|
||||||
(funcall queue
|
(funcall queue
|
||||||
'notesInfo
|
'notesInfo
|
||||||
`((notes . (,(alist-get 'note-id note))))
|
`((notes . (,(alist-get 'note-id note))))
|
||||||
|
@ -454,19 +442,15 @@ Where the subtree is created depends on PREFIX."
|
||||||
(alist-get 'tags note))
|
(alist-get 'tags note))
|
||||||
anki-editor-protected-tags))
|
anki-editor-protected-tags))
|
||||||
(tag-queue (anki-editor--anki-connect-invoke-queue)))
|
(tag-queue (anki-editor--anki-connect-invoke-queue)))
|
||||||
|
|
||||||
(when tags-to-add
|
(when tags-to-add
|
||||||
(funcall tag-queue
|
(funcall tag-queue
|
||||||
'addTags `((notes . (,(alist-get 'note-id note)))
|
'addTags `((notes . (,(alist-get 'note-id note)))
|
||||||
(tags . ,(mapconcat #'identity tags-to-add " ")))))
|
(tags . ,(mapconcat #'identity tags-to-add " ")))))
|
||||||
|
|
||||||
(when tags-to-remove
|
(when tags-to-remove
|
||||||
(funcall tag-queue
|
(funcall tag-queue
|
||||||
'removeTags `((notes . (,(alist-get 'note-id note)))
|
'removeTags `((notes . (,(alist-get 'note-id note)))
|
||||||
(tags . ,(mapconcat #'identity tags-to-remove " ")))))
|
(tags . ,(mapconcat #'identity tags-to-remove " ")))))
|
||||||
|
|
||||||
(funcall tag-queue))))
|
(funcall tag-queue))))
|
||||||
|
|
||||||
(funcall queue)))
|
(funcall queue)))
|
||||||
|
|
||||||
(defun anki-editor--set-failure-reason (reason)
|
(defun anki-editor--set-failure-reason (reason)
|
||||||
|
@ -638,7 +622,7 @@ name and the cdr of which is field content."
|
||||||
;;; Commands
|
;;; Commands
|
||||||
|
|
||||||
(defun anki-editor-push-notes (&optional scope match)
|
(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
|
The default search condition `&ANKI_NOTE_TYPE<>\"\"' will always
|
||||||
be appended to MATCH.
|
be appended to MATCH.
|
||||||
|
|
Loading…
Reference in a new issue