| 2 | 2 |
-- utilities used in the Plan 9 operating system. An NDBL file is a sequence
|
| 3 | 3 |
-- of groups, where each group is a multiset of key-value pairs. This will
|
| 4 | 4 |
-- cover the basics of NDBL; for a more in-depth explanation, consult
|
| 5 | |
-- [https://github.com/aisamanra/ndbl](the github page).
|
| 5 |
-- <https://github.com/aisamanra/ndbl the github page>.
|
| 6 | 6 |
--
|
| 7 | 7 |
-- Grouping in NDBL is done by
|
| 8 | 8 |
-- indentation: a new group is started by listing a key-value pair without
|
|
| 32 | 32 |
-- file=file1.txt
|
| 33 | 33 |
-- file=file2.txt
|
| 34 | 34 |
-- @
|
| 35 |
--
|
| 36 |
-- Be aware that NDBL guarantees that
|
| 37 |
--
|
| 38 |
-- @
|
| 39 |
-- fromJust . decode . encode == id
|
| 40 |
-- @
|
| 41 |
--
|
| 42 |
-- but does NOT guarantee that
|
| 43 |
--
|
| 44 |
-- @
|
| 45 |
-- encode . fromJust . decode == id
|
| 46 |
-- @
|
| 35 | 47 |
|
| 36 | |
module Data.NDBL ( -- * Convenience Types
|
| 37 | |
NDBL
|
| 38 | |
, Pair
|
| 39 | |
-- * MultiMap Representation
|
| 40 | |
-- $mm
|
| 41 | |
, decode
|
| 48 |
module Data.NDBL ( decode
|
| 42 | 49 |
, encode
|
| 43 | |
-- * List-Of-List Representation
|
| 44 | |
-- $ll
|
| 45 | |
, decodeList
|
| 46 | |
, encodeList
|
| 47 | |
-- * Flat List Representation
|
| 48 | |
-- $fl
|
| 49 | |
, decodeFlat
|
| 50 | |
, encodeFlat
|
| 51 | 50 |
) where
|
| 52 | 51 |
|
| 53 | |
import Data.MultiMap (MultiMap)
|
| 54 | |
import qualified Data.MultiMap as M
|
| 55 | |
import Data.Text (Text)
|
| 52 |
import Data.Text (Text)
|
| 56 | 53 |
|
| 57 | 54 |
import Data.NDBL.Parse
|
| 58 | 55 |
import Data.NDBL.Print
|
| 59 | 56 |
|
| 60 | |
type NDBL = [MultiMap Text Text]
|
| 61 | |
type Pair = (Text, Text)
|
| 62 | |
|
| 63 | |
-- $mm
|
| 64 | |
-- The most convenient way of parsing an NDBL file is as a
|
| 65 | |
-- multimap. In this case, the set of groups is given in-order
|
| 66 | |
-- as a list, and each individual group is represented as a
|
| 67 | |
-- multimap with text keys and values.
|
| 68 | |
--
|
| 69 | |
-- This does mean that the empty string is a possible value for the multimap,
|
| 70 | |
-- although all the keys will be at least one character long.
|
| 71 | |
|
| 72 | |
decode :: Text -> Maybe NDBL
|
| 57 |
-- | Decode an NDBL document to a list of lists of key-value pairs.
|
| 58 |
decode :: Text -> Maybe [[(Text, Text)]]
|
| 73 | 59 |
decode t = case pNDBL t of
|
| 74 | |
Right r -> Just (map M.fromList r)
|
| 75 | |
Left _ -> Nothing
|
| 76 | |
|
| 77 | |
encode :: NDBL -> Text
|
| 78 | |
encode = pretty . map M.toList
|
| 79 | |
|
| 80 | |
-- $ll
|
| 81 | |
-- Not every application wants to bring in a dependency on the
|
| 82 | |
-- multimap package, so functions that deal with lists of lists
|
| 83 | |
-- of tuples are also provided.
|
| 84 | |
|
| 85 | |
decodeList :: Text -> Maybe [[Pair]]
|
| 86 | |
decodeList t = case pNDBL t of
|
| 87 | 60 |
Right r -> Just r
|
| 88 | 61 |
Left _ -> Nothing
|
| 89 | 62 |
|
| 90 | |
encodeList :: [[Pair]] -> Text
|
| 91 | |
encodeList = pretty
|
| 63 |
-- | Decode an NDBL document to a list of lists of key-value pairs,
|
| 64 |
-- supplying the parse error from "attoparsec" if decoding fails.
|
| 65 |
decodeEither :: Text -> Either String [[(Text, Text)]]
|
| 66 |
decodeEither = pNDBL
|
| 92 | 67 |
|
| 93 | |
-- $fl
|
| 94 | |
-- Often a config file doesn't need grouping, so these are offered
|
| 95 | |
-- for pure utility.
|
| 96 | |
|
| 97 | |
decodeFlat :: Text -> Maybe [Pair]
|
| 98 | |
decodeFlat t = case pNDBL t of
|
| 99 | |
Right r -> Just $ concat r
|
| 100 | |
Left _ -> Nothing
|
| 101 | |
|
| 102 | |
encodeFlat :: [Pair] -> Text
|
| 103 | |
encodeFlat = pretty . map (:[])
|
| 68 |
-- | Encode an NDBL document to its 'Text' representation.
|
| 69 |
encode :: [[(Text, Text)]] -> Text
|
| 70 |
encode = pretty
|