Skip to content

Wrap HelpItems to table. (#629) #947

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

Merged
merged 2 commits into from
Jun 29, 2020
Merged

Conversation

apogeeoak
Copy link
Contributor

Wrap HelpItems to table in HelpBuilder.

The column widths of the table are allocated to favor minimal rows. Wider columns are allocated more space if it is available.

Added tests to HelpBuilderTest to check that necessary sections properly wrap.

Example:
  Command description.

Usage:
  Example [options]

Options:
  --option-alias-for-a-command-th    Description that is long enough
  at-is-long-enough-to-wrap-to-a-    to wrap to a new line.
  new-line

Removed erroneous trailing whitespace in HelpBuilderTests.Help_describes_default_values_for_complex_root_command_scenario.approved.txt.

Additional auto-formatting in HelpBuilderTest.cs. Removed trailing whitespace and some argument alignment.

Fixes #629

@dnfadmin
Copy link

dnfadmin commented Jun 26, 2020

CLA assistant check
All CLA requirements met.

return collection.Select(selector)
.Select(row => row
.Select(element => RemoveFormatting(element))
.ToList().AsReadOnly())
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this needed? Does the the outer ToList suffice?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A ReadOnlyCollection is not necessary but I used one to follow the guidelines for collections.

I think a multidimensional array is better suited to represent a table. Originally I was going to implement the table view as a separate class with a multidimensional array backing but decided to implement it in place instead so I opted for a ReadOnlyCollection.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that guidance predates the introduction of IReadOnlyCollection<T> and IReadOnlyList<T>. Generally, it's good to return a less specific type than a more specific type.

I'd avoid the multidimensional array as it's harder to reason about.

We have a table abstraction in System.CommandLine.Rendering. That project was started in part out of a desire to have better and more flexible help layouts. I wonder if there's an opportunity for reuse or convergence there.

@Keboo?

return Array.AsReadOnly(Array.Empty<int>());

var columns = table.First().Count;
Debug.Assert(table.All(e => e.Count == columns), $"Every row in {nameof(table)} must have the same number of columns.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove the Debug.Assert.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can remove the Debug.Assert but if ColumnWidths is called with an unequal number of columns an exception will be thrown at an indeterminate time. This should never happen in production so I thought an O(n) check for this was generally wasteful.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would a compensation of some kind be preferable to an exception? Or can we make the incorrect state unrepresentable by the object model?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the object model was a multidimensional array incorrect state would be unrepresentable as it would guarantee a consistent number of columns.

CreateTable will always return a table with a consistent number of columns but if ColumnWidths is called with arbitrary input then this cannot be guaranteed.

@apogeeoak apogeeoak changed the title Wrap HelpItems to table. (#629) Wrap HelpItems to table. (#629) Jun 26, 2020
@apogeeoak
Copy link
Contributor Author

I can squash the commits on approval.

catch (System.IO.IOException)
{
if (console is SystemConsole systemConsole)
return systemConsole.GetConsoleWindowWidth();
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add braces.

@jonsequitur
Copy link
Contributor

Thanks, @apogeeoak! This is a really nice improvement.

@jonsequitur jonsequitur merged commit f2512fe into dotnet:master Jun 29, 2020
@apogeeoak
Copy link
Contributor Author

I would still like to make some changes to this and then squash the commits if possible.

I would like to add in the braces I forgot to add and change CreateTable to immediately evaluate and return an IReadOnlyList instead of an IEnumerable. I think the immediate evaluation is worth the added memory since the result is queried twice and may be an expensive operation. I was also considering changing the caching function from ToArray to ToList but I do not know which is better.

@jonsequitur
Copy link
Contributor

Sorry for the over-eager merge. Further PRs to make optimizations are more than welcome.

@apogeeoak
Copy link
Contributor Author

Should I create a new PR or reuse this one?

@jonsequitur
Copy link
Contributor

Please create a new one.

@apogeeoak apogeeoak deleted the issue-629 branch June 29, 2020 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enum values should be split to multiple lines
3 participants