Don't emit extra newlines in serialization (fixes #9)
Getty Ritter
8 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 |