module Text.Wordlint.Args where
import Prelude hiding (Word)
import System.Console.CmdArgs
import Control.Monad
import Text.Wordlint.Words
import Text.Wordlint.Wordpairs
data Arguments = Arguments
{file :: String
,matchlength :: Int
,words_ :: Int
,lines_ :: Int
,percent_ :: Double
,nocaps :: Bool
,nopunct :: Bool
,blacklist :: String
,whitelist :: String
,all_ :: Bool
,human :: Bool
,sort_ :: String
}
deriving (Data, Typeable, Show, Read)
cliargs :: Arguments
cliargs = Arguments
{file = "" &= help "If not present, read from stdin" &= typFile
,matchlength = 5 &= help "Minimum length of matched words" &= typ "Int" &= groupname "Linting Options"
,words_ = 0 &= help "Maximum distance between matches - number of words. Default 250." &= typ "Int" &= name "w" &= groupname "Linting Options"
,lines_ = 0 &= help "Maximum distance between matches - number of lines" &= typ "Int" &= groupname "Linting Options"
,percent_ = 0 &= help "Maximum distance between matches - percentage of words." &= typ "Double" &= groupname "Linting Options"
,nocaps = False &= help "Ignore capitalization when finding matches." &= groupname "Filter Options"
,nopunct = False &= help "Ignore punctuation when finding matches." &= groupname "Filter Options"
,blacklist = "" &= help "File with newline-separated list of words to filter from output."
&= typFile &= groupname "Filter Options"
,whitelist = "" &= help "File with newline-separated list of words to allow in output."
&= typFile &= groupname "Filter Options"
,all_ = False &= help "Show all matched results regardless of intervening distance" &= groupname "Output Options"
,human = False &= help "Print resutlts in human-readable form." &= groupname "Output Options"
,sort_ = "position" &= help "Sort alphabetically, by position, or by intervening distance"
&= typ "word|position|distance|error" &= groupname "Output Options"
}
&= help "wordlint [OPTION]...[-f FILE]..."
&= summary "Wordlint v0.2.1.0 Gardner 2014-2016 WTFPL"
&= details ["Wordlint finds pairs of repeated words within a given"
,"numerical range of words, lines or percentage of the input."
,"This should be useful to curb redundancy in prose."]
checkFileStdin :: String -> Maybe String
checkFileStdin s | null s = Nothing
| otherwise = Just s
accessInputFileData :: Maybe String -> IO String
accessInputFileData f =
case f of
Nothing -> getContents
Just fp -> readFile fp
accessListFileData :: Maybe String -> IO String
accessListFileData f =
case f of
Nothing -> return ""
Just fp -> readFile fp
setListData :: String -> Maybe [String]
setListData a | null a = Nothing
| otherwise = Just $ lines a
runFilterFlags :: (NumOps a) => Words a -> Arguments -> Maybe [String] -> Maybe [String] -> Words a
runFilterFlags w arg blist wlist = runWhitelistFilter wlist $ runCapsFilter arg $ runBlacklistFilter blist $ runPunctFilter arg $ runBlacklistFilter blist w
runPunctFilter :: (NumOps a) => Arguments -> Words a -> Words a
runPunctFilter arg wordlist = if nopunct arg
then filterWordPunctuation wordlist
else wordlist
runCapsFilter :: (NumOps a) => Arguments -> Words a -> Words a
runCapsFilter arg wordlist = if nocaps arg
then filterWordCapitalization wordlist
else wordlist
runBlacklistFilter :: (NumOps a) => Maybe [String] -> Words a -> Words a
runBlacklistFilter blist wordlist = case blist of
Nothing -> wordlist
Just x -> filterWordBlacklist wordlist x
runWhitelistFilter :: (NumOps a) => Maybe [String] -> Words a -> Words a
runWhitelistFilter wlist wordlist = case wlist of
Nothing -> wordlist
Just x -> filterWordWhitelist wordlist x
checkSortFlag :: (Num a, Ord a, NumOps a) => String -> Wordpairs a -> Wordpairs a
checkSortFlag x y | x == "position" = sortWordPairsByPosition y
| x == "distance" = sortWordPairsByDistance y
| x == "word" = y
| x == "error" = sortWordPairsByPosition y
| otherwise = y
checkIfHumanHeader :: Arguments -> IO ()
checkIfHumanHeader cargs = when (human cargs)
$ putStrLn ("Running "
++ getTypeOfCheck cargs
++ " check[s] on "
++ file cargs
++ "\nWith minimum distance[s] of "
++ getTypeOfCheck cargs
++ " between words of length "
++ show (matchlength cargs) ++ "\n")
getTypeOfCheck :: Arguments -> String
getTypeOfCheck c = isWordsFlag c ++ " " ++ isLinesFlag c ++ " " ++ isPercentFlag c
getTypeNumbers :: Arguments -> String
getTypeNumbers c = convertWordsFlag c ++ " " ++
convertLinesFlag c ++ " " ++ convertPercentFlag c
isWordsFlag :: Arguments -> String
isWordsFlag c | words_ c /= 0 ||
words_ c == 0 && lines_ c == 0 && percent_ c == 0 = "word"
| otherwise = ""
isLinesFlag :: Arguments -> String
isLinesFlag c | lines_ c /= 0 = "line"
| otherwise = ""
isPercentFlag :: Arguments -> String
isPercentFlag c | percent_ c /= 0 = "percentage"
| otherwise = ""
convertWordsFlag :: Arguments -> String
convertWordsFlag c | words_ c /= 0 = show $ words_ c
| otherwise = ""
convertLinesFlag :: Arguments -> String
convertLinesFlag c | lines_ c /= 0 = show $ lines_ c
| otherwise = ""
convertPercentFlag :: Arguments -> String
convertPercentFlag c | percent_ c /= 0 = show $ percent_ c
| otherwise = ""