Skip to content

Commit c3e90ec

Browse files
authored
Merge pull request #523 from krassowski/completion/smarter-use-of-sum-of-squares
Only search for label match if different from insertText match
2 parents f324c69 + a838290 commit c3e90ec

File tree

3 files changed

+50
-10
lines changed

3 files changed

+50
-10
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,20 @@
77
- the priority of the completions from kernel can now be changed by switching new `kernelCompletionsFirst` setting ([#520])
88
- completer panel will now always render markdown documentation if available ([#520])
99
- 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
10-
- the completer now uses `filterText` and `sortText` if available to better filter and sort completions ([#520])
10+
- the completer now uses `filterText` and `sortText` if available to better filter and sort completions ([#520], [#523])
1111
- completer `suppressInvokeIn` setting was removed; `suppressContinuousHintingIn` and `suppressTriggerCharacterIn` settings were added ([#521])
1212
- `suppressContinuousHintingIn` by default includes `def` to improve the experience when writing function names ([#521])
1313

1414
- bug fixes:
1515
- user-invoked completion in strings works again ([#521])
1616
- completer documentation will now consistently show up after filtering the completion items ([#520])
17-
- completions containing HTML-like syntax will be displayed properly (an upstream issue) ([#520])
17+
- completions containing HTML-like syntax will be displayed properly (an upstream issue) ([#520], [#523])
1818
- diagnostics panel will no longer break when foreign documents (e.g. `%%R` cell magics) are removed ([#522])
1919

2020
[#520]: https://github.com/krassowski/jupyterlab-lsp/pull/520
2121
[#521]: https://github.com/krassowski/jupyterlab-lsp/pull/521
2222
[#522]: https://github.com/krassowski/jupyterlab-lsp/pull/522
23+
[#523]: https://github.com/krassowski/jupyterlab-lsp/pull/523
2324

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

packages/jupyterlab-lsp/src/features/completion/model.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ describe('LSPCompleterModel', () => {
3535
model = new LSPCompleterModel();
3636
});
3737

38+
it('returns escaped when no query', () => {
39+
model.setCompletionItems([jupyter_icon_completion]);
40+
model.query = '';
41+
42+
let markedItems = model.completionItems();
43+
expect(markedItems[0].label).to.be.equal(
44+
'<i class="jp-icon-jupyter"></i> Jupyter'
45+
);
46+
});
47+
3848
it('marks html correctly', () => {
3949
model.setCompletionItems([jupyter_icon_completion]);
4050
model.query = 'Jup';
@@ -73,4 +83,23 @@ describe('LSPCompleterModel', () => {
7383
filteredItems = model.completionItems();
7484
expect(filteredItems.length).to.equal(0);
7585
});
86+
87+
it('marks appropriate part of label when filterText matches', () => {
88+
model.setCompletionItems([jupyter_icon_completion]);
89+
// font is in filterText but not in label
90+
model.query = 'font';
91+
92+
// nothing should get highlighted
93+
let markedItems = model.completionItems();
94+
expect(markedItems[0].label).to.be.equal(
95+
'<i class="jp-icon-jupyter"></i> Jupyter'
96+
);
97+
98+
// i is in both label and filterText
99+
model.query = 'i';
100+
markedItems = model.completionItems();
101+
expect(markedItems[0].label).to.be.equal(
102+
'&lt;<mark>i</mark> class="jp-icon-jupyter"&gt;&lt;/i&gt; Jupyter'
103+
);
104+
});
76105
});

packages/jupyterlab-lsp/src/features/completion/model.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,12 @@ export class GenericCompleterModel<
7373

7474
let matched: boolean;
7575

76+
let filterText: string = null;
77+
let filterMatch: StringExt.IMatchResult;
78+
7679
if (query) {
77-
const filterText = this.getFilterText(item);
78-
let filterMatch = StringExt.matchSumOfSquares(filterText, query);
80+
filterText = this.getFilterText(item);
81+
filterMatch = StringExt.matchSumOfSquares(filterText, query);
7982
matched = !!filterMatch;
8083
} else {
8184
matched = true;
@@ -86,25 +89,32 @@ export class GenericCompleterModel<
8689
// If the matches are substrings of label, highlight them
8790
// in this part of the label that can be highlighted (must be a prefix),
8891
// which is intended to avoid highlighting matches in function arguments etc.
89-
const labelPrefix = escapeHTML(this.getHighlightableLabelRegion(item));
92+
let labelMatch: StringExt.IMatchResult;
93+
if (query) {
94+
let labelPrefix = escapeHTML(this.getHighlightableLabelRegion(item));
95+
if (labelPrefix == filterText) {
96+
labelMatch = filterMatch;
97+
} else {
98+
labelMatch = StringExt.matchSumOfSquares(labelPrefix, query);
99+
}
100+
}
90101

91-
let match = StringExt.matchSumOfSquares(labelPrefix, query);
92102
let label: string;
93103
let score: number;
94104

95-
if (match) {
105+
if (labelMatch) {
96106
// Highlight label text if there's a match
97107
// there won't be a match if filter text includes additional keywords
98108
// for easier search that are not a part of the label
99109
let marked = StringExt.highlight(
100110
escapeHTML(item.label),
101-
match.indices,
111+
labelMatch.indices,
102112
this._markFragment
103113
);
104114
label = marked.join('');
105-
score = match.score;
115+
score = labelMatch.score;
106116
} else {
107-
label = item.label;
117+
label = escapeHTML(item.label);
108118
score = 0;
109119
}
110120
// preserve getters (allow for lazily retrieved documentation)

0 commit comments

Comments
 (0)