Repository: pimutils/khal

Issue:
edit of datetime range fails with error parsing range

(venv) allan@vent:~/src/khal$ khal new -i
summary: test
datetime range: now
timezone [EST5EDT]:
description (or "None") [None]: test
event saved
Edit?  do[n]e  [s]ummary  [d]escription  da[t]etime range  re[p]eat  [l]ocation  [c]ategories  [a]larm  [D]elete  [u]rl: t                                                                                                                    
datetime range [2021-05-26 20:28 2021-05-26 21:28]:
error parsing range

The main issue is:

1. "error parsing range"

There are a couple of minor issues.

2. The program asks for "datetime range" but I enter a single datetime.  If the ending interval is optional maybe it should be two fields/questions?  It's a bit weird that the "now" maps to 1 hour interval, while "today" is a full day event.

3. For the "datetime range" I entered the value "now", and the program converts that to a pair of timestamps.  It would be better if at least within the new -i session the value that the user entered was retain.  Alternatively, program could tell user that input x was changed to y so it's not a surprise if you want to edit it.

Discussion:

Patch:
diff --git a/khal/controllers.py b/khal/controllers.py
index 2ab8605..49c3196 100644
--- a/khal/controllers.py
+++ b/khal/controllers.py
@@ -24,6 +24,7 @@ import datetime as dt
 import logging
 import os
 import textwrap
+import re
 from collections import OrderedDict, defaultdict
 from shutil import get_terminal_size
 
@@ -429,6 +430,11 @@ def edit_event(event, collection, locale, allow_quit=False, width=80):
     options["alarm"] = {"short": "a"}
     options["Delete"] = {"short": "D"}
     options["url"] = {"short": "u", "attr": "url", "none": True}
+    # some output contains ansi escape sequences (probably only resets)
+    # if hitting enter, the output (including the escape sequence) gets parsed
+    # and fails the parsing. Therefore we remove ansi escape sequences before
+    # parsing.
+    ansi = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
 
     now = dt.datetime.now()
 
@@ -452,7 +458,7 @@ def edit_event(event, collection, locale, allow_quit=False, width=80):
             current = event.format("{start} {end}", relative_to=now)
             value = prompt("datetime range", default=current)
             try:
-                start, end, allday = parse_datetime.guessrangefstr(value, locale)
+                start, end, allday = parse_datetime.guessrangefstr(ansi.sub('', value), locale)
                 event.update_start_end(start, end)
                 edited = True
             except:  # noqa


Test patch:
diff --git a/tests/cli_test.py b/tests/cli_test.py
index 1ee6bb1..ac1bea2 100644
--- a/tests/cli_test.py
+++ b/tests/cli_test.py
@@ -882,3 +882,26 @@ def test_new_interactive_extensive(runner):
     )
     assert not result.exception
     assert result.exit_code == 0
+
+
+@freeze_time('2015-6-1 8:00')
+def test_issue_1056(runner):
+    """if an ansi escape sequence is contained in the output, we can't parse it
+    properly"""
+
+    runner = runner(print_new='path', default_calendar=False)
+
+    result = runner.invoke(
+        main_khal, 'new -i'.split(),
+        'two\n'
+        'new event\n'
+        'now\n'
+        'Europe/London\n'
+        'None\n'
+        't\n'  # edit datetime range
+        '\n'
+        'n\n'
+    )
+    assert 'error parsing range' not in result.output
+    assert not result.exception
+    assert result.exit_code == 0