Fix undo cursor jumps and formatting
This commit is contained in:
parent
a570acf962
commit
4a3e78e56c
|
|
@ -17,8 +17,8 @@ export abstract class Displayable {
|
||||||
private shortcuts = new Map<string, KeyHandler>();
|
private shortcuts = new Map<string, KeyHandler>();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Attempt to install handlers shortly after construction. If `dom` is not
|
// Attempt to install handlers shortly after construction.
|
||||||
// available yet, retry a few times.
|
// If `dom` is not available yet, retry a few times.
|
||||||
setTimeout(() => this.installHandlers(0), 0);
|
setTimeout(() => this.installHandlers(0), 0);
|
||||||
|
|
||||||
// Add general shortcuts
|
// Add general shortcuts
|
||||||
|
|
|
||||||
|
|
@ -167,10 +167,7 @@ export class OpenFile implements WorkspaceFile {
|
||||||
this.rootState.val = transaction.state;
|
this.rootState.val = transaction.state;
|
||||||
|
|
||||||
if (transaction.changes && !transaction.changes.empty) {
|
if (transaction.changes && !transaction.changes.empty) {
|
||||||
if (this.changes === undefined) {
|
this.changeSet = this.changes.compose(transaction.changes);
|
||||||
this.changes = ChangeSet.empty(this.rootState.val.doc.length);
|
|
||||||
}
|
|
||||||
this.changes = this.changes.compose(transaction.changes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin) {
|
if (origin) {
|
||||||
|
|
@ -178,7 +175,12 @@ export class OpenFile implements WorkspaceFile {
|
||||||
es.forEach((e) => e.dispatch(e.view.state.update(trs), true));
|
es.forEach((e) => e.dispatch(e.view.state.update(trs), true));
|
||||||
} else {
|
} else {
|
||||||
this.editors.forEach((e) => {
|
this.editors.forEach((e) => {
|
||||||
e.dispatch(e.view.state.update(trs), true);
|
const changes = transaction.changes;
|
||||||
|
const userEvent = transaction.annotation(Transaction.userEvent);
|
||||||
|
const annotations = userEvent
|
||||||
|
? [Transaction.userEvent.of(userEvent)]
|
||||||
|
: [];
|
||||||
|
e.dispatch(e.view.state.update({ changes, annotations }), true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,8 +205,16 @@ export class OpenFile implements WorkspaceFile {
|
||||||
get languageId(): string {
|
get languageId(): string {
|
||||||
return inferLanguageFromPath(this.filePath.val || "") || "";
|
return inferLanguageFromPath(this.filePath.val || "") || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
doc: Text;
|
doc: Text;
|
||||||
changes: ChangeSet;
|
private changeSet: ChangeSet;
|
||||||
|
get changes(): ChangeSet {
|
||||||
|
if (!this.changeSet) {
|
||||||
|
this.changeSet = ChangeSet.empty(this.rootState.val.doc.length);
|
||||||
|
}
|
||||||
|
return this.changeSet;
|
||||||
|
}
|
||||||
|
|
||||||
// Return an EditorView to be used by the LSP Workspace for position mapping.
|
// Return an EditorView to be used by the LSP Workspace for position mapping.
|
||||||
// If `main` is provided and belongs to this open file, return it. Otherwise
|
// If `main` is provided and belongs to this open file, return it. Otherwise
|
||||||
// return the first available editor view, or null if none exist.
|
// return the first available editor view, or null if none exist.
|
||||||
|
|
|
||||||
|
|
@ -1,52 +1,76 @@
|
||||||
import type * as lsp from "vscode-languageserver-protocol"
|
import type * as lsp from "vscode-languageserver-protocol";
|
||||||
import {ViewPlugin, ViewUpdate} from "@codemirror/view"
|
import { ChangeSet } from "@codemirror/state";
|
||||||
import {LSPPlugin, LSPClientExtension} from "@codemirror/lsp-client"
|
import { ViewPlugin, ViewUpdate } from "@codemirror/view";
|
||||||
import {OpenFile} from "../filestate"
|
import { LSPPlugin, LSPClientExtension } from "@codemirror/lsp-client";
|
||||||
import { Text } from "@codemirror/state"
|
import { OpenFile } from "../filestate";
|
||||||
|
import { Text } from "@codemirror/state";
|
||||||
|
|
||||||
function toSeverity(sev: lsp.DiagnosticSeverity) {
|
function toSeverity(sev: lsp.DiagnosticSeverity) {
|
||||||
return sev == 1 ? "error" : sev == 2 ? "warning" : sev == 3 ? "info" : "hint"
|
return sev == 1
|
||||||
|
? "error"
|
||||||
|
: sev == 2
|
||||||
|
? "warning"
|
||||||
|
: sev == 3
|
||||||
|
? "info"
|
||||||
|
: "hint";
|
||||||
}
|
}
|
||||||
|
|
||||||
const autoSync = ViewPlugin.fromClass(class {
|
const autoSync = ViewPlugin.fromClass(
|
||||||
pending: any | null = null
|
class {
|
||||||
update(update: ViewUpdate) {
|
pending: any | null = null;
|
||||||
if (update.docChanged) {
|
update(update: ViewUpdate) {
|
||||||
if (this.pending != null) clearTimeout(this.pending)
|
if (update.docChanged) {
|
||||||
this.pending = setTimeout(() => {
|
if (this.pending != null) clearTimeout(this.pending);
|
||||||
this.pending = null
|
this.pending = setTimeout(() => {
|
||||||
const plugin = LSPPlugin.get(update.view)
|
this.pending = null;
|
||||||
if (plugin) plugin.client.sync()
|
const plugin = LSPPlugin.get(update.view);
|
||||||
}, 500)
|
if (plugin) plugin.client.sync();
|
||||||
}
|
}, 500);
|
||||||
}
|
}
|
||||||
destroy() {
|
}
|
||||||
if (this.pending != null) clearTimeout(this.pending)
|
destroy() {
|
||||||
}
|
if (this.pending != null) clearTimeout(this.pending);
|
||||||
})
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
function fromPosition(doc: Text, pos: lsp.Position): number {
|
function fromPosition(doc: Text, pos: lsp.Position): number {
|
||||||
const line = doc.line(pos.line + 1)
|
const line = doc.line(pos.line + 1);
|
||||||
return line.from + pos.character
|
return line.from + pos.character;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serverDiagnostics(): LSPClientExtension {
|
export function serverDiagnostics(): LSPClientExtension {
|
||||||
return {
|
return {
|
||||||
clientCapabilities: {textDocument: {publishDiagnostics: {versionSupport: true}}},
|
clientCapabilities: {
|
||||||
notificationHandlers: {
|
textDocument: { publishDiagnostics: { versionSupport: true } },
|
||||||
"textDocument/publishDiagnostics": (client, params: lsp.PublishDiagnosticsParams) => {
|
},
|
||||||
const file = client.workspace.getFile(params.uri) as OpenFile;
|
notificationHandlers: {
|
||||||
if (!file || params.version != null && params.version != file.version) return false;
|
"textDocument/publishDiagnostics": (
|
||||||
const mapPos = (p: number) => file.changes ? file.changes.mapPos(p) : p;
|
client,
|
||||||
file.setDiagnostics(params.diagnostics.map(item => ({
|
params: lsp.PublishDiagnosticsParams,
|
||||||
from: mapPos(fromPosition(file.doc, item.range.start)),
|
) => {
|
||||||
to: mapPos(fromPosition(file.doc, item.range.end)),
|
const file = client.workspace.getFile(params.uri) as OpenFile;
|
||||||
severity: toSeverity(item.severity ?? 1),
|
if (!file) {
|
||||||
message: item.message,
|
return false;
|
||||||
})));
|
}
|
||||||
return true
|
if (params.version != null && params.version != file.version) {
|
||||||
}
|
return false;
|
||||||
},
|
}
|
||||||
editorExtension: autoSync
|
file.setDiagnostics(
|
||||||
}
|
params.diagnostics.map((item) => ({
|
||||||
|
from: file.changes.mapPos(
|
||||||
|
fromPosition(file.doc, item.range.start),
|
||||||
|
),
|
||||||
|
to: file.changes.mapPos(
|
||||||
|
fromPosition(file.doc, item.range.end),
|
||||||
|
),
|
||||||
|
severity: toSeverity(item.severity ?? 1),
|
||||||
|
message: item.message,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
editorExtension: autoSync,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ let currentWorkspaceRoot: string | null = null;
|
||||||
let watcher: chokidar.FSWatcher | null = null;
|
let watcher: chokidar.FSWatcher | null = null;
|
||||||
|
|
||||||
export function getCurrentWorkspaceRoot(): string | null {
|
export function getCurrentWorkspaceRoot(): string | null {
|
||||||
return currentWorkspaceRoot;
|
return currentWorkspaceRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to (re)create watcher and wire up IPC notifications to renderer
|
// Helper to (re)create watcher and wire up IPC notifications to renderer
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,9 @@ function ensureLspForKey(
|
||||||
const len = parseInt(m[1], 10);
|
const len = parseInt(m[1], 10);
|
||||||
const totalLen = headerEnd + 4 + len;
|
const totalLen = headerEnd + 4 + len;
|
||||||
if (entry.buffer.length < totalLen) break; // wait for more
|
if (entry.buffer.length < totalLen) break; // wait for more
|
||||||
const body = entry.buffer.subarray(headerEnd + 4, totalLen).toString();
|
const body = entry.buffer
|
||||||
|
.subarray(headerEnd + 4, totalLen)
|
||||||
|
.toString();
|
||||||
// Forward body to all attached ports
|
// Forward body to all attached ports
|
||||||
try {
|
try {
|
||||||
entry.ports.forEach((p) => {
|
entry.ports.forEach((p) => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue