From 4192659e031211468ee092e4ec5a5d36a7be9eb8 Mon Sep 17 00:00:00 2001 From: Kiko Beats Date: Fri, 14 Apr 2017 14:37:02 +0200 Subject: [PATCH] Add %J formatter --- README.md | 48 +++++++++++++++++++++++++++++++++++++++++++ examples/formatter.js | 18 ++++++++++++++++ lib/Default.coffee | 12 +++++------ lib/Format.coffee | 36 ++++++++++++++++++++++++-------- package.json | 1 + 5 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 examples/formatter.js diff --git a/README.md b/README.md index 049faab..52cba3f 100755 --- a/README.md +++ b/README.md @@ -159,6 +159,8 @@ or at runtime: acho.level = 'debug'; ``` +See more at [examples/levels](https://github.com/achohq/acho/blob/master/examples/levels.js). + ### Customization You can completely customize the library to your requirements: changes colors, add more types, sort the priorities... the internal structure of the object is public and you can edit it dynamically. **You have the power**. @@ -195,6 +197,52 @@ acho.info('I am hungry'); If you need customize more the output you can setup `.print` `.generateMessage` (see below) that are a more low level methods for generate and print the output message. +## Formatters + +We use [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters: + +| Formatter | Representation | +|-----------|---------------------------------------------------------------| +| `%s` | String. | +| `%d` | Number (both integer and float). | +| `%j` | JSON serialization in one line | +| `%J` | JSON pretty object in multiple lines | +| `%%` | Single percent sign ('%'). This does not consume an argument. | + +By default, the `%j` is applied when you pass an object to be logged: + +```js +acho.info({hello: 'world', foo: 'bar'}) +// => 'info hello=world foo=bar' +``` + +If you want to use a different formatter, use printf markup: + +```js +acho.info('formatting with object interpolation %J', { + hello: 'world', + foo: 'bar', + deep: { + foo: 'bar', + arr: [1, 2, 3, 4, 5] + } +}) + +// info formatting with object interpolation +// hello: "world" +// foo: "bar" +// deep: +// foo: "bar" +// arr: +// 0: 1 +// 1: 2 +// 2: 3 +// 3: 4 +// 4: 5 +``` + +See more at [examples/formatter](https://github.com/achohq/acho/blob/master/examples/formatter.js). + ## API ### Acho({Object} [options]) diff --git a/examples/formatter.js b/examples/formatter.js new file mode 100644 index 0000000..34fe692 --- /dev/null +++ b/examples/formatter.js @@ -0,0 +1,18 @@ +'use strict' + +var Acho = require('..') +var acho = Acho() + +acho.info('formatting plain text: hello world') +acho.info('formatting with number interpolation %d', 123) +acho.info('formatting with float interpolation %d', 3.14) +acho.info('formatting with string interpolation %s', 'hello world') +acho.info('formatting with object interpolation %j', {hello: 'world', foo: 'bar'}) +acho.info('formatting with object interpolation %J', { + hello: 'world', + foo: 'bar', + deep: { + foo: 'bar', + arr: [1, 2, 3, 4, 5] + } +}) diff --git a/lib/Default.coffee b/lib/Default.coffee index 5d1b7e1..60ef2c9 100644 --- a/lib/Default.coffee +++ b/lib/Default.coffee @@ -152,11 +152,11 @@ module.exports = symbol : CONST.FIGURE.warning error: - level : 1 - color : 'red' - symbol: CONST.FIGURE.error + level : 1 + color : 'red' + symbol : CONST.FIGURE.error fatal: - level : 0 - color : 'red' - symbol: CONST.FIGURE.error + level : 0 + color : 'red' + symbol : CONST.FIGURE.error diff --git a/lib/Format.coffee b/lib/Format.coffee index 81fa373..01f26d6 100644 --- a/lib/Format.coffee +++ b/lib/Format.coffee @@ -1,20 +1,36 @@ 'use strict' +fmtObj = require 'fmt-obj' slice = require 'sliced' chalk = require 'chalk' +CONST = require './Constants' + ESCAPE_REGEX = /%{2,2}/g -TYPE_REGEX = /(%?)(%([jds]))/g +TYPE_REGEX = /(%?)(%([Jjds]))/g isString = (obj) -> typeof obj is 'string' isSymbol = (obj) -> typeof obj is 'symbol' isObject = (obj) -> typeof obj is 'object' isFalsy = (value) -> [null, undefined, false].indexOf(value) isnt -1 isArray = (arr) -> Array.isArray(arr) -colorize = (value, color) -> chalk[color](value) hasWhiteSpace = (s) -> s.indexOf(' ') isnt -1 -serialize = (color, obj, key) -> +colorize = (value, color) -> chalk[color](value) + +prettyObj = (obj, color) -> + lineColor = chalk[CONST.LINE_COLOR] + + fmtObj(obj, Infinity, + punctuation: lineColor + annotation: lineColor + property: chalk[color] + literal: lineColor + number: lineColor + string: lineColor + ) + +serialize = (obj, color, key) -> # symbols cannot be directly casted to strings key = key.toString() if isSymbol key obj = obj.toString() if isSymbol obj @@ -38,12 +54,12 @@ serialize = (color, obj, key) -> key = keys[i] value = obj[key] - if isArray(value) + if isArray value msg += key + '=[' j = 0 l = value.length while j < l - msg += serialize(color, value[j]) + msg += serialize(value[j], color) if j < l - 1 msg += ' ' j++ @@ -51,7 +67,7 @@ serialize = (color, obj, key) -> else if value instanceof Date msg += key + '=' + value else - msg += serialize(color, value, colorize(key, color)) + msg += serialize(value, color, colorize(key, color)) if i < length - 1 msg += ' ' i++ @@ -70,14 +86,16 @@ format = (fmt) -> when 'd' arg = colorize(Number(arg), color) when 'j' - arg = serialize color, arg + arg = serialize arg, color + when 'J' + arg = prettyObj arg, color return arg if !escaped args.unshift arg match ) - fmt += ' ' + serialize color, arg for arg in args if args.length + fmt += ' ' + serialize arg, color for arg in args if args.length fmt = fmt.replace(ESCAPE_REGEX, '%') if fmt.replace? - serialize color, fmt + serialize fmt, color module.exports = format diff --git a/package.json b/package.json index 36b1a30..3d9a0e4 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "dependencies": { "chalk": "~1.1.1", "coffee-script": "~1.12.4", + "fmt-obj": "~1.3.0", "pretty-ms": "~2.1.0", "sliced": "~1.0.1" },