Last active
January 21, 2018 10:05
-
-
Save brainysmurf/d7b5cc6641e3021c871a856f5532fb59 to your computer and use it in GitHub Desktop.
FormatLogger is an alternative logging module for google app scripting. This gist is for the package manager.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function () { | |
| return { | |
| self: {"formatLogger": "d7b5cc6641e3021c871a856f5532fb59"}, | |
| packages: [ | |
| {"utgs": "07eaf09769b450f1e0e7b6ae043c2ba5"}, | |
| ] | |
| }; | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function (global, Factory) { | |
| global.pkg = global.pkg || {}; | |
| pkg.formatLogger = function () { return Factory.apply(Factory, [global].concat(Array.prototype.slice.call(arguments))); } | |
| pkg.formatLogger(); // can be overwritten with another call if transformers are desired | |
| })(this, | |
| function Package (global, options) { | |
| options = options || {}; | |
| if (options.useLogger) | |
| options.loggerObject = Logger; | |
| else | |
| options.loggerObject = console; | |
| options.transformers = options.transformers || {}; | |
| options.defaultTransformString = options.defaultTransformString || "{0}"; | |
| options.pprintNewlines = options.pprintNewlines || true; | |
| options.pprintWhitespace = options.pprintWhitespace || 4; | |
| // ValueError :: String -> Error | |
| var ValueError = function(message) { | |
| var err = new Error(message); | |
| err.name = 'ValueError'; | |
| return err; | |
| }; | |
| // defaultTo :: a,a? -> a | |
| var defaultTo = function(x, y) { | |
| return y == null ? x : y; | |
| }; | |
| // create :: Object -> String,*... -> String | |
| var create = function() { | |
| return function(template) { | |
| var args = Array.prototype.slice.call(arguments, 1); | |
| var idx = 0; | |
| var state = 'UNDEFINED'; | |
| return template.replace( | |
| /([{}])\1|[{](.*?)(?:!(.+?))?[}]/g, | |
| function(match, literal, key, xf) { | |
| if (literal != null) { | |
| return literal; | |
| } | |
| if (key.length > 0) { | |
| if (state === 'IMPLICIT') { | |
| throw ValueError('cannot switch from ' + | |
| 'implicit to explicit numbering'); | |
| } | |
| state = 'EXPLICIT'; | |
| } else { | |
| if (state === 'EXPLICIT') { | |
| throw ValueError('cannot switch from ' + | |
| 'explicit to implicit numbering'); | |
| } | |
| state = 'IMPLICIT'; | |
| key = String(idx); | |
| idx += 1; | |
| } | |
| var value = defaultTo('', lookup(args, key.split('.'))); | |
| if (xf == null) { | |
| return value; | |
| } else if (Object.prototype.hasOwnProperty.call(options.transformers, xf)) { | |
| return options.transformers[xf](value); | |
| } else { | |
| throw ValueError('no transformer named "' + xf + '"'); | |
| } | |
| } | |
| ); | |
| }; | |
| }; | |
| var lookup = function(obj, path) { | |
| if (!/^\d+$/.test(path[0])) { | |
| path = ['0'].concat(path); | |
| } | |
| for (var idx = 0; idx < path.length; idx += 1) { | |
| var key = path[idx]; | |
| if (typeof obj[key] === 'function') | |
| obj = obj[key](); | |
| else | |
| obj = obj[key]; | |
| } | |
| return obj; | |
| }; | |
| Object.defineProperty(Object.prototype, 'stringify', { | |
| get: function () { | |
| return function (pretty) { | |
| pretty = pretty || false; | |
| if (pretty) | |
| return (options.pprintNewlines ? "\n" : "") + | |
| options.defaultTransformString.format(JSON.stringify(this, null, options.pprintWhitespace), this); | |
| else | |
| return options.defaultTransformString.format(JSON.stringify(this), this); | |
| } | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(Object.prototype, 'typeof_', { | |
| get: function () { | |
| var result = typeof this; | |
| switch (result) { | |
| case 'string': | |
| break; | |
| case 'boolean': | |
| break; | |
| case 'number': | |
| break; | |
| case 'object': | |
| case 'function': | |
| switch (this.constructor) { | |
| case new String().constructor: | |
| result = 'String'; | |
| break; | |
| case new Boolean().constructor: | |
| result = 'Boolean'; | |
| break; | |
| case new Number().constructor: | |
| result = 'Number'; | |
| break; | |
| case new Array().constructor: | |
| result = 'Array'; | |
| break; | |
| case new RegExp().constructor: | |
| result = 'RegExp'; | |
| break; | |
| case new Date().constructor: | |
| result = 'Date'; | |
| break; | |
| case Function: | |
| result = 'Function'; | |
| break; | |
| default: | |
| result = this.constructor.toString(); | |
| var m = this.constructor.toString().match(/function\s*([^( ]+)\(/); | |
| if (m) | |
| result = m[1]; | |
| else | |
| result = 'Function'; | |
| break; | |
| } | |
| break; | |
| } | |
| return result.substr(0, 1).toUpperCase() + result.substr(1); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(Object.prototype, 'print', { | |
| get: function () { | |
| return this.stringify(false); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(Object.prototype, '__print__', { | |
| get: function () { | |
| options.loggerObject.log.call(options.loggerObject, this.stringify(false) ); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(Object.prototype, 'pprint', { | |
| get: function () { | |
| return this.stringify(true); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(Object.prototype, '__pprint__', { | |
| get: function () { | |
| options.loggerObject.log.call(options.loggerObject, this.stringify(true) ); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(String.prototype, '__log__', { | |
| get: function () { | |
| return function() { | |
| options.loggerObject.log.call(options.loggerObject, this.format.apply(this, Array.prototype.slice.call(arguments)) ); | |
| }.bind(this); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(String.prototype, '__error__', { | |
| get: function () { | |
| return function() { | |
| options.loggerObject.error.call(options.loggerObject, this.format.apply(this, Array.prototype.slice.call(arguments)) ); | |
| }.bind(this); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(String.prototype, '__info__', { | |
| get: function () { | |
| return function() { | |
| options.loggerObject.info.call(options.loggerObject, this.format.apply(this, Array.prototype.slice.call(arguments)) ); | |
| }.bind(this); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(String.prototype, '__warn__', { | |
| get: function () { | |
| return function() { | |
| options.loggerObject.warn.call(options.loggerObject, this.format.apply(this, Array.prototype.slice.call(arguments)) ); | |
| }.bind(this); | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| Object.defineProperty(String.prototype, 'format', { | |
| get: function () { | |
| var $format = create(options.transformers); | |
| return function () { | |
| var args = Array.prototype.slice.call(arguments); | |
| args.unshift(this); | |
| return $format.apply(global, args); | |
| } | |
| }, | |
| configurable: true, | |
| enumerable: false, | |
| }); | |
| } | |
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function () { | |
| return { | |
| version: 0, | |
| packages: [ | |
| {"": ""}, | |
| ] | |
| }; | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function testing___log() { | |
| function getLog_() { | |
| var log, index; | |
| log = Logger.getLog(); | |
| index = log.indexOf('INFO: '); | |
| if (index == -1) | |
| throw Error("Wonky log: " + log); | |
| log = log.slice(index + 'INFO: '.length, log.length-1); | |
| return log; | |
| } | |
| /* | |
| These tests can only be run if the Logger output is clear | |
| */ | |
| if (Logger.getLog() != "") | |
| return; | |
| /* | |
| Sequence of these init is important | |
| formatLogger needs to be inited after utgs | |
| */ | |
| pkg.utgs.init(); | |
| pkg.formatLogger({ | |
| useLogger: true, | |
| defaultTransformString: "<{0}> ({1.typeof_})", | |
| pprintNewLines: false, | |
| }); | |
| describe("format, __print__, __pprint__, __log__", function () { | |
| Logger.clear(); | |
| it("__print__ echoes to log all properties of an object", function () { | |
| var obj = {hello: "Hello", world: "World!"}; | |
| obj.__print__; | |
| assert.objectEquals({ | |
| expected: '<{"hello":"Hello","world":"World!"}> (Object)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear() | |
| it("__print__ converts integer keys into strings (because json)", function () { | |
| var obj = {0: "Hello", 1: "World!"}; | |
| obj.__print__; | |
| assert.objectEquals({ | |
| comment: "Note the number literals have become strings", | |
| expected: '<{"0":"Hello","1":"World!"}> (Object)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__print__ echoes to log all elements of an array", function () { | |
| var arr = [1, 2, "3", {info: 'info'}]; | |
| arr.__print__; | |
| assert.objectEquals({ | |
| expected: '<[1,2,"3",{"info":"info"}]> (Array)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__print__ echoes to log the string", function () { | |
| var str = "This is a testing string"; | |
| str.__print__; | |
| assert.objectEquals({ | |
| expected: '<"This is a testing string"> (String)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__print__ echoes to log the number", function () { | |
| var num = 2342342.34223; | |
| num.__print__; | |
| assert.objectEquals({ | |
| comment: "Notice that literal numbers turn into strings", | |
| expected: "<2342342.34223> (Number)", | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__pprint__ echoes to log pretty print of all properties of an object", function () { | |
| var obj = {hello: "Hello", world: "World!", 0: "zero"}; | |
| obj.__pprint__; | |
| assert.objectEquals({ | |
| expected: '\n<{\n "hello": "Hello",\n "world": "World!",\n "0": "zero"\n}> (Object)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__pprint__ echoes to log pretty print of all elements of an array", function () { | |
| var arr = [1, 2, "3", {info: 'info'}]; | |
| arr.__pprint__; | |
| assert.objectEquals({ | |
| expected: '\n<[\n 1,\n 2,\n "3",\n {\n "info": "info"\n }\n]> (Array)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__pprint__ echoes to log pretty print of the string", function () { | |
| var str = "This is a testing string"; | |
| str.__pprint__; | |
| assert.objectEquals({ | |
| expected: '\n<"This is a testing string"> (String)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__pprint__ echoes to log pretty print of the number", function () { | |
| var num = 2342342.34223; | |
| num.__pprint__; | |
| assert.objectEquals({ | |
| expected: '\n<2342342.34223> (Number)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__log__ echoes same as __print__ to log templated strings", function () { | |
| var obj = {that:"this", will: [1, 23, {hi:'hi'}], 0: "zero"}; | |
| "{0.print}".__log__(obj); | |
| assert.objectEquals({ | |
| comment: "Notice the zero literal became a string", | |
| expected: '<{"that":"this","will":[1,23,{"hi":"hi"}],"0":"zero"}> (Object)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("__log__ echoes with explicit keys and dot properties", function () { | |
| var obj = {that:"this", will: [1, 23, {hi:'hi'}], 0: "zero"}; | |
| var arr = [1, 2, 3, 4]; | |
| "{0.print}\n{1.length}: {1.pprint}".__log__(obj, arr); | |
| assert.objectEquals({ | |
| comment: "Notice the zero literal became a string", | |
| expected: '<{"that":"this","will":[1,23,{"hi":"hi"}],"0":"zero"}> (Object)\n' + '4: \n<[\n 1,\n 2,\n 3,\n 4\n]> (Array)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| it("array?", function () { | |
| var str = "{0.0} {0.1}".format(["hi", "hello"]); | |
| assert.objectEquals({ | |
| comment: "Notation for this is a bit strange", | |
| expected: 'hi hello', | |
| actual: str | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("array with __log__", function () { | |
| "{0.0} {0.1}".__log__(["hi", "hello"]); | |
| assert.objectEquals({ | |
| comment: "", | |
| expected: "hi hello", | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("array2 with __print__", function () { | |
| ["hi", "hello"].__print__; | |
| assert.objectEquals({ | |
| comment: "", | |
| expected: '<["hi","hello"]> (Array)', | |
| actual: getLog_(), | |
| }); | |
| }); | |
| Logger.clear(); | |
| it("object", function () { | |
| var str = "{0.hi} => {0.zup}".format({hi:"hi", zup:'zup'}); | |
| assert.objectEquals({ | |
| expected: 'hi => zup', | |
| actual: str, | |
| }); | |
| }); | |
| it("format", function () { | |
| var str = "{0}".format("hi"); | |
| assert.objectEquals({ | |
| expected: "hi", | |
| actual: str | |
| }); | |
| var str = "{0.hi} {0.zup}".format({hi:"hi", zup:'zup'}); | |
| assert.objectEquals({ | |
| expected: 'hi zup', | |
| actual: str, | |
| }); | |
| }); | |
| it("transformers", function () { | |
| pkg.formatLogger({ | |
| transformers: { | |
| upper: function (s) { return s.toUpperCase(); } | |
| }, | |
| }); | |
| var str = "{0.0!upper}".format(["this should be in upper case"]); | |
| assert.objectEquals({ | |
| expected: 'THIS SHOULD BE IN UPPER CASE', | |
| actual: str, | |
| }); | |
| }); | |
| }); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment