packages feed

bunz 0.0.7 → 0.0.9

raw patch · 5 files changed

+71/−99 lines, 5 files

Files

README.md view
@@ -3,12 +3,14 @@  ## Usage ```-λ   bunz [master] + bunz "{\"foo\":\"bar\"}"+// Beautify plain json string+bunz "{\"foo\":\"bar\"}" {   "foo": "bar" } -λ   bunz [master] + cat test.json | bunz+// Beautify the input+cat test.json | bunz {   "name": "sendy",   "popular": false,
app/Main.hs view
@@ -3,8 +3,8 @@ module Main where  import qualified Beautifier             as B-import qualified Data.Text.Lazy         as T-import qualified Data.Text.Lazy.IO      as TextIO+import qualified Data.Text              as T+import qualified Data.Text.IO           as TextIO import           Data.Version           (showVersion) import           Paths_bunz             (version) import           System.Console.CmdArgs ((&=))@@ -28,9 +28,10 @@ runFromStdInput :: IO () runFromStdInput = TextIO.getContents >>= printBeautified + runFromArgs :: Args -> IO () runFromArgs (Args { jsonString = str }) = printBeautified $ T.pack str  run :: Bool -> IO () run False = runFromStdInput-run True = CA.cmdArgs args >>= runFromArgs+run True  = CA.cmdArgs args >>= runFromArgs
bunz.cabal view
@@ -1,5 +1,5 @@ name:                bunz-version:             0.0.7+version:             0.0.9 synopsis:            CLI tool to beautify JSON string. description:         CLI tool to beautify JSON string. homepage:            https://github.com/sendyhalim/bunz@@ -7,7 +7,7 @@ license-file:        LICENSE author:              Sendy Halim <sendyhalim93@gmail.com> maintainer:          Sendy Halim <sendyhalim93@gmail.com>-copyright:           (c) 2017 Sendy Halim+copyright:           (c) 2019 Sendy Halim category:            CLI, JSON build-type:          Simple extra-source-files:  README.md
src/Beautifier.hs view
@@ -3,64 +3,32 @@  module Beautifier   ( beautify-  , indent+  , indentation   , firstString   , splitAtHead   ) where -import           Data.Int               (Int64)-import           Data.Monoid            ((<>))-import qualified Data.Text.Lazy         as T-import qualified Data.Text.Lazy.Builder as B+import           Data.Int    (Int64)+import           Data.Monoid ((<>))+import qualified Data.Text   as T  -- Doctest setup -- $setup -- >>> :set -XOverloadedStrings -type IndentationLevel = Int64----- | 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--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)--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+type IndentationLevel = Int  spaceIndentation :: T.Text spaceIndentation = "  " -indentation :: IndentationLevel -> B.Builder-indentation level = B.fromLazyText (T.replicate level spaceIndentation)--newline :: B.Builder-newline = B.fromLazyText "\n"+indentation :: IndentationLevel -> T.Text+indentation level = (T.replicate level spaceIndentation) -indent :: IndentationLevel -> B.Builder -> B.Builder-indent level str = indentation level <> str+newline :: T.Text+newline = "\n" -trimmedTail :: B.Builder -> B.Builder-trimmedTail = B.fromLazyText . T.stripStart . T.tail . B.toLazyText+trimmedTail :: T.Text -> T.Text+trimmedTail = T.stripStart . T.tail  -- | Split the given string at its head while honouring escaped string. -- Examples:@@ -70,25 +38,29 @@ -- -- >>> splitAtHead "\nyeay" -- ("\n","yeay")-splitAtHead :: B.Builder -> (B.Builder, B.Builder)-splitAtHead "" = ("", "")-splitAtHead str@(head' -> "\\") = splitAt' 2 str-splitAtHead str = splitAt' 1 str+splitAtHead :: T.Text -> (T.Text, T.Text)+splitAtHead ""                   = ("", "")+splitAtHead str@(T.head -> '\\') = T.splitAt 2 str+splitAtHead str                  = T.splitAt 1 str  -- | Extract string within double quotes `"` including the double quotes ignoring--- the suffix after closing quote `"`+-- the suffix after closing quote `"`. It will ignore unescaped newline within the string. -- -- Examples: -- -- >>> string False "\"test\"whatuppp" -- "\"test\""-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+--+-- >>> string False "\"\ntest\"whatuppp"+-- "\"test\""+string :: Bool -> T.Text -> [T.Text]+string flag str@(T.head -> '\n') = string flag (T.tail str)+string False str@(T.head -> '"') = ["\""] ++ string True (T.tail str)+string True str@(T.head -> '\"') = ["\""]+string True str = let (head, tail) = splitAtHead str in [head] ++ string True tail  -- | Extract the first string value starting from the front.-firstString :: B.Builder -> B.Builder+firstString :: T.Text -> [T.Text] firstString str = string False str  @@ -117,40 +89,36 @@ -- -- >>> extractJsonValue "false,true,false]" -- "false"-extractJsonValue :: B.Builder -> B.Builder-extractJsonValue = liftToBuilder $ T.takeWhile (not . isEndOfValue)+extractJsonValue :: T.Text -> T.Text+extractJsonValue = T.takeWhile (not . isEndOfValue)  -- |Beautify the given JSON text based on the current indentation level.-beautifyText :: IndentationLevel -> B.Builder -> B.Builder+beautifyText :: IndentationLevel -> T.Text -> [T.Text] 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 = drop' (length' groupedString) str-          in groupedString <> beautifyText i restOfTheString-  | head == ":" = ": " <> beautifyText i (trimmedTail str)+  | str == "" = [""]+  | head == ' ' = stripStartThenParse str+  | head == '\n' = stripStartThenParse str+  | head == '\t' = stripStartThenParse str+  | head == '{' = nextLineAfterOpening "{"+  | head == '[' = nextLineAfterOpening "["+  | head == '}' = nextLineAfterClosing "}"+  | head == ']' = nextLineAfterClosing "]"+  | head == ',' = [",", newline, indentation i] ++ (beautifyText i (trimmedTail str))+  | head == '"' =+      let groupedString = mconcat $ firstString str+          restOfTheString = T.drop (T.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)+          valueLength = T.length value+          in [value] ++ beautifyText i (T.drop valueLength str)   where-    head = head' str-    stripStartThenParse = beautifyText i . stripStart'-    nextLineAfterOpening token = token-      <> newline-      <> indent (i + 1) (beautifyText (i + 1) (trimmedTail str))-    nextLineAfterClosing token = newline-      <> indent (i - 1) token-      <> beautifyText (i - 1) (trimmedTail str)+    head = T.head str+    stripStartThenParse = beautifyText i . T.stripStart+    nextLineAfterOpening token = [token , newline , indentation (i + 1)] ++ (beautifyText (i + 1) (trimmedTail str))+    nextLineAfterClosing token = [newline, indentation (i - 1), token] ++ beautifyText (i - 1) (trimmedTail str)   beautify :: T.Text -> T.Text-beautify = B.toLazyText . beautifyText 0 . B.fromLazyText+beautify = mconcat . beautifyText 0
test/BeautifierSpec.hs view
@@ -2,7 +2,8 @@  module BeautifierSpec (main, spec) where -import qualified Beautifier as B+import qualified Beautifier  as B+import           Data.Monoid ((<>)) import           Test.Hspec  main :: IO()@@ -10,18 +11,18 @@  spec :: Spec spec = do-  describe "Beautifier.indent" $ do-    context "When given negative indent level" $ do-      it "should not indent" $ do-        B.indent (-1) "{" `shouldBe` "{"+  describe "Beautifier.indentation" $ do+    context "When given negative indentation level" $ do+      it "should not error" $ do+        B.indentation (-1) <> "{" `shouldBe` "{" -    context "When given 0 indent level" $ do-      it "should not indent" $ do-        B.indent 0 "{" `shouldBe` "{"+    context "When given 0 indentation level" $ do+      it "should not indentation" $ do+        B.indentation 0 <> "{" `shouldBe` "{" -    context "When given 2 indent level" $ do-      it "should indent by 2 levels" $ do-        B.indent 2 "{" `shouldBe` "    {"+    context "When given 2 indentation level" $ do+      it "should indentation by 2 levels" $ do+        B.indentation 2 <> "{" `shouldBe` "    {"    describe "Beautifier.splitAtHead" $ do     context "when text first character is escaped" $ do