Differences in tern.js and sql-hint.js codes

I’m trying to build an autocomplete list for my custom language.

Currently i’m using the following code which triggers autocomplete on any keyup :

editor.on("keyup", function (cm, event) {
        if (!cm.state.completionActive && event.keyCode != 13 && event.keyCode != 32) {
            cm.showHint({
                completeSingle: false
            })
        }
    });

Now i was checking out and really liked some additional features in the tern.js autocomplete demo (like the description on right on select of list element). I was able to figure out most of it however I had few doubts on how it works vs how sql-hint.js (which i’m using currently) works:

  1. Currently, my custom mode is just an overlay on x-sql mode :
    CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/x-sql"), dimensionOverlay);
    I’m curious how does codemirror know that it needs to use sql-hint.js and not some other (like javascript-hint.js). Does it figure this out using the overlay mode name?

  2. One difference I found in tern.js is that unlike other mode hints like sql-hint.js it defines its own hint function and nowhere does it use registerHelper method :
    complete: function(cm) {cm.showHint({hint: this.getHint})}
    On the other hand sql-hint.js uses a registerHelper method :
    CodeMirror.registerHelper("hint", "sql", function(editor, options)
    I don’t completely understand what’s the use for registerHelper? Is it necessary to use registerHelper in custom modes?

  3. At lot of times in tern.js code an parameter ‘c’ is used. e.g. the getHint function is called as :
    this.getHint = function(cm, c) { return hint(self, cm, c); };
    What’s the ‘c’ here? I couldn’t find this argument being passed anywhere.

Sorry for the long post. Appreciate any help! :slight_smile:

1 Like

Your second question answers your first—registerHelper is used to associate some functionality with a given mode, ans sql-hint registers itself as being an autocompleter for SQL.

It stands for ‘callback’, and is the function asynchronous methods use to return their result (modern code would use Promises or async functions for this).

Ok.
So if I want to define a custom autocomplete for my own mode it would be better to use registerHelper rather than overriding the hint function like done in tern.js cm.showHint({hint: this.getHint}) right?

Also if I define registerHelper for my custom mode like this:

CodeMirror.registerHelper('hint', 'customModeName', function(editor) {
/*Hinting logic */
})

How can I override the sql hint and use the newly registered hint on autocomplete?

If I do this :

editor.on("keyup", function (cm, event) {
        if (!cm.state.completionActive && event.keyCode != 13 && event.keyCode != 32) {
            cm.showHint({
                completeSingle: false
            })
        }
    }); 

Which hint logic (sql-hint.js or customModeName hint) would it use now?

The first that returns any results, in the order in which they were loaded. It’d probably make sense not to load sql-hint at all if you don’t want to use it, or directly pass the hint function to make sure you get the one you want. The helpers are a convenience mechanism to tie things together without programmer interaction, but if you’re setting up your own editor and know which hint function you want, you might as well bypass them.

Thanks a lot.
I was able to create my custom autocomplete function within an hour.
The library code looks intimidating at first but soon I understood why certain things were implemented they way they were.
Great work! Marijn :grinning: