-
Notifications
You must be signed in to change notification settings - Fork 30.3k
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
How do I implement MyObject.inspect(depth, inspectOpts)
?
#8442
Comments
cc @addaleax since you've been doing some work w.r.t. util.inspect recently. |
Hi @Havvy – I agree, the examples don’t really go into that aspect. I probably have time to look into that later, but it would be really cool if you could start out with basically showing a full example with the output you’d like to see (and leave out the things you’re unsure about)? |
Here's an initial attempt. Feel free to warp completely. I'm not all that good at documentation. I'm assuming that the inspect will never be called such that you need to handle not returning anything. The main goal here is to tell me the main conventions and logic the I should be thinking about when implementing things, especially recursive things. I went with an example of a Box because it's the simplest thing I could think of that embodied all of the major issues you should run into when implementing this function. When implementing If you want to support custom colors (and no colors), you can style your text by doing To support the If your object is an arraylike, remember to check the And to combine all of these, we look at implementing
The implementation of this would look like: function Box(value) {
this.value = value;
}
Box.prototype[util.inspect.custom] = function (depth, inspectArgs) {
// impl goes here with comments explaining nuances.
} Footnotes:
|
Hmm. How close would this example get to what you want to show? const util = require('util');
class Box {
constructor(value) {
this.value = value;
}
[util.inspect.custom](depth, options) {
const newOptions = Object.assign({}, options, {
depth: options.depth - depth
});
return options.stylize('Box', 'special') + '<' +
util.inspect(this.value, newOptions) + '>';
}
}
util.inspect.defaultOptions.colors = true;
console.log(new Box({}))
console.log(new Box({
aaaaaaaaaaaaaaaaa: 1,
aaaaaaaaaaaaaaaab: 2,
aaaaaaaaaaaaaaaae: 3
}))
console.log(new Box({a:{b:{c:{d:{}}}}})); Output: Box<{}>
Box<{ aaaaaaaaaaaaaaaaa: 1,
aaaaaaaaaaaaaaaab: 2,
aaaaaaaaaaaaaaaae: 3 }>
Box<{ a: [Object] }> I agree, there are some parts, like checking |
It's close. It doesn't seem to be respecting depth properly. const box = new Box({x: 5});
console.log(util.inspect(box));
console.log(util.inspect({wrap: box}));
console.log(util.inspect({wrap: {wrap: box} });
console.log(util.inspect({wrap: {wrap: {wrap: box} } }));
console.log(util.inspect({wrap: {wrap: {wrap: {wrap: box} } } }));
// Expected Outputs
// Box<{ x: 5 }>
// { wrap: Box<{ x: 5 }> }
// { wrap: { wrap: { Box<[Object]> } }
// { wrap: { wrap: { wrap: [Box] } } }
// { wrap: { wrap: { wrap: [Object] } } }
// Actual Outputs
// Box<{ x: 5 }>
// { wrap: Box<{ x: 5 }> }
// { wrap: { wrap: Box<{ x: 5 }> } }
// { wrap: { wrap: { wrap: Box<{ x: 5 }> } } }
// { wrap: { wrap: { wrap: [Object] } } } Experimenting with util.inspect, it shows the short form (e.g. This line So, taking those into consideration, here's a better version: class Box {
constructor(value) {
this.value = value;
}
inspect(depth, options) {
if (depth < 0) {
return options.stylize('[Box]', 'special');
}
const newOptions = Object.assign({}, options, {
depth: options.depth === null ? null : options.depth - 1
});
return options.stylize('Box', 'special') + '<' +
util.inspect(this.value, newOptions) + '>';
}
} |
And here's code dealing with whitespace. (I haven't actually tested this code yet) class Box {
constructor(value) {
this.value = value;
}
inspect(depth, options) {
if (depth < 0) {
return options.stylize('[Box]', 'special');
}
const newOptions = Object.assign({}, options, {
depth: options.depth === null ? null : options.depth - 1
});
// Four space padding because that's the size of "Box<".
const padding = " ";
const inner = util.inspect(this.value, newOptions).replace(/\n/g, "\n" + padding);
return options.stylize('Box', 'special') + '<' + inner + '>';
}
} |
@Havvy I guess that looks pretty okay, and trying it out seems to work just fine – do you want to open a PR against |
Changes the custom inspect example to a more complex object that actually uses the parameters of the custom inspect function. I specifically chose a wrapper of a value called a "Box" that inspects to "Box < inner_inspect_value >". I also want there to be documentation explaining what the code is actually doing. E.g., the padding replacement part is to make the inspected value line up properly when multi-line inputs are given. I also went with having a space between the Box's brackets and the inner value because it matches how objects work, and that should definitely be listed as a convention somewhere in here. Also, the convention to shorten only when depth is less than 0, not e.g. at 0. But I don't know how to write the documentation for that, so I'm leaving that to somebody who reads this message. Partially fixes: nodejs#8442
Changes the custom inspect example to a more complex object that actually uses the parameters of the custom inspect function. I specifically chose a wrapper of a value called a "Box" that inspects to "Box < inner_inspect_value >". I also want there to be documentation explaining what the code is actually doing. E.g., the padding replacement part is to make the inspected value line up properly when multi-line inputs are given. I also went with having a space between the Box's brackets and the inner value because it matches how objects work, and that should definitely be listed as a convention somewhere in here. Also, the convention to shorten only when depth is less than 0, not e.g. at 0. But I don't know how to write the documentation for that, so I'm leaving that to somebody who reads this message. Ref: #8442 PR-URL: #8875 Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Changes the custom inspect example to a more complex object that actually uses the parameters of the custom inspect function. I specifically chose a wrapper of a value called a "Box" that inspects to "Box < inner_inspect_value >". I also want there to be documentation explaining what the code is actually doing. E.g., the padding replacement part is to make the inspected value line up properly when multi-line inputs are given. I also went with having a space between the Box's brackets and the inner value because it matches how objects work, and that should definitely be listed as a convention somewhere in here. Also, the convention to shorten only when depth is less than 0, not e.g. at 0. But I don't know how to write the documentation for that, so I'm leaving that to somebody who reads this message. Ref: #8442 PR-URL: #8875 Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Changes the custom inspect example to a more complex object that actually uses the parameters of the custom inspect function. I specifically chose a wrapper of a value called a "Box" that inspects to "Box < inner_inspect_value >". I also want there to be documentation explaining what the code is actually doing. E.g., the padding replacement part is to make the inspected value line up properly when multi-line inputs are given. I also went with having a space between the Box's brackets and the inner value because it matches how objects work, and that should definitely be listed as a convention somewhere in here. Also, the convention to shorten only when depth is less than 0, not e.g. at 0. But I don't know how to write the documentation for that, so I'm leaving that to somebody who reads this message. Ref: #8442 PR-URL: #8875 Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Changes the custom inspect example to a more complex object that actually uses the parameters of the custom inspect function. I specifically chose a wrapper of a value called a "Box" that inspects to "Box < inner_inspect_value >". I also want there to be documentation explaining what the code is actually doing. E.g., the padding replacement part is to make the inspected value line up properly when multi-line inputs are given. I also went with having a space between the Box's brackets and the inner value because it matches how objects work, and that should definitely be listed as a convention somewhere in here. Also, the convention to shorten only when depth is less than 0, not e.g. at 0. But I don't know how to write the documentation for that, so I'm leaving that to somebody who reads this message. Ref: #8442 PR-URL: #8875 Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
I’m going to close this as #8875 has landed and there hasn’t been any new discussion since then. If you feel like there’s more to this issue, feel free to re-open, or open a new issue or pull request. :) |
I want to implement inspect for my own object. I want to mostly follow the semantics of
inspect
for non-custom implementations, but just by going by the documentation alone, I have no possible way of doing so. What conventions are there? How do I recursively callinspect
while respecting depth? Do I need to handle the case of depth being null?The example ignores the parameters passed to it completely currently. Maybe if we had an example of a
Box
object that inspects as"Box<InnerInspectValue>"
so e.g.inspect({value: "a", inspect: ... })
returns"Box<'a'>"
but the value can be anything (including over objects with custom inspect impls).The text was updated successfully, but these errors were encountered: