bunz 0.0.5 → 0.0.6
raw patch · 2 files changed
+75/−40 lines, 2 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Beautifier: firstString :: Text -> Text
+ Beautifier: firstString :: Builder -> Builder
- Beautifier: indent :: IndentationLevel -> Text -> Text
+ Beautifier: indent :: IndentationLevel -> Builder -> Builder
- Beautifier: splitAtHead :: Text -> (Text, Text)
+ Beautifier: splitAtHead :: Builder -> (Builder, Builder)
Files
- bunz.cabal +2/−2
- src/Beautifier.hs +73/−38
bunz.cabal view
@@ -1,5 +1,5 @@ name: bunz-version: 0.0.5+version: 0.0.6 synopsis: CLI tool to beautify JSON string. description: CLI tool to beautify JSON string. homepage: https://github.com/sendyhalim/bunz@@ -42,7 +42,7 @@ , bunz , doctest >= 0.11 , hspec == 2.4.4- ghc-options: -threaded -rtsopts -with-rtsopts=-N+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -O2 default-language: Haskell2010 source-repository head
src/Beautifier.hs view
@@ -8,9 +8,10 @@ , splitAtHead ) where -import Data.Int (Int64)-import Data.Monoid ((<>))-import qualified Data.Text.Lazy as T+import Data.Int (Int64)+import Data.Monoid ((<>))+import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy.Builder as B -- Doctest setup -- $setup@@ -18,18 +19,49 @@ type IndentationLevel = Int64 -indentation :: T.Text-indentation = " " -newline :: T.Text-newline = "\n"+-- | Lift function that works with Data.Text.Lazy+-- to be able to work with Data.Text.Lazy.Builder.+-- There should be a better and faster way to manipulate builder. We're using+-- this for now because it's a lot faster than just using plain Data.Text.Lazy when+-- concatenating text.+liftToBuilder :: (T.Text -> T.Text) -> (B.Builder -> B.Builder)+liftToBuilder f = B.fromLazyText . f . B.toLazyText -indent :: IndentationLevel -> T.Text -> T.Text-indent level str = T.replicate level indentation <> str+splitAt' :: Int64 -> B.Builder -> (B.Builder, B.Builder)+splitAt' n str = (B.fromLazyText head, B.fromLazyText tail)+ where (head, tail) = T.splitAt n (B.toLazyText str) -trimmedTail :: T.Text -> T.Text-trimmedTail = T.stripStart . T.tail+head' :: B.Builder -> B.Builder+head' = B.singleton . T.head . B.toLazyText +tail' :: B.Builder -> B.Builder+tail' = liftToBuilder T.tail++drop' :: Int64 -> B.Builder -> B.Builder+drop' length = liftToBuilder (T.drop length)++length' :: B.Builder -> Int64+length' = T.length . B.toLazyText++stripStart' :: B.Builder -> B.Builder+stripStart' = liftToBuilder T.stripStart++space :: T.Text+space = " "++indentation :: IndentationLevel -> B.Builder+indentation level = B.fromLazyText (T.replicate level space)++newline :: B.Builder+newline = B.fromLazyText "\n"++indent :: IndentationLevel -> B.Builder -> B.Builder+indent level str = indentation level <> str++trimmedTail :: B.Builder -> B.Builder+trimmedTail = B.fromLazyText . T.stripStart . T.tail . B.toLazyText+ -- | Split the given string at its head while honouring escaped string. -- Examples: --@@ -38,10 +70,10 @@ -- -- >>> splitAtHead "\nyeay" -- ("\n","yeay")-splitAtHead :: T.Text -> (T.Text, T.Text)+splitAtHead :: B.Builder -> (B.Builder, B.Builder) splitAtHead "" = ("", "")-splitAtHead str@(T.head -> '\\') = T.splitAt 2 str-splitAtHead str = T.splitAt 1 str+splitAtHead str@(head' -> "\\") = splitAt' 2 str+splitAtHead str = splitAt' 1 str -- | Extract string within double quotes `"` including the double quotes ignoring -- the suffix after closing quote `"`@@ -50,13 +82,13 @@ -- -- >>> string False "\"test\"whatuppp" -- "\"test\""-string :: Bool -> T.Text -> T.Text-string False str@(T.head -> '"') = "\"" <> string True (T.tail str)-string True str@(T.head -> '"') = "\""+string :: Bool -> B.Builder -> B.Builder+string False str@(head' -> "\"") = "\"" <> string True (tail' str)+string True str@(head' -> "\"") = "\"" string True str = let (head, tail) = splitAtHead str in head <> string True tail -- | Extract the first string value starting from the front.-firstString :: T.Text -> T.Text+firstString :: B.Builder -> B.Builder firstString str = string False str @@ -85,30 +117,33 @@ -- -- >>> extractJsonValue "false,true,false]" -- "false"-extractJsonValue :: T.Text -> T.Text-extractJsonValue = T.takeWhile (not . isEndOfValue)+extractJsonValue :: B.Builder -> B.Builder+extractJsonValue = liftToBuilder $ T.takeWhile (not . isEndOfValue) -- |Beautify the given JSON text based on the current indentation level.-beautifyText :: IndentationLevel -> T.Text -> T.Text+beautifyText :: IndentationLevel -> B.Builder -> B.Builder beautifyText i str | str == "" = ""- | head == ' ' = stripStartThenParse str- | head == '\n' = stripStartThenParse str- | head == '\t' = stripStartThenParse str- | head == '{' = nextLineAfterOpening "{"- | head == '[' = nextLineAfterOpening "["- | head == '}' = nextLineAfterClosing "}"- | head == ']' = nextLineAfterClosing "]"- | head == ',' = "," <> newline <> indent i (beautifyText i (trimmedTail str))- | head == '"' = let groupedString = firstString str- restOfTheString = T.drop (T.length groupedString) str- in groupedString <> beautifyText i restOfTheString- | head == ':' = ": " <> beautifyText i (trimmedTail str)- | otherwise = let value = extractJsonValue str- in value <> beautifyText i (T.drop (T.length value) str)+ | head == " " = stripStartThenParse str+ | head == "\n" = stripStartThenParse str+ | head == "\t" = stripStartThenParse str+ | head == "{" = nextLineAfterOpening "{"+ | head == "[" = nextLineAfterOpening "["+ | head == "}" = nextLineAfterClosing "}"+ | head == "]" = nextLineAfterClosing "]"+ | head == "," = "," <> newline <> indent i (beautifyText i (trimmedTail str))+ | head == "\"" =+ let groupedString = firstString str+ restOfTheString = drop' (length' groupedString) str+ in groupedString <> beautifyText i restOfTheString+ | head == ":" = ": " <> beautifyText i (trimmedTail str)+ | otherwise =+ let value = extractJsonValue str+ valueLength = length' value+ in value <> beautifyText i (drop' valueLength str) where- head = T.head str- stripStartThenParse = beautifyText i . T.stripStart+ head = head' str+ stripStartThenParse = beautifyText i . stripStart' nextLineAfterOpening token = token <> newline <> indent (i + 1) (beautifyText (i + 1) (trimmedTail str))@@ -118,4 +153,4 @@ beautify :: T.Text -> T.Text-beautify = beautifyText 0+beautify = B.toLazyText . beautifyText 0 . B.fromLazyText