splitter-0.1.0.0: Main.hs
module Main (main) where
{-
- This is a remake of 'tee' written in Haskell for the Cross Platform benefits.
-}
import Control.Monad
import Data.List (intercalate)
import System.IO
import System.Environment ( getArgs )
import System.Exit
import System.Console.GetOpt
import System.FilePath
import System.Directory
import Text.Parsec.Error
import Data.Range.Range
import Data.Range.Parser
main :: IO ()
main = do
args <- getArgs
case getOpt Permute options args of
(flags, nonOpts, []) -> handleFlags flags nonOpts
(_, _, msgs) -> error $ concat msgs ++ usageInfo header options
data Flag
= Version
| Help
| Numbered
| Invert
| Start Int
| End Int
deriving(Eq)
header :: String
header = "Usage: split [options] <input>"
versionInfo :: String
versionInfo = "splitter-0.1 by Robert Massaioli (2012-2013)"
options :: [OptDescr Flag]
options =
[ Option "n" ["numbers"] (NoArg Numbered) "include line numbers in final output"
, Option "i" ["invert"] (NoArg Invert) "get the opposite of the lines specified"
, Option "Vv" ["version"] (NoArg Version) "print version number"
, Option "Hh" ["help"] (NoArg Help) "print this help message"
]
handleFlags :: [Flag] -> [String] -> IO ()
handleFlags flags inputs
| Help `elem` flags = putStrLn (usageInfo header options)
| Version `elem` flags = putStrLn versionInfo
| otherwise = case actualRanges of
Left error -> do
putStrLn . show $ error
exitWith (ExitFailure 1)
Right realRanges -> runSplit realRanges
where
actualRanges :: Either ParseError [Range Integer]
actualRanges = parseRanges (intercalate "," inputs)
runSplit :: [Range Integer] -> IO ()
runSplit ranges = do
lines <- liftM lines getContents
go 1 lines
where
go :: Integer -> [String] -> IO ()
go _ [] = return ()
go lineNum (line:ls) = do
when (inRanges realRanges lineNum) $ do
when includeNumbers . putStr $ show lineNum ++ " "
putStrLn line
go (lineNum + 1) ls
includeNumbers = Numbered `elem` flags
realRanges = if Invert `elem` flags
then invert ranges
else ranges