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

Respect the COLUMNS and LINES environment variables when present #596

Merged
merged 8 commits into from
Nov 15, 2023

Conversation

gwynne
Copy link
Contributor

@gwynne gwynne commented Nov 12, 2023

As documented in both the Linux and BSD versions of the environ(7) manpage, many console utilities respect the presence of the COLUMNS and LINES environment variables, treating them as overrides (or, less commonly, fallbacks) of the terminal's reported size (if any). This adds that same behavior to ArgumentParser's screen size logic, affecting the wrapping of the usage generator's output.

Note: These changes follow the semantics of ls(1), where COLUMNS and LINES individually override the values reported by a terminal when they are present. Setting only one of the two variables has no effect on the other. It is also worth noting that at the present time, overriding the screen height (i.e. LINES) has no impact whatsoever on ArgumentParser's behavior.

The new logic only takes effect on non-Windows/WASI platforms.

Checklist

  • I've added at least one test that validates that my change is working, if appropriate
  • I've followed the code style of the rest of the project
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary

…alue, and clean up the code a little in the process.
@rauhul
Copy link
Contributor

rauhul commented Nov 12, 2023

@swift-ci please test

/// The current terminal size, or the default if the width is unavailable.
static var terminalWidth: Int {
terminalSize().width
self.terminalSize().width
Copy link
Contributor

Choose a reason for hiding this comment

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

I appreciate the explicit self

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suffice to say I wish there was an .enableUpcomingFeature() flag called "DisallowImplicitSelf" 🤣

Copy link
Contributor

Choose a reason for hiding this comment

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

+10000000

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

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

This looks great! Any ideas about how to test this? Could we set COLUMNS for some/one of the help generation tests to verify that it gets picked up as the default?

@@ -26,7 +26,8 @@ fileprivate struct Qux: ParsableArguments {
fileprivate struct Quizzo: ParsableArguments {
@Option() var name: String
@Flag() var verbose = false
let count = 0
let count: Int
init() { self.count = 0 } // silence warning about count not being decoded
Copy link
Member

Choose a reason for hiding this comment

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

THANK YOU

Copy link
Contributor

Choose a reason for hiding this comment

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

+1000 this might allow us to enable "warnings as errors"!!

@gwynne
Copy link
Contributor Author

gwynne commented Nov 14, 2023

This looks great! Any ideas about how to test this? Could we set COLUMNS for some/one of the help generation tests to verify that it gets picked up as the default?

Test added!

@natecook1000
Copy link
Member

@swift-ci Please test

@natecook1000 natecook1000 enabled auto-merge (squash) November 14, 2023 17:05
throw XCTSkip("Unsupported on this platform")
#endif

unsetenv("COLUMNS")
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to defer { unsetenv("COLUMNS") } to avoid this test colliding with other tests which assert on help screens?

I'm actually wondering if this is safely testable when swift test --parallel is used...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oof, that's a good point - Definitionally, it can't really be parallel-safe, in that environment variables themselves are mutable shared global state. The best I think I can do is lessen the amount of variance in the COLUMNS value (such as only setting it to 80 and 81, keeping it as close as possible to the default).

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if the best solution is to just not set the env var and skip test coverage. I know thats a gross solution, but I'd much rather have 100% reliable tests than missing test coverage (imo)

Copy link
Contributor

Choose a reason for hiding this comment

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

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 have a partial workaround - I can use CommandLine.arguments to detect when parallel testing is in effect (the commandline signatures are unique on both macOS and Linux), and use that to skip the test. The caveat is that it only works for swift test; I'd have to skip it unconditionally in Xcode.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Update: I tried this solution and it worked in multiple Swift versions on both platforms, so I pushed the code.

Copy link
Member

@natecook1000 natecook1000 Nov 14, 2023

Choose a reason for hiding this comment

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

Alternatively, could we have this test be the only place that checks that the default 80 column width is used, and just specify exact widths in all the other help generation tests? If we're skipping parallel tests and Xcode tests, this will only get run in Linux CI (at least by me)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, yeah, the tests should probably be doing that anyway - in my default Terminal setup (in which I export COLUMNS in my ~/.bash_profile) the tests already spuriously fail even on main.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@natecook1000 Okay, pushed an update that makes all the tests in the same target specify the columns explicitly (parallel testing is inconsistent about tests in other cases in the same target, but tests in other targets always run in a different runner process), and force-unsets the environment variable in the other targets.

@natecook1000
Copy link
Member

@swift-ci Please test

@natecook1000 natecook1000 enabled auto-merge (squash) November 15, 2023 04:15
@natecook1000 natecook1000 merged commit c10af98 into apple:main Nov 15, 2023
2 checks passed
@gwynne gwynne deleted the gwynne/respect-screen-size-env-vars branch November 15, 2023 06:26
This pull request was closed.
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.

3 participants