@lvce-editor/editor-worker 19.71.0 → 19.71.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editorWorkerMain.js +354 -337
- package/package.json +1 -1
package/dist/editorWorkerMain.js
CHANGED
|
@@ -7155,112 +7155,6 @@ const applyEdit = async (editor, changes, selectionChanges) => {
|
|
|
7155
7155
|
return scheduleDocumentAndCursorsSelections(editor, changes, selectionChanges);
|
|
7156
7156
|
};
|
|
7157
7157
|
|
|
7158
|
-
// TODO maybe use a separate worker for bulk edits and bulk edit history
|
|
7159
|
-
|
|
7160
|
-
const sortEditsDescending = edits => {
|
|
7161
|
-
return edits.toSorted((a, b) => b.offset - a.offset);
|
|
7162
|
-
};
|
|
7163
|
-
const applyEditsToText = (text, edits) => {
|
|
7164
|
-
let newText = text;
|
|
7165
|
-
for (const edit of sortEditsDescending(edits)) {
|
|
7166
|
-
newText = newText.slice(0, edit.offset) + edit.inserted + newText.slice(edit.offset + edit.deleted);
|
|
7167
|
-
}
|
|
7168
|
-
return newText;
|
|
7169
|
-
};
|
|
7170
|
-
const getTextChanges = (editor, edits) => {
|
|
7171
|
-
const textChanges = [];
|
|
7172
|
-
for (const edit of sortEditsDescending(edits)) {
|
|
7173
|
-
const startPosition = positionAt(editor, edit.offset);
|
|
7174
|
-
const endPosition = positionAt(editor, edit.offset + edit.deleted);
|
|
7175
|
-
const deleted = getSelectionText(editor, {
|
|
7176
|
-
end: endPosition,
|
|
7177
|
-
start: startPosition
|
|
7178
|
-
});
|
|
7179
|
-
const textChange = {
|
|
7180
|
-
deleted,
|
|
7181
|
-
end: endPosition,
|
|
7182
|
-
inserted: [edit.inserted],
|
|
7183
|
-
origin: Rename,
|
|
7184
|
-
start: startPosition
|
|
7185
|
-
};
|
|
7186
|
-
textChanges.push(textChange);
|
|
7187
|
-
}
|
|
7188
|
-
return textChanges;
|
|
7189
|
-
};
|
|
7190
|
-
const groupEditsByUri = changes => {
|
|
7191
|
-
const editsByUri = new Map();
|
|
7192
|
-
for (const change of changes) {
|
|
7193
|
-
const edits = editsByUri.get(change.uri);
|
|
7194
|
-
if (edits) {
|
|
7195
|
-
edits.push(...change.edits);
|
|
7196
|
-
} else {
|
|
7197
|
-
editsByUri.set(change.uri, [...change.edits]);
|
|
7198
|
-
}
|
|
7199
|
-
}
|
|
7200
|
-
return editsByUri;
|
|
7201
|
-
};
|
|
7202
|
-
const getOpenEditor = (currentEditor, uri) => {
|
|
7203
|
-
if (currentEditor.uri === uri) {
|
|
7204
|
-
return currentEditor;
|
|
7205
|
-
}
|
|
7206
|
-
for (const key of getKeys$2()) {
|
|
7207
|
-
const editor = get$8(Number(key))?.newState;
|
|
7208
|
-
if (editor && !editor.initial && editor.uri === uri && editor.applicationId === currentEditor.applicationId) {
|
|
7209
|
-
return editor;
|
|
7210
|
-
}
|
|
7211
|
-
}
|
|
7212
|
-
return undefined;
|
|
7213
|
-
};
|
|
7214
|
-
const applyWorkspaceEdit = async (editor, changes) => {
|
|
7215
|
-
object(editor);
|
|
7216
|
-
array(changes);
|
|
7217
|
-
let currentEditor = editor;
|
|
7218
|
-
const editsByUri = groupEditsByUri(changes);
|
|
7219
|
-
for (const [uri, edits] of editsByUri) {
|
|
7220
|
-
const openEditor = getOpenEditor(currentEditor, uri);
|
|
7221
|
-
if (openEditor) {
|
|
7222
|
-
const textChanges = getTextChanges(openEditor, edits);
|
|
7223
|
-
const updatedEditor = await scheduleDocumentAndCursorsSelections(openEditor, textChanges);
|
|
7224
|
-
if (openEditor.uid === currentEditor.uid) {
|
|
7225
|
-
currentEditor = updatedEditor;
|
|
7226
|
-
}
|
|
7227
|
-
continue;
|
|
7228
|
-
}
|
|
7229
|
-
const text = await readFile(editor.applicationId, uri);
|
|
7230
|
-
const newText = applyEditsToText(text, edits);
|
|
7231
|
-
await invoke$9(editor.applicationId, 'FileSystem.writeFile', uri, newText);
|
|
7232
|
-
}
|
|
7233
|
-
return currentEditor;
|
|
7234
|
-
};
|
|
7235
|
-
|
|
7236
|
-
const isPersistentWidget = widgetId => {
|
|
7237
|
-
switch (widgetId) {
|
|
7238
|
-
case Find:
|
|
7239
|
-
return true;
|
|
7240
|
-
default:
|
|
7241
|
-
return false;
|
|
7242
|
-
}
|
|
7243
|
-
};
|
|
7244
|
-
|
|
7245
|
-
// TODO widgets should have a persistence property:
|
|
7246
|
-
// 1 = close by click (e.g. completion, hover, source-actions)
|
|
7247
|
-
// 2 = stay open on click (e.g. find)
|
|
7248
|
-
const closeWidgetsMaybe = widgets => {
|
|
7249
|
-
if (widgets.length === 0) {
|
|
7250
|
-
return widgets;
|
|
7251
|
-
}
|
|
7252
|
-
return widgets.filter(widget => isPersistentWidget(widget.id));
|
|
7253
|
-
};
|
|
7254
|
-
|
|
7255
|
-
const hasWidget = (widgets, id) => {
|
|
7256
|
-
for (const widget of widgets) {
|
|
7257
|
-
if (widget.id === id) {
|
|
7258
|
-
return true;
|
|
7259
|
-
}
|
|
7260
|
-
}
|
|
7261
|
-
return false;
|
|
7262
|
-
};
|
|
7263
|
-
|
|
7264
7158
|
const getFormattingEdits = async editor => {
|
|
7265
7159
|
if (editor.largeFile) {
|
|
7266
7160
|
return [];
|
|
@@ -7644,83 +7538,354 @@ const saveUntitledFile = async (uri, content, platform, applicationId) => {
|
|
|
7644
7538
|
if (!filePath) {
|
|
7645
7539
|
return;
|
|
7646
7540
|
}
|
|
7647
|
-
await invoke$9(applicationId, 'FileSystem.writeFile', filePath, content);
|
|
7648
|
-
await invoke$9(applicationId, 'Layout.handleWorkspaceRefresh');
|
|
7649
|
-
return filePath;
|
|
7541
|
+
await invoke$9(applicationId, 'FileSystem.writeFile', filePath, content);
|
|
7542
|
+
await invoke$9(applicationId, 'Layout.handleWorkspaceRefresh');
|
|
7543
|
+
return filePath;
|
|
7544
|
+
};
|
|
7545
|
+
|
|
7546
|
+
const isPermissionDeniedError = error => {
|
|
7547
|
+
const errorCode = 'code' in error ? error.code : undefined;
|
|
7548
|
+
return errorCode === 'EACCES' || error.message.includes('EACCES:');
|
|
7549
|
+
};
|
|
7550
|
+
const showSaveErrorDialog = async error => {
|
|
7551
|
+
if (isPermissionDeniedError(error)) {
|
|
7552
|
+
await invoke$j('ElectronDialog.showMessageBox', {
|
|
7553
|
+
buttons: ['OK'],
|
|
7554
|
+
defaultId: 0,
|
|
7555
|
+
message: "You don't have permission to save changes to this file.",
|
|
7556
|
+
title: 'Unable to Save File',
|
|
7557
|
+
type: 'error'
|
|
7558
|
+
});
|
|
7559
|
+
return;
|
|
7560
|
+
}
|
|
7561
|
+
await invoke$j('ElectronDialog.showMessageBox', {
|
|
7562
|
+
buttons: ['OK'],
|
|
7563
|
+
defaultId: 0,
|
|
7564
|
+
detail: error.message,
|
|
7565
|
+
message: 'Saving the file failed.',
|
|
7566
|
+
title: 'Failed to Save File',
|
|
7567
|
+
type: 'error'
|
|
7568
|
+
});
|
|
7569
|
+
};
|
|
7570
|
+
|
|
7571
|
+
const save$1 = async (editor, skipFormatting = false) => {
|
|
7572
|
+
try {
|
|
7573
|
+
const {
|
|
7574
|
+
applicationId,
|
|
7575
|
+
platform,
|
|
7576
|
+
uri
|
|
7577
|
+
} = editor;
|
|
7578
|
+
if (!isUntitledFile(uri) && (await isReadonlyFile(uri, applicationId))) {
|
|
7579
|
+
return editor;
|
|
7580
|
+
}
|
|
7581
|
+
const newEditor = await getNewEditor(editor, skipFormatting);
|
|
7582
|
+
const content = applyLineEndings(getText$1(newEditor), newEditor.endOfLine);
|
|
7583
|
+
if (isUntitledFile(uri)) {
|
|
7584
|
+
const pickedFilePath = await saveUntitledFile(uri, content, platform, applicationId);
|
|
7585
|
+
if (pickedFilePath) {
|
|
7586
|
+
if (newEditor.modified) {
|
|
7587
|
+
await notifyTabModifiedStatusChange(uri, false, applicationId);
|
|
7588
|
+
}
|
|
7589
|
+
return {
|
|
7590
|
+
...newEditor,
|
|
7591
|
+
modified: false,
|
|
7592
|
+
uri: pickedFilePath
|
|
7593
|
+
};
|
|
7594
|
+
}
|
|
7595
|
+
return newEditor;
|
|
7596
|
+
}
|
|
7597
|
+
await saveNormalFile(uri, content, applicationId);
|
|
7598
|
+
if (newEditor.modified) {
|
|
7599
|
+
await notifyTabModifiedStatusChange(uri, false, applicationId);
|
|
7600
|
+
}
|
|
7601
|
+
return {
|
|
7602
|
+
...newEditor,
|
|
7603
|
+
modified: false
|
|
7604
|
+
};
|
|
7605
|
+
} catch (error) {
|
|
7606
|
+
// @ts-ignore
|
|
7607
|
+
const betterError = new VError(error, `Failed to save file "${editor.uri}"`);
|
|
7608
|
+
await handleError$1(betterError);
|
|
7609
|
+
if (editor.platform === Electron) {
|
|
7610
|
+
try {
|
|
7611
|
+
await showSaveErrorDialog(betterError);
|
|
7612
|
+
} catch (dialogError) {
|
|
7613
|
+
await handleError$1(dialogError);
|
|
7614
|
+
}
|
|
7615
|
+
}
|
|
7616
|
+
return editor;
|
|
7617
|
+
}
|
|
7618
|
+
};
|
|
7619
|
+
|
|
7620
|
+
const editorDiagnosticEffect = {
|
|
7621
|
+
// TODO set effects delay / diagnostic delay
|
|
7622
|
+
apply(editor) {
|
|
7623
|
+
return updateDiagnostics(editor);
|
|
7624
|
+
},
|
|
7625
|
+
isActive: (oldEditor, newEditor) => !oldEditor.initial && !newEditor.loadError && newEditor.diagnosticsEnabled && (oldEditor.lines !== newEditor.lines || oldEditor.languageId !== newEditor.languageId)
|
|
7626
|
+
};
|
|
7627
|
+
|
|
7628
|
+
const cursorUndoLimit = 100;
|
|
7629
|
+
const selectionsEqual = (left, right) => {
|
|
7630
|
+
if (left === right) {
|
|
7631
|
+
return true;
|
|
7632
|
+
}
|
|
7633
|
+
if (left.length !== right.length) {
|
|
7634
|
+
return false;
|
|
7635
|
+
}
|
|
7636
|
+
for (let i = 0; i < left.length; i++) {
|
|
7637
|
+
if (left[i] !== right[i]) {
|
|
7638
|
+
return false;
|
|
7639
|
+
}
|
|
7640
|
+
}
|
|
7641
|
+
return true;
|
|
7642
|
+
};
|
|
7643
|
+
const saveAfterDelay = async (uid, token) => {
|
|
7644
|
+
if (!get$8(uid)) {
|
|
7645
|
+
consume(uid, token);
|
|
7646
|
+
return;
|
|
7647
|
+
}
|
|
7648
|
+
let didSave = false;
|
|
7649
|
+
const save = wrapCommand$1(async editor => {
|
|
7650
|
+
if (!isLatest(uid, token)) {
|
|
7651
|
+
return editor;
|
|
7652
|
+
}
|
|
7653
|
+
consume(uid, token);
|
|
7654
|
+
const autoSave = await get$3('files.autoSave');
|
|
7655
|
+
if (autoSave !== 'afterDelay') {
|
|
7656
|
+
return editor;
|
|
7657
|
+
}
|
|
7658
|
+
const savedEditor = await save$1(editor);
|
|
7659
|
+
didSave = savedEditor !== editor;
|
|
7660
|
+
return savedEditor;
|
|
7661
|
+
});
|
|
7662
|
+
await save(uid);
|
|
7663
|
+
if (didSave) {
|
|
7664
|
+
await invoke$d('Editor.renderPending', uid);
|
|
7665
|
+
}
|
|
7666
|
+
};
|
|
7667
|
+
|
|
7668
|
+
// TODO wrap commands globally, not per editor
|
|
7669
|
+
// TODO only store editor state in editor worker, not in renderer worker also
|
|
7670
|
+
|
|
7671
|
+
const wrapCommand$1 = (fn, preservesTypingCoalescing = false, returnState = true) => async (uid, ...args) => {
|
|
7672
|
+
return enqueue(uid, async () => {
|
|
7673
|
+
const oldInstance = get$8(uid);
|
|
7674
|
+
if (!oldInstance) {
|
|
7675
|
+
return undefined;
|
|
7676
|
+
}
|
|
7677
|
+
const state = oldInstance.newState;
|
|
7678
|
+
const {
|
|
7679
|
+
cursorUndoStack,
|
|
7680
|
+
endOfLine,
|
|
7681
|
+
initial,
|
|
7682
|
+
insertSpaces,
|
|
7683
|
+
isSelecting,
|
|
7684
|
+
lines,
|
|
7685
|
+
modified,
|
|
7686
|
+
redoStack,
|
|
7687
|
+
selections,
|
|
7688
|
+
undoStack,
|
|
7689
|
+
uri
|
|
7690
|
+
} = state;
|
|
7691
|
+
const commandResult = await fn(state, ...args);
|
|
7692
|
+
let newEditor = !preservesTypingCoalescing && commandResult.canCoalesceTyping ? {
|
|
7693
|
+
...commandResult,
|
|
7694
|
+
canCoalesceTyping: false
|
|
7695
|
+
} : commandResult;
|
|
7696
|
+
if (lines !== newEditor.lines && newEditor.cursorUndoStack?.length) {
|
|
7697
|
+
newEditor = {
|
|
7698
|
+
...newEditor,
|
|
7699
|
+
cursorUndoStack: []
|
|
7700
|
+
};
|
|
7701
|
+
} else if (selections && newEditor.selections && !isSelecting && newEditor.cursorUndoStack === cursorUndoStack && (!selectionsEqual(selections, newEditor.selections) || newEditor.isSelecting)) {
|
|
7702
|
+
const previousCursorUndoStack = cursorUndoStack || [];
|
|
7703
|
+
newEditor = {
|
|
7704
|
+
...newEditor,
|
|
7705
|
+
cursorUndoStack: [...previousCursorUndoStack.slice(1 - cursorUndoLimit), new Uint32Array(selections)]
|
|
7706
|
+
};
|
|
7707
|
+
}
|
|
7708
|
+
if (state === newEditor) {
|
|
7709
|
+
return returnState ? newEditor : undefined;
|
|
7710
|
+
}
|
|
7711
|
+
const newEditorWithDerivedState = await updateDerivedState(state, newEditor);
|
|
7712
|
+
set$a(uid, state, newEditorWithDerivedState);
|
|
7713
|
+
await dispose$3();
|
|
7714
|
+
if (editorDiagnosticEffect.isActive(state, newEditorWithDerivedState)) {
|
|
7715
|
+
void editorDiagnosticEffect.apply(newEditorWithDerivedState);
|
|
7716
|
+
}
|
|
7717
|
+
const finalEditor = newEditorWithDerivedState;
|
|
7718
|
+
await notifyEditorStatusChange(state, finalEditor);
|
|
7719
|
+
if (!initial && uri === finalEditor.uri && (endOfLine !== finalEditor.endOfLine || insertSpaces !== finalEditor.insertSpaces || lines !== finalEditor.lines || modified !== finalEditor.modified || redoStack !== finalEditor.redoStack || undoStack !== finalEditor.undoStack)) {
|
|
7720
|
+
for (const key of getKeys$2()) {
|
|
7721
|
+
const otherUid = Number(key);
|
|
7722
|
+
const instance = get$8(otherUid);
|
|
7723
|
+
const editor = instance?.newState;
|
|
7724
|
+
if (otherUid === uid || !instance || !editor || editor.initial || editor.uri !== finalEditor.uri || editor.applicationId !== finalEditor.applicationId) {
|
|
7725
|
+
continue;
|
|
7726
|
+
}
|
|
7727
|
+
const synchronizedEditor = await updateDerivedState(editor, {
|
|
7728
|
+
...editor,
|
|
7729
|
+
decorations: finalEditor.decorations,
|
|
7730
|
+
diagnostics: finalEditor.diagnostics,
|
|
7731
|
+
endOfLine: finalEditor.endOfLine,
|
|
7732
|
+
incrementalEdits: emptyIncrementalEdits,
|
|
7733
|
+
insertSpaces: finalEditor.insertSpaces,
|
|
7734
|
+
invalidStartIndex: Math.min(editor.invalidStartIndex, finalEditor.invalidStartIndex),
|
|
7735
|
+
lines: finalEditor.lines,
|
|
7736
|
+
modified: finalEditor.modified,
|
|
7737
|
+
redoStack: finalEditor.redoStack,
|
|
7738
|
+
undoStack: finalEditor.undoStack,
|
|
7739
|
+
visualDecorations: finalEditor.visualDecorations
|
|
7740
|
+
});
|
|
7741
|
+
set$a(otherUid, instance.oldState, synchronizedEditor);
|
|
7742
|
+
if (editorDiagnosticEffect.isActive(editor, synchronizedEditor)) {
|
|
7743
|
+
void editorDiagnosticEffect.apply(synchronizedEditor);
|
|
7744
|
+
}
|
|
7745
|
+
}
|
|
7746
|
+
}
|
|
7747
|
+
if (lines !== finalEditor.lines && !isUntitledFile(finalEditor.uri)) {
|
|
7748
|
+
schedule(uid, token => saveAfterDelay(uid, token));
|
|
7749
|
+
} else if (modified && !finalEditor.modified) {
|
|
7750
|
+
dispose$4(uid);
|
|
7751
|
+
}
|
|
7752
|
+
return returnState ? finalEditor : undefined;
|
|
7753
|
+
});
|
|
7754
|
+
};
|
|
7755
|
+
const wrapFocusCommand$1 = (fn, returnState = true) => {
|
|
7756
|
+
const command = wrapCommand$1((editor, widgetRevision) => {
|
|
7757
|
+
if (editor.widgetRevision !== widgetRevision && editor.focus !== FocusEditorText$1) {
|
|
7758
|
+
return editor;
|
|
7759
|
+
}
|
|
7760
|
+
return fn(editor);
|
|
7761
|
+
}, false, returnState);
|
|
7762
|
+
return uid => {
|
|
7763
|
+
// DOM focus events can arrive while a queued command is still opening a widget.
|
|
7764
|
+
const widgetRevision = get$8(uid)?.newState.widgetRevision;
|
|
7765
|
+
return command(uid, widgetRevision);
|
|
7766
|
+
};
|
|
7767
|
+
};
|
|
7768
|
+
|
|
7769
|
+
// Optional provider work must not hold the editing queue while another worker responds.
|
|
7770
|
+
const wrapDeferredCommand$1 = (fn, returnState = true) => {
|
|
7771
|
+
const apply = wrapCommand$1((editor, snapshot, result) => editor === snapshot ? result : editor, false, returnState);
|
|
7772
|
+
return async (uid, ...args) => {
|
|
7773
|
+
const snapshot = await enqueue(uid, async () => get$8(uid)?.newState);
|
|
7774
|
+
if (!snapshot) {
|
|
7775
|
+
return undefined;
|
|
7776
|
+
}
|
|
7777
|
+
const result = await fn(snapshot, ...args);
|
|
7778
|
+
return apply(uid, snapshot, result);
|
|
7779
|
+
};
|
|
7780
|
+
};
|
|
7781
|
+
|
|
7782
|
+
// TODO maybe use a separate worker for bulk edits and bulk edit history
|
|
7783
|
+
|
|
7784
|
+
const sortEditsDescending = edits => {
|
|
7785
|
+
return edits.toSorted((a, b) => b.offset - a.offset);
|
|
7786
|
+
};
|
|
7787
|
+
const applyEditsToText = (text, edits) => {
|
|
7788
|
+
let newText = text;
|
|
7789
|
+
for (const edit of sortEditsDescending(edits)) {
|
|
7790
|
+
newText = newText.slice(0, edit.offset) + edit.inserted + newText.slice(edit.offset + edit.deleted);
|
|
7791
|
+
}
|
|
7792
|
+
return newText;
|
|
7793
|
+
};
|
|
7794
|
+
const getTextChanges = (editor, edits) => {
|
|
7795
|
+
const textChanges = [];
|
|
7796
|
+
for (const edit of sortEditsDescending(edits)) {
|
|
7797
|
+
const startPosition = positionAt(editor, edit.offset);
|
|
7798
|
+
const endPosition = positionAt(editor, edit.offset + edit.deleted);
|
|
7799
|
+
const deleted = getSelectionText(editor, {
|
|
7800
|
+
end: endPosition,
|
|
7801
|
+
start: startPosition
|
|
7802
|
+
});
|
|
7803
|
+
const textChange = {
|
|
7804
|
+
deleted,
|
|
7805
|
+
end: endPosition,
|
|
7806
|
+
inserted: [edit.inserted],
|
|
7807
|
+
origin: Rename,
|
|
7808
|
+
start: startPosition
|
|
7809
|
+
};
|
|
7810
|
+
textChanges.push(textChange);
|
|
7811
|
+
}
|
|
7812
|
+
return textChanges;
|
|
7813
|
+
};
|
|
7814
|
+
const groupEditsByUri = changes => {
|
|
7815
|
+
const editsByUri = new Map();
|
|
7816
|
+
for (const change of changes) {
|
|
7817
|
+
const edits = editsByUri.get(change.uri);
|
|
7818
|
+
if (edits) {
|
|
7819
|
+
edits.push(...change.edits);
|
|
7820
|
+
} else {
|
|
7821
|
+
editsByUri.set(change.uri, [...change.edits]);
|
|
7822
|
+
}
|
|
7823
|
+
}
|
|
7824
|
+
return editsByUri;
|
|
7825
|
+
};
|
|
7826
|
+
const getOpenEditor = (currentEditor, uri) => {
|
|
7827
|
+
if (currentEditor.uri === uri) {
|
|
7828
|
+
return currentEditor;
|
|
7829
|
+
}
|
|
7830
|
+
for (const key of getKeys$2()) {
|
|
7831
|
+
const editor = get$8(Number(key))?.newState;
|
|
7832
|
+
if (editor && !editor.initial && editor.uri === uri && editor.applicationId === currentEditor.applicationId) {
|
|
7833
|
+
return editor;
|
|
7834
|
+
}
|
|
7835
|
+
}
|
|
7836
|
+
return undefined;
|
|
7837
|
+
};
|
|
7838
|
+
const updateOpenEditor = wrapCommand$1(scheduleDocumentAndCursorsSelections);
|
|
7839
|
+
const applyWorkspaceEdit = async (editor, changes) => {
|
|
7840
|
+
object(editor);
|
|
7841
|
+
array(changes);
|
|
7842
|
+
let currentEditor = editor;
|
|
7843
|
+
const editsByUri = groupEditsByUri(changes);
|
|
7844
|
+
for (const [uri, edits] of editsByUri) {
|
|
7845
|
+
const openEditor = getOpenEditor(currentEditor, uri);
|
|
7846
|
+
if (openEditor) {
|
|
7847
|
+
const textChanges = getTextChanges(openEditor, edits);
|
|
7848
|
+
if (openEditor.uid === currentEditor.uid) {
|
|
7849
|
+
currentEditor = await scheduleDocumentAndCursorsSelections(openEditor, textChanges);
|
|
7850
|
+
} else {
|
|
7851
|
+
await updateOpenEditor(openEditor.uid, textChanges);
|
|
7852
|
+
await invoke$5('Editor.renderPending', openEditor.uid);
|
|
7853
|
+
}
|
|
7854
|
+
continue;
|
|
7855
|
+
}
|
|
7856
|
+
const text = await readFile(editor.applicationId, uri);
|
|
7857
|
+
const newText = applyEditsToText(text, edits);
|
|
7858
|
+
await invoke$9(editor.applicationId, 'FileSystem.writeFile', uri, newText);
|
|
7859
|
+
}
|
|
7860
|
+
return currentEditor;
|
|
7650
7861
|
};
|
|
7651
7862
|
|
|
7652
|
-
const
|
|
7653
|
-
|
|
7654
|
-
|
|
7863
|
+
const isPersistentWidget = widgetId => {
|
|
7864
|
+
switch (widgetId) {
|
|
7865
|
+
case Find:
|
|
7866
|
+
return true;
|
|
7867
|
+
default:
|
|
7868
|
+
return false;
|
|
7869
|
+
}
|
|
7655
7870
|
};
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
type: 'error'
|
|
7664
|
-
});
|
|
7665
|
-
return;
|
|
7871
|
+
|
|
7872
|
+
// TODO widgets should have a persistence property:
|
|
7873
|
+
// 1 = close by click (e.g. completion, hover, source-actions)
|
|
7874
|
+
// 2 = stay open on click (e.g. find)
|
|
7875
|
+
const closeWidgetsMaybe = widgets => {
|
|
7876
|
+
if (widgets.length === 0) {
|
|
7877
|
+
return widgets;
|
|
7666
7878
|
}
|
|
7667
|
-
|
|
7668
|
-
buttons: ['OK'],
|
|
7669
|
-
defaultId: 0,
|
|
7670
|
-
detail: error.message,
|
|
7671
|
-
message: 'Saving the file failed.',
|
|
7672
|
-
title: 'Failed to Save File',
|
|
7673
|
-
type: 'error'
|
|
7674
|
-
});
|
|
7879
|
+
return widgets.filter(widget => isPersistentWidget(widget.id));
|
|
7675
7880
|
};
|
|
7676
7881
|
|
|
7677
|
-
const
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
platform,
|
|
7682
|
-
uri
|
|
7683
|
-
} = editor;
|
|
7684
|
-
if (!isUntitledFile(uri) && (await isReadonlyFile(uri, applicationId))) {
|
|
7685
|
-
return editor;
|
|
7686
|
-
}
|
|
7687
|
-
const newEditor = await getNewEditor(editor, skipFormatting);
|
|
7688
|
-
const content = applyLineEndings(getText$1(newEditor), newEditor.endOfLine);
|
|
7689
|
-
if (isUntitledFile(uri)) {
|
|
7690
|
-
const pickedFilePath = await saveUntitledFile(uri, content, platform, applicationId);
|
|
7691
|
-
if (pickedFilePath) {
|
|
7692
|
-
if (newEditor.modified) {
|
|
7693
|
-
await notifyTabModifiedStatusChange(uri, false, applicationId);
|
|
7694
|
-
}
|
|
7695
|
-
return {
|
|
7696
|
-
...newEditor,
|
|
7697
|
-
modified: false,
|
|
7698
|
-
uri: pickedFilePath
|
|
7699
|
-
};
|
|
7700
|
-
}
|
|
7701
|
-
return newEditor;
|
|
7702
|
-
}
|
|
7703
|
-
await saveNormalFile(uri, content, applicationId);
|
|
7704
|
-
if (newEditor.modified) {
|
|
7705
|
-
await notifyTabModifiedStatusChange(uri, false, applicationId);
|
|
7706
|
-
}
|
|
7707
|
-
return {
|
|
7708
|
-
...newEditor,
|
|
7709
|
-
modified: false
|
|
7710
|
-
};
|
|
7711
|
-
} catch (error) {
|
|
7712
|
-
// @ts-ignore
|
|
7713
|
-
const betterError = new VError(error, `Failed to save file "${editor.uri}"`);
|
|
7714
|
-
await handleError$1(betterError);
|
|
7715
|
-
if (editor.platform === Electron) {
|
|
7716
|
-
try {
|
|
7717
|
-
await showSaveErrorDialog(betterError);
|
|
7718
|
-
} catch (dialogError) {
|
|
7719
|
-
await handleError$1(dialogError);
|
|
7720
|
-
}
|
|
7882
|
+
const hasWidget = (widgets, id) => {
|
|
7883
|
+
for (const widget of widgets) {
|
|
7884
|
+
if (widget.id === id) {
|
|
7885
|
+
return true;
|
|
7721
7886
|
}
|
|
7722
|
-
return editor;
|
|
7723
7887
|
}
|
|
7888
|
+
return false;
|
|
7724
7889
|
};
|
|
7725
7890
|
|
|
7726
7891
|
const handleBlur$1 = async editor => {
|
|
@@ -9503,6 +9668,7 @@ const EditorCloseColorPicker = 'Editor: Close Color Picker';
|
|
|
9503
9668
|
const EditorCopyLineDown = 'Editor: Copy Line Down';
|
|
9504
9669
|
const EditorCopyLineUp = 'Editor: Copy Line Up';
|
|
9505
9670
|
const EditorDecrementSelection = 'Editor: Decrement Selection';
|
|
9671
|
+
const EditorExpandSelection = 'Editor: Expand Selection';
|
|
9506
9672
|
const EditorFormatDocumentForced = 'Editor: Format Document (forced)';
|
|
9507
9673
|
const EditorGoToDefinition = 'Editor: Go To Definition';
|
|
9508
9674
|
const EditorGoToTypeDefinition = 'Editor: Go To Type Definition';
|
|
@@ -9512,6 +9678,7 @@ const EditorIncrementSelection = 'Editor: Increment Selection';
|
|
|
9512
9678
|
const EditorOpenColorPicker = 'Editor: Open Color Picker';
|
|
9513
9679
|
const EditorSelectAllOccurrences = 'Editor: Select All Occurrences';
|
|
9514
9680
|
const EditorSelectDown = 'Editor: Select Down';
|
|
9681
|
+
const EditorShrinkSelection = 'Editor: Shrink Selection';
|
|
9515
9682
|
const EditorSelectInsideString = 'Editor: Select Inside String';
|
|
9516
9683
|
const EditorSelectNextOccurrence = 'Editor: Select Next Occurrence';
|
|
9517
9684
|
const EditorSelectUp = 'Editor: Select Up';
|
|
@@ -9675,6 +9842,12 @@ const editorToggleComment = () => {
|
|
|
9675
9842
|
const editorDecrementSelection = () => {
|
|
9676
9843
|
return i18nString(EditorDecrementSelection);
|
|
9677
9844
|
};
|
|
9845
|
+
const editorExpandSelection = () => {
|
|
9846
|
+
return i18nString(EditorExpandSelection);
|
|
9847
|
+
};
|
|
9848
|
+
const editorShrinkSelection = () => {
|
|
9849
|
+
return i18nString(EditorShrinkSelection);
|
|
9850
|
+
};
|
|
9678
9851
|
const editorSelectUp = () => {
|
|
9679
9852
|
return i18nString(EditorSelectUp);
|
|
9680
9853
|
};
|
|
@@ -15557,6 +15730,12 @@ const getQuickPickMenuEntries = () => {
|
|
|
15557
15730
|
}, {
|
|
15558
15731
|
id: 'Editor.cursorUndo',
|
|
15559
15732
|
label: cursorUndo()
|
|
15733
|
+
}, {
|
|
15734
|
+
id: 'Editor.expandSelection',
|
|
15735
|
+
label: editorExpandSelection()
|
|
15736
|
+
}, {
|
|
15737
|
+
id: 'Editor.shrinkSelection',
|
|
15738
|
+
label: editorShrinkSelection()
|
|
15560
15739
|
}, {
|
|
15561
15740
|
id: 'Editor.fold',
|
|
15562
15741
|
label: fold()
|
|
@@ -18046,168 +18225,6 @@ const revealProblem = (editor, rowIndex, columnIndex) => {
|
|
|
18046
18225
|
};
|
|
18047
18226
|
};
|
|
18048
18227
|
|
|
18049
|
-
const editorDiagnosticEffect = {
|
|
18050
|
-
// TODO set effects delay / diagnostic delay
|
|
18051
|
-
apply(editor) {
|
|
18052
|
-
return updateDiagnostics(editor);
|
|
18053
|
-
},
|
|
18054
|
-
isActive: (oldEditor, newEditor) => !oldEditor.initial && !newEditor.loadError && newEditor.diagnosticsEnabled && (oldEditor.lines !== newEditor.lines || oldEditor.languageId !== newEditor.languageId)
|
|
18055
|
-
};
|
|
18056
|
-
|
|
18057
|
-
const cursorUndoLimit = 100;
|
|
18058
|
-
const selectionsEqual = (left, right) => {
|
|
18059
|
-
if (left === right) {
|
|
18060
|
-
return true;
|
|
18061
|
-
}
|
|
18062
|
-
if (left.length !== right.length) {
|
|
18063
|
-
return false;
|
|
18064
|
-
}
|
|
18065
|
-
for (let i = 0; i < left.length; i++) {
|
|
18066
|
-
if (left[i] !== right[i]) {
|
|
18067
|
-
return false;
|
|
18068
|
-
}
|
|
18069
|
-
}
|
|
18070
|
-
return true;
|
|
18071
|
-
};
|
|
18072
|
-
const saveAfterDelay = async (uid, token) => {
|
|
18073
|
-
if (!get$8(uid)) {
|
|
18074
|
-
consume(uid, token);
|
|
18075
|
-
return;
|
|
18076
|
-
}
|
|
18077
|
-
let didSave = false;
|
|
18078
|
-
const save = wrapCommand$1(async editor => {
|
|
18079
|
-
if (!isLatest(uid, token)) {
|
|
18080
|
-
return editor;
|
|
18081
|
-
}
|
|
18082
|
-
consume(uid, token);
|
|
18083
|
-
const autoSave = await get$3('files.autoSave');
|
|
18084
|
-
if (autoSave !== 'afterDelay') {
|
|
18085
|
-
return editor;
|
|
18086
|
-
}
|
|
18087
|
-
const savedEditor = await save$1(editor);
|
|
18088
|
-
didSave = savedEditor !== editor;
|
|
18089
|
-
return savedEditor;
|
|
18090
|
-
});
|
|
18091
|
-
await save(uid);
|
|
18092
|
-
if (didSave) {
|
|
18093
|
-
await invoke$d('Editor.renderPending', uid);
|
|
18094
|
-
}
|
|
18095
|
-
};
|
|
18096
|
-
|
|
18097
|
-
// TODO wrap commands globally, not per editor
|
|
18098
|
-
// TODO only store editor state in editor worker, not in renderer worker also
|
|
18099
|
-
|
|
18100
|
-
const wrapCommand$1 = (fn, preservesTypingCoalescing = false, returnState = true) => async (uid, ...args) => {
|
|
18101
|
-
return enqueue(uid, async () => {
|
|
18102
|
-
const oldInstance = get$8(uid);
|
|
18103
|
-
if (!oldInstance) {
|
|
18104
|
-
return undefined;
|
|
18105
|
-
}
|
|
18106
|
-
const state = oldInstance.newState;
|
|
18107
|
-
const {
|
|
18108
|
-
cursorUndoStack,
|
|
18109
|
-
endOfLine,
|
|
18110
|
-
initial,
|
|
18111
|
-
insertSpaces,
|
|
18112
|
-
isSelecting,
|
|
18113
|
-
lines,
|
|
18114
|
-
modified,
|
|
18115
|
-
redoStack,
|
|
18116
|
-
selections,
|
|
18117
|
-
undoStack,
|
|
18118
|
-
uri
|
|
18119
|
-
} = state;
|
|
18120
|
-
const commandResult = await fn(state, ...args);
|
|
18121
|
-
let newEditor = !preservesTypingCoalescing && commandResult.canCoalesceTyping ? {
|
|
18122
|
-
...commandResult,
|
|
18123
|
-
canCoalesceTyping: false
|
|
18124
|
-
} : commandResult;
|
|
18125
|
-
if (lines !== newEditor.lines && newEditor.cursorUndoStack?.length) {
|
|
18126
|
-
newEditor = {
|
|
18127
|
-
...newEditor,
|
|
18128
|
-
cursorUndoStack: []
|
|
18129
|
-
};
|
|
18130
|
-
} else if (selections && newEditor.selections && !isSelecting && newEditor.cursorUndoStack === cursorUndoStack && (!selectionsEqual(selections, newEditor.selections) || newEditor.isSelecting)) {
|
|
18131
|
-
const previousCursorUndoStack = cursorUndoStack || [];
|
|
18132
|
-
newEditor = {
|
|
18133
|
-
...newEditor,
|
|
18134
|
-
cursorUndoStack: [...previousCursorUndoStack.slice(1 - cursorUndoLimit), new Uint32Array(selections)]
|
|
18135
|
-
};
|
|
18136
|
-
}
|
|
18137
|
-
if (state === newEditor) {
|
|
18138
|
-
return returnState ? newEditor : undefined;
|
|
18139
|
-
}
|
|
18140
|
-
const newEditorWithDerivedState = await updateDerivedState(state, newEditor);
|
|
18141
|
-
set$a(uid, state, newEditorWithDerivedState);
|
|
18142
|
-
await dispose$3();
|
|
18143
|
-
if (editorDiagnosticEffect.isActive(state, newEditorWithDerivedState)) {
|
|
18144
|
-
void editorDiagnosticEffect.apply(newEditorWithDerivedState);
|
|
18145
|
-
}
|
|
18146
|
-
const finalEditor = newEditorWithDerivedState;
|
|
18147
|
-
await notifyEditorStatusChange(state, finalEditor);
|
|
18148
|
-
if (!initial && uri === finalEditor.uri && (endOfLine !== finalEditor.endOfLine || insertSpaces !== finalEditor.insertSpaces || lines !== finalEditor.lines || modified !== finalEditor.modified || redoStack !== finalEditor.redoStack || undoStack !== finalEditor.undoStack)) {
|
|
18149
|
-
for (const key of getKeys$2()) {
|
|
18150
|
-
const otherUid = Number(key);
|
|
18151
|
-
const instance = get$8(otherUid);
|
|
18152
|
-
const editor = instance?.newState;
|
|
18153
|
-
if (otherUid === uid || !instance || !editor || editor.initial || editor.uri !== finalEditor.uri || editor.applicationId !== finalEditor.applicationId) {
|
|
18154
|
-
continue;
|
|
18155
|
-
}
|
|
18156
|
-
const synchronizedEditor = await updateDerivedState(editor, {
|
|
18157
|
-
...editor,
|
|
18158
|
-
decorations: finalEditor.decorations,
|
|
18159
|
-
diagnostics: finalEditor.diagnostics,
|
|
18160
|
-
endOfLine: finalEditor.endOfLine,
|
|
18161
|
-
incrementalEdits: emptyIncrementalEdits,
|
|
18162
|
-
insertSpaces: finalEditor.insertSpaces,
|
|
18163
|
-
invalidStartIndex: Math.min(editor.invalidStartIndex, finalEditor.invalidStartIndex),
|
|
18164
|
-
lines: finalEditor.lines,
|
|
18165
|
-
modified: finalEditor.modified,
|
|
18166
|
-
redoStack: finalEditor.redoStack,
|
|
18167
|
-
undoStack: finalEditor.undoStack,
|
|
18168
|
-
visualDecorations: finalEditor.visualDecorations
|
|
18169
|
-
});
|
|
18170
|
-
set$a(otherUid, instance.oldState, synchronizedEditor);
|
|
18171
|
-
if (editorDiagnosticEffect.isActive(editor, synchronizedEditor)) {
|
|
18172
|
-
void editorDiagnosticEffect.apply(synchronizedEditor);
|
|
18173
|
-
}
|
|
18174
|
-
}
|
|
18175
|
-
}
|
|
18176
|
-
if (lines !== finalEditor.lines && !isUntitledFile(finalEditor.uri)) {
|
|
18177
|
-
schedule(uid, token => saveAfterDelay(uid, token));
|
|
18178
|
-
} else if (modified && !finalEditor.modified) {
|
|
18179
|
-
dispose$4(uid);
|
|
18180
|
-
}
|
|
18181
|
-
return returnState ? finalEditor : undefined;
|
|
18182
|
-
});
|
|
18183
|
-
};
|
|
18184
|
-
const wrapFocusCommand$1 = (fn, returnState = true) => {
|
|
18185
|
-
const command = wrapCommand$1((editor, widgetRevision) => {
|
|
18186
|
-
if (editor.widgetRevision !== widgetRevision && editor.focus !== FocusEditorText$1) {
|
|
18187
|
-
return editor;
|
|
18188
|
-
}
|
|
18189
|
-
return fn(editor);
|
|
18190
|
-
}, false, returnState);
|
|
18191
|
-
return uid => {
|
|
18192
|
-
// DOM focus events can arrive while a queued command is still opening a widget.
|
|
18193
|
-
const widgetRevision = get$8(uid)?.newState.widgetRevision;
|
|
18194
|
-
return command(uid, widgetRevision);
|
|
18195
|
-
};
|
|
18196
|
-
};
|
|
18197
|
-
|
|
18198
|
-
// Optional provider work must not hold the editing queue while another worker responds.
|
|
18199
|
-
const wrapDeferredCommand$1 = (fn, returnState = true) => {
|
|
18200
|
-
const apply = wrapCommand$1((editor, snapshot, result) => editor === snapshot ? result : editor, false, returnState);
|
|
18201
|
-
return async (uid, ...args) => {
|
|
18202
|
-
const snapshot = await enqueue(uid, async () => get$8(uid)?.newState);
|
|
18203
|
-
if (!snapshot) {
|
|
18204
|
-
return undefined;
|
|
18205
|
-
}
|
|
18206
|
-
const result = await fn(snapshot, ...args);
|
|
18207
|
-
return apply(uid, snapshot, result);
|
|
18208
|
-
};
|
|
18209
|
-
};
|
|
18210
|
-
|
|
18211
18228
|
const save = async (uid, skipFormatting = false) => {
|
|
18212
18229
|
let savedFrom;
|
|
18213
18230
|
const saveContent = wrapCommand$1(async editor => {
|