sak-0.1.0.1: src/Main.hs
{-# LANGUAGE OverloadedStrings #-}
module Main ( main ) where
import Compression
import qualified Data.ByteString.Lazy as BSL
import Data.Semigroup ((<>))
import Options.Applicative
import Version (allVersionsString)
data Command = Decompress !FilePath !(Maybe FilePath)
| Compress !FilePath !FilePath !CompressionLevel
| Transcode !FilePath !FilePath !CompressionLevel
| Verify !FilePath
decompressFile :: FilePath -- ^ Compressed file
-> FilePath -- ^ Output
-> IO ()
decompressFile inp o = BSL.writeFile o =<< f inp
where f = toFileDecompressor (detectCompression inp)
compressFile :: CompressionLevel
-> FilePath -- ^ Input file
-> FilePath -- ^ Compressed output
-> IO ()
compressFile lvl inp o = BSL.writeFile o =<< f inp
where f = toFileCompressor (detectCompression o) lvl
run :: Command -> IO ()
run (Decompress i Nothing) = decompressFile i (uncompressedExt i)
run (Decompress i (Just o)) = decompressFile i o
run (Compress i o lvl) = compressFile lvl i o
run (Transcode i o lvl) = do
let cO = detectCompression o
guessSz <- case cO of
Lzip -> Just . (8*) . fromIntegral <$> fileSize i
_ -> pure Nothing
BSL.writeFile o . toCompressor cO lvl guessSz =<< toFileDecompressor (detectCompression i) i
run (Verify i) = check (detectCompression i) =<< BSL.readFile i
fileCompletions :: HasCompleter f => Mod f a
fileCompletions = completer (bashCompleter "file -o plusdirs")
inpFile :: Parser FilePath
inpFile = fileHelp "Input file"
verify :: Parser Command
verify = Verify <$> inpFile
compressionLevel :: Parser CompressionLevel
compressionLevel =
compressCustom
<|> compressBest
<|> compressFast
compressCustom :: Parser CompressionLevel
compressCustom =
Custom <$>
option auto
(long "compression-level"
<> short 'l'
<> value 6
<> metavar "LVL"
<> help "Compression level (usually 0-9)"
<> completer (listCompleter (show <$> [(0::Int)..22]))
)
compressBest :: Parser CompressionLevel
compressBest =
flag' Best (long "best")
compressFast :: Parser CompressionLevel
compressFast =
flag' Fastest (long "fastest")
transcode :: Parser Command
transcode = Transcode
<$> inpFile
<*> fileHelp "Output"
<*> compressionLevel
decompress :: Parser Command
decompress = Decompress
<$> fileHelp "File to decompress"
<*> optional outFile
outFile :: Parser FilePath
outFile = fileHelp "Decompressed output"
compress :: Parser Command
compress = Compress
<$> fileHelp "File to compress"
<*> fileHelp "Compressed output"
<*> compressionLevel
fileHelp :: String -> Parser FilePath
fileHelp helpTxt =
argument str
(metavar "FILE"
<> fileCompletions
<> help helpTxt)
cmd :: Parser Command
cmd = hsubparser
(command "decompress" (info decompress (progDesc "Decompress a file"))
<> command "compress" (info compress (progDesc "Compress a file"))
<> command "transcode" (info transcode (progDesc "Convert a file's compression"))
<> command "verify" (info verify (progDesc "Check the integrity of a compressed file"))
)
versionMod :: Parser (a -> a)
versionMod = infoOption allVersionsString (short 'V' <> long "version" <> help "Show version")
topLevel :: ParserInfo Command
topLevel = info (helper <*> versionMod <*> cmd)
(fullDesc
<> progDesc "A Haskell compressor tool"
<> header "sak - a Swiss-army knife for compression")
main :: IO ()
main = run =<< execParser topLevel