Monaco-editor: Allow completion providers for specific instances

Created on 25 Sep 2017  路  9Comments  路  Source: microsoft/monaco-editor

Completion providers can currently only be configured globally for a language. This interferes with an intent such as providing completion of database table names in an SQL editor where the lists differ between different editor instances.

In my specific case, I am (or was trying to) use Monaco with Angular 4, but it's not really related.

*question

Most helpful comment

I found a way to do it:

let completionData = {
  users: ["id", "name", "email"]
};

monaco.languages.registerCompletionItemProvider('sql', {
  provideCompletionItems: function(model, position) {
    return completionData[model.tableName].map(_ => ({
      label: _,
      insertText: _
    }));
  }
});

let editor = monaco.editor.create(document.getElementById("container"), {
  value: "",
  language: "sql",
});

editor.model.tableName = "users";

try it out at the playground

All 9 comments

could this one help? #509

I don't think so. I have all the data locally, this isn't about sync versus async. I just have editors working with different database schemas and thus they need to complete different sets of table and column names.

One workaround would be to store the data on the editor instance and if we can teach the provider to be aware of which editor it is competing (not sure if that's possible), then we could access that data. However, we could never remove this data and this we'd be creating a memory leak.

Actually we wouldn't have a memory leak. But still, this feels like a total hack nonetheless.

Providers specific to editor instances seem like a cleaner solution to me. Or at least a properly supported way of storing data on the editor and referencing it from the provider, although that'd still be less flexible.

I found a way to do it:

let completionData = {
  users: ["id", "name", "email"]
};

monaco.languages.registerCompletionItemProvider('sql', {
  provideCompletionItems: function(model, position) {
    return completionData[model.tableName].map(_ => ({
      label: _,
      insertText: _
    }));
  }
});

let editor = monaco.editor.create(document.getElementById("container"), {
  value: "",
  language: "sql",
});

editor.model.tableName = "users";

try it out at the playground

But is that actually a supported way to do it? It just feels like a hack and not a solution. You also don't get propert typing through Typescript.

I too think it's a hack.. I'm not a maintainer of this project
Maybe a Map is better in terms of typing? (haven't tested the typescript part)

let completionData = new Map<monaco.editor.IModel, string[]>();

monaco.languages.registerCompletionItemProvider('sql', {
    provideCompletionItems: function(model, position) {
        return completionData.get(model).map(_=>({
            label:_,
            insertText:_
        }));
    }
});

let editor=monaco.editor.create(document.getElementById("container"), {
    value: "",
    language: "sql",
});

completionData.set(editor.getModel(), ["id","name","email"]);

IMHO the best way to do this is:

  • create editors with the extra option { model: null }
  • create models with custom URIs via monaco.editor.createModel
  • set models as needed to editors via editorInstance.setModel(modelInstance).
  • use model.uri in the completion provider implementation to distinguish and do custom things on different models.

@Airblader . According to what @alexandrudima suggests. In the implementation of autocompleteProvider you can check. If( this._editor.getModel() === model) to check

I appreciate it, but personally I no longer need this as we have moved away to a different editor solution for our purposes. I'll keep this open though as there seem to be others interested in this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aarinsmith picture aarinsmith  路  3Comments

andreymarchenko picture andreymarchenko  路  3Comments

chengtie picture chengtie  路  3Comments

Kedyn picture Kedyn  路  3Comments

poloten4uk picture poloten4uk  路  3Comments