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.Map as Map
28import Data.Monoid ((<>))
29import qualified Data.Text as Text
30import qualified Numeric
31import System.IO (IOMode(WriteMode), withBinaryFile)
40 | Object [(String, Value)]
47array :: [Value] -> Value
52object :: [(String,Value)] -> Value
57text :: Text.Text -> Value
59 String (encodeString (Text.unpack txt))
62string :: String -> Value
64 String (encodeString str)
82dict :: (k -> String) -> (v -> Value) -> Map.Map k v -> Value
83dict encodeKey encodeValue pairs =
84 Object $ map (encodeKey *** encodeValue) (Map.toList pairs)
87list :: (a -> Value) -> [a] -> Value
88list encodeEntry entries =
89 Array $ map encodeEntry entries
96(==>) :: a -> b -> (a, b)
105write :: FilePath -> Value -> IO ()
107 withBinaryFile path WriteMode $ \handle ->
108 B.hPutBuilder handle (encode value)
111writeUgly :: FilePath -> Value -> IO ()
112writeUgly path value =
113 withBinaryFile path WriteMode $ \handle ->
114 B.hPutBuilder handle (encodeUgly value)
121encodeUgly :: Value -> B.Builder
127 Array (first : rest) ->
130 B.char7 ',' <> encodeUgly entry
132 B.char7 '[' <> encodeUgly first <> mconcat (map encodeEntry rest) <> B.char7 ']'
137 Object (first : rest) ->
139 encodeEntry char (key, entry) =
140 B.char7 char <> encodeString key <> B.char7 ':' <> encodeUgly entry
142 encodeEntry '[' first <> mconcat (map (encodeEntry ',') rest) <> B.char7 ']'
148 B.string7 (if boolean then "true" else "false")
161encode :: Value -> B.Builder
166encodeHelp :: BSC.ByteString -> Value -> B.Builder
167encodeHelp indent value =
172 Array (first : rest) ->
173 encodeArray indent first rest
178 Object (first : rest) ->
179 encodeObject indent first rest
185 B.string7 (if boolean then "true" else "false")
198encodeArray :: BSC.ByteString -> Value -> [Value] -> B.Builder
200 encodeSequence arrayOpen arrayClose encodeHelp
203arrayOpen :: B.Builder
208arrayClose :: B.Builder
217encodeObject :: BSC.ByteString -> (String, Value) -> [(String, Value)] -> B.Builder
219 encodeSequence objectOpen objectClose encodeField
222objectOpen :: B.Builder
227objectClose :: B.Builder
232encodeField :: BSC.ByteString -> (String, Value) -> B.Builder
233encodeField indent (key, value) =
234 encodeString key <> B.string7 ": " <> encodeHelp indent value
241encodeSequence :: B.Builder -> B.Builder -> (BSC.ByteString -> a -> B.Builder) -> BSC.ByteString -> a -> [a] -> B.Builder
242encodeSequence open close encodeEntry indent first rest =
248 B.byteString newIndent
251 newline <> B.byteString indent <> close
253 addValue field builder =
256 <> encodeEntry newIndent field
261 <> encodeEntry newIndent first
262 <> foldr addValue closer rest
265commaNewline :: B.Builder
279encodeString :: String -> B.Builder
281 B.char7 '"' <> escape str <> B.char7 '"'
284escape :: String -> B.Builder
295 B.stringUtf8 front <> escapeChar char <> escape rest
298isEscape :: Char -> Bool
300 c == '\"' || c == '\\' || c < '\x20'
303escapeChar :: Char -> B.Builder
306 '\"' -> B.string7 "\\\""
307 '\\' -> B.string7 "\\\\"
308 '\n' -> B.string7 "\\n"
309 '\r' -> B.string7 "\\r"
310 '\t' -> B.string7 "\\t"
311 _ -> if char < '\x20' then toEscapeCode char else B.charUtf8 char
314toEscapeCode :: Char -> B.Builder
318 Numeric.showHex (fromEnum char) ""
321 "\\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