Modules (188)

TokenUtils

Description

Dependencies

Functions

Private

_manageCache

Caches the tokens for the given editor/line if needed

cm non-nullable CodeMirror
line non-nullable number
Returns: Array.<Object>
(Cached) array of tokens
    function _manageCache(cm, line) {
        if (!cache || !cache.tokens || cache.line !== line || cache.cm !== cm) {
            // Cache is no longer matching -> Update
            var tokens = cm.getLineTokens(line, false);
            // Add empty beginning-of-line token for backwards compatibility
            tokens.unshift(cm.getTokenAt({line: line, ch: 0}, false));
            cache = {
                cm: cm,
                line: line,
                timeStamp: Date.now(),
                tokens: tokens
            };
            cm.off("changes", _clearCache);
            cm.on("changes", _clearCache);
        }
        return cache.tokens;
    }
Public API

getInitialContext

Creates a context object for the given editor and position, suitable for passing to the move functions.

cm non-nullable CodeMirror
pos non-nullable {ch:number, line:number}
Returns: !{editor:!CodeMirror,pos:!{ch:number,line:number},token:Object}
    function getInitialContext(cm, pos) {
        return {
            "editor": cm,
            "pos": pos,
            "token": cm.getTokenAt(pos, true)
        };
    }
Public API

getModeAt

Returns the mode object and mode name string at a given position

cm non-nullable CodeMirror
CodeMirror instance
pos non-nullable {line:number, ch:number}
Position to query for mode
precise boolean
If given, results in more current results. Suppresses caching.
Returns: mode:{Object},name:string
    function getModeAt(cm, pos, precise) {
        precise = precise || true;
        var modeData = cm.getMode(),
            name;

        if (modeData.innerMode) {
            modeData = CodeMirror.innerMode(modeData, getTokenAt(cm, pos, precise).state).mode;
        }

        name = (modeData.name === "xml") ?
                modeData.configuration : modeData.name;

        return {mode: modeData, name: name};
    }

    exports.getTokenAt              = getTokenAt;
    exports.movePrevToken           = movePrevToken;
    exports.moveNextToken           = moveNextToken;
    exports.isAtStart               = isAtStart;
    exports.isAtEnd                 = isAtEnd;
    exports.moveSkippingWhitespace  = moveSkippingWhitespace;
    exports.getInitialContext       = getInitialContext;
    exports.offsetInToken           = offsetInToken;
    exports.getModeAt               = getModeAt;
});
Public API

getTokenAt

Like cm.getTokenAt, but with caching. Way more performant for long lines.

cm non-nullable CodeMirror
pos non-nullable {ch:number, line:number}
precise boolean
If given, results in more current results. Suppresses caching.
Returns: Object
Token for position
    function getTokenAt(cm, pos, precise) {
        if (precise) {
            _clearCache(); // reset cache
            return cm.getTokenAt(pos, precise);
        }
        var cachedTokens    = _manageCache(cm, pos.line),
            tokenIndex      = _.sortedIndex(cachedTokens, {end: pos.ch}, "end"), // binary search is faster for long arrays
            token           = cachedTokens[tokenIndex];
        return token || cm.getTokenAt(pos, precise); // fall back to CMs getTokenAt, for example in an empty line
    }
Public API

isAtEnd

ctx non-nullable {editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}
Returns: boolean
true if moveNextToken() would return false without changing pos
    function isAtEnd(ctx) {
        var eol = ctx.editor.getLine(ctx.pos.line).length;
        return (ctx.pos.ch >= eol || ctx.token.end >= eol) && (ctx.pos.line >= ctx.editor.lineCount() - 1);
    }
Public API

isAtStart

ctx non-nullable {editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}
Returns: boolean
true if movePrevToken() would return false without changing pos
    function isAtStart(ctx) {
        return (ctx.pos.ch <= 0 || ctx.token.start <= 0) && (ctx.pos.line <= 0);
    }
Public API

moveNextToken

Moves the given context forward by one token.

ctx non-nullable {editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}
precise optional boolean
If code is being edited, use true (default) for accuracy. If parsing unchanging code, use false to use cache for performance.
Returns: boolean
whether the context changed
    function moveNextToken(ctx, precise) {
        var eol = ctx.editor.getLine(ctx.pos.line).length;
        if (precise === undefined) {
            precise = true;
        }

        if (ctx.pos.ch >= eol || ctx.token.end >= eol) {
            //move down a line
            if (ctx.pos.line >= ctx.editor.lineCount() - 1) {
                return false; //at the bottom
            }
            ctx.pos.line++;
            ctx.pos.ch = 0;
        } else {
            ctx.pos.ch = ctx.token.end + 1;
        }
        ctx.token = getTokenAt(ctx.editor, ctx.pos, precise);
        return true;
    }
Public API

movePrevToken

Moves the given context backwards by one token.

ctx non-nullable {editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}
precise optional boolean
If code is being edited, use true (default) for accuracy. If parsing unchanging code, use false to use cache for performance.
Returns: boolean
whether the context changed
    function movePrevToken(ctx, precise) {
        if (precise === undefined) {
            precise = true;
        }

        if (ctx.pos.ch <= 0 || ctx.token.start <= 0) {
            //move up a line
            if (ctx.pos.line <= 0) {
                return false; //at the top already
            }
            ctx.pos.line--;
            ctx.pos.ch = ctx.editor.getLine(ctx.pos.line).length;
        } else {
            ctx.pos.ch = ctx.token.start;
        }
        ctx.token = getTokenAt(ctx.editor, ctx.pos, precise);
        return true;
    }
Public API

moveSkippingWhitespace

Moves the given context in the given direction, skipping any whitespace it hits.

moveFxn function
the function to move the context
ctx non-nullable {editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}
Returns: boolean
whether the context changed
    function moveSkippingWhitespace(moveFxn, ctx) {
        if (!moveFxn(ctx)) {
            return false;
        }
        while (!ctx.token.type && !/\S/.test(ctx.token.string)) {
            if (!moveFxn(ctx)) {
                return false;
            }
        }
        return true;
    }
Public API

offsetInToken

In the given context, get the character offset of pos from the start of the token.

context non-nullable {editor:!CodeMirror, pos:!{ch:number, line:number}, token:Object}
Returns: number
    function offsetInToken(ctx) {
        var offset = ctx.pos.ch - ctx.token.start;
        if (offset < 0) {
            console.log("CodeHintUtils: _offsetInToken - Invalid context: pos not in the current token!");
        }
        return offset;
    }