1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
24import Prelude hiding (null)
25import Control.Arrow ((***))
26import qualified Data.ByteString.Char8 as BSC
27import qualified Data.ByteString.Builder as B
28import qualified Data.Map as Map
29import qualified Data.Scientific as Sci
30import Data.Monoid ((<>))
31import qualified Data.Text as Text
32import qualified Numeric
33import System.IO (IOMode(WriteMode), withBinaryFile)
42 | Object [(String, Value)]
46 | Number Sci.Scientific
50array :: [Value] -> Value
55object :: [(String,Value)] -> Value
60text :: Text.Text -> Value
62 String (encodeString (Text.unpack txt))
65string :: String -> Value
67 String (encodeString str)
80number :: Sci.Scientific -> Value
90dict :: (k -> String) -> (v -> Value) -> Map.Map k v -> Value
91dict encodeKey encodeValue pairs =
92 Object $ map (encodeKey *** encodeValue) (Map.toList pairs)
95list :: (a -> Value) -> [a] -> Value
96list encodeEntry entries =
97 Array $ map encodeEntry entries
104(==>) :: a -> b -> (a, b)
113write :: FilePath -> Value -> IO ()
115 withBinaryFile path WriteMode $ \handle ->
116 B.hPutBuilder handle (encode value)
119writeUgly :: FilePath -> Value -> IO ()
120writeUgly path value =
121 withBinaryFile path WriteMode $ \handle ->
122 B.hPutBuilder handle (encodeUgly value)
129encodeUgly :: Value -> B.Builder
135 Array (first : rest) ->
138 B.char7 ',' <> encodeUgly entry
140 B.char7 '[' <> encodeUgly first <> mconcat (map encodeEntry rest) <> B.char7 ']'
145 Object (first : rest) ->
147 encodeEntry char (key, entry) =
148 B.char7 char <> encodeString key <> B.char7 ':' <> encodeUgly entry
150 encodeEntry '{' first <> mconcat (map (encodeEntry ',') rest) <> B.char7 '}'
156 B.string7 (if boolean then "true" else "false")
162 B.string7 (Sci.formatScientific Sci.Generic Nothing scientific)
172encode :: Value -> B.Builder
177encodeHelp :: BSC.ByteString -> Value -> B.Builder
178encodeHelp indent value =
183 Array (first : rest) ->
184 encodeArray indent first rest
189 Object (first : rest) ->
190 encodeObject indent first rest
196 B.string7 (if boolean then "true" else "false")
202 B.string7 (Sci.formatScientific Sci.Generic Nothing scientific)
212encodeArray :: BSC.ByteString -> Value -> [Value] -> B.Builder
214 encodeSequence arrayOpen arrayClose encodeHelp
217arrayOpen :: B.Builder
222arrayClose :: B.Builder
231encodeObject :: BSC.ByteString -> (String, Value) -> [(String, Value)] -> B.Builder
233 encodeSequence objectOpen objectClose encodeField
236objectOpen :: B.Builder
241objectClose :: B.Builder
246encodeField :: BSC.ByteString -> (String, Value) -> B.Builder
247encodeField indent (key, value) =
248 encodeString key <> B.string7 ": " <> encodeHelp indent value
255encodeSequence :: B.Builder -> B.Builder -> (BSC.ByteString -> a -> B.Builder) -> BSC.ByteString -> a -> [a] -> B.Builder
256encodeSequence open close encodeEntry indent first rest =
262 B.byteString newIndent
265 newline <> B.byteString indent <> close
267 addValue field builder =
270 <> encodeEntry newIndent field
275 <> encodeEntry newIndent first
276 <> foldr addValue closer rest
279commaNewline :: B.Builder
293encodeString :: String -> B.Builder
295 B.char7 '"' <> escape str <> B.char7 '"'
298escape :: String -> B.Builder
309 B.stringUtf8 front <> escapeChar char <> escape rest
312isEscape :: Char -> Bool
314 c == '\"' || c == '\\' || c < '\x20'
317escapeChar :: Char -> B.Builder
320 '\"' -> B.string7 "\\\""
321 '\\' -> B.string7 "\\\\"
322 '\n' -> B.string7 "\\n"
323 '\r' -> B.string7 "\\r"
324 '\t' -> B.string7 "\\t"
325 _ -> if char < '\x20' then toEscapeCode char else B.charUtf8 char
328toEscapeCode :: Char -> B.Builder
332 Numeric.showHex (fromEnum char) ""
335 "\\u" ++ replicate (4 - length hex) '0' ++ hex
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