Skip to content
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

Introducing "dynamic mode" allowing enable/disable on the fly #156

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ BIN := $(THIS_DIR)/node_modules/.bin
NODE ?= $(shell which node)
NPM ?= $(NODE) $(shell which npm)
BROWSERIFY ?= $(NODE) $(BIN)/browserify
MOCHA ?= $(NODE) $(BIN)/_mocha

all: dist/debug.js

Expand All @@ -21,7 +22,7 @@ clean:
dist:
@mkdir -p $@

dist/debug.js: node_modules browser.js debug.js dist
dist/debug.js: node_modules browser.js debug.js able.js | dist
@$(BROWSERIFY) \
--standalone debug \
. > $@
Expand All @@ -30,4 +31,7 @@ node_modules: package.json
@NODE_ENV= $(NPM) install
@touch node_modules

.PHONY: all install clean
test:
@$(MOCHA) -R dot

.PHONY: all install clean test
148 changes: 148 additions & 0 deletions able.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/**
* in-memory cache
*/

var enabled = [];
var disabled = [];

/**
* Checks if the specified `ns` is enabled.
*
* @param {String} ns Wildcards are not supported here

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for not supporting wildcards here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been a really long time... but I think it was just for simplicity. Imagine I've enabled mocha* but disabled mocha:runner, what would you expect enabled("mocha*") to return? (since there is a clear exception to this rule that makes it so the wildcard technically can't be true 100% of the time)

* @returns {Boolean}
*/

exports.enabled = function (ns) {
if (find(disabled, ns, true) > -1) return false;
if (find(enabled, ns, true) > -1) return true;
return false;
};

/**
* Destroys the lists of enabled/disabled. (primarilly for testing purposes)
*/

exports.clear = function () {
disabled.length = enabled.length = 0; // truncates w/o destroying
};

/**
* Outputs the list of enable/disabled in a single string.
*
* @returns {String}
*/

exports.stringify = function () {
var e = enabled.map(function (item) {
return item.string;
});

var d = disabled.map(function (item) {
return '-' + item.string;
});

return e.concat(d).join(',');
};

/**
* Parses a list and enables/disables accordingly.
*
* This list can either be passed from the user directly, or from .stringify()
*
* @param {String} str
*/

exports.parse = function (str) {
if (!str) return [];
return (str || '').trim().split(/[\s,]+/).filter(function (item) {
return !!item;
});
};

/**
* Enables the specified `ns`.
*
* @param {String} ns
*/

exports.enable = function (ns) {
// special case, empty the current list and allow it to append
if ('*' == ns) exports.clear();

prune(disabled, ns);
if (find(enabled, ns) > -1) return;

enabled.push({
string: ns,
regex: regex(ns)
});
};

/**
* Disables the specified `ns`.
*
* @param {String} ns
*/

exports.disable = function (ns) {
// special case, empty the current list (since default is to allow nothing)
if ('*' == ns) return exports.clear();

prune(enabled, ns);
if (find(disabled, ns) > -1) return;

disabled.push({
string: ns,
regex: regex(ns)
});
};

/**
* Searches for the given `ns` in the `arr`.
*
* By default, it only matches on the raw string, but if `regex` is set, it will
* match via the `RegExp` instead.
*
* Returns the index of the match, or -1 if not found.
*
* @param {Array} arr
* @param {String} ns
* @param {Boolean} [regex]
* @returns {Number}
*/

function find(arr, ns, regex) {
var ret = -1;
arr.some(function (item, x) {
if (regex ? item.regex.test(ns) : ns === item.string) {
ret = x;
return true;
}
});
return ret;
}

/**
* Wraps around `find(...)`, but also removes the found item.
*
* @param {Array} arr
* @param {String} ns
* @param {Boolean} [regex]
*/

function prune(arr, ns, regex) {
var x = find(arr, ns, regex);
if (x > -1) arr.splice(x, 1);
}

/**
* Converts a raw `ns` into a `RegExp`.
*
* @param {String} ns
* @returns {RegExp}
*/

function regex(ns) {
var pattern = ns.replace(/\*/g, '.*?');
return new RegExp('^' + pattern + '$');
}
4 changes: 3 additions & 1 deletion browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ function log() {
* @api private
*/

function save(namespaces) {
function save() {
try {
var namespaces = able.stringify();

if (null == namespaces) {
localStorage.removeItem('debug');
} else {
Expand Down
3 changes: 2 additions & 1 deletion component.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"main": "browser.js",
"scripts": [
"browser.js",
"debug.js"
"debug.js",
"able.js"
],
"dependencies": {
"guille/ms.js": "0.6.1"
Expand Down
117 changes: 58 additions & 59 deletions debug.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@

/**
* Enabled/disabled status management
*/

var able = require('./able');

/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
Expand All @@ -8,17 +14,12 @@

exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = require('ms');
exports.dynamic = dynamic;
exports.enable = enable;
exports.disable = disable;
exports.enabled = able.enabled;

/**
* The currently active debug mode names, and names to skip.
*/

exports.names = [];
exports.skips = [];

/**
* Map of special "%n" handling functions, for the debug "format" argument.
Expand All @@ -28,6 +29,12 @@ exports.skips = [];

exports.formatters = {};

/**
* Flag for dynamic status.
*/

var isDynamic = false;

/**
* Previously assigned color.
*/
Expand Down Expand Up @@ -117,81 +124,73 @@ function debug(namespace) {
logFn.apply(self, args);
}
enabled.enabled = true;
enabled.namespace = namespace;

var fn = exports.enabled(namespace) ? enabled : disabled;
function dynamic() {
if (!exports.enabled(namespace)) return disabled();
return enabled.apply(enabled, arguments);
}
dynamic.namespace = namespace;

fn.namespace = namespace;
function fn() {
if (isDynamic) return dynamic;
return exports.enabled(namespace) ? enabled : disabled;
}

return fn;
return fn();
}

/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
* Coerce `val`.
*
* @param {String} namespaces
* @api public
* @param {Mixed} val
* @return {Mixed}
* @api private
*/

function enable(namespaces) {
exports.save(namespaces);

var split = (namespaces || '').split(/[\s,]+/);
var len = split.length;

for (var i = 0; i < len; i++) {
if (!split[i]) continue; // ignore empty strings
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
exports.names.push(new RegExp('^' + namespaces + '$'));
}
}
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}

/**
* Disable debug output.
* Get/set the dynamic flag
*
* @api public
* @param {Boolean} [flag]
* @returns {Boolean}
*/

function disable() {
exports.enable('');
function dynamic(flag) {
if (0 == arguments.length) return isDynamic;
isDynamic = !!flag;
}

/**
* Returns true if the given mode name is enabled, false otherwise.
* Enables a string of namespaces (disables those with hyphen prefixes)
*
* @param {String} name
* @return {Boolean}
* @api public
* @param {String} namespaces
*/

function enabled(name) {
var i, len;
for (i = 0, len = exports.skips.length; i < len; i++) {
if (exports.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = exports.names.length; i < len; i++) {
if (exports.names[i].test(name)) {
return true;
}
}
return false;
function enable(namespaces) {
able.parse(namespaces).forEach(function (ns) {
if ('-' == ns[0]) able.disable(ns.slice(1));
else able.enable(ns);
});

exports.save();
}

/**
* Coerce `val`.
* Disables a string of namespaces (ignores hyphen prefixs if found)
*
* @param {Mixed} val
* @return {Mixed}
* @api private
* @param {String} namespaces
*/

function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
function disable(namespaces) {
able.parse(namespaces).forEach(function (ns) {
if ('-' == ns[0]) ns = ns.slice(1);
able.disable(ns);
});

exports.save();
}
Loading