Add testing for the new reindent behavior.
This also provides a reference function to reimplement
the behavior in Janet.
# # off by 1 error in inttypes
(assert (= (int/s64 "-0x8000_0000_0000_0000") (+ (int/s64 "0x7FFF_FFFF_FFFF_FFFF") 1)) "int types wrap around")
+#
+# Longstring indentation
+#
+
+(defn reindent
+ "Reindent a the contents of a longstring as the Janet parser would.
+ This include removing leading and trailing newlines."
+ [text indent]
+
+ # Detect minimum indent
+ (var rewrite true)
+ (each index (string/find-all "\n" text)
+ (for i (+ index 1) (+ index indent 1)
+ (case (get text i)
+ nil (break)
+ (chr "\n") (break)
+ (chr " ") nil
+ (set rewrite false))))
+
+ # Only re-indent if no dedented characters.
+ (def str
+ (if rewrite
+ (peg/replace-all ~(* "\n" (between 0 ,indent " ")) "\n" text)
+ text))
+
+ (def first-nl (= (chr "\n") (first str)))
+ (def last-nl (= (chr "\n") (last str)))
+ (string/slice str (if first-nl 1 0) (if last-nl -2)))
+
+(defn reindent-reference
+ "Same as reindent but use parser functionality. Useful for validating conformance."
+ [text indent]
+ (if (empty? text) (break text))
+ (def source-code
+ (string (string/repeat " " indent) "``````"
+ text
+ "``````"))
+ (parse source-code))
+
+(var indent-counter 0)
+(defn check-indent
+ [text indent]
+ (++ indent-counter)
+ (let [a (reindent text indent)
+ b (reindent-reference text indent)]
+ (assert (= a b) (string "indent " indent-counter " (indent=" indent ")"))))
+
+(check-indent "" 0)
+(check-indent "\n" 0)
+(check-indent "\n" 1)
+(check-indent "\n\n" 0)
+(check-indent "\n\n" 1)
+(check-indent "\nHello, world!" 0)
+(check-indent "\nHello, world!" 1)
+(check-indent "Hello, world!" 0)
+(check-indent "Hello, world!" 1)
+(check-indent "\n Hello, world!" 4)
+(check-indent "\n Hello, world!\n" 4)
+(check-indent "\n Hello, world!\n " 4)
+(check-indent "\n Hello, world!\n " 4)
+(check-indent "\n Hello, world!\n dedented text\n " 4)
+(check-indent "\n Hello, world!\n indented text\n " 4)
+
(end-suite)
