diff --git a/src/views/editors-hint.css b/src/views/editors-hint.css index 291bae67..8deeff24 100644 --- a/src/views/editors-hint.css +++ b/src/views/editors-hint.css @@ -57,6 +57,13 @@ padding: 0 .5ex 0 2ex; } +.discovery-view-editor-hint .signature { + color: rgba(153, 153, 153, 0.5); + font-family: Tahoma; + font-size: 95%; + padding: 0 0 0 0.3ex; +} + .discovery-view-editor-hint.active { background: rgba(0, 170, 255, .2); } diff --git a/src/views/editors.js b/src/views/editors.js index 54c5e526..9dfbc9b6 100644 --- a/src/views/editors.js +++ b/src/views/editors.js @@ -9,7 +9,32 @@ import modeView from './editor-mode-view'; import 'codemirror/mode/javascript/javascript'; import './editors-hint.js'; -function renderQueryAutocompleteItem(el, self, { entry: { value, current, type }}) { +function renderMethodSignature(meta) { + meta = meta || {}; + + function renderParam(param) { + const paramParts = [ + param.isRest ? '...' : null, + escapeHtml(param.name), + param.isOptional ? '?' : null + ]; + + return `${paramParts.filter(Boolean).join('')}`; + } + + const params = meta.params || []; + const paramsPart = params.map(param => { + if (typeof param === 'string') { + return renderParam({name: param}); + } + + return renderParam(param); + }); + + return `(${paramsPart.join(', ')})`; +} + +function renderQueryAutocompleteItem(el, self, { entry: { value, current, type, meta }}) { const startChar = current[0]; const lastChar = current[current.length - 1]; const start = startChar === '"' || startChar === "'" ? 1 : 0; @@ -25,6 +50,10 @@ function renderQueryAutocompleteItem(el, self, { entry: { value, current, type } ); } + if (type === 'method') { + value += renderMethodSignature(meta); + } + el.appendChild(createElement('span', 'name', value)); el.appendChild(createElement('span', 'type', type)); } @@ -38,7 +67,7 @@ class Editor extends Emitter { const self = this; const cm = CodeMirror(this.el, { - extraKeys: { 'Alt-Space': 'autocomplete' }, + extraKeys: { 'Ctrl-Space': 'showHint' }, mode: mode || 'javascript', theme: 'neo', indentUnit: 0, @@ -50,24 +79,31 @@ class Editor extends Emitter { } }); + CodeMirror.commands.showHint = (cm)=>{ + cm.showHint(); + }; + cm.on('change', () => this.emit('change', cm.getValue())); - if (typeof hint === 'function') { - // patch prepareSelection to inject a context hint - // const ps = cm.display.input.prepareSelection; - // cm.display.input.prepareSelection = function(...args) { - // const selection = ps.apply(this, args); - // if (selection.cursors.firstChild) { - // selection.cursors.firstChild.appendChild(createElement('div', 'context-hint', 'asd')); - // } - // return selection; - // }; - - cm.on('cursorActivity', cm => { - cm.state.focused && cm.showHint(); - }); - cm.on('focus', cm => !cm.state.completionActive && cm.showHint()); - } + const completionTriggerType = ['variable', 'property', 'operator']; + const completionTriggerKeys = ['.', '$']; + + cm.on('keyup', function(editor, event) { + if (event.keyCode < 48) { + return; + } + + const cursor = editor.getDoc().getCursor(); + const token = editor.getTokenAt(cursor); + + if (!completionTriggerType.includes(token.type) && !completionTriggerKeys.includes(token.string)) { + return; + } + + if (!editor.state.completionActive) { + editor.showHint(); + } + }); this.cm = cm; } diff --git a/src/widget/data-extension-api.js b/src/widget/data-extension-api.js index 32c7469f..c388361a 100644 --- a/src/widget/data-extension-api.js +++ b/src/widget/data-extension-api.js @@ -43,7 +43,8 @@ export function createDataExtensionApi(instance) { marker: lookupObjectMarker, markerAll: lookupObjectMarkerAll }; - let joraSetup = jora.setup(queryCustomMethods); + let queryCustomMethodsInfo = {}; + let joraSetup = jora.setup(queryCustomMethods, queryCustomMethodsInfo); return { apply() { @@ -118,9 +119,24 @@ export function createDataExtensionApi(instance) { }, addValueAnnotation, addQueryHelpers(helpers) { + const helpersMethods = {}; + const helpersMethodsInfo = {}; + + for (const [name, descriptor] of Object.entries(helpers)) { + if (typeof descriptor === 'function') { + helpersMethods[name] = descriptor; + } else { + helpersMethods[name] = descriptor.method; + helpersMethodsInfo[name] = descriptor; + } + } + joraSetup = jora.setup(queryCustomMethods = { ...queryCustomMethods, - ...helpers + ...helpersMethods + }, queryCustomMethodsInfo = { + ...queryCustomMethodsInfo, + ...helpersMethodsInfo }); }, query(query, ...args) {