3 * This is the common logic for both the Node.js and web browser
4 * implementations of `debug()`.
6 * Expose `debug()` as the module.
9 exports = module.exports = debug;
10 exports.coerce = coerce;
11 exports.disable = disable;
12 exports.enable = enable;
13 exports.enabled = enabled;
14 exports.humanize = require('ms');
17 * The currently active debug mode names, and names to skip.
24 * Map of special "%n" handling functions, for the debug "format" argument.
26 * Valid key names are a single, lowercased letter, i.e. "n".
29 exports.formatters = {};
32 * Previously assigned color.
38 * Previous log timestamp.
50 function selectColor() {
51 return exports.colors[prevColor++ % exports.colors.length];
55 * Create a debugger with the given `namespace`.
57 * @param {String} namespace
62 function debug(namespace) {
64 // define the `disabled` version
67 disabled.enabled = false;
69 // define the `enabled` version
74 // set `diff` timestamp
75 var curr = +new Date();
76 var ms = curr - (prevTime || curr);
82 // add the `color` if not set
83 if (null == self.useColors) self.useColors = exports.useColors();
84 if (null == self.color && self.useColors) self.color = selectColor();
86 var args = Array.prototype.slice.call(arguments);
88 args[0] = exports.coerce(args[0]);
90 if ('string' !== typeof args[0]) {
91 // anything else let's inspect with %o
92 args = ['%o'].concat(args);
95 // apply any `formatters` transformations
97 args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
98 // if we encounter an escaped % then don't increase the array index
99 if (match === '%%') return match;
101 var formatter = exports.formatters[format];
102 if ('function' === typeof formatter) {
103 var val = args[index];
104 match = formatter.call(self, val);
106 // now we need to remove `args[index]` since it's inlined in the `format`
107 args.splice(index, 1);
113 if ('function' === typeof exports.formatArgs) {
114 args = exports.formatArgs.apply(self, args);
116 var logFn = enabled.log || exports.log || console.log.bind(console);
117 logFn.apply(self, args);
119 enabled.enabled = true;
121 var fn = exports.enabled(namespace) ? enabled : disabled;
123 fn.namespace = namespace;
129 * Enables a debug mode by namespaces. This can include modes
130 * separated by a colon and wildcards.
132 * @param {String} namespaces
136 function enable(namespaces) {
137 exports.save(namespaces);
139 var split = (namespaces || '').split(/[\s,]+/);
140 var len = split.length;
142 for (var i = 0; i < len; i++) {
143 if (!split[i]) continue; // ignore empty strings
144 namespaces = split[i].replace(/\*/g, '.*?');
145 if (namespaces[0] === '-') {
146 exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
148 exports.names.push(new RegExp('^' + namespaces + '$'));
154 * Disable debug output.
164 * Returns true if the given mode name is enabled, false otherwise.
166 * @param {String} name
171 function enabled(name) {
173 for (i = 0, len = exports.skips.length; i < len; i++) {
174 if (exports.skips[i].test(name)) {
178 for (i = 0, len = exports.names.length; i < len; i++) {
179 if (exports.names[i].test(name)) {
194 function coerce(val) {
195 if (val instanceof Error) return val.stack || val.message;