Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow tab-invoked completion in strings, suppress autoinvoke in def #521

Merged
merged 5 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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