115 lines
3.5 KiB
Haskell
115 lines
3.5 KiB
Haskell
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Main(main, parseTask, serializeTask, getPriority, comparePriority, TaskMap) where
|
|
|
|
import System.IO
|
|
import System.Directory
|
|
import Data.Text (Text, pack, unpack, isInfixOf, lines, unlines, strip)
|
|
import qualified Data.Text.IO as TIO
|
|
import qualified Data.ByteString as BS
|
|
import qualified Data.ByteString.Char8 as BSC
|
|
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 <- BSC.readFile todoFile
|
|
let taskMap = parseTask (pack (BSC.unpack 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 <- BSC.readFile todoFile
|
|
let taskMap = parseTask (pack (BSC.unpack contents))
|
|
newId = if Map.null taskMap then 1 else fst (Map.findMax taskMap) + 1
|
|
newTaskMap = Map.insert newId (pack task) taskMap
|
|
BSC.writeFile todoFile (BSC.pack (unpack (serializeTask newTaskMap)))
|
|
else BSC.writeFile todoFile (BSC.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 = parseTask 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 = parseTask 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
|
|
|
|
parseTask :: Text -> TaskMap
|
|
parseTask = Map.fromList . zip [1..] . Data.Text.lines
|
|
|
|
serializeTask :: TaskMap -> Text
|
|
serializeTask = Data.Text.unlines . map snd . Map.toList
|
|
|
|
showTask :: (Int, Text) -> String
|
|
showTask (_, task) = unpack task |