packages feed

pdfinfo 0.1.3.3 → 1.4.0

raw patch · 2 files changed

+60/−55 lines, 2 filesdep +process-extrasdep +textdep −processdep ~mtl

Dependencies added: process-extras, text

Dependencies removed: process

Dependency ranges changed: mtl

Files

pdfinfo.cabal view
@@ -1,21 +1,23 @@ name:                pdfinfo-version:             0.1.3.3+version:             1.4.0 synopsis:            Wrapper around the pdfinfo command. description:         Just a wrapper around the pdfinfo command. See man pdfinfo. license:             BSD3 license-file:        LICENSE author:              Chris Done maintainer:          chrisdone@gmail.com-copyright:           2010 Chris Done+copyright:           2013 Chris Done category:            Text build-type:          Simple-cabal-version:       >=1.2+cabal-version:       >=1.8 library-  ghc-options:        -O2 -Wall+  ghc-options:       -O2 -Wall   exposed-modules:   Text.PDF.Info   hs-source-dirs:    src/   build-depends:     base >= 4 && < 5,                      old-locale >= 1.0.0.0 && < 1.1,                      time >= 1.1 && < 1.5,-                     process >= 1.0 && < 1.2,-                     mtl >= 1.1 && < 2.2+                     process-extras,+                     text,+                     -- mtl-2.1 contains a severe bug+                     mtl >= 1.1 && < 2.1 || >= 2.1.1 && < 2.2
src/Text/PDF/Info.hs view
@@ -1,6 +1,9 @@-{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, ViewPatterns #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE OverloadedStrings #-} {-# OPTIONS -Wall #-}+ module Text.PDF.Info     (-- * Reading PDF info      pdfInfo@@ -16,44 +19,48 @@     ,readRight)     where -import Prelude-import Control.Monad.Error-import System.Process-import Control.Applicative-import Control.Arrow-import Data.Char-import Data.Time-import System.Locale-import Control.Exception as E+import           Control.Applicative+import           Control.Arrow+import           Control.Exception as E+import           Control.Monad.Error +import           Data.Text (Text)+import qualified Data.Text as T+import           Data.Time+import           Prelude+import           System.Exit+import           System.Locale+import           System.Process.Text+ -- | A type representing the output from the pdfinfo command. data PDFInfo = PDFInfo {-    pdfInfoTitle        :: Maybe String  -- ^ Title-  , pdfInfoSubject      :: Maybe String  -- ^ Subject-  , pdfInfoAuthor       :: Maybe String  -- ^ Author: E.g. Chris Done-  , pdfInfoCreator      :: Maybe String  -- ^ Creator: E.g. Microsoft Office Word 2007-  , pdfInfoProducer     :: Maybe String  -- ^ Producer: E.g. Microsoft Office Word 2007-  , pdfInfoCreationDate :: Maybe UTCTime -- ^ Creation Date-  , pdfInfoModDate      :: Maybe UTCTime -- ^ Modification Date-  , pdfInfoTagged       :: Maybe Bool    -- ^ Tagged?-  , pdfInfoPages        :: Maybe Integer -- ^ Pages: E.g. 238-  , pdfInfoEncrypted    :: Maybe Bool    -- ^ Encrypted?-  , pdfInfoPageSize     :: Maybe PDFSize -- ^ Page: E.g. 595.32 x 841.92 pts (A4)-  , pdfInfoFileSize     :: Maybe Integer -- ^ File: E.g. 4061737 bytes-  , pdfInfoOptimized    :: Maybe Bool    -- ^ Optimized?-  , pdfInfoPDFVersion   :: Maybe Double  -- ^ PDF: E.g. 1.5+    pdfInfoTitle        :: !(Maybe Text)    -- ^ Title+  , pdfInfoSubject      :: !(Maybe Text)    -- ^ Subject+  , pdfInfoAuthor       :: !(Maybe Text)    -- ^ Author: E.g. Chris Done+  , pdfInfoCreator      :: !(Maybe Text)    -- ^ Creator: E.g. Microsoft Office Word 2007+  , pdfInfoProducer     :: !(Maybe Text)    -- ^ Producer: E.g. Microsoft Office Word 2007+  , pdfInfoCreationDate :: !(Maybe UTCTime) -- ^ Creation Date+  , pdfInfoModDate      :: !(Maybe UTCTime) -- ^ Modification Date+  , pdfInfoTagged       :: !(Maybe Bool)    -- ^ Tagged?+  , pdfInfoPages        :: !(Maybe Integer) -- ^ Pages: E.g. 238+  , pdfInfoEncrypted    :: !(Maybe Bool)    -- ^ Encrypted?+  , pdfInfoPageSize     :: !(Maybe PDFSize) -- ^ Page: E.g. 595.32 x 841.92 pts (A4)+  , pdfInfoFileSize     :: !(Maybe Integer) -- ^ File: E.g. 4061737 bytes+  , pdfInfoOptimized    :: !(Maybe Bool)    -- ^ Optimized?+  , pdfInfoPDFVersion   :: !(Maybe Double)  -- ^ PDF: E.g. 1.5   } deriving Show  -- | Possible things that can go wrong while reading the info.-data PDFInfoError =-    ParseError String        -- ^ Couldn't parse a property value.-  | ProcessError IOException -- ^ Error to do with the pdfinfo process.-  | NoMessage                -- ^ No message given.-  | SomeError String         -- ^ Some nonspecific error.+data PDFInfoError+  = ParseError !String        -- ^ Couldn't parse a property value.+  | ProcessFailure !Text      -- ^ Process exited with this stderr.+  | ProcessError !IOException -- ^ Error to do with the pdfinfo process.+  | NoMessage                 -- ^ No message given.+  | SomeError String          -- ^ Some nonspecific error.   deriving Show  -- | Size of the PDF in pts.-data PDFSize = PDFSize { pdfSizeW :: Float, pdfSizeH :: Float }+data PDFSize = PDFSize { pdfSizeW :: !Float, pdfSizeH :: !Float }   deriving (Eq,Show)  instance Error PDFInfoError where noMsg = NoMessage; strMsg = SomeError@@ -65,11 +72,14 @@ -- running the process. pdfInfo :: MonadIO m => FilePath -> m (Either PDFInfoError PDFInfo) pdfInfo path = liftIO $ loadInfo `E.catch` ioErrorHandler where-  loadInfo = parse <$> readProcess "pdfinfo" [path] ""+  loadInfo = do (code,out,err) <- readProcessWithExitCode "pdfinfo" ["-enc","UTF-8",path] ""+                case code of+                  ExitSuccess -> return (parse out)+                  ExitFailure{} -> return (Left (ProcessFailure err))   ioErrorHandler = return . Left . ProcessError  -- | Parse PDFInfo's output.-parse :: String -> Either PDFInfoError PDFInfo+parse :: Text -> Either PDFInfoError PDFInfo parse out = runParse $   PDFInfo <$> string "Title"           <*> string "Subject"@@ -85,48 +95,41 @@           <*> integer "File size"           <*> bool "Optimized"           <*> floating "PDF version"-     where string = get id           date = get (>>= parseDate)           size = get (>>= parseSize)           bool = get $ fmap $ \yes -> yes == "yes"           floating = readIt           integer = readIt-          readIt :: Read a => String -> ParsePDFInfo (Maybe a)+          readIt :: Read a => Text -> ParsePDFInfo (Maybe a)           readIt = get (>>= readRight)--          properties = map split . lines $ out+          properties = map split . T.lines $ out           get f name =             case lookup name properties of-              Just ok -> catchError (Just <$> (f $ return $ trim ok))+              Just ok -> catchError (Just <$> (f $ return $ T.strip ok))                                     (\_ -> return Nothing)               Nothing -> return Nothing -          split = second (drop 2) . span (/=':')-          trim = bi reverse (dropWhile isSpace) . dropWhile isSpace+          split = second (T.drop 2) . T.span (/=':')  -- | Parse a page size. This is loosely defined.-parseSize :: String -> ParsePDFInfo PDFSize+parseSize :: Text -> ParsePDFInfo PDFSize parseSize s =-  case words s of+  case T.words s of     ((readRight -> Right x):"x":(readRight -> Right y):_) ->         return $ PDFSize x y     _ -> throwError $ ParseError $ "Unable to read size: " ++ show s  -- | Parse a date according to pdfinfo's format.-parseDate :: String -> ParsePDFInfo UTCTime+parseDate :: Text -> ParsePDFInfo UTCTime parseDate s =-  case parseTime defaultTimeLocale "%a %b %e %H:%M:%S %Y" s of+  case parseTime defaultTimeLocale "%a %b %e %H:%M:%S %Y" (T.unpack s) of     Just ok -> return ok     Nothing -> throwError $ ParseError $ "Unable to parse date: " ++ show s  -- | Read a value, maybe, allow misc trailing data.-readRight :: (MonadError PDFInfoError m,Read a) => String -> m a+readRight :: (MonadError PDFInfoError m,Read a) => Text -> m a readRight s =-  case reads s of+  case reads (T.unpack s) of     [(v,_)] -> return v     _ -> throwError $ ParseError $ "Couldn't read value: " ++ show s---- | Untwist a value, apply a function, twist it back.-bi :: (c1 -> c) -> (c -> c1) -> c1 -> c-bi g f = g . f . g