property-list-0.1: src/Data/PropertyList.hs
module Data.PropertyList
( -- * The basic property list types
-- |Property lists have several supported representations, but the main
-- one most end users will care about is 'PropertyList'. This is a basic
-- algebraic representation of property lists which can be constructed
-- using the polymorphic constructors described below and pattern-matched
-- using the polymorphic destructors (designed for convenient usage with
-- the ViewPatterns extension)
--
-- Also provided is the 'PartialPropertyList' representation, which is
-- a property list that is extended by adding a new constructor containing
-- some arbitrary type chosen by the user. It is mostly used as an
-- intermediate represenation for property lists that have been parsed
-- into their overall shape but not all elements have been parsed into
-- their final format.
--
-- The 'UnparsedXmlPlistItem' and 'UnparsedBPListRecord' types are used
-- with 'PartialPropertyList', and that is really their only purpose - to
-- represent unparseable items during intermediate stages of translation.
PropertyList
, PartialPropertyList
, UnparsedBPListRecord(..)
, UnparsedXmlPlistItem(..)
-- * Constructors and destructors for property lists
-- |The \"pl*\" operations construct 'PropertyList's, 'PartialPropertyList's,
-- or any other types defining an unlifted algebra for the 'PropertyListS'
-- signature.
--
-- The \"fromPl*\" operations are ViewPattern matching operations for
-- 'PropertyList', 'PartialPropertyList', or any other type defining
-- a 'Maybe'-lifted coalgebra for 'PropertyListS'.
--
-- The generality of these operations means that they can also be used
-- to directly generate or analyze \"external\" formats such as the XML
-- 'Plist' representation.
, plArray, fromPlArray
, plData, fromPlData
, plDate, fromPlDate
, plDict, fromPlDict
, plReal, fromPlReal
, plInt, fromPlInt
, plString, fromPlString
, plBool, fromPlBool
-- * The internal algebraic model for property lists
-- | Internally, conversions between various property list representations
-- are all defined in terms of universal algebra, which is basically just
-- fancy math-talk for \"very general interfaces that let you convert between
-- certain kinds of representations easily and efficiently\".
--
-- Most users do not need to understand this stuff - the class names are
-- only exported because they appear in the types of the constructors and
-- destructors. For more detailed info, see "Data.PropertyList.Algebra".
, PListAlgebra, PListCoalgebra
, InitialPList, TerminalPList
-- * Parsing and formatting property lists using any supported format
, readPropertyListFromFile
, writePropertyListToFile
-- * Parsing and formatting property lists using the Binary format
, readBinaryPropertyList
, encodeBinaryPropertyList
, readBinaryPropertyListFromFile
, writeBinaryPropertyListToFile
-- * Parsing and formatting property lists using the XML format
, readXmlPropertyList
, showXmlPropertyList
, readXmlPropertyListFromFile
, writeXmlPropertyListToFile
-- * Manipulating property lists
--
-- |This module exports a class ('PropertyListItem') and several functions
-- used to manipulate 'PropertyList's and their contents at a high level,
-- viewing and manipulating the data in the tree through ad-hoc
-- transformations.
--
-- For example, consider the following property list:
--
-- > myPlist = plDict $ M.fromList
-- > [ ("foo", plInt 4)
-- > , ("bar", plString "qux")
-- > , ("subDict", plDict $ M.fromList
-- > [ ("item 1", plString "This is item 1!")
-- > , ("item B", plBool True)
-- > ])
-- > ] :: PropertyList
--
-- Some typical actions you might do with a plist like this (Note that
-- in many cases a 'Just' is added - this is because the key-path operations
-- are defined in terms of 'Maybe' so that operations like 'setItemAtKeyPath'
-- or 'alterItemAtKeyPath' can create new items where none already exist):
--
-- > getItemAtKeyPath ["subDict", "item B"] (Just myPlist) :: Maybe Bool
--
-- (returns @Just True@)
--
-- > getItemAtKeyPath ["subDict"] (Just myPlist) :: Maybe (M.Map String String)
--
-- (returns @Just (M.fromList [(\"item 1\", \"This is item 1!\"), (\"item B\", \"YES\")])@.
-- Note the stringification of non-string items. In general, 'PropertyListItem'
-- instances are expected to do \"reasonable\" conversions to try and make sense
-- of what the user is asking the system to do.)
--
-- > setItemAtKeyPath ["omg", "lolwut"] (Just "roflcopter") (Just myPlist)
--
-- (returns a modified version of @myPlist@ with
-- @plDict $ M.fromList [(\"omg\",
-- plDict $ M.fromList [(\"lolwut\",
-- plString \"roflcopter\")])]@
-- added to the root dictionary)
--
-- > setItemAtKeyPath ["foo"] Nothing (Just myPlist)
--
-- (returns a modified version of @myPlist@ with the \"foo\" entry in the
-- root dictionary deleted)
--
-- > setItemAtKeyPath ["foo", "bar", "baz"] (Just "qux") Nothing
--
-- (returns a new dictionary with @plString \"qux\"@ at the key path foo.bar.baz)
--
, module Data.PropertyList.PropertyListItem
, module Data.PropertyList.KeyPath
) where
import Control.Exception (try, SomeException(..))
import Data.PropertyList.Algebra
import Data.PropertyList.Binary
import Data.PropertyList.Types
import Data.PropertyList.Xml
import Data.PropertyList.PropertyListItem
import Data.PropertyList.KeyPath
-- | Read a property list from a file, trying all supported property list formats.
-- Presently, the \"XML1\" and \"bplist00\" formats are supported. See also
-- 'readXmlPropertyListFromFile' and 'readBinaryPropertyListFromFile'.
readPropertyListFromFile :: FilePath -> IO PropertyList
readPropertyListFromFile file = do
partial <- readPartial file
case partial of
Left xml -> completePropertyListByM barf xml
Right bin -> completePropertyListByM barf bin
where
readPartial :: FilePath -> IO (Either
(PartialPropertyList UnparsedXmlPlistItem)
(PartialPropertyList UnparsedBPListRecord))
readPartial file = do
mbPartial <- try (readBinaryPartialPropertyListFromFile file)
case mbPartial of
Left SomeException{} -> fmap Left (readXmlPartialPropertyListFromFile file)
Right bin -> return (Right bin)
barf :: Show a => a -> IO PropertyList
barf unparsed = fail ("Unparseable item found: " ++ show unparsed)
-- | Write a property list to a file, using a \"preferred\" property list format.
-- Presently, that is the \"XML1\" format. See also 'writeXmlPropertyListToFile'.
writePropertyListToFile :: FilePath -> PropertyList -> IO ()
writePropertyListToFile = writeXmlPropertyListToFile