import type { Value } from "Json/Value" import Tuple from "Tuple" import {} from "Number" import Dictionary from "Dictionary" import PP from "PrettyPrint" import { JsonString, JsonInteger, JsonFloat, JsonBoolean, JsonNull, JsonArray, JsonObject } from "Json/Value" import String from "String" // Pretty Printer // -------------- jsonToDoc :: Value -> PP.Doc export jsonToDoc = (value) => where(value) { JsonString(s) => pipe( escapeString, PP.text, PP.quotes )(s) JsonBoolean(b) => PP.text(show(b)) JsonInteger(i) => PP.text(show(i)) JsonFloat(f) => PP.text(show(f)) JsonNull => PP.text("null") JsonArray(items) => PP.group( PP.hcat([ PP.lbracket, PP.nest( 2, PP.hcat([ PP.linebreak, PP.sepBy( PP.hcat([PP.comma, PP.line]), map(jsonToDoc, items) ), ]) ), PP.linebreak, PP.rbracket, ]) ) JsonObject(fields) => PP.group( PP.hcat([ PP.lbrace, PP.nest( 2, PP.hcat([ PP.linebreak, PP.sepBy( PP.hcat([PP.comma, PP.line]), map( (f) => PP.hcat([ PP.text(`"${Tuple.fst(f)}"`), PP.colon, PP.space, jsonToDoc(Tuple.snd(f)) ]), Dictionary.toList(fields) ) ), ]) ), PP.linebreak, PP.rbrace, ]) ) } escapeString :: String -> String escapeString = (s) => { go :: List Char -> List Char go = (chars) => where(chars) { ['"', ...cs] => ['\\', '"', ...go(cs)] ['\n', ...cs] => ['\\', 'n', ...go(cs)] ['\t', ...cs] => ['\\', 't', ...go(cs)] ['\r', ...cs] => ['\\', 'r', ...go(cs)] [c, ...cs] => [c, ...go(cs)] [] => [] } return pipe( String.toList, go, String.fromList )(s) } // Printer Public API // ------------------ string :: String -> Value export string = (s) => JsonString(s) integer :: Integer -> Value export integer = (i) => JsonInteger(i) float :: Float -> Value export float = (f) => JsonFloat(f) boolean :: Boolean -> Value export boolean = (b) => JsonBoolean(b) null :: Value export null = JsonNull list :: (a -> Value) -> List a -> Value export list = (transformer, items) => JsonArray(map(transformer, items)) dict :: (a -> Value) -> Dictionary String a -> Value export dict = (transformer, items) => JsonObject(map(transformer, items)) object :: List #[String, Value] -> Value export object = (items) => JsonObject(Dictionary.fromList(items)) print :: Integer -> Value -> String export print = (width, value) => pipe( jsonToDoc, PP.prettyPrint(width) )(value) export printJson = print