From 1bd60db8b7e515d7dd27b6a154bd83a6b31ff657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=BE=20=D0=9A=D0=B0=D1=82?= =?UTF-8?q?=D1=8E=D1=85=D0=B0?= Date: Wed, 7 Aug 2024 19:46:28 +0300 Subject: [PATCH] [FIX] Fix display of subcommands grouped by topic. --- source/commandr/help.d | 16 ++++++++++++++-- source/commandr/program.d | 8 ++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/source/commandr/help.d b/source/commandr/help.d index 9779053..2a35e91 100644 --- a/source/commandr/help.d +++ b/source/commandr/help.d @@ -2,7 +2,7 @@ module commandr.help; import commandr.program; import commandr.option; -import std.algorithm : filter, map, any, chunkBy; +import std.algorithm : filter, map, any, chunkBy, sort; import std.array : join, array; import std.conv : to; import std.stdio : writefln, writeln, write; @@ -160,7 +160,19 @@ struct HelpPrinter { } private void printSubcommands(Command[string] commands) { - auto grouped = commands.values.chunkBy!(a => a.topic).array; + auto grouped = commands.values + .sort!((a, b) { + // Note, when we used chunkBy, it is expected that range + // is already sorted by the key, thus before grouping, + // we have to sort by topic first. + // And then by name for better output + // (because associative array do not preserver order). + if (a.topic == b.topic) + return a.name < b.name; + return a.topic < b.topic; + }) + .chunkBy!(a => a.topic) + .array; if (grouped.length == 1 && grouped[0][0] is null) { foreach(key, command; commands) { diff --git a/source/commandr/program.d b/source/commandr/program.d index fea344c..5bfef6e 100644 --- a/source/commandr/program.d +++ b/source/commandr/program.d @@ -252,6 +252,9 @@ public class Command { throw new InvalidProgramException("cannot have sub-commands and non-required argument"); } + // TODO: may be update only if command do not have topic yet, + // or only when _topicStart is set. + // Because otherwise, topic set on command is overwritten here. command._topic = this._topicStart; command._parent = this; _commands[command.name] = command; @@ -847,8 +850,13 @@ unittest { .topic("z") .topicGroup("general purpose") .add(new Command("b", "desc")) + .add(new Command("c", "desc")) + .topicGroup("other") + .add(new Command("d", "desc")) ; assert(p.topic == "z"); assert(p.commands["b"].topic == "general purpose"); + assert(p.commands["c"].topic == "general purpose"); + assert(p.commands["d"].topic == "other"); }