CLI: Help improvements - Table output with color and routing support#40848
CLI: Help improvements - Table output with color and routing support#40848dkbennett wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
⚠️ Not ready to approve
The updated table-output unit tests introduce dangling references via cap.lines() temporaries, and a large amount of existing help E2E coverage is disabled by SKIP_TEST_UNSTABLE() rather than being updated to validate the new help behavior.
Pull request overview
This PR modernizes the WSLC CLI help experience by reworking help rendering to use the shared TableOutput infrastructure (including word-wrap and VT formatting), while also improving help output routing (stdout vs stderr) and making usage reflect the invoked executable name.
Changes:
- Refactors
TableOutputto write viaReporter, addsFormattedCellsupport, and introduces whole-line output plus word-wrapping columns. - Reworks command help generation to use table rendering, VT emphasis, global options grouping, and correct output routing on errors; sets executable name from
argv[0]. - Updates/extends unit and E2E tests for the new rendering/routing behavior (with many existing help-output E2E tests currently skipped).
File summaries
| File | Description |
|---|---|
| test/windows/wslc/WSLCCLITestHelpers.h | Refactors TableOutputCapture to capture output via Reporter/pipe for new table rendering. |
| test/windows/wslc/WSLCCLITableOutputUnitTests.cpp | Updates/adds extensive unit coverage for wrapping, FormattedCell, and WriteLine behavior. |
| test/windows/wslc/e2e/WSLCExecutor.h | Adds stderr substring helper for new help-routing assertions. |
| test/windows/wslc/e2e/WSLCExecutor.cpp | Implements stderr substring helper; switches header expectation to localized API. |
| test/windows/wslc/e2e/WSLCE2EVolumeTests.cpp | Skips legacy help-output E2E tests for volume command. |
| test/windows/wslc/e2e/WSLCE2EVolumeRemoveTests.cpp | Skips legacy help-output E2E tests for volume remove. |
| test/windows/wslc/e2e/WSLCE2EVolumePruneTests.cpp | Skips legacy help-output E2E tests for volume prune help/error paths. |
| test/windows/wslc/e2e/WSLCE2EVolumeListTests.cpp | Skips legacy help-output E2E test for volume list --help. |
| test/windows/wslc/e2e/WSLCE2EVolumeInspectTests.cpp | Skips legacy help-output E2E tests for volume inspect help/error paths. |
| test/windows/wslc/e2e/WSLCE2EVolumeCreateTests.cpp | Skips legacy help-output E2E test for volume create --help. |
| test/windows/wslc/e2e/WSLCE2ERegistryTests.cpp | Skips legacy help-output E2E tests for registry login/logout --help. |
| test/windows/wslc/e2e/WSLCE2EPushPullTests.cpp | Skips legacy help-output E2E tests for image push/pull (and root aliases). |
| test/windows/wslc/e2e/WSLCE2ENetworkTests.cpp | Skips legacy help-output E2E tests for network command. |
| test/windows/wslc/e2e/WSLCE2ENetworkRemoveTests.cpp | Skips legacy help-output E2E tests for network remove. |
| test/windows/wslc/e2e/WSLCE2ENetworkListTests.cpp | Skips legacy help-output E2E test for network list --help. |
| test/windows/wslc/e2e/WSLCE2ENetworkInspectTests.cpp | Skips legacy help-output E2E tests for network inspect help/error paths. |
| test/windows/wslc/e2e/WSLCE2ENetworkCreateTests.cpp | Skips legacy help-output E2E tests for network create help/error paths. |
| test/windows/wslc/e2e/WSLCE2EInspectTests.cpp | Skips legacy help-output E2E tests for inspect help/error paths. |
| test/windows/wslc/e2e/WSLCE2EImageTests.cpp | Skips legacy help-output E2E tests for image command. |
| test/windows/wslc/e2e/WSLCE2EImageTagTests.cpp | Skips legacy help-output E2E tests for image tag help/error paths. |
| test/windows/wslc/e2e/WSLCE2EImageSaveTests.cpp | Skips legacy help-output E2E tests for image save help/error paths. |
| test/windows/wslc/e2e/WSLCE2EImagePruneTests.cpp | Skips legacy help-output E2E tests for image prune help/error paths. |
| test/windows/wslc/e2e/WSLCE2EImageListTests.cpp | Skips legacy help-output E2E tests for image list help/error paths. |
| test/windows/wslc/e2e/WSLCE2EImageInspectTests.cpp | Skips legacy help-output E2E tests for image inspect help/error paths. |
| test/windows/wslc/e2e/WSLCE2EImageImportTests.cpp | Skips legacy help-output E2E tests for image import help/error paths. |
| test/windows/wslc/e2e/WSLCE2EImageDeleteTests.cpp | Skips legacy help-output E2E tests for image delete help/error paths. |
| test/windows/wslc/e2e/WSLCE2EContainerTests.cpp | Skips legacy help-output E2E tests for container command. |
| test/windows/wslc/e2e/WSLCE2EContainerStopTests.cpp | Skips legacy help-output E2E test for container stop --help. |
| test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp | Skips legacy help-output E2E test for container run --help. |
| test/windows/wslc/e2e/WSLCE2EContainerRemoveTests.cpp | Skips legacy help-output E2E test for container remove --help. |
| test/windows/wslc/e2e/WSLCE2EContainerPruneTests.cpp | Skips legacy help-output E2E test for container prune --help. |
| test/windows/wslc/e2e/WSLCE2EContainerListTests.cpp | Skips legacy help-output E2E tests for container list help/error paths. |
| test/windows/wslc/e2e/WSLCE2EContainerKillTests.cpp | Skips legacy help-output E2E test for container kill --help. |
| test/windows/wslc/e2e/WSLCE2EContainerInspectTests.cpp | Skips legacy help-output E2E tests for container inspect help/error paths. |
| test/windows/wslc/e2e/WSLCE2EContainerExecTests.cpp | Skips legacy help-output E2E tests for container exec help/error paths. |
| test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp | Skips legacy help-output E2E tests for container create help/error paths. |
| test/windows/wslc/e2e/WSLCE2EContainerAttachTests.cpp | Skips legacy help-output E2E test for container attach --help. |
| test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp | Adds new help routing/color tests; skips legacy “exact help output” tests. |
| src/windows/wslc/tasks/VolumeTasks.cpp | Updates table output usage to pass Reporter and WriteRow. |
| src/windows/wslc/tasks/SessionTasks.cpp | Updates session listing to use new TableOutput constructor and WriteRow. |
| src/windows/wslc/tasks/NetworkTasks.cpp | Updates network listing to pass Reporter and use WriteRow. |
| src/windows/wslc/tasks/ImageTasks.cpp | Updates image listing to use new column config shape and Reporter-backed table output. |
| src/windows/wslc/tasks/ContainerTasks.cpp | Updates container list/stats tables to new config shape and Reporter/WriteRow. |
| src/windows/wslc/core/TableOutput.h | Major refactor: FormattedCell, wrapping, standalone lines, Reporter integration, new overflow modes. |
| src/windows/wslc/core/Main.cpp | Extracts executable name from argv[0]; routes help-on-error via Reporter. |
| src/windows/wslc/core/Command.h | Switches executable name to runtime global; updates OutputHelp signature to accept Reporter. |
| src/windows/wslc/core/Command.cpp | Reimplements help output using table rendering, VT emphasis, and stdout/stderr routing. |
| src/windows/wslc/commands/VolumeCommand.cpp | Routes help output through context.Reporter. |
| src/windows/wslc/commands/SystemCommand.cpp | Routes help output through context.Reporter. |
| src/windows/wslc/commands/SessionCommand.cpp | Routes help output through context.Reporter. |
| src/windows/wslc/commands/RootCommand.cpp | Routes help output through context.Reporter. |
| src/windows/wslc/commands/RegistryCommand.cpp | Routes help output through context.Reporter. |
| src/windows/wslc/commands/NetworkCommand.cpp | Routes help output through context.Reporter. |
| src/windows/wslc/commands/ImageCommand.cpp | Routes help output through context.Reporter. |
| src/windows/wslc/commands/ContainerCommand.cpp | Routes help output through context.Reporter. |
| localization/strings/en-US/Resources.resw | Adds localized headings used by the new help layout (Commands/Options/Global Options/etc.). |
Copilot's findings
- Files reviewed: 56/56 changed files
- Comments generated: 46
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
…provements Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
13cee59 to
d72c536
Compare
There was a problem hiding this comment.
⚠️ Not ready to approve
TableOutput currently gates all FormattedCell sequences on IsColorEnabled(), which can incorrectly suppress non-color VT sequences under --no-color and conflicts with the intended Reporter/VT behavior.
Copilot's findings
- Files reviewed: 59/59 changed files
- Comments generated: 2
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
⚠️ Not ready to approve
There are confirmed formatting/correctness issues in the new table/help rendering logic (notably FormattedCell::VisibleWidth() behavior) that should be fixed before approval.
Copilot's findings
- Files reviewed: 59/59 changed files
- Comments generated: 2
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| // Visible width: count characters that are not part of {} placeholders. | ||
| size_t VisibleWidth() const | ||
| { | ||
| size_t width = 0; | ||
| for (size_t i = 0; i < fmt.size(); ++i) | ||
| { | ||
| if (i + 1 < fmt.size() && fmt[i] == L'{' && fmt[i + 1] == L'}') | ||
| { | ||
| ++i; // skip the pair | ||
| } | ||
| else | ||
| { | ||
| ++width; | ||
| } | ||
| } | ||
| return width; | ||
| } |
| std::wstring usageText = Localization::WSLCCLI_Usage(s_ExecutableName, std::wstring_view{commandChain}); | ||
| reporter.Write(helpLevel, L"{}{}{}", HelpHeadingEmphasis, usageText, Format::Default); | ||
|
|
… set Render() and RenderTruncated() now take both vtEnabled and colorEnabled flags, matching Reporter's contract: VT off strips all sequences, color off strips only color sequences (non-color sequences pass through). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…oft/WSL into user/dkbennett/betterhelp
There was a problem hiding this comment.
⚠️ Not ready to approve
TableOutput.h now uses THROW_HR_IF but does not include the WIL header that defines it, making the header non-self-contained and potentially breaking builds depending on include order.
Copilot's findings
- Files reviewed: 59/59 changed files
- Comments generated: 1
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
| #include <algorithm> | ||
| #include <array> | ||
| #include <cwchar> | ||
| #include <functional> | ||
| #include <sstream> | ||
| #include <initializer_list> | ||
| #include <optional> | ||
| #include <string> |
Summary of the Pull Request
Help improvements
TableOutput Improvements (extends beyond just help, any table can utilize these benefits, though no other ones have yet)
Colored cells and naturally handles VT and color disable. Cells now have FormattedCell (which can be a simple string) for easy color or VT introduction that are stripped when no color or VT is disabled.
Whole-line writing possible within the table output.
Columns can support word-wrap
TableOutput now uses the Reporter for writing output and has a cleaner API.
It was original intent to separate fixing up dead tests but the review bot was complaining about that loudly, so this is a one-shot that fixes up all the tests and removes unused test code. The main changes to the tests are around the routing change (help output for argument errors is now in stderr, not stdout) and because of that we now search for the specific error in the stderr instead of trying to match exact help output. The help output tests now verify help is output on stdout but does not explicitly verify the exact format of the help.
PR Checklist
Detailed Description of the Pull Request / Additional comments
Tests
Validation Steps Performed