Category: Dynamic scripting

  • Using enum values as strictly typed object keys


    In TypeScript, it’s often useful to define interfaces or complex (structured)
    types whose properties (or keys) may only be values of a previously defined
    enum type.

    Here’s a good example: an object declaring a set of buttons for a modal dialog.

    Instead of this…

    type DialogButtons = {
      yes?: boolean,
      no?: boolean,
      cancel?: boolean
    }
    
    interface IDialog {
      buttons: DialogButtons
    }
    
    const dialog: IDialog = {
      buttons: {
        yes: true,
        no: false
      }
    }
    
    console.log("yes" in dialog.buttons) // true
    console.log(dialog.buttons.yes) // true
    
    console.log("no" in dialog.buttons) // true
    console.log(dialog.buttons.no) // false
    
    console.log("cancel" in dialog.buttons) // false
    console.log(dialog.buttons.cancel) // undefined

    This works, but once we try to use these values in other contexts, the approach becomes difficult to use. What if we want to pass which button was pressed to a callback function?

    It would be cumbersome. Therefore…

    …we can use enum values.

    enum DialogButton {
      YES = "yes",
      NO = "no",
      CANCEL = "cancel"
    }
    
    interface IDialog {
      buttons: { [B in DialogButton]?: boolean },
      callback: (button: DialogButton) => void
    }
    
    const dialog: IDialog = {
      buttons: {
        [DialogButton.YES]: true,
        [DialogButton.NO]: false
      },
      callback(button) {
        console.log(button)
      }
    }
    
    console.log(DialogButton.YES in dialog.buttons) // true
    console.log(DialogButton.NO in dialog.buttons) // true
    console.log(DialogButton.CANCEL in dialog.buttons) // false
    
    console.log(dialog.buttons[DialogButton.YES]) // true
    console.log(dialog.buttons[DialogButton.NO]) // false
    console.log(dialog.buttons[DialogButton.CANCEL]) // undefined
    
    dialog.callback(DialogButton.YES) // yes
    dialog.callback(DialogButton.NO) // no
    dialog.callback(DialogButton.CANCEL) // cancel

    This uses the a TypeScript feature called Mapped Types
    and allows us to play around with the actual button values with a lot more flexibility, for example we could
    define an array of buttons.

    function renderButtons(buttons: [DialogButton]): [HTMLElement] {
      // ...
    }

    Code gist: https://gist.github.com/vpalos/0aab903ef607d6da31229b957d91d888.

    Enjoy!

  • Universal getter for plain JS objects.

    Many times in JavaScript we have to reach deep into objects to access fields that could possibly not be there at all; for example let’s assume I have a JS object called options into which I’ve just read an entire JSON configuration file. Trying to access a field like options.application.cache.enable directly will potentially fail (e.g. when any of the intermediate levels is missing)…

    if (options.application.cache.enable) {
        // do stuff
    }
    

    …therefore this kind of work will usually involve some kind of testing for the existence of each level, so as to gracefully handle any misbehaving data. Also, many times I’ve seen the following approach used in these scenarios which is quite bad for anything more than a single depth level:

    if (options && options.application && ...) {
        // do stuff
    }
    

    So, just as a little helper, here is a small method that may prove to be quite handy when having to deal with data whose structure we’re not certain of (here’s a proper Gist entry).
    (more…)

  • Quickly filtering large lists of texts.

    Recently, I had to make a mock-up of a filtering function (something I need for a project I work on) so I can show-case it around. And since this mock-up seems to impress some people, I decided to share this function with everybody so others may enjoy the “loot” :).

    Briefing

    The function (i.e. filter()) basically receives a query, a large list of text items and (optionally) some options. It then proceeds to filter that list based on the query and returns an array with the index numbers of the matching items and (optionally) an array with the marked texts of the matching items (i.e. highlighted captures). The documentation comment should provide all the needed insight on this thing.

    Demo

    Here you can play with the mocked-up demo (works on a list of ~23000 items).

    Source

    Since I usually store these short snippets of code among my gists, you can find this function here. You should always check the gist for the most up-to-date code!

    /**
     * Demo: http://vpalos.com/sandbox/filter.js
     *
     * A generic search algorithm designed for filtering (very) large lists of strings; when an input string
     * contains all the parts (words or characters; whitespace is ignored) of the query, spread-out over the text
     * then the string is considered to be a match. It works with the way internet browsers (e.g. Firefox, Google
     * Chrome) filter address-bar suggestions on user input. It is also quite fast; on my i7 laptop, filtering
     *     1) a list of ~23000 items takes around 50ms (yes, milliseconds!);
     *     2) a list of ~1 million text items took under 1 second.
     * It works both in NodeJS as well as in browser environments (so far I only tested FF and GC).
     *
     * It has two functioning modes:
     * 1) word-mode: each (whitespace-separated) word in the input query must be found **whole** in the text:
     *     e.g. "foo bar" will match "123foo456bar789" but not "f oo ba r";
     * 2) charater-mode: the input query is matched per-character (whitespace is completely ignored):
     *     e.g. "foo bar" will match "f o o b a r" and even "-f.oo-ba.r-".
     *
     * Options (values below are the defaults):
     * {
     *     "case": false,               // true: case-sensitive
     *                                  // false: case-insensitive
     *
     *     "mark": true,                // true: returns item numbers + matches with highlighted captures
     *                                  // false: returns item numbers only
     *
     *     "prefix": "<strong>",        // highlight prefix string
     *     "suffix": "</strong>",       // highlight suffix string
     *
     *     "word": true,                // true: whole-word mode
     *                                  // false: character mode
     *
     *     "limit": 0                   // limit results to this amount
     *                                  // 0 means return the whole result (unlimited)
     * }
     *
     * @param {string} query The search query, consisting of space-separated chunks of characters.
     * @param {string|array} items A string or an array of strings to filter; if a string is given then it is
     *                             first split into an array of individual lines of text and then filtered (note
     *                             that).
     * @param {string} prefix String which will come before every highlighted substring (i.e. capture).
     * @param {string} suffix String which will come after every highlighted substring (i.e. capture).
     * @return {object} Returns the following object with matched items information:
     *                  {
     *                      "items": [...],     // array of matched item-numbers
     *                      "marks": [...]      // if mark == true, array of matches with highlighted captures
     *                  }
     */
    function filter(query, items, options) {
    
        // option producer
        function option(name, value) {
            options = options || {};
            return typeof(options[name]) !== 'undefined' ? options[name] : value;
        }
    
        // prepare options
        var o_case   = option("case",   false);
        var o_mark   = option("mark",   true);
        var o_prefix = option("prefix", "<strong>");
        var o_suffix = option("suffix", "</strong>");
        var o_word   = option("word",   true);
        var o_limit  = option("limit",  0);
    
        // prepare query
        query  = o_case ? query : query.toLowerCase();
        query  = query.replace(/\s+/g, o_word ? ' ' : '');
        query  = query.replace(/(^\s+|\s+$)/g, '');
        query  = query.split(o_word ? ' ' : '');
        var ql = query.length;
    
        // prepare items
        if (typeof(items) === "string") {
            items = items.split('\n');
        }
    
        // prepare results
        var matches = {
            items: [],
            marks: []
        };
    
        // search
        for (var ii = 0, il = items.length; ii < il; ii++) {
    
            // prepare text
            var text = o_case ? items[ii] : items[ii].toLowerCase();
            var mark = "";
    
            // traverse
            var ti = 0;
            var wi = 0;
            var wl = 0;
            for (var qi = 0; qi < ql; qi++) {
                wl = query[qi].length;
                wi = text.indexOf(query[qi], ti);
                if (wi === -1) {
                    break;
                }
                if (o_mark) {
                    if (wi > 0) {
                        mark += items[ii].slice(ti, wi);
                    }
                    mark += o_prefix + items[ii].slice(wi, wi + wl) + o_suffix;
                }
                ti = wi + wl;
            }
    
            // capture
            if (qi == ql) {
                if (o_mark) {
                    mark += items[ii].slice(ti);
                    matches.marks.push(mark);
                }
                if (matches.items.push(ii) === o_limit && o_limit) {
                    break;
                }
            }
        }
    
        // ready
        return matches;
    }
    

    [Update] Thanks to vladpalos for pointing-out some flaws in my initial code which, in the end, led me to simply using String.indexOf() for finding sub-matches.

    So…

    Let me know how this can be improved!

  • JS classes for the masses.

    Following on an older post of mine, I decided to write a new article about an(other) implementation of OOP Classes in JavaScript. This is something that brings a lot of value from very few lines of code and I want to share it with everyone and see how it can be improved.

    First let’s see the code (you should check here for the latest version) and then I’ll try and explain the relevant benefits/features but jump straight to the goodies if you like, knock yourself out! 🙂

    /**
     * Class.js: A class factory.
     */
    function Class(members) {
    
        // setup proxy
        var Proxy = function() {};
        Proxy.prototype = (members.base || Class).prototype;
    
        // setup constructor
        members.init = members.init || function() {
            if (Proxy.prototype.hasOwnProperty("init")) {
                Proxy.prototype.init.apply(this, arguments);
            }
        };
        var Shell = members.init;
    
        // setup inheritance
        Shell.prototype = new Proxy();
        Shell.prototype.base = Proxy.prototype;
    
        // setup identity
        Shell.prototype.constructor = Shell;
    
        // setup augmentation
        Shell.grow = function(items) {
            for (var item in items) {
                if (!Shell.prototype.hasOwnProperty(item)) {
                    Shell.prototype[item] = items[item];
                }
            }
            return Shell;
        };
    
        // attach members and return the new class
        return Shell.grow(members);
    }
    

    Observations

    Each Class points to (via .prototype) a corresponding Proxy object that holds the class’s member fields. In turn, this Proxy points to (via .prototype) the Proxy of the inherited class (i.e. the super-Class) and so on. So, each Class points to its own Proxy which points to the ancestor Proxy and so on, until the top level ancestor is reached. (more…)

  • Lua-TTyrant: a TokyoTyrant binding for Lua.

    Some time ago I started a small project to implement a C-to-Lua binding of the TokyoTyrant library, called “lua-ttyrant“. A few days ago, while working with a script that was actually using it, I decided to polish it up, finish it and eventually submit it to be included in the LuaRocks repositories. Given the fact that the “rock” was just accepted by the LuaRocks team, I thought a new post was in order.

    Files

    The lua-ttyrant source code can be found here (among my github repos).
    The lua-ttyrant rockspec can be found here (among all the public Lua rocks).

    Prerequisites

    • TokyoTyant library and headers.
    • LuaRocks.

    Prerequisites on Debian/Ubuntu distros:

    sudo apt-get install libtokyotyrant-dev
    

    Installation

    sudo luarocks install lua-ttyrant
    

    Status

    The binding is in beta for now. Please contribute a ticket if you find anything wrong with it. For anything else please see the doc/DETAILS file. Enjoy! 🙂

  • A simple(r) approach for class-based OOP in JavaScript.

    Like others before me, I found JavaScript’s prototype-based OOP support – while very powerful – quite cumbersome in some situations where I needed a certain structure or hierarchy of objects, situations in which one quickly comes to the conclusion that the best answer would be the concept of a Class.

    However, while I am well aware that the web is filled with various implementations of classical (i.e. class-based) object orientation in JavaScript, I can not help the feeling that they are over-engineered and over-complicated without need, quite often attempting to provide more functionality than is actually necessary. In short, I don’t feel they’re “classical” at all.

    This is why I started working on my own implementation of classical OOP  in JavaScript, which is shown below. Currently this is only a proposal, although I already started using it in one of my projects. Anyway, let’s look at it first then I’ll try and explain how it works.

    The Code

    /** Class factory. */
    function Class(members) {
    
        // proxy constructor
        var Proxy = function() {
            for (var item in members) {
                this[item] = members[item];
            }
        };
    
        // proxy inheritance
        Proxy.prototype = (members.base || Class).prototype;
    
        // class constructor
        var Build = members.init || function() {};
    
        // class inheritance
        Build.prototype = new Proxy();
        Build.prototype.base = Proxy.prototype;
        Build.prototype.constructor = Build;
    
        // ready
        return Build;
    }

    That is all, and this little function can have a whole world of nifty consequences like deep inheritance or access to the super-class via this.base (and others). But here is what happens: the basic principle at work here is the Proxy object, which essentially, contains all the members of our new class (the ones that are passed to the Class factory function as the members parameter). (more…)

  • Command-line option parser in JavaScript.

    Here’s a small but very effective command-line option parser written in JavaScript (uses NodeJs). You can get the up-to-date source code at http://gist.github.com/982499.

    I wrote this because I needed it for a project and I did not think it was worth it to install some npm package just for this. The comment should explain most things you will need but ask me if you don’t understand something. Note that this code is not well tested (yet!) since I just wrote it this morning so post a comment when you find a bug.

    Supports:

    • Short and long options (i.e. ‘-t|--test‘).
    • Option parameters (i.e. ‘-f /etc/resolv.conf‘).
    • Mandatory options.
    • Implicit help option.
    • Option callback functions.
    • Cumulated short options (i.e. ‘-ab‘).
    • Repeatable options (i.e. ‘--add value1 --add value2‘).
    • Non-option arguments.

    Notes (extracted from the comments):

    • Parser is case-sensitive.
    • The ‘-h|–help’ option is provided implicitly.
    • Successfully parsed options will be available as fields in the “options” object.
    • Non-option arguments found will be available in order in the “arguments” array.
    • Options and their parameters must be separated by space.
    • Either one of «short» or «long» must always be provided.
    • The «callback» function is optional and is invoked each time the option is encountered.
    • Cumulated short options are supported (i.e. ‘-tv‘).
    • If an error occurs, the process is halted and the help message is shown.
    • Options with the “multiple” attribute will be cumulated into arrays (even if found only once).
    • The parser does *not* test for duplicate definitions in the schema array.

    See the code for everything else you need to use it (i.e. a sample schema definition). I will not waste any more time talking about it; if you like it, paste it at the top of your NodeJS script and start playing with it, e.g.:

    $ node options.js -tf /some/file.txt foo bar

    Also, please tell me about any improvements or fixes you produce. Thanks and… enjoy! 🙂

  • Case study: fixed number of iterations with LPeg

    Words seem to fail to describe just how awesome LPeg is. Designed as a Lua implementation of the PEG concept, it is a true programming gem! Please, if you dont’t know what it is, take some time to familiarize yourself with it! It’s not the easiest thing to grasp, but you will not regret it! It is certainly one of the most worthwhile learning efforts you can make in generic parsing.

    One great feature of LPeg is that it’s binary-safe, meaning that (unlike regular expressions) it can be safely used to parse binary data! This makes it an excellent tool for parsing binary protocols, especially network communication protocols, such as the Action Message Format (used by Adobe Flash for making remote calls and even in FLV movie files). I’ll leave it to you to explore the possibilities…

    Beware that from here on, I assume that you know your way around Lua, LPeg and how they work.

    The problem

    That being said, this article is actually about an unusual roadblock I hit while using LPeg to build a Lua-based AMF parser, and the various solutions I found and/or came up with to overcome it (you didn’t think that I mentioned AMF before by accident, did you?).

    The issue is LPeg’s implementation of repetitive patterns: in particular, its inability to match (or capture) a fixed number of occurrences of a certain pattern, although it can match a minimum or a maximum number of such occurrences, which is perfect for stream-oriented parsing (such as parsing programming languages) but insufficient for binary data.

    Just to clarify, here’s a small list of LPeg patterns which correspond to the typical PCRE repetitive constructs (in each case we’re trying to match the string ‘cloth’):

    Matching occurrences of ‘cloth’ PCRE pattern LPeg pattern
    0 or more (at least 0) /(cloth)*/ lpeg.P'cloth'^0
    1 or more (at least 1) /(cloth)+/ lpeg.P'cloth'^1
    X or more (at least X) /(cloth){X,}/ lpeg.P'cloth'^X
    1 or less (at most 1) /(cloth)?/ lpeg.P'cloth'^-1
    X or less (at most X) /(cloth){,X}/ lpeg.P'cloth'^-X
    A: precisely X (no more, no less) /(cloth){X,X}/ -- unavailable --
    B: anywhere between X and Y /(cloth){X,Y}/ -- unavailable --

    For the last two cases (i.e. A and B), LPeg does not offer any simple constructs so we have to find a complex one. Let’s put aside the case B for now, and try to tackle A… (more…)

  • Lua2C, an updated version

    I know I have been “missing in action” lately but I am working furiously, and I seem to have too little time for my blog (very sad face). But, just for a breath of fresh air, I thought I’d share something with the world.

    Entering lua2c.lua

    Lately I became quite interested in Lua (a lot actually). It has phenomenal speed, exceptional interfacing with C and some features and libraries that just make my day (i.e. coroutines, lpeg, lua-ev and others), and since I needed to embed some Lua scripts (entirely) in a C project I’m currently working on, I ended up adapting Mike Edgar’s “bin2c.lua” script (which takes a Lua script and turns it into a C header file) to suit my needs.

    Basic functionality

    Specifically, this adaptation generates a function that takes a Lua state as the only argument and then runs the embedded Lua code in the given state after which it returns the status (as opposed to putting the code straight in the top-level scope of the generated file). This makes it easier to embed code in C and then invoke it, and also to apply the same code onto multiple Lua states (e.g. multiple threads).

    Check further down for a short usage sample. (more…)