Call an Ace custom autocompleter on every keystroke

64 Views Asked by At

I'm adding a custom auto-completer to Ace. I have it working just fine as such, except my custom auto-completer is only called every few keypresses, which doesn't really work in practice.

For example, if I type "W", my auto-completer is returning ["W", "Waiter", "Wales"]. I then type "Wi" and my auto-completer code is not called again. The above list is filtered by Ace to display just "Waiter" as an option, highlighting the first and third characters. But I want it to call my completer so I can call the backend and get a new list of options based on the "Wi" prefix. Eventually, this happens on the fourth keypress. Once I type "Will", my function is called again, I return new options, and the option list shown to the user is updated.

I can't work out the behaviour. If I type "University", my auto-completer is only called on "U" and "Unive" -- so five characters needed this time rather than four. Why is this?!

I'd like Ace to call my function on every keypress. Is this possible?!

I'm actually using Ace via react-ace:

  <AceEditor
    mode="java"
    theme="github"
    onChange={(value) => setText(value)}
    enableLiveAutocompletion={true}
  />

My auto-complete function:

import * as ace from "ace-builds/src-noconflict/ace";
const langTools = ace.acequire("ace/ext/language_tools");

const myCompleter = {
  getCompletions: function (editor, session, pos, prefix, callback) {
    if (prefix.length === 0) {
      callback(null, []);
      return;
    }

    backend.autocomplete(prefix).then((options) => {
      callback(
          null,
          options.map((option, index) => {
            return {
              caption: option,
              value: option,
            };
          })
      );
    });
  },
};

langTools.setCompleters([myCompleter]);

Edit

I've done some looking through the source code and I think I understand now why it's an "arbitrary" number of keypresses before my code is called again.

I think the design of the autocompleter in Ace is that the completion provider should provide all possible autocompletions. Ace will then filter that list as the user types. When there are no filtered options left, Autocomplete.prototype.detach is called, which makes the completer inactive. The user sees no autocompletions at this point. On the next keypress, Autocomplete.prototype.updateCompletions is called, and, because the completer is inactive, my completion provider code is called again, populating a new list of options. The process then repeats.

If I ensure the keepPopupPosition parameter to Autocomplete.prototype.updateCompletions is always false, everythign works as I want it to. If I've understood the code correctly, my use case is just not how Ace is supposed to work. Looks like raising a PR to add my use case is the only option here, but let me know if I've misunderstood something!

0

There are 0 best solutions below