Don't emit extra newlines in serialization (fixes #9)
Getty Ritter
7 years ago
69 | 69 | |
70 | 70 | import Data.Ini.Config.Raw |
71 | 71 | |
72 |
-- |
|
72 | -- * Utility functions | |
73 | ||
74 | -- | This is a | |
75 | -- <https://hackage.haskell.org/package/lens lens>-compatible | |
76 | -- type alias | |
73 | 77 | type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t |
74 | 78 | |
75 | 79 | lkp :: Text -> Seq (Text, a) -> Maybe a |
82 | 86 | rmv :: Text -> Seq (Field s) -> Seq (Field s) |
83 | 87 | rmv n = Seq.filter (\ f -> T.toLower (fieldName f) /= T.toLower n) |
84 | 88 | |
85 | fieldName :: Field s -> Text | |
86 | fieldName (Field _ FieldDescription { fdName = n }) = n | |
87 | fieldName (FieldMb _ FieldDescription { fdName = n }) = n | |
88 | ||
89 | fieldComment :: Field s -> Seq Text | |
90 | fieldComment (Field _ FieldDescription { fdComment = n }) = n | |
91 | fieldComment (FieldMb _ FieldDescription { fdComment = n }) = n | |
92 | ||
89 | -- The & operator is really useful here, but it didn't show up in | |
90 | -- earlier versions, so it gets redefined here. | |
93 | 91 | #if __GLASGOW_HASKELL__ < 710 |
94 | 92 | {- | '&' is a reverse application operator. This provides notational |
95 | 93 | convenience. Its precedence is one higher than that of the |
99 | 97 | a & f = f a |
100 | 98 | infixl 1 & |
101 | 99 | #endif |
100 | ||
101 | -- * Type definitions | |
102 | 102 | |
103 | 103 | -- | A value of type "FieldValue" packages up a parser and emitter |
104 | 104 | -- function into a single value. These are used for bidirectional |
155 | 155 | data Field s |
156 | 156 | = forall a. Eq a => Field (Lens s s a a) (FieldDescription a) |
157 | 157 | | forall a. Eq a => FieldMb (Lens s s (Maybe a) (Maybe a)) (FieldDescription a) |
158 | ||
159 | -- convenience accessors for things in a Field | |
160 | fieldName :: Field s -> Text | |
161 | fieldName (Field _ FieldDescription { fdName = n }) = n | |
162 | fieldName (FieldMb _ FieldDescription { fdName = n }) = n | |
163 | ||
164 | fieldComment :: Field s -> Seq Text | |
165 | fieldComment (Field _ FieldDescription { fdComment = n }) = n | |
166 | fieldComment (FieldMb _ FieldDescription { fdComment = n }) = n | |
158 | 167 | |
159 | 168 | -- | A 'FieldDescription' is a declarative representation of the |
160 | 169 | -- structure of a field. This includes the name of the field and the |
417 | 426 | { vLineNo = 0 |
418 | 427 | , vName = fdName descr |
419 | 428 | , vValue = val |
420 |
, vComments = |
|
429 | , vComments = mkComments (fdComment descr) | |
421 | 430 | , vCommentedOut = optional |
422 | 431 | , vDelimiter = '=' |
423 | 432 | } |
506 | 515 | F.for sections $ \ (name, sec) -> do |
507 | 516 | let err = (Left ("Unexpected top-level section: " ++ show name)) |
508 | 517 | Section _ spec _ <- maybe err Right |
509 |
(F.find (\ (Section n _ _) -> |
|
518 | (F.find (\ (Section n _ _) -> T.toLower n == name) fields) | |
510 | 519 | newVals <- updateIniSection s (isVals sec) spec pol |
511 | 520 | return (name, sec { isVals = newVals }) |
512 | 521 | |
653 | 662 | > user = terry |
654 | 663 | |
655 | 664 | We'd like to parse this INI file into a @Config@ type which we've |
656 | defined like this, using "lens" or a similar library to provide | |
657 | lenses: | |
665 | defined like this, using | |
666 | <https://hackage.haskell.org/package/lens lens> or a similar library | |
667 | to provide lenses: | |
658 | 668 | |
659 | 669 | > data Config = Config |
660 | 670 | > { _cfHost :: String |