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
|