From 2df7acf4880ddb8a8b300a5aaeea08705d265b2f Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 24 Sep 2022 12:46:49 -0700 Subject: [PATCH] Add machine readable --list output (#1592) * Add machine readable --list output * Refactor list_journals() Create three new methods for each journal list format. - JSON, YAML, STDOUT * Added journal list export test * Update test regex to handle windows filepaths --- jrnl/args.py | 8 +++++- jrnl/commands.py | 4 +-- jrnl/output.py | 43 ++++++++++++++++++++++++++----- tests/bdd/features/format.feature | 15 +++++++++++ tests/lib/then_steps.py | 1 + 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/jrnl/args.py b/jrnl/args.py index 4b2ba8ce..c6b0f1a0 100644 --- a/jrnl/args.py +++ b/jrnl/args.py @@ -85,7 +85,13 @@ def parse_args(args=[]): action="store_const", const=postconfig_list, dest="postconfig_cmd", - help="List all configured journals", + help=""" + List all configured journals. + + Optional parameters: + + --format [json or yaml] + """, ) standalone.add_argument( "--ls", diff --git a/jrnl/commands.py b/jrnl/commands.py index a96a2956..6100422b 100644 --- a/jrnl/commands.py +++ b/jrnl/commands.py @@ -56,10 +56,10 @@ def preconfig_version(_): print(output) -def postconfig_list(config, **kwargs): +def postconfig_list(args, config, **kwargs): from jrnl.output import list_journals - print(list_journals(config)) + print(list_journals(config, args.export)) def postconfig_import(args, config, **kwargs): diff --git a/jrnl/output.py b/jrnl/output.py index b82ec122..2db0362e 100644 --- a/jrnl/output.py +++ b/jrnl/output.py @@ -25,19 +25,50 @@ def deprecated_cmd(old_cmd, new_cmd, callback=None, **kwargs): callback(**kwargs) -def list_journals(configuration): - from jrnl import config +def journal_list_to_json(journal_list): + import json - """List the journals specified in the configuration file""" - result = f"Journals defined in config ({config.get_config_path()})\n" - ml = min(max(len(k) for k in configuration["journals"]), 20) - for journal, cfg in configuration["journals"].items(): + return json.dumps(journal_list) + + +def journal_list_to_yaml(journal_list): + from io import StringIO + + from ruamel.yaml import YAML + + output = StringIO() + YAML().dump(journal_list, output) + return output.getvalue() + + +def journal_list_to_stdout(journal_list): + result = f"Journals defined in config ({journal_list['config_path']})\n" + ml = min(max(len(k) for k in journal_list["journals"]), 20) + for journal, cfg in journal_list["journals"].items(): result += " * {:{}} -> {}\n".format( journal, ml, cfg["journal"] if isinstance(cfg, dict) else cfg ) return result +def list_journals(configuration, format=None): + from jrnl import config + + """List the journals specified in the configuration file""" + + journal_list = { + "config_path": config.get_config_path(), + "journals": configuration["journals"], + } + + if format == "json": + return journal_list_to_json(journal_list) + elif format == "yaml": + return journal_list_to_yaml(journal_list) + else: + return journal_list_to_stdout(journal_list) + + def print_msg(msg: Message, **kwargs) -> Union[None, str]: """Helper function to print a single message""" kwargs["style"] = msg.style diff --git a/tests/bdd/features/format.feature b/tests/bdd/features/format.feature index 8e395d05..2cc7d9a1 100644 --- a/tests/bdd/features/format.feature +++ b/tests/bdd/features/format.feature @@ -597,3 +597,18 @@ Feature: Custom formats When we run "jrnl --format text --file {cache_dir}" Then the cache directory should contain 5 files And we should get no error + + Scenario: Export journal list to multiple formats. + Given we use the config "basic_onefile.yaml" + When we run "jrnl --list" + Then the output should match + Journals defined in config \(.+basic_onefile\.yaml\) + \* default -> features/journals/basic_onefile\.journal + When we run "jrnl --list --format json" + Then the output should match + {"config_path": ".+basic_onefile\.yaml", "journals": {"default": "features/journals/basic_onefile\.journal"}} + When we run "jrnl --list --format yaml" + Then the output should match + config_path: .+basic_onefile\.yaml + journals: + default: features/journals/basic_onefile\.journal diff --git a/tests/lib/then_steps.py b/tests/lib/then_steps.py index 28bc41cf..cb7e9766 100644 --- a/tests/lib/then_steps.py +++ b/tests/lib/then_steps.py @@ -23,6 +23,7 @@ def should_get_no_error(cli_run): assert cli_run["status"] == 0, cli_run["status"] +@then(parse("the output should match\n{regex}")) @then(parse('the output should match "{regex}"')) def output_should_match(regex, cli_run): out = cli_run["stdout"]