From 67d9aecfb64ca101350eb302975672bcc1adba6b Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Wed, 25 Aug 2021 20:04:53 +0200 Subject: [PATCH] Add editor breadcrumbs to demo This uses some untyped and undocumented monaco APIs. Closes #41 --- examples/demo/src/index.css | 24 ++++++++++++++ examples/demo/src/index.ejs | 1 + examples/demo/src/index.ts | 64 +++++++++++++++++++++++++++++++------ 3 files changed, 80 insertions(+), 9 deletions(-) diff --git a/examples/demo/src/index.css b/examples/demo/src/index.css index 152459d..b9a8879 100644 --- a/examples/demo/src/index.css +++ b/examples/demo/src/index.css @@ -59,6 +59,30 @@ nav { margin: 1.5rem; } +#breadcrumbs { + border-bottom: 1px solid var(--shadow-color); + color: var(--foreground-color); + flex: 0 0 1rem; +} + +.breadcrumb { + cursor: pointer; +} + +#breadcrumbs::before, +.breadcrumb:not(:last-child)::after { + content: '›'; + margin: 0 0.2rem; +} + +.breadcrumb.array::before { + content: '[]'; +} + +.breadcrumb.object::before { + content: '{}'; +} + #editor { flex: 1 1 auto; } diff --git a/examples/demo/src/index.ejs b/examples/demo/src/index.ejs index db7ca97..b0c847f 100644 --- a/examples/demo/src/index.ejs +++ b/examples/demo/src/index.ejs @@ -24,6 +24,7 @@
+
diff --git a/examples/demo/src/index.ts b/examples/demo/src/index.ts index e0711e0..888c0a8 100644 --- a/examples/demo/src/index.ts +++ b/examples/demo/src/index.ts @@ -1,6 +1,14 @@ import './index.css'; -import { editor, Environment } from 'monaco-editor/esm/vs/editor/editor.api'; +import { CancellationToken } from 'monaco-editor/esm/vs/base/common/cancellation'; +import { getDocumentSymbols } from 'monaco-editor/esm/vs/editor/contrib/documentSymbols/documentSymbols'; +import { + editor, + Environment, + languages, + Position, + Range, +} from 'monaco-editor/esm/vs/editor/editor.api'; import { setDiagnosticsOptions } from 'monaco-yaml'; // NOTE: This will give you all editor featues. If you would prefer to limit to only the editor @@ -123,6 +131,9 @@ reference: array: - string: 12 enum: Mewtwo + reference: + reference: + boolean: true # JSON referenses can be clicked for navigation @@ -146,6 +157,45 @@ const ed = editor.create(document.getElementById('editor'), { theme: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'vs-dark' : 'vs-light', }); +function* iterateSymbols( + symbols: languages.DocumentSymbol[], + position: Position, +): Iterable { + for (const symbol of symbols) { + if (Range.containsPosition(symbol.range, position)) { + yield symbol; + yield* iterateSymbols(symbol.children, position); + } + } +} + +ed.onDidChangeCursorPosition(async (event) => { + const breadcrumbs = document.getElementById('breadcrumbs'); + const symbols = await getDocumentSymbols(ed.getModel(), false, CancellationToken.None); + while (breadcrumbs.lastChild) { + breadcrumbs.lastChild.remove(); + } + for (const symbol of iterateSymbols(symbols, event.position)) { + const breadcrumb = document.createElement('span'); + breadcrumb.setAttribute('role', 'button'); + breadcrumb.classList.add('breadcrumb'); + breadcrumb.textContent = symbol.name; + if (symbol.kind === languages.SymbolKind.Array) { + breadcrumb.classList.add('array'); + } else if (symbol.kind === languages.SymbolKind.Module) { + breadcrumb.classList.add('object'); + } + breadcrumb.addEventListener('click', () => { + ed.setPosition({ + lineNumber: symbol.range.startLineNumber, + column: symbol.range.startColumn, + }); + ed.focus(); + }); + breadcrumbs.append(breadcrumb); + } +}); + editor.onDidChangeMarkers(([resource]) => { const problems = document.getElementById('problems'); const markers = editor.getModelMarkers({ resource }); @@ -162,14 +212,10 @@ editor.onDidChangeMarkers(([resource]) => { text.classList.add('problem-text'); text.textContent = marker.message; wrapper.append(codicon, text); - wrapper.addEventListener( - 'click', - () => { - ed.setPosition({ lineNumber: marker.startLineNumber, column: marker.startColumn }); - ed.focus(); - }, - false, - ); + wrapper.addEventListener('click', () => { + ed.setPosition({ lineNumber: marker.startLineNumber, column: marker.startColumn }); + ed.focus(); + }); problems.append(wrapper); } });