ui-modules/utils/yaml-editor/addon/hint/super-hint.js (78 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import CodeMirror from 'codemirror'; /** * Creates a customised CodeMirror hint (https://codemirror.net/doc/manual.html#addon_show-hint) based on useful * information such has an helper text, a description, etc. */ class SuperHint { constructor(hint, name, helper, description) { this.hint = hint; this.name = name; this.helper = helper; this.description = description; } /** * Returns a an object that can be used by the `show-hint` plugin of CodeMirror. The returned object contains a * `render` function that will display a VS editor style hint. * * @return {{text: *, render: (function(*))}} */ getHint() { return { text: this.hint, render: (li) => { let pTitle = document.createElement('p'); pTitle.className = 'CodeMirror-superhint-title'; li.appendChild(pTitle); let spanName = document.createElement('span'); spanName.className = 'CodeMirror-superhint-name'; spanName.appendChild(document.createTextNode(this.name)); pTitle.appendChild(spanName); if (this.helper) { let spanHelper = document.createElement('span'); spanHelper.className = 'CodeMirror-superhint-helper'; spanHelper.appendChild(document.createTextNode(this.helper)); pTitle.appendChild(spanHelper); } if (this.description) { let pDescription = document.createElement('p'); pDescription.className = 'CodeMirror-superhint-description'; pDescription.appendChild(document.createTextNode(this.description)); li.appendChild(pDescription); } } } } } CodeMirror.defineExtension('superHint', (hint, name, helper, description) => new SuperHint(hint, name, helper, description)); CodeMirror.defineExtension('superHintLoader', () => { let loadingState = document.createElement('ul'); loadingState.className = 'CodeMirror-hints'; let loading = loadingState.appendChild(document.createElement('li')); loading.className = 'CodeMirror-hint CodeMirror-hint-loading'; loading.appendChild(document.createTextNode('Loading')); return loadingState; }); CodeMirror.registerHelper('hint', 'super', (cm, callback, options) => { let loadingState = cm.superHintLoader(); let removeLoadingState = () => { if (loadingState) { loadingState.remove(); } cm.off('cursorActivity', removeLoadingState); }; cm.on('cursorActivity', removeLoadingState); cm.addWidget(cm.getCursor(), loadingState); let promises = cm.getHelpers(CodeMirror.Pos(0, 0), 'superHint').reduce((promises, helper) => promises.concat(helper(cm, options)), []); Promise.all(promises).then(results => { removeLoadingState(); let superHints = results.reduce((hints, result) => { let list = hints.list.concat(result.list); return Object.assign(hints, result, {list: list}); }, {list: []}); superHints.list = superHints.list.map(superHints => superHints.getHint()); callback(superHints); }).catch(error => { removeLoadingState(); CodeMirror.signal(cm, 'superhint-error', error); callback({ list: [], from: cm.getCursor(), to: cm.getCursor() }); }); }); CodeMirror.hint.super.async = true; CodeMirror.defineOption('hintOptions', { hint: CodeMirror.hint.super, completeSingle: false });