Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support json as an output option for most commands #1308

Merged
merged 35 commits into from
Oct 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7328e8c
add json option to at command
PsychicNoodles May 6, 2021
6667715
added list json formatting
PsychicNoodles May 6, 2021
d996489
fix color wrap
PsychicNoodles May 7, 2021
65a173d
fixed formatting
PsychicNoodles May 7, 2021
cdb8568
added missing tail reset
PsychicNoodles May 7, 2021
322cdc2
fix search formatter usage
PsychicNoodles May 7, 2021
43a172f
fixed missing human_formatter
PsychicNoodles May 7, 2021
c7ef007
fix formatter usage in test
PsychicNoodles May 7, 2021
c7dc9fa
added colors param to human formatter
PsychicNoodles May 7, 2021
eb0fdfc
fix formatter usage in test
PsychicNoodles May 7, 2021
d875a4d
added cli tests
PsychicNoodles May 8, 2021
245c105
added json option to search
PsychicNoodles May 8, 2021
5062071
moved formatters to util
PsychicNoodles May 8, 2021
5955c5d
add json to new
PsychicNoodles May 8, 2021
bf2062b
corrected style
PsychicNoodles May 8, 2021
bcd3ced
added test for human_formatter width
PsychicNoodles May 8, 2021
e4f0cd1
update method docs
PsychicNoodles May 8, 2021
747a0c2
update usage doc
PsychicNoodles May 8, 2021
02ebf1f
add json feature to changelog
PsychicNoodles May 8, 2021
83cd781
rename event.format to event.attributes
PsychicNoodles May 8, 2021
f3591c6
added special field formatting
PsychicNoodles May 8, 2021
4ec1680
added missing formatter
PsychicNoodles May 9, 2021
0154b23
add self to authors :)
PsychicNoodles May 9, 2021
1ad1b75
add list of content attributes
PsychicNoodles May 10, 2021
63d7ffb
added all fields option for json
PsychicNoodles May 10, 2021
feacba0
fix long lines
PsychicNoodles May 10, 2021
fbe4c89
fix formatter mistakes
PsychicNoodles May 11, 2021
88801e2
remove unnecessary dict call
PsychicNoodles May 11, 2021
44d3282
remove mutable default arguments
PsychicNoodles May 11, 2021
d2e39b1
add to json option docs
PsychicNoodles May 11, 2021
eb7b1ce
added missing format template options
PsychicNoodles May 11, 2021
f31faec
typo
PsychicNoodles May 11, 2021
f4ca976
cli_test format()
geier Oct 27, 2023
ef55a88
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 27, 2023
1d60f78
make ruff happy
geier Oct 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ Raúl Medina - raulmgcontact [at] gmail (dot] com
Matthew Rademaker - matthew.rademaker [at] gmail [dot] com
Valentin Iovene - val [at] too [dot] gy
Julian Wollrath
Mattori Birnbaum - me [at] mattori [dot] com - https://mattori.com
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ not released yet
* NEW properties of ikhal themes (dark and light) can now be overriden from the
config file (via the new [palette] section, check the documenation)
* NEW timedelta strings can now have a leading `+`, e.g. `+1d`
* NEW Add `--json` option to output event data as JSON objects

0.11.2
======
Expand Down
57 changes: 53 additions & 4 deletions doc/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,21 @@ Several options are common to almost all of :program:`khal`'s commands
url-separator
A separator: " :: " that appears when there is a url.

duration
The duration of the event in terms of days, hours, months, and seconds
(abbreviated to `d`, `h`, `m`, and `s` respectively).

repeat-pattern
The raw iCal recurrence rule if the event is repeating.

all-day
A boolean indicating whether it is an all-day event or not.

categories
The categories of the event.

By default, all-day events have no times. To see a start and end time anyway simply
add `-full` to the end of any template with start/end, for instance
add `-full` to the end of any template with start/end or duration, for instance
`start-time` becomes `start-time-full` and will always show start and end times (instead
of being empty for all-day events).

Expand All @@ -191,6 +204,40 @@ Several options are common to almost all of :program:`khal`'s commands
khal list --format "{title} {description}"


.. option:: --json FIELD ...

Works similar to :option:`--format`, but instead of defining a format string a JSON
object is created for each specified field. The matching events are collected into
a JSON array. This option accepts the following subset of :option:`--format`
template options

::
Comment on lines +212 to +214
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template options
::
template options::


title, description, uid, start, start-long, start-date,
start-date-long, start-time, end, end-long, end-date,
end-date-long, end-time, start-full, start-long-full,
start-date-full, start-date-long-full, start-time-full,
end-full, end-long-full, end-date-full, end-date-long-full,
end-time-full, repeat-symbol, location, calendar,
calendar-color, start-style, to-style, end-style,
start-end-time-style, end-necessary, end-necessary-long,
status, cancelled, organizer, url, duration, duration-full,
repeat-pattern, all-day, categories


Note that `calendar-color` will be the actual color name rather than the ANSI color code,
and the `repeat-symbol`, `status`, and `cancelled` values will have leading/trailing
whitespace stripped. Additionally, if only the special value `all` is specified then
all fields will be enabled.

Below is an example command which prints a JSON list of objects containing the title and
description of all events today.

::
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this renders a :, right?

Suggested change
::
.. code-block:: python


khal list --json title --json description


.. option:: --day-format DAYFORMAT

works similar to :option:`--format`, but for day headings. It only has a few
Expand Down Expand Up @@ -231,8 +278,9 @@ shows all events scheduled for a given date (or datetime) range, with custom
formatting:
::
Comment on lines 278 to 279
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
formatting:
::
formatting::


khal list [-a CALENDAR ... | -d CALENDAR ...] [--format FORMAT]
[--day-format DAYFORMAT] [--once] [--notstarted] [START [END | DELTA] ]
khal list [-a CALENDAR ... | -d CALENDAR ...]
[--format FORMAT] [--json FIELD ...] [--day-format DAYFORMAT]
[--once] [--notstarted] [START [END | DELTA] ]

START and END can both be given as dates, datetimes or times (it is assumed
today is meant in the case of only a given time) in the formats configured in
Expand Down Expand Up @@ -270,7 +318,8 @@ start.

::

khal at [-a CALENDAR ... | -d CALENDAR ...] [--format FORMAT]
khal at [-a CALENDAR ... | -d CALENDAR ...]
[--format FORMAT] [--json FIELD ...]
[--notstarted] [[START DATE] TIME | now]

calendar
Expand Down
27 changes: 20 additions & 7 deletions khal/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from .exceptions import FatalError
from .settings import InvalidSettingsError, NoConfigFile, get_config
from .terminal import colored
from .utils import human_formatter, json_formatter

try:
from setproctitle import setproctitle
Expand Down Expand Up @@ -313,11 +314,12 @@ def calendar(ctx, include_calendar, exclude_calendar, daterange, once,
)
@click.option('--notstarted', help=('Print only events that have not started.'),
is_flag=True)
@click.option('--json', help=("Fields to output in json"), multiple=True)
@click.argument('DATERANGE', nargs=-1, required=False,
metavar='[DATETIME [DATETIME | RANGE]]')
@click.pass_context
def klist(ctx, include_calendar, exclude_calendar,
daterange, once, notstarted, format, day_format):
daterange, once, notstarted, json, format, day_format):
"""List all events between a start (default: today) and (optional)
end datetime."""
try:
Expand All @@ -332,7 +334,8 @@ def klist(ctx, include_calendar, exclude_calendar,
once=once,
notstarted=notstarted,
conf=ctx.obj['conf'],
env={"calendars": ctx.obj['conf']['calendars']}
env={"calendars": ctx.obj['conf']['calendars']},
json=json
)
if event_column:
click.echo('\n'.join(event_column))
Expand All @@ -358,14 +361,15 @@ def klist(ctx, include_calendar, exclude_calendar,
help=('Stop an event repeating on this date.'))
@click.option('--format', '-f',
help=('The format to print the event.'))
@click.option('--json', help=("Fields to output in json"), multiple=True)
@click.option('--alarms', '-m',
help=('Alarm times for the new event as DELTAs comma separated'))
@click.option('--url', help=("URI for the event."))
@click.argument('info', metavar='[START [END | DELTA] [TIMEZONE] [SUMMARY] [:: DESCRIPTION]]',
nargs=-1)
@click.pass_context
def new(ctx, calendar, info, location, categories, repeat, until, alarms, url, format,
interactive):
json, interactive):
'''Create a new event from arguments.

START and END can be either dates, times or datetimes, please have a
Expand Down Expand Up @@ -413,6 +417,7 @@ def new(ctx, calendar, info, location, categories, repeat, until, alarms, url, f
alarms=alarms,
url=url,
format=format,
json=json
)
except FatalError as error:
logger.debug(error, exc_info=True)
Expand Down Expand Up @@ -583,9 +588,10 @@ def printics(ctx, ics, format):
@multi_calendar_option
@click.option('--format', '-f',
help=('The format of the events.'))
@click.option('--json', help=("Fields to output in json"), multiple=True)
@click.argument('search_string')
@click.pass_context
def search(ctx, format, search_string, include_calendar, exclude_calendar):
def search(ctx, format, json, search_string, include_calendar, exclude_calendar):
'''Search for events matching SEARCH_STRING.

For recurring events, only the master event and different overwritten
Expand All @@ -604,8 +610,13 @@ def search(ctx, format, search_string, include_calendar, exclude_calendar):
term_width, _ = get_terminal_size()
now = dt.datetime.now()
env = {"calendars": ctx.obj['conf']['calendars']}
if len(json) == 0:
formatter = human_formatter(format)
else:
formatter = json_formatter(json)
for event in events:
desc = textwrap.wrap(event.format(format, relative_to=now, env=env), term_width)
desc = textwrap.wrap(formatter(
event.attributes(relative_to=now, env=env)), term_width)
event_column.extend(
[colored(d, event.color,
bold_for_light_color=ctx.obj['conf']['view']['bold_for_light_color'])
Expand Down Expand Up @@ -655,9 +666,10 @@ def edit(ctx, format, search_string, show_past, include_calendar, exclude_calend
help=('The format of the day line.'))
@click.option('--notstarted', help=('Print only events that have not started'),
is_flag=True)
@click.option('--json', help=("Fields to output in json"), multiple=True)
@click.argument('DATETIME', nargs=-1, required=False, metavar='[[START DATE] TIME | now]')
@click.pass_context
def at(ctx, datetime, notstarted, format, day_format, include_calendar, exclude_calendar):
def at(ctx, datetime, notstarted, format, day_format, json, include_calendar, exclude_calendar):
'''Print all events at a specific datetime (defaults to now).'''
if not datetime:
datetime = ("now",)
Expand All @@ -675,7 +687,8 @@ def at(ctx, datetime, notstarted, format, day_format, include_calendar, exclude_
once=True,
notstarted=notstarted,
conf=ctx.obj['conf'],
env={"calendars": ctx.obj['conf']['calendars']}
env={"calendars": ctx.obj['conf']['calendars']},
json=json
)
if rows:
click.echo('\n'.join(rows))
Expand Down
Loading