1
\$\begingroup\$

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?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 22, 2020 at 12:30
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I'd look at python decorators as something, that accepts function and returns function, which is usually original function wrapped in another function and some added behaviour.

Change signature of your "decorator" functions to match that and you got something like decorators. Don't have much time at the moment to write examples, but you get the idea :-)

Edit: I took a closer look at your code, but it seems very specific to your framework and I can't make complete sense of it to dare refactoring (doesn't mean it's bad code). At least here are some examples of wrapper functions to help you started: https://gist.github.com/harrylove/1230566/d064e5c216384d3846f73ed555e9899be02e8f98

answered Mar 22, 2020 at 20:33
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.