Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

freitagbr
Copy link
Contributor

Fixes #559

@freitagbr freitagbr changed the base branch from master to dev November 28, 2016 00:35
});

test.cb('-ne option', t => {
const script = "require('../global.js'); echo('-ne', 'message');";
Copy link
Member

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?

Copy link
Contributor Author

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);
Copy link
Member

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.

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 don't think it matters, because console.log is just a wrapper around process.stdout.write. See this.

Copy link
Contributor Author

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.

Copy link
Member

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) {
Copy link
Member

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).

Copy link
Contributor Author

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?

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 think we can use common.parseOptions to parse the first argument. If we catch the option not recognized error, then just print that string.

Copy link
Member

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).

Copy link
Contributor Author

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) {
Copy link
Member

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.

Copy link
Contributor Author

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 '-'.

Copy link
Member

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?

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 would prefer an extra silence argument or option for parseOptions. Plugins could probably make use of the option, too.

@freitagbr
Copy link
Contributor Author

@nfischer I refactored echo to use common.parseOptions, can you take a look when you get a chance?

@nfischer
Copy link
Member

nfischer commented Dec 8, 2016

@freitagbr please rebase off dev

@freitagbr
Copy link
Contributor Author

Done.

src/echo.js Outdated
// ignore -e
if (options) {
// first argument was options string,
// so do not print it
Copy link
Member

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.
Copy link
Member

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';
Copy link
Member

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);

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 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.

Copy link
Member

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
nfischer previously approved these changes Dec 9, 2016
Copy link
Member

@nfischer nfischer left a 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

@freitagbr
Copy link
Contributor Author

I'll wait for the pull request I submitted (#615) to be merged before moving on here.

@freitagbr
Copy link
Contributor Author

There's an issue here. When passing a string starting with -, but containing unrecognized options, stderr on the return object is set:

> echo('-hi')
-hi
{ [String: '-hi\n']
  stdout: '-hi\n',
  stderr: 'echo: option not recognized: h',
  code: 1,
  cat: [Function: bound ],
  head: [Function: bound ],
  tail: [Function: bound ],
  to: [Function: bound ],
  toEnd: [Function: bound ],
  sed: [Function: bound ],
  sort: [Function: bound ],
  uniq: [Function: bound ],
  grep: [Function: bound ],
  exec: [Function: bound ] }

This is obviously not how echo behaves in the shell.

@nfischer
Copy link
Member

@freitagbr can you manually clear out common.state.error? That should do the trick.

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 nfischer dismissed their stale review December 10, 2016 14:34

needs change

Copy link
Member

@nfischer nfischer left a 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

@freitagbr
Copy link
Contributor Author

@nfischer I added the fix, though there is already a test case that checks that stderr === ''

@nfischer
Copy link
Member

@freitagbr it needs to check for ret.stderr. The .stderr isn't ever being outputted (that's what the runScript checks), but it was being returned as a property (so we need to check function return value).

@freitagbr
Copy link
Contributor Author

Ok, test added. PTAL

ava-test/echo.js Outdated
});

test('stderr with unrecognized options is null', t => {
const ret = shell.echo('-asdf');
Copy link
Member

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

Copy link
Contributor Author

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 => {
Copy link
Member

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.

@freitagbr
Copy link
Contributor Author

@nfischer PTAL

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.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.