Skip to content

Commit

Permalink
add, view, update and remove functions
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmachina committed Oct 2, 2017
0 parents commit 65ba9a0
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.o
*.hi
todo
170 changes: 170 additions & 0 deletions Actions.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}

module Actions
(
add
,remove
,view
,todoDone
,update
) where

import System.IO
import System.Posix.Files
import System.Posix.Types
import System.Directory
import System.Environment
import Data.List
import Control.DeepSeq
import GHC.IO
import GHC.Generics
import qualified Data.Char as Char
data Todo = Todo
{
todoId :: Int
, title :: String
, done :: Bool
} deriving (Show, Read, Eq,Generic, NFData)

type TodoList = [Todo]

data Filter = Done | Pending deriving (Show, Read)

parseContents :: String -> TodoList
parseContents contents =
if contents == ""
then []
else read contents :: TodoList

add :: [String] -> IO ()
add [title] = do
(todoList, fileName) <- extractTodoList
let nextId = if todoList == []
then 1
else (todoId $ last todoList) + 1
todo = Todo { todoId = nextId
, title = title
, done = False }
newTodoList = todoList ++ [todo]
message = "\nTODO Added: \n\n" ++ (showStrTodo todo) ++ "\n"

(todoList,fileName) `deepseq` writeFile fileName $ show newTodoList

putStrLn message

remove :: [String] -> IO ()
remove [numberString] = do
(todoList, fileName) <- extractTodoList
let todoId' = read numberString :: Int
maybeTodo = getTodoById todoId' todoList
case maybeTodo of
Just todo -> do
let newTodoList = delete todo todoList
message = "\n\nTODO Removed:\n\n" ++ showStrTodo todo ++ "\n"
(todoList, fileName) `deepseq` writeFile fileName $ show newTodoList
putStrLn message
Nothing -> putStrLn "TODO not found!"
parseList :: TodoList -> String
parseList [] = "Oops, no todos added yet \nUse todos add 'some task'"
parseList todoList =
foldl (\t1 t2 -> t1 ++ "\n" ++ (showStrTodo t2)) "" todoList

filterDone :: TodoList -> TodoList
filterDone todoList =
filter (\t -> done t == True) todoList

capitalize :: String -> String
capitalize str = Char.toUpper (head str) : tail str

toUpper :: String -> String
toUpper str = map (\c -> Char.toUpper c) str

filterPending :: TodoList -> TodoList
filterPending todoList =
filter (\t -> done t == False) todoList
view :: [String] -> IO ()
view [] = do
homeDir <- getHomeDirectory
let fileName = homeDir ++ "/.todos"
contents <- readFile fileName
let todoList = parseContents contents
header = "\n" ++ "TODO - Showing Todo List \n\n"
putStr $ header ++ (parseList todoList) ++ "\n\n"
view [filterStr] = do
(todoList, _) <- extractTodoList
let todoFilter = read (capitalize filterStr) :: Filter
filteredTodoList = case todoFilter of
Done -> filterDone todoList
Pending -> filterPending todoList
header = "\nTODO - Showing " ++ (show todoFilter) ++ "\n\n"
contents = header ++ (parseList filteredTodoList) ++ "\n\n"
putStrLn contents

getTodoById :: Int -> TodoList -> Maybe Todo
getTodoById todoId' =
find (\t -> todoId t == todoId')

updateInTodoList :: Todo -> TodoList -> TodoList
updateInTodoList todo =
map (\t -> if todoId t == todoId todo
then todo
else t)
update :: [String] -> IO ()
update [] = do putStrLn "Tell me the todo ID and the new title"
update [todoId'] = do putStrLn "Tell me the new title"
update [todoIdStr, newTitle] = do
(todoList, fileName) <- extractTodoList
let maybeTodo = getTodoById (read todoIdStr :: Int) todoList
case maybeTodo of
Just todo -> do
let newTodo = todo { title = newTitle }
newTodoList = updateInTodoList newTodo todoList
message = "\nTodo updated:\n\n" ++ (showStrTodo newTodo) ++ "\n"
writeFile fileName $ show newTodoList
putStrLn message
Nothing -> do putStrLn "\nTODO Not found\n"





showStrTodo :: Todo -> String
showStrTodo todo =
let todoId' = show $ todoId todo
title' = title todo
done' = if done todo then "Done" else "Pending"
in todoId' ++ " - " ++ title' ++ " [ " ++ done' ++ " ]"

extractTodoList :: IO (TodoList, FilePath)
extractTodoList = do
homeDir <- getHomeDirectory
let fileName = homeDir ++ "/.todos"
contents <- readFile fileName
if contents == ""
then return ([], fileName)
else return (read contents :: TodoList, fileName)

markAsDone :: Int -> TodoList -> String -> IO ()
markAsDone todoId' todoList fileName = do
let newTodoList = map
(\t -> if todoId' == todoId t
then t { done = True }
else t
) todoList
writeFile fileName $ show newTodoList

todoDone :: [String] -> IO ()
todoDone [] = do putStr "You need to tell me the Todo ID"
todoDone [todoIdStr] = do
(todoList, fileName) <- extractTodoList

let maybeTodo = find (\t -> Just (todoId t) == Just (read todoIdStr :: Int)) todoList
todoId' = case maybeTodo of
Just todo -> todoId todo
Nothing -> 0
if todoId' == 0 then putStrLn "Todo not found"
else markAsDone todoId' todoList fileName




30 changes: 30 additions & 0 deletions todo.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import System.Environment
import Actions
import System.IO
import System.Directory

type Todo = String
dispatch :: [(String, [String] -> IO ())]
dispatch = [ ("add", add)
, ("remove", remove)
, ("view", view)
, ("done", todoDone)
, ("update", update)]
main = do
(command:args) <- getArgs
let (Just action) = lookup command dispatch
createTodosFileIfNotExists
action args

createTodosFileIfNotExists :: IO ()
createTodosFileIfNotExists = do
homeDir <- getHomeDirectory
let fileName = homeDir ++ "/.todos"
fileExist <- doesFileExist fileName
if fileExist
then return ()
else do
handle <- openFile fileName WriteMode
hPutStr handle ""
hClose handle

3 changes: 3 additions & 0 deletions todo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Brand new task
another task
new Task

0 comments on commit 65ba9a0

Please sign in to comment.