Skip to content

Commit 0d93b46

Browse files
committed
inline hint with full completion preview for functions
1 parent 0f3507a commit 0d93b46

File tree

6 files changed

+121
-14
lines changed

6 files changed

+121
-14
lines changed

client/modules/IDE/components/Editor.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ class Editor extends React.Component {
269269
if (this.props.autocompleteHinter !== prevProps.autocompleteHinter) {
270270
if (!this.props.autocompleteHinter) {
271271
// close the hinter window once the preference is turned off
272-
CodeMirror.showHint(this._cm, () => {});
272+
CodeMirror.showHint(this._cm, () => {}, {});
273273
}
274274
}
275275

@@ -352,7 +352,7 @@ class Editor extends React.Component {
352352

353353
showHint(_cm) {
354354
if (!this.props.autocompleteHinter) {
355-
CodeMirror.showHint(_cm, () => {});
355+
CodeMirror.showHint(_cm, () => {}, {});
356356
return;
357357
}
358358

@@ -425,7 +425,9 @@ class Editor extends React.Component {
425425
const c = _cm.getCursor();
426426
const token = _cm.getTokenAt(c);
427427

428-
const hints = this.hinter.search(token.string);
428+
const hints = this.hinter
429+
.search(token.string)
430+
.filter((h) => h.item.text[0] === token.string[0]);
429431

430432
return {
431433
list: hints,

client/modules/IDE/components/show-hint.js

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,55 @@
286286
<span aria-hidden="true">&#10132;</span></a></p>`;
287287
}
288288

289+
function getInlineHintSuggestion(focus, tokenLength) {
290+
const suggestionItem = focus.item;
291+
const baseCompletion = `<span class="inline-hinter-suggestion">${suggestionItem.text.slice(
292+
tokenLength
293+
)}</span>`;
294+
if (suggestionItem.type !== 'fun') return baseCompletion;
295+
296+
// for functions
297+
return (
298+
baseCompletion +
299+
'<span class="inline-hinter-suggestion-light">(' +
300+
(suggestionItem.params && suggestionItem.params.length
301+
? suggestionItem.params.map(({ p, o }) => (o ? `[${p}]` : p)).join(', ')
302+
: '') +
303+
')</span>'
304+
);
305+
}
306+
307+
function removeInlineHint(cm) {
308+
if (cm.state.inlineHint) {
309+
cm.state.inlineHint.clear();
310+
cm.state.inlineHint = null;
311+
}
312+
}
313+
314+
function changeInlineHint(cm, focus) {
315+
// Copilot-style inline suggestion for autocomplete feature
316+
removeInlineHint(cm);
317+
318+
const cursor = cm.getCursor();
319+
const token = cm.getTokenAt(cursor);
320+
321+
if (token && focus.item) {
322+
const suggestionHTML = getInlineHintSuggestion(
323+
focus,
324+
token.string.length
325+
);
326+
327+
const widgetElement = document.createElement('span');
328+
widgetElement.className = 'autocomplete-inline-hinter';
329+
widgetElement.innerHTML = suggestionHTML;
330+
331+
const widget = cm.setBookmark(cursor, { widget: widgetElement });
332+
cm.state.inlineHint = widget;
333+
334+
cm.setCursor(cursor);
335+
}
336+
}
337+
289338
function Widget(completion, data) {
290339
this.id = 'cm-complete-' + Math.floor(Math.random(1e6));
291340
this.completion = completion;
@@ -306,6 +355,9 @@
306355
hints.className = 'CodeMirror-hints ' + theme;
307356
this.selectedHint = data.selectedHint || 0;
308357

358+
// Show inline hint
359+
changeInlineHint(cm, data.list[this.selectedHint]);
360+
309361
var completions = data.list;
310362

311363
for (var i = 0; i < completions.length; ++i) {
@@ -431,10 +483,10 @@
431483
cm.addKeyMap(
432484
(this.keyMap = buildKeyMap(completion, {
433485
moveFocus: function (n, avoidWrap) {
434-
widget.changeActive(widget.selectedHint + n, avoidWrap);
486+
return widget.changeActive(widget.selectedHint + n, avoidWrap);
435487
},
436488
setFocus: function (n) {
437-
widget.changeActive(n);
489+
return widget.changeActive(n);
438490
},
439491
menuSize: function () {
440492
return widget.screenAmount();
@@ -540,6 +592,8 @@
540592
cm.off('focus', this.onFocus);
541593
}
542594
cm.off('scroll', this.onScroll);
595+
596+
removeInlineHint(cm);
543597
},
544598

545599
disable: function () {
@@ -561,7 +615,12 @@
561615
if (i >= this.data.list.length)
562616
i = avoidWrap ? this.data.list.length - 1 : 0;
563617
else if (i < 0) i = avoidWrap ? 0 : this.data.list.length - 1;
564-
if (this.selectedHint == i) return;
618+
619+
if (this.selectedHint == i) {
620+
changeInlineHint(this.completion.cm, this.data.list[this.selectedHint]);
621+
return this.data.list[this.selectedHint];
622+
}
623+
565624
var node = this.hints.childNodes[this.selectedHint];
566625
if (node) {
567626
node.className = node.className.replace(
@@ -583,6 +642,9 @@
583642
this.data.list[this.selectedHint],
584643
node
585644
);
645+
646+
changeInlineHint(this.completion.cm, this.data.list[this.selectedHint]);
647+
return this.data.list[this.selectedHint];
586648
},
587649

588650
scrollToActive: function () {

client/styles/abstracts/_variables.scss

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ $themes: (
135135
hint-var-active-border-bottom-color: #D52889,
136136
hint-item-active-type-text-color: $white,
137137
hint-item-active-outline: none,
138-
hint-item-active-outline-offset: 0
138+
hint-item-active-outline-offset: 0,
139+
hint-inline-text-color-light: $middle-light,
140+
hint-inline-text-color: $middle-gray,
139141
),
140142
dark: (
141143
logo-color: $p5js-pink,
@@ -234,7 +236,9 @@ $themes: (
234236
hint-var-active-border-bottom-color: #DE4A9B,
235237
hint-item-active-type-text-color: $darker,
236238
hint-item-active-outline: none,
237-
hint-item-active-outline-offset: 0
239+
hint-item-active-outline-offset: 0,
240+
hint-inline-text-color-light: $middle-gray,
241+
hint-inline-text-color: #cfcfcf,
238242
),
239243
contrast: (
240244
logo-color: $yellow,
@@ -333,7 +337,9 @@ $themes: (
333337
hint-var-active-border-bottom-color: none,
334338
hint-item-active-type-text-color: $lighter,
335339
hint-item-active-outline: 2px solid $lighter,
336-
hint-item-active-outline-offset: -2px
340+
hint-item-active-outline-offset: -2px,
341+
hint-inline-text-color-light: $middle-gray,
342+
hint-inline-text-color: #cfcfcf,
337343
)
338344
);
339345

client/styles/components/_hints.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,31 @@
160160
}
161161
}
162162
}
163+
164+
// Inline hinter
165+
.CodeMirror-widget {
166+
line-height: inherit;
167+
168+
@include themify() {
169+
.autocomplete-inline-hinter {
170+
// make the border left look like a cursor and animate like a cursor
171+
border-left: #{1.2 / $base-font-size}rem solid getThemifyVariable(hint-inline-text-color);
172+
animation: inline-hint-caret-blink 1s step-end infinite;
173+
pointer-events: none;
174+
175+
.inline-hinter-suggestion {
176+
color: getThemifyVariable(hint-inline-text-color);
177+
font-style: italic;
178+
}
179+
180+
.inline-hinter-suggestion-light {
181+
color: getThemifyVariable(hint-inline-text-color-light);
182+
font-style: italic;
183+
}
184+
}
185+
}
186+
}
187+
188+
@keyframes inline-hint-caret-blink {
189+
50% { border-color: transparent; }
190+
}

0 commit comments

Comments
 (0)