1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
25import Prelude hiding (null)
26import Control.Arrow ((***))
27import qualified Data.ByteString.Char8 as BSC
28import qualified Data.ByteString.Builder as B
29import qualified Data.Map as Map
30import qualified Data.Scientific as Sci
31import Data.Monoid ((<>))
32import qualified Data.Name as Name
33import qualified Data.Utf8 as Utf8
36import qualified Json.String as Json
45 | Object [(Json.String, Value)]
49 | Number Sci.Scientific
53array :: [Value] -> Value
58object :: [(Json.String, Value)] -> Value
63string :: Json.String -> Value
65 String (B.char7 '"' <> Json.toBuilder str <> B.char7 '"')
68name :: Name.Name -> Value
70 String (B.char7 '"' <> Name.toBuilder nm <> B.char7 '"')
83number :: Sci.Scientific -> Value
93dict :: (k -> Json.String) -> (v -> Value) -> Map.Map k v -> Value
94dict encodeKey encodeValue pairs =
95 Object $ map (encodeKey *** encodeValue) (Map.toList pairs)
98list :: (a -> Value) -> [a] -> Value
99list encodeEntry entries =
100 Array $ map encodeEntry entries
107chars :: [Char] -> Value -- TODO can this be done better? Look for examples.
109 String (B.char7 '"' <> B.stringUtf8 (escape chrs) <> B.char7 '"')
112escape :: [Char] -> [Char] -- TODO is this correct?
119 | c == '\n' -> '\\' : 'n' : escape cs
120 | c == '\"' -> '\\' : '"' : escape cs
121 | c == '\'' -> '\\' : '\'' : escape cs
122 | otherwise -> c : escape cs
129(==>) :: [Char] -> value -> (Json.String, value)
131 (Json.fromChars key, value)
138write :: FilePath -> Value -> IO ()
140 File.writeBuilder path (encode value <> "\n")
143writeUgly :: FilePath -> Value -> IO ()
144writeUgly path value =
145 File.writeBuilder path (encodeUgly value)
152encodeUgly :: Value -> B.Builder
158 Array (first : rest) ->
161 B.char7 ',' <> encodeUgly entry
163 B.char7 '[' <> encodeUgly first <> mconcat (map encodeEntry rest) <> B.char7 ']'
168 Object (first : rest) ->
170 encodeEntry char (key, entry) =
171 B.char7 char <> B.char7 '"' <> Utf8.toBuilder key <> B.string7 "\":" <> encodeUgly entry
173 encodeEntry '{' first <> mconcat (map (encodeEntry ',') rest) <> B.char7 '}'
179 B.string7 (if boolean then "true" else "false")
185 B.string7 (Sci.formatScientific Sci.Generic Nothing scientific)
195encode :: Value -> B.Builder
200encodeHelp :: BSC.ByteString -> Value -> B.Builder
201encodeHelp indent value =
206 Array (first : rest) ->
207 encodeArray indent first rest
212 Object (first : rest) ->
213 encodeObject indent first rest
219 B.string7 (if boolean then "true" else "false")
225 B.string7 (Sci.formatScientific Sci.Generic Nothing scientific)
235encodeArray :: BSC.ByteString -> Value -> [Value] -> B.Builder
237 encodeSequence arrayOpen arrayClose encodeHelp
240arrayOpen :: B.Builder
245arrayClose :: B.Builder
254encodeObject :: BSC.ByteString -> (Json.String, Value) -> [(Json.String, Value)] -> B.Builder
256 encodeSequence objectOpen objectClose encodeField
259objectOpen :: B.Builder
264objectClose :: B.Builder
269encodeField :: BSC.ByteString -> (Json.String, Value) -> B.Builder
270encodeField indent (key, value) =
271 B.char7 '"' <> Utf8.toBuilder key <> B.string7 "\": " <> encodeHelp indent value
278encodeSequence :: B.Builder -> B.Builder -> (BSC.ByteString -> a -> B.Builder) -> BSC.ByteString -> a -> [a] -> B.Builder
279encodeSequence open close encodeEntry indent first rest =
285 B.byteString newIndent
288 newline <> B.byteString indent <> close
290 addValue field builder =
293 <> encodeEntry newIndent field
298 <> encodeEntry newIndent first
299 <> foldr addValue closer rest
302commaNewline :: B.Builder
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