Repository: pimutils/khal

Issue:
at/list/search should return nothing if no matching events are found
at/calendar/list currently returns "No events\n" if no events are found.  search returns "\n".  I suggest at, list and search are consistent and return "" if they have nothing to say.  I don't have a strong opinion on calendar.

Discussion:
geier: lgtm. @WhyNotHugo  what do you think?
geier: Sleeping about this, we probably should at least add some debug logging, that no events were found.

Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 165337f..ea6bc2a 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -11,10 +11,12 @@ may want to subscribe to `GitHub's tag feed
 0.10.5
 ======
 not released
+
 * NEW Add widget to interactive event editor that allows adding attendees as
   comma separated list of email addresses
-
 * NEW Add support for Python 3.10
+* `search`, `at`, and `list` don't print "No events" anymore if no matching
+  events are found
 
 0.10.4
 ======
diff --git a/khal/cli.py b/khal/cli.py
index e86f364..ed707e6 100644
--- a/khal/cli.py
+++ b/khal/cli.py
@@ -323,7 +323,11 @@ def _get_cli():
                 conf=ctx.obj['conf'],
                 env={"calendars": ctx.obj['conf']['calendars']}
             )
-            click.echo('\n'.join(event_column))
+            if event_column:
+                click.echo('\n'.join(event_column))
+            else:
+                logger.debug('No events found')
+
         except FatalError as error:
             logger.debug(error, exc_info=True)
             logger.fatal(error)
@@ -586,7 +590,10 @@ def _get_cli():
                              bold_for_light_color=ctx.obj['conf']['view']['bold_for_light_color'])
                      for d in desc]
                 )
-            click.echo('\n'.join(event_column))
+            if event_column:
+                click.echo('\n'.join(event_column))
+            else:
+                logger.debug('No events found')
         except FatalError as error:
             logger.debug(error, exc_info=True)
             logger.fatal(error)
@@ -647,7 +654,8 @@ def _get_cli():
                 conf=ctx.obj['conf'],
                 env={"calendars": ctx.obj['conf']['calendars']}
             )
-            click.echo('\n'.join(rows))
+            if rows:
+                click.echo('\n'.join(rows))
         except FatalError as error:
             logger.debug(error, exc_info=True)
             logger.fatal(error)
diff --git a/khal/controllers.py b/khal/controllers.py
index 83fcf06..2c5ed56 100644
--- a/khal/controllers.py
+++ b/khal/controllers.py
@@ -110,6 +110,8 @@ def calendar(collection, agenda_format=None, notstarted=False, once=False, dater
         width=rwidth,
         env=env,
     )
+    if not event_column:
+        event_column = [style('No events', bold=True)]
     calendar_column = calendar_display.vertical_month(
         month=start.month,
         year=start.year,
@@ -294,8 +296,6 @@ def khal_list(
         event_column.extend(current_events)
         start = dt.datetime(*start.date().timetuple()[:3]) + dt.timedelta(days=1)
 
-    if event_column == []:
-        event_column = [style('No events', bold=True)]
     return event_column
 
 


Test patch:
diff --git a/tests/cli_test.py b/tests/cli_test.py
index 0c5af03..3ced576 100644
--- a/tests/cli_test.py
+++ b/tests/cli_test.py
@@ -106,7 +106,7 @@ def test_direct_modification(runner):
     runner = runner()
 
     result = runner.invoke(main_khal, ['list'])
-    assert result.output == 'No events\n'
+    assert result.output == ''
     assert not result.exception
 
     cal_dt = _get_text('event_dt_simple')
@@ -121,14 +121,14 @@ def test_direct_modification(runner):
     os.remove(str(event))
     result = runner.invoke(main_khal, ['list'])
     assert not result.exception
-    assert result.output == 'No events\n'
+    assert result.output == ''
 
 
 def test_simple(runner):
     runner = runner(days=2)
     result = runner.invoke(main_khal, ['list'])
     assert not result.exception
-    assert result.output == 'No events\n'
+    assert result.output == ''
 
     now = dt.datetime.now().strftime('%d.%m.%Y')
     result = runner.invoke(
@@ -332,6 +332,8 @@ def test_attach_calendar(runner):
     assert not result.exception
 
 
+# "see #905"
+@pytest.mark.xfail
 @pytest.mark.parametrize('contents', [
     '',
     'BEGIN:VCALENDAR\nBEGIN:VTODO\nEND:VTODO\nEND:VCALENDAR\n'
@@ -343,7 +345,7 @@ def test_no_vevent(runner, tmpdir, contents):
 
     result = runner.invoke(main_khal, ['list'])
     assert not result.exception
-    assert 'No events' in result.output
+    assert result.output == ''
 
 
 def test_printformats(runner):
@@ -545,11 +547,10 @@ def test_color_option(runner):
     runner = runner(days=2)
 
     result = runner.invoke(main_khal, ['--no-color', 'list'])
-    assert result.output == 'No events\n'
+    assert result.output == ''
 
     result = runner.invoke(main_khal, ['--color', 'list'])
-    assert 'No events' in result.output
-    assert result.output != 'No events\n'
+    assert result.output == ''
 
 
 def choices(dateformat=0, timeformat=0,
@@ -810,7 +811,7 @@ def test_edit(runner):
     runner = runner()
     result = runner.invoke(main_khal, ['list'])
     assert not result.exception
-    assert result.output == 'No events\n'
+    assert result.output == ''
 
     for name in ['event_dt_simple', 'event_d_15']:
         cal_dt = _get_text(name)
diff --git a/tests/controller_test.py b/tests/controller_test.py
index e979154..8d06532 100644
--- a/tests/controller_test.py
+++ b/tests/controller_test.py
@@ -88,8 +88,8 @@ class TestGetAgenda:
             'DTEND:20110908T170000\r\n'
             'END:VEVENT\r\n'
         ), utils.cal1))
-        assert 'no events' in '\n'.join(
-            khal_list(coll, [], conf, agenda_format=event_format, day_format="{name}")).lower()
+        assert '\n'.join(khal_list(coll, [], conf,
+                         agenda_format=event_format, day_format="{name}")).lower() == ''
 
 
 class TestImport: