.
Вот код функции >view
:
>view :: [String] –> IO ()
>view [fileName] = do
> contents <– readFile fileName
> let todoTasks = lines contents
> numberedTasks = zipWith (\n line –> show n ++ " – " ++ line)
> [0..] todoTasks
> putStr $ unlines numberedTasks
Программа, которая удаляла задачу из списка, производила практически те же самые действия: мы отображали список задач, чтобы пользователь мог выбрать, какую из них удалить. Но в этой функции мы просто отображаем список.
Ну и наконец реализуем функцию >remove
. Функция будет очень похожа на программу для удаления элемента, так что если вы не понимаете, как работает функция удаления, прочитайте пояснения к её определению. Основное отличие – мы не задаём жёстко имя файла, а получаем его как аргумент. Также мы не спрашиваем у пользователя номер задачи для удаления – его мы также получаем в виде аргумента.
>remove :: [String] -> IO ()
>remove [fileName, numberString] = do
> contents <- readFile fileName
> let todoTasks = lines contents
> number = read numberString
> newTodoItems = unlines $ delete (todoTasks !! number) todoTasks
> bracketOnError (openTempFile "." "temp")
> (\(tempName, tempHandle) –> do
> hClose tempHandle
> removeFile tempName)
> (\(tempName, tempHandle) –> do
> hPutStr tempHandle newTodoItems
> hClose tempHandle
> removeFile fileName
> renameFile tempName fileName)
Мы открываем файл, полное имя которого задаётся в идентификаторе >fileName
, открываем временный файл, удаляем строку по индексу, записываем во временный файл, удаляем исходный файл и переименовываем временный в >fileName
. Приведём полный листинг программы во всей её красе:
>import System.Environment
>import System.Directory
>import System.IO
>import Control.Exception
>import Data.List
>dispatch :: String -> [String] -> IO ()
>dispatch "add" = add
>dispatch "view" = view
>dispatch "remove" = remove
>main = do
> (command:argList) <- getArgs
> dispatch command argList
>add :: [String] -> IO ()
>add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n")
>view :: [String] -> IO ()
>view [fileName] = do
> contents <- readFile fileName
> let todoTasks = lines contents
> numberedTasks = zipWith (\n line -> show n ++ " – " ++ line)
> [0..] todoTasks
> putStr $ unlines numberedTasks
>remove :: [String] -> IO ()
>remove [fileName, numberString] = do
> contents <- readFile fileName
> let todoTasks = lines contents
> number = read numberString
> newTodoItems = unlines $ delete (todoTasks !! number) todoTasks