42 lines
1.5 KiB
Haskell
42 lines
1.5 KiB
Haskell
|
import Control.Monad.State (MonadState(..), evalStateT)
|
||
|
import Control.Monad.Except.IOH (handle)
|
||
|
import Control.Monad.Trans (lift)
|
||
|
import qualified Data.ByteString.Char8 as BS (readFile)
|
||
|
import qualified Data.ByteString.Lazy.Char8 as Lazy (writeFile)
|
||
|
import Data.Map ((!), fromSet)
|
||
|
import qualified Data.Set as Set (fromList)
|
||
|
import PDF (Document, UnifiedLayers(..), parseDocument, render)
|
||
|
import PDF.Box (at)
|
||
|
import PDF.Pages (Pages(..))
|
||
|
import System.Environment (getArgs)
|
||
|
import System.Exit (die)
|
||
|
import System.FilePath (replaceBaseName, takeBaseName)
|
||
|
import Text.Read (readEither)
|
||
|
|
||
|
parseRange :: String -> Either String (Int, Int)
|
||
|
parseRange = evalStateT $ do
|
||
|
from <- lift . readEither =<< state (break (== '-'))
|
||
|
get >>= makeRange from
|
||
|
where
|
||
|
makeRange from "" = return (from, from)
|
||
|
makeRange from (_:to) = (,) from <$> lift (readEither to)
|
||
|
|
||
|
cut :: (Int, Int) -> Document -> IO Document
|
||
|
cut (p1, p2) doc = ((
|
||
|
at UnifiedLayers .at Pages $ \pages ->
|
||
|
return $ fromSet (pages!) $ Set.fromList [pMin .. pMax]
|
||
|
) doc) `handle` die
|
||
|
where
|
||
|
(pMin, pMax) = (min p1 p2, max p1 p2)
|
||
|
|
||
|
main :: IO ()
|
||
|
main = do
|
||
|
[inputPath, inputRange] <- getArgs
|
||
|
range <- catchLeft $ parseRange inputRange
|
||
|
doc <- catchLeft =<< parseDocument <$> BS.readFile inputPath
|
||
|
Lazy.writeFile (outputPath inputPath inputRange) . render =<< cut range doc
|
||
|
where
|
||
|
catchLeft = either die return
|
||
|
outputPath fileName range =
|
||
|
replaceBaseName fileName (takeBaseName fileName ++ "_p" ++ range)
|