Skip to content

Commit 3782976

Browse files
authored
Merge pull request #893 from krassowski/elide-filepaths
Implement eliding for paths/files
2 parents 3df79a3 + ee46daf commit 3782976

File tree

3 files changed

+59
-2
lines changed

3 files changed

+59
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- implement jump target selector and jump to references ([#739])
77
- implement settings UI using native JupyterLab 3.3 UI ([#778])
88
- add option to show hover tooltip automatically ([#864], thanks @yamaton)
9+
- implement eliding for long paths/files in completer ([#893])
910
- bug fixes:
1011
- use correct websocket URL if configured as different from base URL ([#820], thanks @MikeSem)
1112
- clean up all completer styles when completer feature is disabled ([#829]).
@@ -61,6 +62,7 @@
6162
[#860]: https://github.com/jupyter-lsp/jupyterlab-lsp/pull/860
6263
[#864]: https://github.com/jupyter-lsp/jupyterlab-lsp/pull/864
6364
[#882]: https://github.com/jupyter-lsp/jupyterlab-lsp/pull/882
65+
[#893]: https://github.com/jupyter-lsp/jupyterlab-lsp/pull/893
6466

6567
### `@krassowski/jupyterlab-lsp 3.10.1` (2022-03-21)
6668

packages/completion-theme/style/index.css

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
}
2626

2727
.lsp-completer.jp-Completer {
28-
--lsp-completer-max-label-width: 300px;
28+
--lsp-completer-max-label-width: 350px;
2929
--lsp-completer-max-detail-width: 200px;
3030
}
3131

@@ -93,6 +93,22 @@ body[data-lsp-completer-layout='detail-below'] .jp-Completer-match {
9393
text-overflow: clip;
9494
}
9595

96+
.lsp-completer mark.lsp-elide:first-child {
97+
display: inline-block;
98+
overflow-x: clip;
99+
text-overflow: ellipsis;
100+
white-space: nowrap;
101+
direction: rtl;
102+
/* stretch to as much space as possible */
103+
flex-shrink: 1;
104+
/* always reserve small space to fit the ellipsis */
105+
min-width: 20px;
106+
}
107+
108+
.lsp-completer .lsp-elide-wrapper {
109+
display: flex;
110+
}
111+
96112
body[data-lsp-completer-layout='detail-below'] .jp-Completer-typeExtended {
97113
grid-area: detail;
98114
text-align: left;

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Signal } from '@lumino/signaling';
88
import { ILSPLogConsole } from '../../tokens';
99

1010
import { CompletionLabIntegration } from './completion';
11-
import { LazyCompletionItem } from './item';
11+
import { LazyCompletionItem, IExtendedCompletionItem } from './item';
1212

1313
export interface ICompletionData {
1414
item: LazyCompletionItem;
@@ -31,6 +31,7 @@ export class LSPCompletionRenderer
3131

3232
protected ITEM_PLACEHOLDER_CLASS = 'lsp-detail-placeholder';
3333
protected EXTRA_INFO_CLASS = 'jp-Completer-typeExtended';
34+
protected LABEL_CLASS = 'jp-Completer-match';
3435

3536
constructor(protected options: LSPCompletionRenderer.IOptions) {
3637
super();
@@ -113,6 +114,7 @@ export class LSPCompletionRenderer
113114
if (extraText) {
114115
const extraElement = li.getElementsByClassName(this.EXTRA_INFO_CLASS)[0];
115116
extraElement.textContent = extraText;
117+
this._elideMark(item, li);
116118
}
117119
}
118120

@@ -136,13 +138,50 @@ export class LSPCompletionRenderer
136138
this.visibilityObserver.observe(li);
137139
// TODO: build custom li from ground up
138140
this.updateExtraInfo(lsp_item, li);
141+
this._elideMark(lsp_item, li);
139142
} else {
140143
this.updateExtraInfo(item, li);
144+
this._elideMark(lsp_item, li);
141145
}
142146

143147
return li;
144148
}
145149

150+
private _elideMark(item: IExtendedCompletionItem, li: HTMLLIElement) {
151+
if (!item || !item.type) {
152+
return;
153+
}
154+
const type = item.type.toLowerCase();
155+
if (type !== 'file' && type !== 'path') {
156+
// do not elide for non-paths.
157+
return;
158+
}
159+
const labelElement = li.getElementsByClassName(this.LABEL_CLASS)[0];
160+
const originalHTMLLabel = labelElement.childNodes;
161+
let hasMark = false;
162+
for (const node of originalHTMLLabel) {
163+
if (node.nodeType === Node.ELEMENT_NODE) {
164+
const element = node as Element;
165+
const text = element.textContent;
166+
if (element.tagName === 'MARK' && text) {
167+
const elidableElement = document.createElement('bdo');
168+
elidableElement.setAttribute('dir', 'ltr');
169+
elidableElement.textContent = text;
170+
elidableElement.title = text;
171+
element.replaceChildren(elidableElement);
172+
element.classList.add('lsp-elide');
173+
hasMark = true;
174+
}
175+
}
176+
}
177+
if (hasMark) {
178+
const wrapper = document.createElement('div');
179+
wrapper.className = 'lsp-elide-wrapper';
180+
wrapper.replaceChildren(...labelElement.childNodes);
181+
labelElement.replaceChildren(wrapper);
182+
}
183+
}
184+
146185
createDocumentationNode(item: LazyCompletionItem): HTMLElement {
147186
// note: not worth trying to `fetchDocumentation()` as this is not
148187
// invoked if documentation is empty (as of jlab 3.2)

0 commit comments

Comments
 (0)