diff --git a/CHANGELOG.md b/CHANGELOG.md index f52899a..e964c66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- handle due date parsing errors in `mxtodo-create-todo` ## [0.1.0] - 2021-08-07 ### Added diff --git a/mxtodo.el b/mxtodo.el index 82aaa4b..efe1ac1 100644 --- a/mxtodo.el +++ b/mxtodo.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2021 Robert Voyer. ;; Author: Robert Voyer -;; Version: 0.1 +;; Version: 0.1.0 ;; Package-Requires: ((emacs "26.1") (dash "2.19.0") (f "0.20.0") (ts "0.2")) ;; Keywords: calendar, convenience ;; URL: https://github.com/rlvoyer/mxtodo @@ -359,9 +359,17 @@ with incomplete todo items first, followed by completed todo items." (beginning-of-line) (looking-at-p "[[:space:]]*$"))) +(defun mxtodo--parse-date (date-str) + "Parse the specified date string into a ts or return an error if it failed to parse." + (condition-case + nil + (cl-values (ts-parse-fill 'begin date-str) nil) + (error + (cl-values nil (format "Unable to parse specified date string %s; date must be ISO-8601-formatted." date-str))))) + ;;;###autoload (defun mxtodo-create-todo (&optional buffer-name todo-text due-date-ts) - "Add a TODO to today's daily note." + "Add a todo to today's daily note, updating todo buffer with name BUFFER-NAME." (interactive) (save-excursion (progn @@ -372,8 +380,10 @@ with incomplete todo items first, followed by completed todo items." (unless due-date-ts (let ((due-date-read (read-string "(Optional) Enter a due date: "))) (if (not (string= "" due-date-read)) - (setq due-date-ts (ts-parse-fill 'begin due-date-read)) - (setq due-date-ts nil)))) + (-let [(due-date-parsed err) (mxtodo--parse-date due-date-read)] + (if (not (equal err nil)) + (error err) + (setq due-date-ts due-date-parsed)))))) (let ((file-name (mxtodo-create-daily-note))) (progn (goto-char (point-max)) diff --git a/test/test.el b/test/test.el index 59158e3..81fd73f 100644 --- a/test/test.el +++ b/test/test.el @@ -53,28 +53,6 @@ (expected (vector "write more tests" nil expected-due-date))) (should (equal (aref expected 2) (aref actual 2))))) -(ert-deftest test-make-todo-from-temp-file-line () - "Tests that a TODO can be constructed from a temp file line." - (let ((expected - (make-mxtodo-item :file-path "/Users/robertvoyer/Documents/Notes/2021-6-24.md" - :file-line-number 10 - :file-display-date-ts (make-ts :year 2021 - :month 6 - :day 24 - :hour 0 - :minute 0 - :second 0) - :file-last-update-ts (make-ts :unix 1624637870) - :text "write some unit tests" - :is-completed t)) - (actual - (mxtodo--make-todo-from-temp-file-line "/Users/robertvoyer/Documents/Notes/2021-6-24.md 10 - [x] write some unit tests 1624637870"))) - (should (equal expected actual)))) - -(defun todo-text-no-properties (rendered-todo-item) - "Test helper function that renders a RENDERED-TODO-ITEM as a string with no properties." - (substring-no-properties rendered-todo-item 0 (next-single-property-change 0 'invisible rendered-todo-item))) - (ert-deftest test-render-date () "Tests that a TODO date renders correctly." (let* ((date @@ -130,6 +108,53 @@ (actual (todo-text-no-properties (mxtodo--render-todo input-todo)))) (should (equal expected actual)))) +(ert-deftest test-parse-bad-date-returns-cl-values-with-a-non-nil-error () + "Tests that mxtodo--parse-date fails on non-ISO-8601-formatted input." + (let ((expected (cl-values nil "Unable to parse specified date string 2021-8-7; date must be ISO-8601-formatted.")) + (actual (mxtodo--parse-date "2021-8-7"))) + (should (equal expected actual)))) + +(ert-deftest test-parse-good-date-returns-cl-values () + "Tests that mxtodo--parse-date succeeds on ISO-8601-formatted input." + (let* ((date-str "2021-08-07") + (expected-error nil) + (expected-year 2021) + (expected-month 8) + (expected-day 7) + (actual (mxtodo--parse-date date-str)) + (actual-error (nth 1 actual)) + (actual-date (car actual)) + (actual-year (ts-year actual-date)) + (actual-month (ts-month actual-date)) + (actual-day (ts-day actual-date))) + (progn + (should (equal expected-error actual-error)) + (should (equal expected-year actual-year)) + (should (equal expected-month actual-month)) + (should (equal expected-day actual-day))))) + + +(ert-deftest test-make-todo-from-temp-file-line () + "Tests that a TODO can be constructed from a temp file line." + (let ((expected + (make-mxtodo-item :file-path "/Users/robertvoyer/Documents/Notes/2021-6-24.md" + :file-line-number 10 + :file-display-date-ts (make-ts :year 2021 + :month 6 + :day 24 + :hour 0 + :minute 0 + :second 0) + :file-last-update-ts (make-ts :unix 1624637870) + :text "write some unit tests" + :is-completed t)) + (actual + (mxtodo--make-todo-from-temp-file-line "/Users/robertvoyer/Documents/Notes/2021-6-24.md 10 - [x] write some unit tests 1624637870"))) + (should (equal expected actual)))) + +(defun todo-text-no-properties (rendered-todo-item) + "Test helper function that renders a RENDERED-TODO-ITEM as a string with no properties." + (substring-no-properties rendered-todo-item 0 (next-single-property-change 0 'invisible rendered-todo-item))) (defun nshuffle (sequence) "Shuffle SEQUENCE."