1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
23import Prelude hiding (null)
24import Control.Arrow ((***))
25import qualified Data.ByteString.Char8 as BSC
26import qualified Data.ByteString.Builder as B
27import qualified Data.ByteString.Builder.Prim as BP
28import Data.ByteString.Builder.Prim ((>*<))
29import qualified Data.Map as Map
30import qualified Data.Scientific as Sci
31import Data.Monoid ((<>))
32import qualified Data.Text as Text
33import qualified Data.Text.Encoding as Text
34import qualified Data.Word as W
35import System.IO (IOMode(WriteMode), withBinaryFile)
44 | Object [(Text.Text, Value)]
48 | Number Sci.Scientific
52array :: [Value] -> Value
57object :: [(Text.Text,Value)] -> Value
62text :: Text.Text -> Value
77number :: Sci.Scientific -> Value
87dict :: (k -> Text.Text) -> (v -> Value) -> Map.Map k v -> Value
88dict encodeKey encodeValue pairs =
89 Object $ map (encodeKey *** encodeValue) (Map.toList pairs)
92list :: (a -> Value) -> [a] -> Value
93list encodeEntry entries =
94 Array $ map encodeEntry entries
101(==>) :: a -> b -> (a, b)
110write :: FilePath -> Value -> IO ()
112 withBinaryFile path WriteMode $ \handle ->
113 B.hPutBuilder handle (encode value)
116writeUgly :: FilePath -> Value -> IO ()
117writeUgly path value =
118 withBinaryFile path WriteMode $ \handle ->
119 B.hPutBuilder handle (encodeUgly value)
126encodeUgly :: Value -> B.Builder
132 Array (first : rest) ->
135 B.char7 ',' <> encodeUgly entry
137 B.char7 '[' <> encodeUgly first <> mconcat (map encodeEntry rest) <> B.char7 ']'
142 Object (first : rest) ->
144 encodeEntry char (key, entry) =
145 B.char7 char <> encodeString key <> B.char7 ':' <> encodeUgly entry
147 encodeEntry '{' first <> mconcat (map (encodeEntry ',') rest) <> B.char7 '}'
153 B.string7 (if boolean then "true" else "false")
159 B.string7 (Sci.formatScientific Sci.Generic Nothing scientific)
169encode :: Value -> B.Builder
174encodeHelp :: BSC.ByteString -> Value -> B.Builder
175encodeHelp indent value =
180 Array (first : rest) ->
181 encodeArray indent first rest
186 Object (first : rest) ->
187 encodeObject indent first rest
193 B.string7 (if boolean then "true" else "false")
199 B.string7 (Sci.formatScientific Sci.Generic Nothing scientific)
209encodeArray :: BSC.ByteString -> Value -> [Value] -> B.Builder
211 encodeSequence arrayOpen arrayClose encodeHelp
214arrayOpen :: B.Builder
219arrayClose :: B.Builder
228encodeObject :: BSC.ByteString -> (Text.Text, Value) -> [(Text.Text, Value)] -> B.Builder
230 encodeSequence objectOpen objectClose encodeField
233objectOpen :: B.Builder
238objectClose :: B.Builder
243encodeField :: BSC.ByteString -> (Text.Text, Value) -> B.Builder
244encodeField indent (key, value) =
245 encodeString key <> B.string7 ": " <> encodeHelp indent value
252encodeSequence :: B.Builder -> B.Builder -> (BSC.ByteString -> a -> B.Builder) -> BSC.ByteString -> a -> [a] -> B.Builder
253encodeSequence open close encodeEntry indent first rest =
259 B.byteString newIndent
262 newline <> B.byteString indent <> close
264 addValue field builder =
267 <> encodeEntry newIndent field
272 <> encodeEntry newIndent first
273 <> foldr addValue closer rest
276commaNewline :: B.Builder
290encodeString :: Text.Text -> B.Builder
292 B.char7 '"' <> Text.encodeUtf8BuilderEscaped escapeAscii txt <> B.char7 '"'
295{-# INLINE escapeAscii #-}
296escapeAscii :: BP.BoundedPrim W.Word8
298 BP.condB (== 0x5C {- \\ -}) (ascii2 ('\\','\\')) $
299 BP.condB (== 0x22 {- \" -}) (ascii2 ('\\','"' )) $
300 BP.condB (>= 0x20 ) (BP.liftFixedToBounded BP.word8) $
301 BP.condB (== 0x0A {- \n -}) (ascii2 ('\\','n' )) $
302 BP.condB (== 0x0D {- \r -}) (ascii2 ('\\','r' )) $
303 BP.condB (== 0x09 {- \t -}) (ascii2 ('\\','t' )) $
304 BP.liftFixedToBounded hexEscape -- fallback for chars < 0x20
306 hexEscape :: BP.FixedPrim W.Word8
307 hexEscape = (\c -> ('\\', ('u', fromIntegral c))) BP.>$<
308 BP.char8 >*< BP.char8 >*< BP.word16HexFixed
312ascii2 :: (Char, Char) -> BP.BoundedPrim a
314 BP.liftFixedToBounded $ const cs BP.>$< BP.char7 >*< BP.char7
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list