Flag Control

by plus5keen

JavaScript

(function (global, _) {
    function FlagSet() { this._flags = {}; }
    
    _.extend(FlagSet.prototype, {
        addFlag: function (flagName) {
            this._flags[flagName] = { name: flagName };
            return this;
        },
        addFlags: function (flagNames) {
            return _.reduce(flagNames, function (self, flagName) {
                return self.addFlag(flagName);
            }, this);
        },
        getFlags: function () { return _.clone(this._flags); },
        hasFlag: function (flag) {
            if (!flag) { return false; }
            if (flag.name) {
                return this._flags[flag.name] === flag;
            } else {
                return !!this._flags[flag];
            }
            return false;
        },
        useFlags: (function () {
            function buildFlags(flagSet, result, flags) {
                if (!flags) { return result; }
                if (_.isArray(flags) || _.isArguments(flags)) {
                    return _.reduce(flags, function (memo, flag) {
                        return buildFlags(flagSet, memo, flag);
                    }, result);
                }
                result[flags.name || flags] = flagSet.hasFlag(flags);
                return result;
            }
            return function (flags) {
                return buildFlags(this, {}, flags);
            };
        }())
    });
    
    global.FlagSet = FlagSet;
}(this, this._));

(function (FlagSet) {
    var fs = new FlagSet().addFlags(['log', 'ret']);
    var stuff = fs.getFlags();
    
    function doStuff(value, flags) {
        flags = fs.useFlags(_.rest(arguments));
        if (flags.log) {
            console.log(value);
        }
        if (flags.ret) {
            return value;
        }
    }
    
    doStuff('lost forever');
    doStuff('first logged', stuff.log);
    doStuff(stuff.log, stuff.log);
    console.log(doStuff('third logged; logged after return', stuff.ret));
    console.log(doStuff('fourth and...