| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| /** | |
| * @fileoverview Utilities for printing objects nicely. | |
| */ | |
| /** | |
| * Returns a string containing a representation of the object | |
| * | |
| * @param {*} obj The object to print | |
| * @param {*} options Optional boolean parameters. | |
| * If this contains a property called "whitespace", you will get pretty printing. | |
| * If this contains a property called "quotes", you will get quotation | |
| * marks around strings. | |
| * @param {*} depth The function is recursive; this indicates the levels | |
| * of recursive depth. | |
| */ | |
| function sprint_go(obj, options, depth) { | |
| let whitespace = options.hasOwnProperty('whitespace'); | |
| let quote = options.hasOwnProperty('quotes') ? '"' : ''; | |
| let output = ''; | |
| let newline = ''; | |
| let indent = ''; | |
| let outdent = ''; | |
| let type = (typeof obj); | |
| if (whitespace) { | |
| newline = '\n'; | |
| for (let i = 0; i < depth - 1; i++) { | |
| outdent += ' '; | |
| } | |
| indent = outdent + ' '; | |
| } | |
| // Implementation note: JSON.stringify dies with BigInt and friends, so we do it the hard way. | |
| if (obj == null) { | |
| output += 'null'; | |
| return output; | |
| } | |
| if (Array.isArray(obj)) { | |
| output += '[' + newline; | |
| for (let i = 0; i < obj.length; i++) { | |
| if (i != 0) { | |
| output += ',' + newline; | |
| } | |
| output += indent; | |
| output += sprint_go(obj[i], options, depth + 1); | |
| } | |
| output += newline + outdent + ']'; | |
| return output; | |
| } | |
| switch (type) { | |
| case 'number': | |
| output += Number(obj).toString(10); | |
| return output; | |
| case 'string': | |
| output += quote + obj + quote; | |
| return output; | |
| case 'boolean': | |
| output += obj ? 'true' : 'false'; | |
| return output; | |
| case 'object': | |
| output += '{' + newline; | |
| let first = true; | |
| for (const property in obj) { | |
| if (!first) { | |
| output += ',' + newline; | |
| } | |
| output += indent; | |
| output += sprint_go(property, options, depth + 1); | |
| output += ' : '; | |
| output += sprint_go(obj[property], options, depth + 1); | |
| first = false; | |
| } | |
| output += newline + outdent + '}'; | |
| return output; | |
| } | |
| if (typeof obj.toString == 'function') { | |
| output += obj.toString(); | |
| return output; | |
| } | |
| throw 'Unknown object type for ' + obj; | |
| } | |
| /** | |
| * Returns a pretty printed representation of this object. | |
| * | |
| * @param {*} obj | |
| * @param {*} options Optional boolean parameters. | |
| * If this contains a property called "whitespace", you will get pretty printing. | |
| * If this contains a property called "quotes", you will get quotation | |
| * marks around strings. | |
| */ | |
| function sprint(obj, options) { | |
| if (!options) { | |
| options = {quotes: true}; | |
| } | |
| return sprint_go(obj, options, 1); | |
| } | |
| /** | |
| * Prints an object on the given fd. | |
| * | |
| * @param {*} fd Something like "std.out" or "std.err" | |
| * @param {*} obj The object to print. | |
| * @param {*} options Optional boolean parameters (see sprint) | |
| */ | |
| function fprint(fd, obj, options) { | |
| if (!options) { | |
| options = {quotes: true, whitespace: true}; | |
| } | |
| fd.printf('%s', sprint_go(obj, options, 1)); | |
| } | |
| /** | |
| * Prints an object on stdout. | |
| * | |
| * @param {*} obj The object to print. | |
| * @param {*} options Optional boolean parameters (see sprint) | |
| */ | |
| function print(obj, options) { | |
| fprint(std.out, obj, options) | |
| } | |
| /** | |
| * Returns a string containing a tabular representation of the given array. | |
| * The given array is an array of objects. Each property is one column in | |
| * the table. The first element is assumed to contain exactly the properties | |
| * to be printed. If subsequent elements are missing some of those properties, | |
| * an exception will be thrown. If subsequent elements have additional | |
| * properties, they will not be printed. | |
| * | |
| * @param {*} arr The array to print in tabular form. | |
| */ | |
| function scols(arr) { | |
| let schema = []; | |
| let outArr = []; | |
| let colWidths = []; | |
| if (!Array.isArray(arr)) { | |
| throw 'Attempt to print non-array value'; | |
| } | |
| if (arr.length < 1) { | |
| throw 'No columns for array detected' | |
| } | |
| for (let prop in arr[0]) { | |
| if (arr[0].hasOwnProperty(prop)) { | |
| schema.push(prop); | |
| colWidths.push(prop.length >= 1 ? prop.length + 1 : 1); | |
| } | |
| } | |
| for (let i = 0; i < arr.length; i++) { | |
| let newElt = []; | |
| for (let j = 0; j < schema.length; j++) { | |
| let str = sprint_go(arr[i][schema[j]], {}, 1); | |
| if (colWidths[j] < str.length + 1) { | |
| colWidths[j] = str.length + 1; | |
| } | |
| newElt.push(str); | |
| } | |
| outArr.push(newElt); | |
| } | |
| let output = '\n'; | |
| for (let i = 0; i < schema.length; i++) { | |
| output += schema[i].padStart(colWidths[i], ' '); | |
| } | |
| output += '\n'; | |
| for (let i = 0; i < outArr.length; i++) { | |
| for (let j = 0; j < schema.length; j++) { | |
| output += outArr[i][j].padStart(colWidths[j], ' '); | |
| } | |
| output += '\n'; | |
| } | |
| return output; | |
| } | |
| /** | |
| * Prints a tabular representation of the given array arr to file descriptor | |
| * fd. Example: pp,fpcols(std.err, []). | |
| * | |
| * For more on the tabular representation, see scols. | |
| * | |
| * @param {*} fd The file descriptor to which to write | |
| * @param {*} arr The array to print to that file descriptor. | |
| */ | |
| function fpcols(fd, arr) { | |
| fd.printf('%s', scols(arr)); | |
| } | |
| /** | |
| * Prints a tabular representation of the given array arr to stdout. | |
| * | |
| * For more on the tabular representation, see scols. | |
| * | |
| * @param {*} arr The array to print. | |
| */ | |
| function pcols(arr) { | |
| fpcols(std.out, arr); | |
| } | |
| export {print, fprint, sprint, pcols, fpcols, scols} |