branch: externals/tomelr
commit 7d8d41f15b6d5a2d2325160490482b133c56f845
Author: Kaushal Modi <[email protected]>
Commit: Kaushal Modi <[email protected]>
feat: Encode to multi-line TOML string automatically
.. if the string has newlines or quote chars.
---
README.org | 20 +++++++++++----
test/tscalar.el | 16 ++++++++++++
tomelr.el | 77 ++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 80 insertions(+), 33 deletions(-)
diff --git a/README.org b/README.org
index 176979b7ed..6583e6dcca 100644
--- a/README.org
+++ b/README.org
@@ -23,7 +23,7 @@ specification defined below.
- [X] Boolean
- [X] Integer
- [X] Float
- - [ ] String
+ - [X] String
- [ ] Date + Time with Offset
- [ ] Date
- [ ] Nil
@@ -149,15 +149,24 @@ flt7 = 6.626e-34
: "flt6": -0.02,
: "flt7": 6.626e-34
: }
-*** String
+*** DONE String
+CLOSED: [2022-04-28 Thu 22:10]
https://toml.io/en/v1.0.0#string
**** S-expression
#+begin_src emacs-lisp :eval no :noweb-ref scalar-string
-'((str . "Roses are red\nViolets are blue"))
+'((str1 . "Roses are red")
+ (str2 . "Roses are red\nViolets are blue"))
#+end_src
**** TOML
+#+begin_src emacs-lisp :noweb yes :exports results :wrap src toml
+(tomelr-encode
+ <<scalar-string>>)
+#+end_src
+
+#+RESULTS:
#+begin_src toml
-str = """
+str1 = "Roses are red"
+str2 = """
Roses are red
Violets are blue"""
#+end_src
@@ -169,7 +178,8 @@ Violets are blue"""
#+RESULTS:
: {
-: "str": "Roses are red\nViolets are blue"
+: "str1": "Roses are red",
+: "str2": "Roses are red\nViolets are blue"
: }
*** Date + Time with Offset
https://toml.io/en/v1.0.0#offset-date-time
diff --git a/test/tscalar.el b/test/tscalar.el
index a052eff7db..27fd940d00 100644
--- a/test/tscalar.el
+++ b/test/tscalar.el
@@ -74,5 +74,21 @@
(push (tomelr-encode el) out))
(should (equal ref (nreverse out)))))
+;;;; Scalar - String
+(ert-deftest test-scalar-string ()
+ (let ((inp '(((string1 . "Roses are red"))
+ ((string2 . "Roses are red\nViolets are blue")) ;Newline in
string
+ ((string3 . "\"Hello!\"")))) ;Quote in string
+ (ref '("string1 = \"Roses are red\""
+ "string2 = \"\"\"
+Roses are red
+Violets are blue\"\"\""
+ "string3 = \"\"\"
+\"Hello!\"\"\"\""))
+ out)
+ (dolist (el inp)
+ (push (tomelr-encode el) out))
+ (should (equal ref (nreverse out)))))
+
(provide 'tscalar)
diff --git a/tomelr.el b/tomelr.el
index 805dcdb8a9..342ba01a5d 100644
--- a/tomelr.el
+++ b/tomelr.el
@@ -130,35 +130,56 @@ Return nil if KEYWORD is not recognized as a TOML
keyword."
(and keyword (insert keyword))))
;;;; Strings
-(defconst tomelr-special-chars
- '((?\" . ?\")
- (?\\ . ?\\)
- (?b . ?\b)
- (?f . ?\f)
- (?n . ?\n)
- (?r . ?\r)
- (?t . ?\t))
- "Characters which are escaped in TOML, with their Elisp counterparts.")
-
-(defun tomelr--print-string (string &optional from)
+(defun tomelr--print-string (string &optional trim-init-chars)
"Insert a TOML representation of STRING at point.
-FROM is the index of STRING to start from and defaults to 0."
- ;; (message "[tomelr--print-string DBG] string = %s" string)
- (insert ?\")
- (goto-char (prog1 (point) (princ string)))
- (and from (delete-char from))
- ;; Escape only quotation mark, backslash, and the control
- ;; characters U+0000 to U+001F (RFC 4627, ECMA-404).
- (while (re-search-forward (rx (in ?\" ?\\ cntrl)) nil 'move)
- (let ((char (preceding-char)))
- (delete-char -1)
- (insert ?\\ (or
- ;; Special TOML character (\n, \r, etc.).
- (car (rassq char tomelr-special-chars))
- ;; Fallback: UCS code point in \uNNNN form.
- (format "u%04x" char)))))
- (insert ?\")
- string)
+
+If TRIM-INIT-CHARS is positive, those many initial characters
+of the STRING are not inserted.
+
+Return the same STRING passed as input."
+ (let ((special-chars '((?b . ?\b) ;U+0008
+ (?f . ?\f) ;U+000C
+ (?\\ . ?\\)))
+ special-chars-re
+ begin-q end-q)
+ ;; Use multi-line string quotation if the string contains a " char
+ ;; or a newline.
+ (if (string-match-p "\n\\|\"" string)
+ (progn ;Triple quotation """STRING"""
+ ;; From https://toml.io/en/v1.0.0#string, Any Unicode
+ ;; character may be used except those that must be escaped:
+ ;; backslash and the control characters other than tab, line
+ ;; feed, and carriage return (U+0000 to U+0008, U+000B,
+ ;; U+000C, U+000E to U+001F, U+007F).
+ (setq special-chars-re (rx (in ?\\
+ (?\u0000 . ?\u0008)
+ ?\u000B ?\u000C
+ (?\u000E . ?\u001F)
+ ?\u007F)))
+ (setq begin-q "\"\"\"\n")
+ (setq end-q "\"\"\""))
+ (progn ;Basic quotation "STRING"
+ (setq special-chars-re (rx (in ?\" ?\\ cntrl ?\u007F))) ;cntrl is same
as (?\u0000 . ?\u001F)
+ (push '(?\" . ?\") special-chars)
+ (push '(?t . ?\t) special-chars) ;U+0009
+ (push '(?n . ?\n) special-chars) ;U+000A
+ (push '(?r . ?\r) special-chars) ;U+000D
+ (setq begin-q "\"")
+ (setq end-q begin-q)))
+ ;; (message "[tomelr--print-string DBG] string = `%s'" string)
+ (insert begin-q)
+ (goto-char (prog1 (point) (princ string)))
+ (and trim-init-chars (delete-char trim-init-chars))
+ (while (re-search-forward special-chars-re nil :noerror)
+ (let ((char (preceding-char)))
+ (delete-char -1)
+ (insert ?\\ (or
+ ;; Escape special characters
+ (car (rassq char special-chars))
+ ;; Fallback: UCS code point in \uNNNN form.
+ (format "u%04x" char)))))
+ (insert end-q)
+ string))
(defun tomelr-encode-string (string)
"Return a TOML representation of STRING."