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] " 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