mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-03 18:29:09 +00:00
online_editor: Make outline widget print some data
This commit is contained in:
parent
ec79a98d0d
commit
c629c4ab62
3 changed files with 160 additions and 8 deletions
|
@ -109,8 +109,9 @@ class EditorPaneWidget extends Widget {
|
|||
monaco.editor.ICodeEditorViewState | null | undefined
|
||||
>;
|
||||
#editor: monaco.editor.IStandaloneCodeEditor | null;
|
||||
#keystroke_timeout_handle: number | undefined;
|
||||
#base_url: string | undefined;
|
||||
#client?: MonacoLanguageClient;
|
||||
#keystroke_timeout_handle?: number;
|
||||
#base_url?: string;
|
||||
#edit_era: number;
|
||||
#disposables: monaco.IDisposable[] = [];
|
||||
#current_properties = "";
|
||||
|
@ -184,6 +185,14 @@ class EditorPaneWidget extends Widget {
|
|||
return commands.getCommands();
|
||||
}
|
||||
|
||||
get language_client(): MonacoLanguageClient | undefined {
|
||||
return this.#client;
|
||||
}
|
||||
|
||||
get current_text_document_uri(): string | undefined {
|
||||
return this.#editor?.getModel()?.uri.toString();
|
||||
}
|
||||
|
||||
compile() {
|
||||
this.update_preview();
|
||||
}
|
||||
|
@ -448,11 +457,14 @@ class EditorPaneWidget extends Widget {
|
|||
);
|
||||
const writer = new BrowserMessageWriter(lsp_worker);
|
||||
|
||||
const languageClient = createLanguageClient({ reader, writer });
|
||||
this.#client = createLanguageClient({ reader, writer });
|
||||
|
||||
languageClient.start();
|
||||
this.#client.start();
|
||||
|
||||
reader.onClose(() => languageClient.stop());
|
||||
reader.onClose(() => {
|
||||
this.#client.stop();
|
||||
this.#client = null;
|
||||
});
|
||||
|
||||
resolve_lsp_worker_promise();
|
||||
}
|
||||
|
@ -608,6 +620,14 @@ export class EditorWidget extends Widget {
|
|||
return this.#editor.current_editor_content;
|
||||
}
|
||||
|
||||
get language_client(): MonacoLanguageClient | undefined {
|
||||
return this.#editor.language_client;
|
||||
}
|
||||
|
||||
get current_text_document_uri(): string | undefined {
|
||||
return this.#editor.current_text_document_uri;
|
||||
}
|
||||
|
||||
compile() {
|
||||
this.#editor.compile();
|
||||
}
|
||||
|
|
|
@ -310,7 +310,9 @@ function main() {
|
|||
],
|
||||
[
|
||||
() => {
|
||||
return new OutlineWidget();
|
||||
return new OutlineWidget(() => {
|
||||
return [editor.language_client, editor.current_text_document_uri];
|
||||
});
|
||||
},
|
||||
{ mode: "tab-after", ref: "Welcome" },
|
||||
],
|
||||
|
|
|
@ -6,7 +6,79 @@
|
|||
import { Message } from "@lumino/messaging";
|
||||
import { Widget } from "@lumino/widgets";
|
||||
|
||||
import { MonacoLanguageClient } from "monaco-languageclient";
|
||||
|
||||
import {
|
||||
DocumentSymbolRequest,
|
||||
DocumentSymbolParams,
|
||||
DocumentSymbol,
|
||||
SymbolInformation,
|
||||
} from "vscode-languageserver-protocol";
|
||||
|
||||
const SYMBOL_KIND_MAP = [
|
||||
"kind-unknown",
|
||||
"kind-file",
|
||||
"kind-module",
|
||||
"kind-namespace",
|
||||
"kind-package",
|
||||
"kind-class",
|
||||
"kind-method",
|
||||
"kind-property",
|
||||
"kind-field",
|
||||
"kind-constructor",
|
||||
"kind-enum",
|
||||
"kind-interface",
|
||||
"kind-function",
|
||||
"kind-variable",
|
||||
"kind-constant",
|
||||
"kind-string",
|
||||
"kind-number",
|
||||
"kind-boolean",
|
||||
"kind-array",
|
||||
"kind-object",
|
||||
"kind-key",
|
||||
"kind-null",
|
||||
"kind-enum-member",
|
||||
"kind-struct",
|
||||
"kind-event",
|
||||
"kind-operator",
|
||||
"kind-type-parameter",
|
||||
];
|
||||
|
||||
function set_data(
|
||||
data: DocumentSymbol[],
|
||||
indent: number,
|
||||
table: HTMLTableElement,
|
||||
) {
|
||||
for (const d of data) {
|
||||
const row = document.createElement("tr");
|
||||
row.className = "outline-element";
|
||||
if (d.deprecated || (d.tags != null && 1 in d.tags)) {
|
||||
row.classList.add("deprecated");
|
||||
}
|
||||
if (d.kind >= SYMBOL_KIND_MAP.length || d.kind < 1) {
|
||||
row.classList.add(SYMBOL_KIND_MAP[0]);
|
||||
} else {
|
||||
row.classList.add(SYMBOL_KIND_MAP[d.kind]);
|
||||
}
|
||||
row.classList.add("indent-" + indent);
|
||||
|
||||
const cell = document.createElement("td");
|
||||
cell.innerText = d.name;
|
||||
|
||||
row.appendChild(cell);
|
||||
table.appendChild(row);
|
||||
|
||||
if (d.children != null) {
|
||||
set_data(d.children, indent + 1, table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class OutlineWidget extends Widget {
|
||||
#callback: () => [MonacoLanguageClient | undefined, string | undefined];
|
||||
#intervalId = -1;
|
||||
|
||||
static createNode(): HTMLElement {
|
||||
const node = document.createElement("div");
|
||||
const content = document.createElement("div");
|
||||
|
@ -14,17 +86,75 @@ export class OutlineWidget extends Widget {
|
|||
return node;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
constructor(
|
||||
callback: () => [MonacoLanguageClient | undefined, string | undefined],
|
||||
) {
|
||||
super({ node: OutlineWidget.createNode() });
|
||||
this.#callback = callback;
|
||||
this.setFlag(Widget.Flag.DisallowLayout);
|
||||
this.addClass("content");
|
||||
this.addClass("outline".toLowerCase());
|
||||
this.addClass("outline");
|
||||
this.title.label = "Document Outline";
|
||||
this.title.closable = true;
|
||||
this.title.caption = `Document Outline`;
|
||||
|
||||
this.#intervalId = window.setInterval(() => {
|
||||
const [client, uri] = this.#callback();
|
||||
if (client != null && uri != null) {
|
||||
client
|
||||
.sendRequest(DocumentSymbolRequest.type, {
|
||||
textDocument: { uri: uri },
|
||||
} as DocumentSymbolParams)
|
||||
.then((r: DocumentSymbol[] | SymbolInformation[] | null) =>
|
||||
this.update_data(r),
|
||||
);
|
||||
} else {
|
||||
if (uri == null) {
|
||||
// No document is open
|
||||
this.clear_data();
|
||||
} else {
|
||||
this.set_error("Language server not available");
|
||||
}
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
protected get contentNode(): HTMLDivElement {
|
||||
return this.node.getElementsByTagName("div")[0] as HTMLDivElement;
|
||||
}
|
||||
|
||||
protected update_data(data: DocumentSymbol[] | SymbolInformation[] | null) {
|
||||
if (data == null) {
|
||||
this.set_error("No data received");
|
||||
return;
|
||||
}
|
||||
if (data.length > 0 && "location" in data[0]) {
|
||||
// location is a required key in SymbolInformation that does not exist in DocumentSymbol
|
||||
this.set_error("Invalid data format received");
|
||||
return;
|
||||
}
|
||||
const table = document.createElement("table");
|
||||
table.className = "outline-table";
|
||||
|
||||
set_data(data as DocumentSymbol[], 0, table);
|
||||
|
||||
this.clear_data();
|
||||
this.contentNode.appendChild(table);
|
||||
}
|
||||
|
||||
protected clear_data() {
|
||||
this.contentNode.innerText = "";
|
||||
}
|
||||
|
||||
protected set_error(message: string) {
|
||||
this.contentNode.innerHTML = '<div class="error">' + message + "</div>";
|
||||
}
|
||||
|
||||
protected onCloseRequest(msg: Message): void {
|
||||
if (this.#intervalId !== -1) {
|
||||
clearInterval(this.#intervalId);
|
||||
this.#intervalId = -1;
|
||||
}
|
||||
super.onCloseRequest(msg);
|
||||
this.dispose();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue