I am building an ad-hoc text-editor. I have two functions which use a cache, provideHover
and provideCompletionItems
.
"use strict";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
const $ = require("jquery");
const urlResolve = require("url-resolve");
const AUTOCOMPLETE_ENDPOINT = "http://localhost:7000/";
const LRU = require("lru-cache");
const options = {
max: 500,
length: (suggestions, key) => { return suggestions.length }
};
const cache = new LRU(options);
const definition_cache = new LRU(options);
(function () {
// create div to avoid needing a HtmlWebpackPlugin template
const div = document.createElement('div');
div.id = 'root';
div.style = 'width:800px; height:600px; border:1px solid #ccc;';
document.body.appendChild(div);
})();
monaco.editor.create(
document.getElementById('root'),
{
value: ``,
language: 'python',
theme: 'vs-dark'
}
);
const getCompletions = (text) => {
return $.ajax({
url: urlResolve(AUTOCOMPLETE_ENDPOINT, "suggestion"),
type: 'GET',
"data": {
"text": text
}
});
};
const getDocumentation = (cursorInfo) => {
const line = cursorInfo.line;
const column = cursorInfo.column;
const text = cursorInfo.text;
return $.ajax({
url: urlResolve(AUTOCOMPLETE_ENDPOINT, "documentation"),
type: 'GET',
"data": {
"line": line,
"column": column,
"text": text,
"highlighted": cursorInfo.highlighted
}
});
}
monaco.languages.registerHoverProvider("python", {
provideHover: async (model, position) => {
const lineNumber = position.lineNumber;
const snippet = model.getWordAtPosition(position);
const text = model.getValueInRange({ startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: snippet.endColumn });
if (definition_cache.has(text)) {
console.log("hit");
return {
contents: [{ value: definition_cache.get(text) }]
}
}
const response = await getDocumentation({ "line": lineNumber, "column": snippet.endColumn, "text": text, "highlighted": snippet.word });
definition_cache.set(text, response.documentation);
return {
contents: [{ value: response.documentation }]
}
}
});
monaco.languages.registerCompletionItemProvider('python', {
provideCompletionItems: async (model, position) => {
const text = model.getValueInRange({ startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column });
if (cache.has(text)) {
const suggestions = cache.get(text);
return {
"suggestions": suggestions
};
}
const completions = await getCompletions(text)
const suggestions = completions.map(c => ({
label: c.name,
insertText: c.name
}));
cache.set(text, suggestions)
return {
"suggestions": suggestions
};
}
});
As it stands, the introduction of the cache makes the code quite ugly (in my opinion). I'd like to refactor it so that I have only one cache usage that applies in both situations -- something like a Python decorator.
How do I make the code cleaner?