-
Notifications
You must be signed in to change notification settings - Fork 744
Add "-n" option to echo #590
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
Conversation
| }); | ||
|
|
||
| test.cb('-ne option', t => { | ||
| const script = "require('../global.js'); echo('-ne', 'message');"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also test echo -en 'foo\n' to make sure that -e still works?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can add a test for that.
| output = format.apply(null, messages) + '\n'; | ||
| } | ||
|
|
||
| console.log.apply(console, messages); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's only use process.stdout.write for when -n is passed. Calling process.exit immediately after process.stdout.write has some issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it matters, because console.log is just a wrapper around process.stdout.write. See this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference, it has been that way since at least v0.7.4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm ok, let's use this approach then.
src/echo.js
Outdated
| var option = ['-e', '-n', '-ne', '-en'].indexOf(messages[0]); | ||
| var output; | ||
|
|
||
| if (option >= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be easier to just check:
- is the first argument a real option?
- do the options contain
-n?
And just switch the behavior on that condition. That way we can keep using console.log by default, which has some nicer behavior (see my comment below).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we check if the first argument is a real option? Would using the cmdOptions attribute in common.register solve this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can use common.parseOptions to parse the first argument. If we catch the option not recognized error, then just print that string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but it won't throw the error as an exception, it'll return early from the echo function. You can hack around it by setting config.fatal to have it throw an exception. A clearer way is to add an option to common.error to throw an exception instead of exiting (regardless of config.fatal).
The approach you have here works if we only have two options, but it gets cumbersome if we ever support -E (which we may want to support in the future).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I've added a function to echo.js that parses options just for echo. This means adding -E later on will be easier.
src/echo.js
Outdated
| return output; | ||
| } | ||
|
|
||
| function parseEchoOptions(opts) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, let's use common.parseOptions(). It actually does throw an exception upon error regardless of config.fatal. It behaves exactly how we want, and it'll be much cleaner to reuse the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parseOptions will still log to stdout when it doesn't recognize an option:
> try {
... common.parseOptions('-b', {a: 'test'})
... } catch (_) {
... console.log('whoops')
... }
shell.js: option not recognized: b
whoops
This is not good if someone tries to echo a string that happens to start with '-'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see the issue. I think it may be better to either:
- hack around this by temporarily setting
config.silent = true(document what we're doing in comments) - add a way to silence
parseOptions(exception only, no stdio)
I think the approach we take depends on if we want to expose this feature in parseOptions in the plugin API.
@freitagbr What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer an extra silence argument or option for parseOptions. Plugins could probably make use of the option, too.
4f4b422 to
74242aa
Compare
|
@nfischer I refactored |
74242aa to
09d8643
Compare
|
@freitagbr please rebase off |
09d8643 to
11629fb
Compare
|
Done. |
src/echo.js
Outdated
| // ignore -e | ||
| if (options) { | ||
| // first argument was options string, | ||
| // so do not print it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Join these lines?
src/echo.js
Outdated
| // If the first argument starts with '-', | ||
| // parse it as options string. | ||
| // If parseOptions throws, | ||
| // it wasn't an options string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Join these lines?
src/echo.js
Outdated
| output += '\n'; | ||
| } | ||
| } else { | ||
| output = format.apply(null, messages) + '\n'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're appending \n in this branch, but we're also appending it above. Can we flatten-out this logic? Something like:
try {
options = common.parseOptions(messages[0], { ... }, { silent: true });
messages.shift();
} catch (e) {
options = {};
}
output = format.apply(null, messages);
if (!options.no_newline) {
output += '\n';
}
process.stdout.write(output);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we still need to check if the first argument starts with '-', because we don't know if it needs to be printed or not otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, sure. parseOptions has useless behavior if you pass it a string that doesn't start with -.
nfischer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approval. See #614 in case you want to fix that first, otherwise FFTM
|
I'll wait for the pull request I submitted (#615) to be merged before moving on here. |
|
There's an issue here. When passing a string starting with This is obviously not how |
|
@freitagbr can you manually clear out I doubt there's a great way to test it, but maybe you could add a test like: const ret = shell.echo('-n', ''); // echo nothing
t.falsy(ret.stderr);
t.is(ret.stdout, '');
t.is(ret.code, 0);This case wouldn't add stderr anyway, but it'll save us from huge future regressions while also not polluting the output. |
nfischer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a fix for .stderr
609d7c8 to
e018604
Compare
|
@nfischer I added the fix, though there is already a test case that checks that |
|
@freitagbr it needs to check for |
|
Ok, test added. PTAL |
ava-test/echo.js
Outdated
| }); | ||
|
|
||
| test('stderr with unrecognized options is null', t => { | ||
| const ret = shell.echo('-asdf'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@freitagbr will this output to the console? If so, let's at least add a TODO to mute console output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it does. I suppose we can fix this along with mocking process.stdout like you suggested for #622.
ava-test/echo.js
Outdated
| }); | ||
| }); | ||
|
|
||
| test('stderr with unrecognized options is null', t => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/null/empty/ or s/null/falsy/
We may want to switch stderr from null to the empty string in a future release.
ec4810e to
37ea827
Compare
|
@nfischer PTAL |
Fixes #559