Skip to content

Commit d2fb4b9

Browse files
rcosta358codex
andcommitted
Remove editor folding and restore diagnostic navigation
Co-authored-by: Codex <codex@openai.com>
1 parent b4be3dc commit d2fb4b9

8 files changed

Lines changed: 76 additions & 23 deletions

File tree

‎package-lock.json‎

Lines changed: 6 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
1212
"z3-solver": "4.16.0"
1313
},
1414
"dependencies": {
15+
"@codemirror/autocomplete": "6.20.3",
16+
"@codemirror/commands": "6.11.1",
1517
"@codemirror/lang-java": "6.0.2",
1618
"@codemirror/language": "6.12.4",
1719
"@codemirror/lint": "6.8.5",
20+
"@codemirror/search": "6.7.2",
21+
"@codemirror/state": "6.7.6",
22+
"@codemirror/view": "6.43.13",
1823
"@lezer/highlight": "1.2.5",
19-
"ansi_up": "6.0.6",
20-
"codemirror": "6.0.2"
24+
"ansi_up": "6.0.6"
2125
}
2226
}

‎playground/editor.css‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
#lj-status[data-state="warning"] { color: #f6c177; }
3232
#lj-status:not(.sr-only) + #lj-results:not(:empty) { border-top: 1px solid #ffffff1a; }
3333
.main-content #lj-results pre { margin: 0; }
34+
.main-content #lj-results a { color: #e6edf7; text-decoration: underline; text-underline-offset: .2em; }
35+
.main-content #lj-results a:hover { color: #e6edf7; }
36+
.main-content #lj-results a:focus-visible { outline: 2px solid #7dd3fc; outline-offset: 3px; }
3437
#lj-results .ansi-black-fg { color: #111827; }
3538
#lj-results .ansi-bright-black-fg { color: #9ca3af; }
3639
#lj-status[data-state="error"],

‎scripts/playground/diagnostics.mjs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ export function editorDiagnostic(issue, length) {
1313
export function diagnosticHtml(output) {
1414
const ansi = new AnsiUp();
1515
ansi.use_classes = true;
16-
return ansi.ansi_to_html(shortenLocations(output).replace(/^(?:\r?\n)+/, ''));
16+
return ansi.ansi_to_html(shortenLocations(output).replace(/^(?:\r?\n)+/, ''))
17+
.replace(/^(\/playground\/[^<\r\n]+:(\d+))(?=\r?\n|$|<\/span>)/gm,
18+
'<a href="#lj-editor" data-line="$2">$1</a>');
1719
}

‎scripts/playground/diagnostics.test.mjs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import test from 'node:test';
22
import assert from 'node:assert/strict';
33
import { diagnosticHtml, editorDiagnostic } from './diagnostics.mjs';
44

5+
test('make diagnostic and declaration locations editor links without linking source excerpts', () => {
6+
const html = diagnosticHtml('Error\n6 | String path = "/playground/Example.java:99";\n\n/files/playground/Example.java:6\u001b[0m\n\n--> Refinement declared here:\n/files/playground/Example.java:5\u001b[0m\n');
7+
assert.match(html, /<a href="#lj-editor" data-line="6">\/playground\/Example.java:6<\/a>/);
8+
assert.match(html, /<a href="#lj-editor" data-line="5">\/playground\/Example.java:5<\/a>/);
9+
assert.equal((html.match(/<a /g) || []).length, 2);
10+
});
11+
512
test('omit leading CLI blank lines while preserving diagnostic spacing and colors', () => {
613
const diagnostic = '\u001b[31mError\u001b[0m\n6 | code\n | ^^^\n\nExample.java:6\n';
714
assert.equal(diagnosticHtml('\n\n' + diagnostic), diagnosticHtml(diagnostic));
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { EditorState } from '@codemirror/state';
2+
import { lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine, keymap } from '@codemirror/view';
3+
import { indentOnInput, bracketMatching } from '@codemirror/language';
4+
import { history, defaultKeymap, historyKeymap } from '@codemirror/commands';
5+
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
6+
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
7+
import { lintKeymap } from '@codemirror/lint';
8+
9+
export const editorSetup = [
10+
lineNumbers(),
11+
highlightActiveLineGutter(),
12+
highlightSpecialChars(),
13+
history(),
14+
drawSelection(),
15+
dropCursor(),
16+
EditorState.allowMultipleSelections.of(true),
17+
indentOnInput(),
18+
bracketMatching(),
19+
closeBrackets(),
20+
autocompletion(),
21+
rectangularSelection(),
22+
crosshairCursor(),
23+
highlightActiveLine(),
24+
highlightSelectionMatches(),
25+
keymap.of([
26+
...closeBracketsKeymap,
27+
...defaultKeymap,
28+
...searchKeymap,
29+
...historyKeymap,
30+
...completionKeymap,
31+
...lintKeymap
32+
])
33+
];

‎scripts/playground/editor-theme.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EditorView } from 'codemirror';
1+
import { EditorView } from '@codemirror/view';
22
import { javaLanguage } from '@codemirror/lang-java';
33
import { HighlightStyle, LanguageSupport, syntaxHighlighting } from '@codemirror/language';
44
import { styleTags, tags } from '@lezer/highlight';

‎scripts/playground/editor.js‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { EditorView, basicSetup } from 'codemirror';
1+
import { EditorView } from '@codemirror/view';
22
import { setDiagnostics } from '@codemirror/lint';
33
import { examples } from './examples.mjs';
44
import { diagnosticHtml, editorDiagnostic } from './diagnostics.mjs';
55
import { editorJava, editorTheme } from './editor-theme.mjs';
6+
import { editorSetup } from './editor-setup.mjs';
67

78
const root = document.querySelector('#lj-playground');
89
const example = document.querySelector('#lj-example');
@@ -18,7 +19,7 @@ let source;
1819
let timer;
1920
const view = new EditorView({
2021
doc: examples.positive,
21-
extensions: [basicSetup, editorJava, editorTheme, EditorView.contentAttributes.of({ 'aria-label': 'Java source code' }),
22+
extensions: [editorSetup, editorJava, editorTheme, EditorView.contentAttributes.of({ 'aria-label': 'Java source code' }),
2223
EditorView.updateListener.of(update => {
2324
if (update.docChanged) {
2425
queueMicrotask(() => view.dispatch(setDiagnostics(view.state, [])));
@@ -57,6 +58,20 @@ function render(result) {
5758
const pre = document.createElement('pre');
5859
const code = document.createElement('code');
5960
code.innerHTML = diagnosticHtml(issues.map(issue => issue.output).join('\n') + (result.details || ''));
61+
for (const link of code.querySelectorAll('a[data-line]')) {
62+
const lineNumber = Number(link.dataset.line);
63+
if (lineNumber < 1 || lineNumber > view.state.doc.lines) continue;
64+
link.onclick = event => {
65+
event.preventDefault();
66+
const issue = issues.find(issue => issue.line === lineNumber);
67+
const mark = issue && editorDiagnostic(issue, view.state.doc.length);
68+
const line = view.state.doc.line(lineNumber);
69+
const anchor = mark?.from ?? line.from + line.text.search(/\S|$/);
70+
view.dom.scrollIntoView({ block: 'center', inline: 'nearest' });
71+
view.dispatch({ selection: { anchor }, effects: EditorView.scrollIntoView(anchor, { y: 'center' }) });
72+
view.focus();
73+
};
74+
}
6075
pre.append(code);
6176
results.append(pre);
6277
}

0 commit comments

Comments
 (0)