module Main( main ) where
import System ( getArgs, system, exitWith )
import System.Console.GetOpt
import System.Posix.Files
main:: IO()
main = do
args <- getArgs
case getOpt RequireOrder options args of
([Edit], _, []) -> spawnEditor
([Help], _, _) -> putStrLn \$ usageInfo header options ++ description
([], [], []) -> displayTodo
([], nonOpts, []) -> addTodo nonOpts
([], [], msgs) -> error \$ concat msgs ++ usageInfo header options ++ description
_ -> error \$ usageInfo header options ++ description
data Flag = Edit | Help
options :: [OptDescr Flag]
options = [
Option ['e'] ["edit"] (NoArg Edit) "edit the todo list",
Option ['h'] ["help"] (NoArg Help) "display this help"
]
header :: String
header = "Usage: todo [OPTIONS] [todo item]"
description :: String
description = unlines [ ""
, "The default operation is to just cat the TODO file. Calling todo with"
, "a non-option argument will add that argument to the TODO file."
]
todoFile :: String
todoFile = "TODO"
-- TODO -- needs to check for existing emacs process first and run emacsclient in that case...
spawnEditor :: IO ()
spawnEditor = system ("emacs " ++ todoFile) >>= exitWith
addTodo :: [String] -> IO ()
addTodo nonOpts = do
print "Updating todo list..."
appendFile todoFile \$ (unwords nonOpts) ++ "\n"
displayTodo :: IO ()
displayTodo = fileExist todoFile >>=
(\a -> if a
then readFile todoFile >>= putStr . removeDones
else putStrLn "nothing to do!")
removeDones :: String -> String
removeDones = unlines . filter (not . contains "DONE") . lines
contains :: String -> String -> Bool
contains target source = any (== target) \$ words source
It's not the greatest Haskell code I'm sure, but its the first I've done that wasn't pure functional code, it works, and was fun to sort out.
ps. Looks like my attempts at formatting code were less than fully successful. It's all there, just click and drag to select it... sorry