haskell_todo_app/app/Main.hs
2024-05-25 21:09:43 +02:00

113 lines
3.3 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
module Main where
import System.IO
import System.Directory
import Data.Text (Text, pack, unpack, isInfixOf, lines, unlines, strip, splitOn)
import qualified Data.Text.IO as TIO
import Control.Monad (when)
import Data.List (sortBy)
import Data.Ord (comparing)
import Data.Char (isAlpha)
import qualified Data.Map as Map
import Data.Function (on)
todoFile :: FilePath
todoFile = "todo.txt"
type TaskMap = Map.Map Int Text
main :: IO ()
main = do
putStrLn "Welcome to the Haskell Todo App"
putStrLn "1. Display tasks"
putStrLn "2. Add task"
putStrLn "3. Filter tasks by tag"
putStrLn "4. Sort tasks by priority"
putStrLn "5. Exit"
putStr "Choose an option: "
hFlush stdout
option <- getLine
case option of
"1" -> displayTasks
"2" -> addTask
"3" -> filterTasksByTag
"4" -> sortTasksByPriority
"5" -> putStrLn "Goodbye!"
_ -> putStrLn "Invalid option" >> main
displayTasks :: IO ()
displayTasks = do
exists <- doesFileExist todoFile
if exists
then do
contents <- TIO.readFile todoFile
let taskMap = parseTasks contents
putStrLn "Tasks:"
mapM_ (putStrLn . showTask) (Map.toList taskMap)
else putStrLn "No tasks found."
main
addTask :: IO ()
addTask = do
putStr "Enter the task: "
hFlush stdout
task <- getLine
exists <- doesFileExist todoFile
if exists
then do
contents <- TIO.readFile todoFile
let taskMap = parseTasks contents
newId = if Map.null taskMap then 1 else fst (Map.findMax taskMap) + 1
newTaskMap = Map.insert newId (pack task) taskMap
TIO.writeFile todoFile (serializeTasks newTaskMap)
else TIO.writeFile todoFile (pack task <> "\n")
putStrLn "Task added."
main
filterTasksByTag :: IO ()
filterTasksByTag = do
putStr "Enter the tag to filter by (e.g., +GarageSale): "
hFlush stdout
tag <- getLine
exists <- doesFileExist todoFile
if exists
then do
contents <- TIO.readFile todoFile
let taskMap = parseTasks contents
filteredTasks = Map.filter (isInfixOf (pack tag)) taskMap
putStrLn "Filtered tasks:"
mapM_ (putStrLn . showTask) (Map.toList filteredTasks)
else putStrLn "No tasks found."
main
sortTasksByPriority :: IO ()
sortTasksByPriority = do
exists <- doesFileExist todoFile
if exists
then do
contents <- TIO.readFile todoFile
let taskMap = parseTasks contents
sortedTasks = sortBy (comparePriority `on` snd) (Map.toList taskMap)
putStrLn "Sorted tasks by priority:"
mapM_ (putStrLn . showTask) sortedTasks
else putStrLn "No tasks found."
main
comparePriority :: Text -> Text -> Ordering
comparePriority t1 t2 = comparing getPriority t1 t2
getPriority :: Text -> Maybe Char
getPriority t = case unpack (strip t) of
('(':p:')':_) | isAlpha p -> Just p
_ -> Nothing
parseTasks :: Text -> TaskMap
parseTasks = Map.fromList . zip [1..] . Data.Text.lines
serializeTasks :: TaskMap -> Text
serializeTasks = Data.Text.unlines . map snd . Map.toList
showTask :: (Int, Text) -> String
showTask (_, task) = unpack task