Skip to content

Commit

Permalink
Merge pull request #521 from krassowski/completion/model-and-sorting
Browse files Browse the repository at this point in the history
Allow tab-invoked completion in strings, suppress autoinvoke in def
  • Loading branch information
krassowski authored Feb 14, 2021
2 parents 5bf9427 + 5ffa488 commit a7f07c6
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 23 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
- completer panel will now always render markdown documentation if available ([#520])
- the implementation re-renders the panel as it is the best we can do until [jupyterlab#9663](https://github.com/jupyterlab/jupyterlab/pull/9663) is merged
- the completer now uses `filterText` and `sortText` if available to better filter and sort completions ([#520])
- completer `suppressInvokeIn` setting was removed; `suppressContinuousHintingIn` and `suppressTriggerCharacterIn` settings were added ([#521])
- `suppressContinuousHintingIn` by default includes `def` to improve the experience when writing function names ([#521])

- bug fixes:
- user-invoked completion in strings works again ([#521])
- completer documentation will now consistently show up after filtering the completion items ([#520])
- completions containing HTML-like syntax will be displayed properly (an upstream issue) ([#520])

[#520]: https://github.com/krassowski/jupyterlab-lsp/pull/520
[#521]: https://github.com/krassowski/jupyterlab-lsp/pull/521

### `@krassowski/jupyterlab-lsp 3.3.1` (2020-02-07)

Expand Down
15 changes: 14 additions & 1 deletion atest/05_Features/Completion.robot
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,24 @@ Works After Kernel Restart In New Cells
Works In File Editor
[Setup] Prepare File for Editing Python completion completion.py
Place Cursor In File Editor At 9 2
Capture Page Screenshot 01-editor-ready.png
Wait Until Fully Initialized
Trigger Completer
Completer Should Suggest add
[Teardown] Clean Up After Working With File completion.py

Completes In Strings Or Python Dictionaries
[Setup] Prepare File for Editing Python completion completion.py
Place Cursor In File Editor At 16 0
Wait Until Fully Initialized
Press Keys None test_dict['']
Place Cursor In File Editor At 16 11
Trigger Completer
# note: in jedi-language-server this would be key_a without '
Completer Should Suggest 'key_a
Select Completer Suggestion 'key_a
Wait Until Keyword Succeeds 40x 0.5s File Editor Line Should Equal 15 test_dict['key_a']
[Teardown] Clean Up After Working With File completion.py

Continious Hinting Works
Configure JupyterLab Plugin {"continuousHinting": true} plugin id=${COMPLETION PLUGIN ID}
Prepare File for Editing Python completion completion.py
Expand Down
8 changes: 7 additions & 1 deletion atest/examples/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ def add(a: int, b: int):
return a, b


ad
ad


test_dict = {
'key_a': 1,
'key_b': 2
}
15 changes: 12 additions & 3 deletions packages/jupyterlab-lsp/schema/completion.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,23 @@
"default": false,
"description": "Whether to enable continuous hinting (Hinterland mode)."
},
"suppressInvokeIn": {
"title": "Suppress invoke in specific code fragments",
"suppressContinuousHintingIn": {
"title": "Suppress invoke continuous hinting in specific code fragments",
"type": "array",
"items": {
"type": "string"
},
"default": ["comment", "string", "def"],
"description": "An array of CodeMirror tokens for which the continuous hinting should be suppressed. The token names vary between languages (modes)."
},
"suppressTriggerCharacterIn": {
"title": "Suppress invoke via trigger character in specific code fragments",
"type": "array",
"items": {
"type": "string"
},
"default": ["comment", "string"],
"description": "An array of CodeMirror tokens for which the auto-invoke should be suppressed. Adding 'def' will prevent continuous hinting when writing a function name in Python, Julia, JavaScript and other languages. The token names vary between languages (modes)."
"description": "An array of CodeMirror tokens for which the auto-invoke after entering a trigger (e.g. `.` in Python or `::` in R) character should be suppressed. The token names vary between languages (modes)."
},
"kernelResponseTimeout": {
"title": "Kernel completion response timeout",
Expand Down
18 changes: 10 additions & 8 deletions packages/jupyterlab-lsp/src/features/completion/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class CompletionCM extends CodeMirrorIntegration {
);
(this.feature.labIntegration as CompletionLabIntegration)
.invoke_completer(CompletionTriggerKind.TriggerCharacter)
.catch(console.warn);
.catch(this.console.warn);
return;
}

Expand All @@ -74,7 +74,7 @@ export class CompletionCM extends CodeMirrorIntegration {
) {
(this.feature.labIntegration as CompletionLabIntegration)
.invoke_completer(AdditionalCompletionTriggerKinds.AutoInvoked)
.catch(console.warn);
.catch(this.console.warn);
}
}
}
Expand Down Expand Up @@ -198,13 +198,18 @@ export class CompletionLabIntegration implements IFeatureLabIntegration {
completer.model = new LSPCompleterModel();
}

get completer() {
protected get completer() {
// TODO upstream: make completer public?
return this.current_completion_handler.completer;
}

protected get model(): LSPCompleterModel {
return this.completer.model as LSPCompleterModel;
}

invoke_completer(kind: ExtendedCompletionTriggerKind) {
// TODO: ideally this would not re-trigger if list of items not isIncomplete
let command: string;

this.current_completion_connector.trigger_kind = kind;

if (this.adapterManager.currentAdapter instanceof NotebookAdapter) {
Expand Down Expand Up @@ -234,12 +239,9 @@ export class CompletionLabIntegration implements IFeatureLabIntegration {
}

private get current_items() {
// TODO upstream: make completer public?
let completer = this.current_completion_handler.completer;

// TODO upstream: allow to get completionItems() without markup
// (note: not trivial as _markup() does filtering too)
return completer.model.completionItems();
return this.model.completionItems();
}

private get current_index() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ export class LSPConnector
return this.options.settings.composite.kernelCompletionsFirst;
}

protected get suppress_auto_invoke_in(): string[] {
return this.options.settings.composite.suppressInvokeIn;
protected get suppress_continuous_hinting_in(): string[] {
return this.options.settings.composite.suppressContinuousHintingIn;
}

protected get suppress_trigger_character_in(): string[] {
return this.options.settings.composite.suppressTriggerCharacterIn;
}

get should_show_documentation(): boolean {
Expand Down Expand Up @@ -155,9 +159,16 @@ export class LSPConnector
const cursor = editor.getCursorPosition();
const token = editor.getTokenForPosition(cursor);

if (this.suppress_auto_invoke_in.indexOf(token.type) !== -1) {
this.console.log('Suppressing completer auto-invoke in', token.type);
return;
if (this.trigger_kind == AdditionalCompletionTriggerKinds.AutoInvoked) {
if (this.suppress_continuous_hinting_in.indexOf(token.type) !== -1) {
this.console.debug('Suppressing completer auto-invoke in', token.type);
return;
}
} else if (this.trigger_kind == CompletionTriggerKind.TriggerCharacter) {
if (this.suppress_trigger_character_in.indexOf(token.type) !== -1) {
this.console.debug('Suppressing completer auto-invoke in', token.type);
return;
}
}

const start = editor.getPositionAt(token.offset);
Expand Down Expand Up @@ -343,9 +354,15 @@ export class LSPConnector
this.console.debug('Transformed');
// required to make the repetitive trigger characters like :: or ::: work for R with R languageserver,
// see https://github.com/krassowski/jupyterlab-lsp/issues/436
const prefix_offset = token.value.length;
let prefix_offset = token.value.length;
// completion of dictionaries for Python with jedi-language-server was
// causing an issue for dic['<tab>'] case; to avoid this let's make
// sure that prefix.length >= prefix.offset
if (all_non_prefixed && prefix_offset > prefix.length) {
prefix_offset = prefix.length;
}

return {
let response = {
// note in the ContextCompleter it was:
// start: token.offset,
// end: token.offset + token.value.length,
Expand All @@ -359,6 +376,14 @@ export class LSPConnector
end: token.offset + prefix.length,
items: items
};
if (response.start > response.end) {
console.warn(
'Response contains start beyond end; this should not happen!',
response
);
}

return response;
}

protected icon_for(type: string): LabIcon {
Expand Down
3 changes: 0 additions & 3 deletions packages/jupyterlab-lsp/src/features/completion/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,9 @@ export class GenericCompleterModel<
let unfilteredItems = super.completionItems() as T[];
this.query = query;

//if (query) {
// always want to sort
// TODO does this behave strangely with %%<tab> if always sorting?
return this._sortAndFilter(query, unfilteredItems);
//}
//return unfilteredItems;
}

setCompletionItems(newValue: T[]) {
Expand Down

0 comments on commit a7f07c6

Please sign in to comment.