多文件的 Monaco 编辑器智能提示

16
我正在使用monaco-editor,并且希望从多个文件中包含建议。 我不确定最佳方法是什么,但基本上,我希望当我从file2.js导出某些函数时,能够在建议中从另一个file1.js中访问它们。 有什么想法吗? 谢谢! 文件1
var express = require('express');
var pug = require('pug');
var config = require('./config');
var fs = require('fs');
var router = express.Router();
var utils = require('/utils');
// Here I would like to use the function newTest from the other file 
but it does not show in the suggestions
router.get('/', function (req, res) {
    console.log("ip - ", req.connection.remoteAddress)
    res.send(pug.compileFile('views/main.pug')({
        config
    }))
});
module.exports = router;

文件2

function newTest() {
    
}
module.exports.newTest = newTest;

编辑文件

$(document).ready(function() {
// I prefetch my models, then I have a callback to create an instance of the editor
preFetchAllModels(function() {
    var models = monaco.editor.getModels();
    // I check that I have my models (file1 and file2) prefetched before creating the editor
    console.log("models", models);
    monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true)

    monacoEditor = monaco.editor.create(document.getElementById("editor"), {
        value: "loading...",
        language: "javascript",
        theme: 'monokai',
        lineHeight: 20,
        fontSize: 16,
        wordWrap: "bounded",
        automaticLayout: true,
        wrappingIndent: 'indent'
    });
});

你有查看文档吗?https://microsoft.github.io/monaco-editor/api/index.html - Fizik26
是的,我花了很多时间在文档中尝试查找,但没有任何成功。 - Bastien L.
1
你好,欢迎来到 Stack Overflow。你的问题可以通过提供一个具体的例子来改进,说明你已经尝试了什么,以及这些努力的结果是什么? - geekzster
3个回答

13
为了实现跨多个文件的 IntelliSense 目标,您需要使用单个 monaco.editor 实例,并在应用程序启动期间为每个要 IntelliSense 的文件初始化一个新模型。另外,为了支持自动完成,您必须实现一个完成项提供程序。请阅读下面的详细信息。

应用程序初始加载

  1. 使用 const myEditorInstance = monaco.editor.create({ ... , model: null }) 创建一个单独的编辑器实例。
  2. 通过 monaco.editor.createModel(...) 创建 n 个模型实例,其中 n 是文件的数量。
  3. 渴望的模型同步配置语言默认值:monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true)
  4. 要启用自动完成,您需要根据CompletionItemProvider api 实现一个方法。

处理初始加载后的各种事件

  • 通过 monaco.editor.getModels() 获取现有模型列表。
  • 打开文件(无论是用户点击按钮还是编写的代码自动化打开),使用 myEditorInstance.setModel(model) 将编辑器实例的模型设置为要打开的文件。
  • 关闭文件时,应使用 myEditorInstance.saveViewState() 保存该模型的视图状态(包括光标位置等)。
  • 如果再次打开该文件,则可以使用 myEditorInstance.restoreState() 恢复先前的模型状态。
  • 如果文件被重命名或删除,您需要正确处理相应的模型,并在文件被重命名的情况下重新初始化该模型。

  • 谢谢Peter。我按照你说的在创建编辑器实例之前创建了n个模型实例。然后我还配置了setEagerModelSync。到目前为止,我还没有启用自动完成,因为我不太确定如何操作。但是,即使没有启用自动完成,我应该能够看到建议吗?因为我没有看到来自其他文件的函数...也许它可以与URI相关联?(URI是否必须提供文件,或者仅用作ID?)感谢您的帮助! - Bastien L.
    1
    @BastienL,请编辑您的原始问题,尽可能添加代码,并尝试整合您的问题,以便我们更好地理解问题并提供帮助。 - Peter
    1
    比官方教程更好,更容易理解如何构建 Monaco 编辑器的教程。谢谢。 - NoxFly

    6

    我和你的使用情况几乎相同,只是我有一个文件作为我的“定义”,用于填充主编辑器的自动完成。根据Peter提供的答案,我能够组合出以下工作示例。我认为你缺少的部分是创建模型,然后使用editor.setModel(model)将其分配给你的编辑器。

    const editorOptions = {
        minimap: { enabled: false },
        scrollBeyondLastLine: false,
        model: null,
        language: "javascript"
    }
    
    const initEditor = () => {
      monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true)
    
      const defModel = monaco.editor.createModel(
        "const helloWorld = () => { return \"Hello World!\"; }",
        "javascript"
      )
    
      const textModel = monaco.editor.createModel(
        "helloWorld()",
        "javascript"
      )
    
      const e1 = monaco.editor.create(
        document.getElementById("editor1"), editorOptions
      )
      
      e1.setModel(defModel)
      
      const e2 = monaco.editor.create(
        document.getElementById("editor2"), editorOptions
      )
      
      e2.setModel(textModel)  
    }
    
    require.config({
        paths: {
            vs: "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.18.0/min/vs"
        }
    })
    
    require(["vs/editor/editor.main"], initEditor)
    .editor {
      margin: 1em 0;
      border: 1px solid #999;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.18.0/min/vs/loader.js"></script>
    
    <h3>Definitions</h3>
    
    <div class="editor" id="editor1" style="width: 100%; height: 40px"></div>
    
    <h3>Editor</h3>
    
    <div class="editor" id="editor2" style="width: 100%; height: 300px"></div>


    0

    看起来以下代码解决了问题:

    monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
            allowNonTsExtensions: true
    });
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接