Adds support for setting output writers and the exit code handler at the scope of the application.
While a CLI application most commonly does want to call os.Exit to handle exit codes, and print errors or usage information to the stderr file descriptor... it's also useful to be able to control these. In this PR, that ability is introduced.
The main motivation for this (at least for me!) is for testing. By allowing these to be user-controlled, it becomes possible for users to write tests of their CLI behavior. (This is a big win, in my book! IMO, it's very important to be able to write end-to-end tests of CLIs, because UX bugs in the last mile are otherwise very easy to accumulate. To try to do this without the ability to control exit behavior and where messages are written, the next nearest fallback option is to invoke the whole program as a subprocess... but this is a fairly awful fallback, and carries considerable complexity burdens; invoking go-install in the middle of go-test... well, let's say it "does not spark joy".)
Previously, within this library, the needs for the library's own self-testing were satisfied by using package-scope variables, which aside from being global, were also unexported. This is no longer necessary. The internal tests now use the same mechanisms that will be available to users. (As a bonus, the tests could now be parallelized without issue, though I haven't taken that step in this commit.)
I've tried to implement this change in a minimally invasive way, and I think it's pretty safe. Tests all still pass :) There are a couple requests for review embedded in the comments in the diff (mostly for stylistic things).
Adds support for setting output writers and the exit code handler at the scope of the application.
While a CLI application most commonly does want to call os.Exit to handle exit codes, and print errors or usage information to the stderr file descriptor... it's also useful to be able to control these. In this PR, that ability is introduced.
The main motivation for this (at least for me!) is for testing. By allowing these to be user-controlled, it becomes possible for users to write tests of their CLI behavior. (This is a big win, in my book! IMO, it's very important to be able to write end-to-end tests of CLIs, because UX bugs in the last mile are otherwise very easy to accumulate. To try to do this without the ability to control exit behavior and where messages are written, the next nearest fallback option is to invoke the whole program as a subprocess... but this is a fairly awful fallback, and carries considerable complexity burdens; invoking go-install in the middle of go-test... well, let's say it "does not spark joy".)
Previously, within this library, the needs for the library's own self-testing were satisfied by using package-scope variables, which aside from being global, were also unexported. This is no longer necessary. The internal tests now use the same mechanisms that will be available to users. (As a bonus, the tests could now be parallelized without issue, though I haven't taken that step in this commit.)
I've tried to implement this change in a minimally invasive way, and I think it's pretty safe. Tests all still pass :) There are a couple requests for review embedded in the comments in the diff (mostly for stylistic things).
I'm not sure if there were open issues for all of this, but at least https://github.com/jawher/mow.cli/issues/112 is addressed by this.