Douglas Crockford

Blog

Books

Videos

2024 Appearances

Slides

JavaScript

Misty

JSLint

JSON

Github

Electric Communities

Flickr Photo Album

LinkedIn

Mastodon/Layer8

ResearchGate

Pronouns: pe/per

About

Context Coloring

Syntax coloring is very popular, especially with coders who still struggle with basic syntax. I think we can do better. Color can more profitably help us to quickly understand the structure of a program.

We have a color for the top level stuff (say black). Functions defined at the top level are green. Inner functions are brown. Inner inner functions are blue, and so on. Spotting the functions in a program and their nesting is much more important than an assist in discriminating between identifiers and strings.

For example, this is the fullfill function from How JavaScript Works, Chapter 9.

const rx_delete_default = /[<>&%"\\]/g;

const rx_syntactic_variable = /\{([^{}:\s]+)(?::([^{}:\s]+))?\}/g;

function default_encoder(replacement) {
    return String(replacement).replace(rx_delete_default, "");
}

export default Object.freeze(function fulfill(
    string,
    container,
    encoder = default_encoder
) {
    return string.replace(
        rx_syntactic_variable,
        function (original, path, encoding = "") {
            try {
                let replacement = (
                    typeof container === "function"
                    ? container
                    : path.split(".").reduce(
                        function (refinement, element) {
                            return refinement[element];
                        },
                        container
                    )
                );
                if (typeof replacement === "function") {
                    replacement = replacement(path, encoding);
                }
                replacement = (
                    typeof encoder === "object"
                    ? encoder[encoding]
                    : encoder
                )(replacement, path, encoding);
                if (
                    typeof replacement === "number"
                    || typeof replacement === "boolean"
                ) {
                    replacement = String(replacement);
                }
                return (
                    typeof replacement === "string"
                    ? replacement
                    : original
                );
            } catch (ignore) {
                return original;
            }
        }
    );
});

Each level of function is given a specific color, but variables retain the color of the function (or context) in which they are declared. I call this Context Coloring. This allows us to instantly see how the nested functions close over the outer functions.

Syntax coloring isn't useless, it is childish, like training wheels or school paste. It is great for a while, and then you might grow up. I no longer need help in separating operators from numbers. But assistance in finding the functions and their contexts and influences is valuable.