gdritter repos config-ini / 7c6bee1
Renamed skipIfMissing and added allOptional Getty Ritter 7 years ago
2 changed file(s) with 34 addition(s) and 16 deletion(s). Collapse all Expand all
3737 confPort .= field "port" number
3838 & comment [ "the port in question" ]
3939 confUseEncryption .= flag "encryption"
40 & skipIfMissing
40 & optional
4141 & comment [ "whether to use encryption (defaults to true)" ]
4242 confHostname .= field "hostname" text
43 & skipIfMissing
43 & optional
4444 & comment [ "hostname to connect to (optional)" ]
4545 confConfigFile .=? field "config file" text
4646 & placeholderValue "<file path>"
47 section "LOCAL" $ do
47 section "LOCAL" & allOptional $ do
4848 confPath .= field "path" (listWithSeparator ":" text)
49 & skipIfMissing
5049 & comment [ "a colon-separated path list" ]
5150
5251 example :: Text
3434 -- * Section-Level Parsing
3535 -- $sections
3636 , section
37 , allOptional
3738
3839 -- * Field-Level Parsing
3940 -- $fields
4445 , flag
4546 , comment
4647 , placeholderValue
47 , skipIfMissing
48 , optional
4849
4950 -- * FieldValues
5051 -- $fieldvalues
6566 ) where
6667
6768 import Control.Monad.Trans.State.Strict (State, runState, modify)
69 import qualified Control.Monad.Trans.State.Strict as State
6870 import qualified Data.Foldable as F
6971 #if __GLASGOW_HASKELL__ >= 710
7072 import Data.Function ((&))
7173 #endif
7274 import Data.Monoid ((<>))
73 import Data.Sequence ((<|), Seq, ViewL(..))
75 import Data.Sequence ((<|), Seq, ViewL(..), ViewR(..))
7476 import qualified Data.Sequence as Seq
7577 import Data.Text (Text)
7678 import qualified Data.Text as T
242244 section :: Text -> SectionSpec s () -> IniSpec s ()
243245 section name (SectionSpec mote) = IniSpec $ do
244246 let fields = runBidirM mote
245 modify (Seq.|> Section (normalize name) fields (allOptional fields))
246
247 allOptional :: (Seq (Field s)) -> Bool
248 allOptional = all isOptional
247 modify (Seq.|> Section (normalize name) fields (allFieldsOptional fields))
248
249 allFieldsOptional :: (Seq (Field s)) -> Bool
250 allFieldsOptional = all isOptional
249251 where isOptional (Field _ fd) = fdSkipIfMissing fd
250252 isOptional (FieldMb _ _) = True
253
254 allOptional
255 :: (SectionSpec s () -> IniSpec s ())
256 -> (SectionSpec s () -> IniSpec s ())
257 allOptional k spec = IniSpec $ do
258 let IniSpec comp = k spec
259 comp
260 modify (\ s -> case Seq.viewr s of
261 EmptyR -> s
262 rs :> Section name fields _ ->
263 rs Seq.|> Section name (fmap makeOptional fields) True)
264
265 makeOptional :: Field s -> Field s
266 makeOptional (Field l d) = Field l d { fdSkipIfMissing = True }
267 makeOptional (FieldMb l d) = FieldMb l d { fdSkipIfMissing = True }
251268
252269 data Section s = Section NormalizedText (Seq (Field s)) Bool
253270
339356
340357 -- | If the field is not found in parsing, simply skip instead of
341358 -- raising an error or setting anything.
342 skipIfMissing :: FieldDescription t -> FieldDescription t
343 skipIfMissing fd = fd { fdSkipIfMissing = True }
359 optional :: FieldDescription t -> FieldDescription t
360 optional fd = fd { fdSkipIfMissing = True }
344361
345362 infixr 0 .=
346363 infixr 0 .=?
456473 s' <- parseFields s (Seq.viewl fs) v
457474 parseSections s' (Seq.viewl rest) i
458475 | opt = parseSections s (Seq.viewl rest) i
459 | otherwise = Left ("Unable to find section " ++ show name)
476 | otherwise = Left ("Unable to find section " ++
477 show (normalizedText name))
460478
461479 -- Now that we've got 'set', we can walk the field descriptions and
462480 -- find them. There's some fiddly logic, but the high-level idea is
472490 parseFields (set l value s) (Seq.viewl fs) sect
473491 | fdSkipIfMissing descr =
474492 parseFields s (Seq.viewl fs) sect
475 | otherwise = Left ("Unable to find field " ++ show (fdName descr))
493 | otherwise = Left ("Unable to find field " ++
494 show (normalizedText (fdName descr)))
476495 parseFields s (FieldMb l descr Seq.:< fs) sect
477496 | Just v <- lkp (fdName descr) (isVals sect) = do
478497 value <- fvParse (fdValue descr) (T.strip (vValue v))
499518 , isStartLine = 0
500519 , isEndLine = 0
501520 , isComments = Seq.empty
502 } where mkIniValue val descr optional =
521 } where mkIniValue val descr opt =
503522 ( fdName descr
504523 , IniValue
505524 { vLineNo = 0
506525 , vName = actualText (fdName descr)
507526 , vValue = val
508527 , vComments = mkComments (fdComment descr)
509 , vCommentedOut = optional
528 , vCommentedOut = opt
510529 , vDelimiter = '='
511530 }
512531 )