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

console: implement minimal console.group() #14910

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 27 additions & 0 deletions doc/api/console.md
Expand Up @@ -286,6 +286,32 @@ If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`][] is called on each argument and the resulting string
values are concatenated. See [`util.format()`][] for more information.

### console.group([...label])
<!-- YAML
added: REPLACEME
-->

* `label` {any}

Increases indentation of subsequent lines by two spaces.

If one or more `label`s are provided, those are printed first without the
additional indentation.

### console.groupCollapsed()
<!-- YAML
added: REPLACEME
-->

An alias for [`console.group()`][].

### console.groupEnd()
<!-- YAML
added: REPLACEME
-->

Decreases indentation of subsequent lines by two spaces.

### console.info([data][, ...args])
<!-- YAML
added: v0.1.100
Expand Down Expand Up @@ -390,6 +416,7 @@ added: v0.1.100
The `console.warn()` function is an alias for [`console.error()`][].

[`console.error()`]: #console_console_error_data_args
[`console.group()`]: #console_console_group_label
[`console.log()`]: #console_console_log_data_args
[`console.time()`]: #console_console_time_label
[`console.timeEnd()`]: #console_console_timeend_label
Expand Down
24 changes: 21 additions & 3 deletions lib/console.js
Expand Up @@ -25,6 +25,9 @@ const errors = require('internal/errors');
const util = require('util');
const kCounts = Symbol('counts');

// Track amount of indentation required via `console.group()`.
const kGroupIndent = Symbol('groupIndent');

function Console(stdout, stderr, ignoreErrors = true) {
if (!(this instanceof Console)) {
return new Console(stdout, stderr, ignoreErrors);
Expand Down Expand Up @@ -57,6 +60,7 @@ function Console(stdout, stderr, ignoreErrors = true) {
Object.defineProperty(this, '_stderrErrorHandler', prop);

this[kCounts] = new Map();
this[kGroupIndent] = '';

// bind the prototype functions to this Console instance
var keys = Object.keys(Console.prototype);
Expand Down Expand Up @@ -111,7 +115,7 @@ function write(ignoreErrors, stream, string, errorhandler) {
Console.prototype.log = function log(...args) {
write(this._ignoreErrors,
this._stdout,
`${util.format.apply(null, args)}\n`,
`${this[kGroupIndent]}${util.format.apply(null, args)}\n`,
this._stdoutErrorHandler);
};

Expand All @@ -122,7 +126,7 @@ Console.prototype.info = Console.prototype.log;
Console.prototype.warn = function warn(...args) {
write(this._ignoreErrors,
this._stderr,
`${util.format.apply(null, args)}\n`,
`${this[kGroupIndent]}${util.format.apply(null, args)}\n`,
this._stderrErrorHandler);
};

Expand All @@ -134,7 +138,7 @@ Console.prototype.dir = function dir(object, options) {
options = Object.assign({ customInspect: false }, options);
write(this._ignoreErrors,
this._stdout,
`${util.inspect(object, options)}\n`,
`${this[kGroupIndent]}${util.inspect(object, options)}\n`,
this._stdoutErrorHandler);
};

Expand Down Expand Up @@ -214,6 +218,20 @@ Console.prototype.countReset = function countReset(label = 'default') {
counts.delete(`${label}`);
};

Console.prototype.group = function group(...data) {
if (data.length > 0) {
this.log(...data);
}
this[kGroupIndent] += ' ';
};

Console.prototype.groupCollapsed = Console.prototype.group;

Console.prototype.groupEnd = function groupEnd() {
this[kGroupIndent] =
this[kGroupIndent].slice(0, this[kGroupIndent].length - 2);
};

module.exports = new Console(process.stdout, process.stderr);
module.exports.Console = Console;

Expand Down
111 changes: 111 additions & 0 deletions test/parallel/test-console-group.js
@@ -0,0 +1,111 @@
'use strict';
const common = require('../common');

const assert = require('assert');
const Console = require('console').Console;

let c, stdout, stderr;

function setup() {
stdout = '';
common.hijackStdout(function(data) {
stdout += data;
});

stderr = '';
common.hijackStderr(function(data) {
stderr += data;
});

c = new Console(process.stdout, process.stderr);
}

function teardown() {
common.restoreStdout();
common.restoreStderr();
}

// Basic group() functionality
{
setup();
const expectedOut = 'This is the outer level\n' +
' Level 2\n' +
' Level 3\n' +
' Back to level 2\n' +
'Back to the outer level\n' +
'Still at the outer level\n';


const expectedErr = ' More of level 3\n';

c.log('This is the outer level');
c.group();
c.log('Level 2');
c.group();
c.log('Level 3');
c.warn('More of level 3');
c.groupEnd();
c.log('Back to level 2');
c.groupEnd();
c.log('Back to the outer level');
c.groupEnd();
c.log('Still at the outer level');

assert.strictEqual(stdout, expectedOut);
assert.strictEqual(stderr, expectedErr);
teardown();
}

// Group indentation is tracked per Console instance.
{
setup();
const expectedOut = 'No indentation\n' +
'None here either\n' +
' Now the first console is indenting\n' +
'But the second one does not\n';
const expectedErr = '';

const c2 = new Console(process.stdout, process.stderr);
c.log('No indentation');
c2.log('None here either');
c.group();
c.log('Now the first console is indenting');
c2.log('But the second one does not');

assert.strictEqual(stdout, expectedOut);
assert.strictEqual(stderr, expectedErr);
teardown();
}

// Make sure labels work.
{
setup();
const expectedOut = 'This is a label\n' +
' And this is the data for that label\n';
const expectedErr = '';

c.group('This is a label');
c.log('And this is the data for that label');

assert.strictEqual(stdout, expectedOut);
assert.strictEqual(stderr, expectedErr);
teardown();
}

// Check that console.groupCollapsed() is an alias of console.group()
{
setup();
const expectedOut = 'Label\n' +
' Level 2\n' +
' Level 3\n';
const expectedErr = '';

c.groupCollapsed('Label');
c.log('Level 2');
c.groupCollapsed();
c.log('Level 3');

assert.strictEqual(stdout, expectedOut);
assert.strictEqual(stderr, expectedErr);
teardown();
}