----------------------------------------------------------------------------- -- | -- Module : Distribution.Text -- Copyright : Duncan Coutts 2007 -- -- Maintainer : cabal-devel@haskell.org -- Portability : portable -- -- This defines a 'Text' class which is a bit like the 'Read' and 'Show' -- classes. The difference is that is uses a modern pretty printer and parser -- system and the format is not expected to be Haskell concrete syntax but -- rather the external human readable representation used by Cabal. -- module Distribution.Text ( Text(..), display, simpleParse, ) where import qualified Distribution.Compat.ReadP as Parse import qualified Text.PrettyPrint as Disp import Data.Version (Version(Version)) import qualified Data.Char as Char (isDigit, isAlphaNum, isSpace) class Text a where disp :: a -> Disp.Doc parse :: Parse.ReadP r a display :: Text a => a -> String display = Disp.renderStyle style . disp where style = Disp.Style { Disp.mode = Disp.PageMode, Disp.lineLength = 79, Disp.ribbonsPerLine = 1.0 } simpleParse :: Text a => String -> Maybe a simpleParse str = case [ p | (p, s) <- Parse.readP_to_S parse str , all Char.isSpace s ] of [] -> Nothing (p:_) -> Just p -- ----------------------------------------------------------------------------- -- Instances for types from the base package instance Text Bool where disp = Disp.text . show parse = Parse.choice [ (Parse.string "True" Parse.+++ Parse.string "true") >> return True , (Parse.string "False" Parse.+++ Parse.string "false") >> return False ] instance Text Version where disp (Version branch _tags) -- Death to version tags!! = Disp.hcat (Disp.punctuate (Disp.char '.') (map Disp.int branch)) parse = do branch <- Parse.sepBy1 digits (Parse.char '.') tags <- Parse.many (Parse.char '-' >> Parse.munch1 Char.isAlphaNum) return (Version branch tags) --TODO: should we ignore the tags? where digits = do first <- Parse.satisfy Char.isDigit if first == '0' then return 0 else do rest <- Parse.munch Char.isDigit return (read (first : rest))