From d52f47d2cb5600062dafdd3d80049021540f4ec5 Mon Sep 17 00:00:00 2001 From: Sergey Melyukov Date: Mon, 14 Mar 2022 10:44:47 +0300 Subject: [PATCH 1/5] improve hint ux --- src/views/editors.js | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/views/editors.js b/src/views/editors.js index 54c5e526..93ce2558 100644 --- a/src/views/editors.js +++ b/src/views/editors.js @@ -38,7 +38,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 +50,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']; + 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; } From 7119b02e1c0413cdeabde03522683c7fb46e85de Mon Sep 17 00:00:00 2001 From: Sergey Melyukov Date: Mon, 14 Mar 2022 13:31:34 +0300 Subject: [PATCH 2/5] show hint after operator --- src/views/editors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/editors.js b/src/views/editors.js index 93ce2558..9792a3d3 100644 --- a/src/views/editors.js +++ b/src/views/editors.js @@ -56,7 +56,7 @@ class Editor extends Emitter { cm.on('change', () => this.emit('change', cm.getValue())); - const completionTriggerType = ['variable', 'property']; + const completionTriggerType = ['variable', 'property', 'operator']; const completionTriggerKeys = ['.', '$']; cm.on('keyup', function(editor, event) { From 759f79f65764b486787a28f0c76cfa4025b0649a Mon Sep 17 00:00:00 2001 From: Sergey Melyukov Date: Mon, 14 Mar 2022 14:05:42 +0300 Subject: [PATCH 3/5] improve hint method-items style --- src/views/editors-hint.css | 7 +++++++ src/views/editors.js | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/views/editors-hint.css b/src/views/editors-hint.css index 291bae67..94b16af9 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 .postfix { + 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 9792a3d3..3a785810 100644 --- a/src/views/editors.js +++ b/src/views/editors.js @@ -9,6 +9,12 @@ import modeView from './editor-mode-view'; import 'codemirror/mode/javascript/javascript'; import './editors-hint.js'; +function getMethodPostfix(value, type) { + if (type === 'method' && !value.includes('(')) { + return '()'; + } +} + function renderQueryAutocompleteItem(el, self, { entry: { value, current, type }}) { const startChar = current[0]; const lastChar = current[current.length - 1]; @@ -16,6 +22,7 @@ function renderQueryAutocompleteItem(el, self, { entry: { value, current, type } const end = lastChar === '"' || lastChar === "'" ? 1 : 0; const pattern = current.toLowerCase().substring(start, current.length - end); const offset = pattern ? value.toLowerCase().indexOf(pattern, value[0] === '"' || value[0] === "'" ? 1 : 0) : -1; + const postfix = getMethodPostfix(value, type); if (offset !== -1) { value = ( @@ -25,6 +32,10 @@ function renderQueryAutocompleteItem(el, self, { entry: { value, current, type } ); } + if (postfix) { + value += `${postfix}`; + } + el.appendChild(createElement('span', 'name', value)); el.appendChild(createElement('span', 'type', type)); } From e3ca5abb547b6dd58b49c0bc570b86ba441001a0 Mon Sep 17 00:00:00 2001 From: Sergey Melyukov Date: Mon, 14 Mar 2022 19:29:18 +0300 Subject: [PATCH 4/5] fix --- src/views/editors.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/views/editors.js b/src/views/editors.js index 3a785810..086ced18 100644 --- a/src/views/editors.js +++ b/src/views/editors.js @@ -9,12 +9,6 @@ import modeView from './editor-mode-view'; import 'codemirror/mode/javascript/javascript'; import './editors-hint.js'; -function getMethodPostfix(value, type) { - if (type === 'method' && !value.includes('(')) { - return '()'; - } -} - function renderQueryAutocompleteItem(el, self, { entry: { value, current, type }}) { const startChar = current[0]; const lastChar = current[current.length - 1]; @@ -22,7 +16,6 @@ function renderQueryAutocompleteItem(el, self, { entry: { value, current, type } const end = lastChar === '"' || lastChar === "'" ? 1 : 0; const pattern = current.toLowerCase().substring(start, current.length - end); const offset = pattern ? value.toLowerCase().indexOf(pattern, value[0] === '"' || value[0] === "'" ? 1 : 0) : -1; - const postfix = getMethodPostfix(value, type); if (offset !== -1) { value = ( @@ -32,8 +25,8 @@ function renderQueryAutocompleteItem(el, self, { entry: { value, current, type } ); } - if (postfix) { - value += `${postfix}`; + if (type === 'method') { + value += '()'; } el.appendChild(createElement('span', 'name', value)); From 056ed521627b3efb25b9398ae0a070f47133283b Mon Sep 17 00:00:00 2001 From: Sergey Melyukov Date: Tue, 15 Mar 2022 14:00:00 +0300 Subject: [PATCH 5/5] add method signture --- src/views/editors-hint.css | 2 +- src/views/editors.js | 29 +++++++++++++++++++++++++++-- src/widget/data-extension-api.js | 20 ++++++++++++++++++-- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/views/editors-hint.css b/src/views/editors-hint.css index 94b16af9..8deeff24 100644 --- a/src/views/editors-hint.css +++ b/src/views/editors-hint.css @@ -57,7 +57,7 @@ padding: 0 .5ex 0 2ex; } -.discovery-view-editor-hint .postfix { +.discovery-view-editor-hint .signature { color: rgba(153, 153, 153, 0.5); font-family: Tahoma; font-size: 95%; diff --git a/src/views/editors.js b/src/views/editors.js index 086ced18..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; @@ -26,7 +51,7 @@ function renderQueryAutocompleteItem(el, self, { entry: { value, current, type } } if (type === 'method') { - value += '()'; + value += renderMethodSignature(meta); } el.appendChild(createElement('span', 'name', value)); 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) {