Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1803448

Browse files
committed
Echo stdout (#677)
* Add newline to output of echo (#557) * Add newline to output of echo * Add test * Throw an error if the options string does not start with '-' (#615) * Throw an error if the options string does not start with '-' * Add test * Change message grammar * Add -n option to echo * Fix null argument issue * Add -n tests * Add documentation * Add -en escaped character test * Add function to parse options for echo * Use parseOptions to parse echo options * Simplify control flow * parseOptions throws now * Allow null to be echoed * Prevent echo stderr on unrecognized option * Add test to check stderr of returned value * Use consistent variable name * Change test message, leave TODO about console output
1 parent 97a8c19 commit 1803448

File tree

5 files changed

+102
-7
lines changed

5 files changed

+102
-7
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,14 @@ See also: pushd, popd
259259
Available options:
260260

261261
+ `-e`: interpret backslash escapes (default)
262+
+ `-n`: remove trailing newline from output
262263

263264
Examples:
264265

265266
```javascript
266267
echo('hello world');
267268
var str = echo('hello world');
269+
echo('-n', 'no newline at end');
268270
```
269271

270272
Prints string to stdout, and returns string with additional utility methods

src/common.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ exports.getUserHome = getUserHome;
172172
// parseOptions('-a', {'a':'alice', 'b':'bob'});
173173
// Returns {'reference': 'string-value', 'bob': false} when passed two dictionaries of the form:
174174
// parseOptions({'-r': 'string-value'}, {'r':'reference', 'b':'bob'});
175+
// Throws an error when passed a string that does not start with '-':
176+
// parseOptions('a', {'a':'alice'}); // throws
175177
function parseOptions(opt, map, errorOptions) {
176178
// Validate input
177179
if (typeof opt !== 'string' && !isObject(opt)) {

src/echo.js

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
var format = require('util').format;
2+
13
var common = require('./common');
24

35
common.register('echo', _echo, {
@@ -9,26 +11,52 @@ common.register('echo', _echo, {
911
//@ Available options:
1012
//@
1113
//@ + `-e`: interpret backslash escapes (default)
14+
//@ + `-n`: remove trailing newline from output
1215
//@
1316
//@ Examples:
1417
//@
1518
//@ ```javascript
1619
//@ echo('hello world');
1720
//@ var str = echo('hello world');
21+
//@ echo('-n', 'no newline at end');
1822
//@ ```
1923
//@
2024
//@ Prints string to stdout, and returns string with additional utility methods
2125
//@ like `.to()`.
22-
function _echo(opts, messages) {
26+
function _echo(opts) {
2327
// allow strings starting with '-', see issue #20
24-
messages = [].slice.call(arguments, opts ? 0 : 1);
28+
var messages = [].slice.call(arguments, opts ? 0 : 1);
29+
var options = {};
30+
31+
// If the first argument starts with '-', parse it as options string.
32+
// If parseOptions throws, it wasn't an options string.
33+
try {
34+
options = common.parseOptions(messages[0], {
35+
'e': 'escapes',
36+
'n': 'no_newline'
37+
}, {
38+
silent: true
39+
});
2540

26-
if (messages[0] === '-e') {
27-
// ignore -e
28-
messages.shift();
41+
// Allow null to be echoed
42+
if (messages[0]) {
43+
messages.shift();
44+
}
45+
} catch (_) {
46+
// Clear out error if an error occurred
47+
common.state.error = null;
2948
}
3049

31-
console.log.apply(console, messages);
32-
return messages.join(' ') + '\n';
50+
var output = format.apply(null, messages);
51+
52+
// Add newline if -n is not passed.
53+
if (!options.no_newline) {
54+
output += '\n';
55+
}
56+
57+
process.stdout.write(output);
58+
59+
return output;
3360
}
61+
3462
module.exports = _echo;

test/common.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ test('common.parseOptions using an object to hold options', t => {
269269
t.false(result.reverse);
270270
});
271271

272+
test('common.parseOptions throws when passed a string not starting with "-"', t => {
273+
t.throws(() => {
274+
common.parseOptions('a', { '-a': 'throws' });
275+
}, 'Options string must start with "-"');
276+
});
277+
272278
test('Some basic tests on the ShellString type', t => {
273279
const result = shell.ShellString('foo');
274280
t.is(result.toString(), 'foo');

test/echo.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,60 @@ test.cb('piping to a file', t => {
7979
t.end();
8080
});
8181
});
82+
83+
test.cb('-n option', t => {
84+
const script = "require('../global.js'); echo('-n', 'message');";
85+
utils.runScript(script, (err, stdout) => {
86+
t.falsy(err);
87+
t.is(stdout, 'message');
88+
t.end();
89+
});
90+
});
91+
92+
test.cb('-ne option', t => {
93+
const script = "require('../global.js'); echo('-ne', 'message');";
94+
utils.runScript(script, (err, stdout) => {
95+
t.falsy(err);
96+
t.is(stdout, 'message');
97+
t.end();
98+
});
99+
});
100+
101+
test.cb('-en option', t => {
102+
const script = "require('../global.js'); echo('-en', 'message');";
103+
utils.runScript(script, (err, stdout) => {
104+
t.falsy(err);
105+
t.is(stdout, 'message');
106+
t.end();
107+
});
108+
});
109+
110+
test.cb('-en option with escaped characters', t => {
111+
const script = "require('../global.js'); echo('-en', '\\tmessage\\n');";
112+
utils.runScript(script, (err, stdout) => {
113+
t.falsy(err);
114+
t.is(stdout, '\tmessage\n');
115+
t.end();
116+
});
117+
});
118+
119+
test.cb('piping to a file with -n', t => {
120+
// see issue #476
121+
shell.mkdir(t.context.tmp);
122+
const tmp = `${t.context.tmp}/echo.txt`;
123+
const script = `require('../global.js'); echo('-n', 'A').toEnd('${tmp}'); echo('-n', 'B').toEnd('${tmp}');`;
124+
utils.runScript(script, (err, stdout) => {
125+
const result = shell.cat(tmp);
126+
t.falsy(err);
127+
t.is(stdout, 'AB');
128+
t.is(result.toString(), 'AB');
129+
t.end();
130+
});
131+
});
132+
133+
test('stderr with unrecognized options is empty', t => {
134+
// TODO: console output here needs to be muted
135+
const result = shell.echo('-asdf');
136+
t.falsy(result.stderr);
137+
t.is(result.stdout, '-asdf\n');
138+
});

0 commit comments

Comments
 (0)