дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-15 22:25:48 +02:00
Порівняти коміти
1
Коміти
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
205241c0b3 |
No files matched your search
@@ -290,6 +290,20 @@ export const documentSynced = Facet.define<() => Promise<void>, (() => Promise<v
|
||||
combine: (values) => values[0] ?? null,
|
||||
});
|
||||
|
||||
/**
|
||||
* Undo / Redo of an editor whose history is kept outside CodeMirror (notebook cells share
|
||||
* the notebook's backend history). Commands that would call CodeMirror's history (Vim's
|
||||
* `u` / `Ctrl-R`) go through it instead.
|
||||
*/
|
||||
export interface ExternalHistory {
|
||||
undo(): void;
|
||||
redo(): void;
|
||||
}
|
||||
|
||||
export const externalHistory = Facet.define<ExternalHistory, ExternalHistory | null>({
|
||||
combine: (values) => values[0] ?? null,
|
||||
});
|
||||
|
||||
export function whenSynced(view: EditorView): Promise<void> {
|
||||
return view.state.facet(documentSynced)?.() ?? Promise.resolve();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { defaultKeymap, indentWithTab } from "@codemirror/commands";
|
||||
import { bracketMatching, indentOnInput, syntaxHighlighting } from "@codemirror/language";
|
||||
import type { NotebookCellDoc } from "@/bindings";
|
||||
import { cellEditorExtensions, embeddedEditorExtensions } from "@/editor/api";
|
||||
import { cellEditorExtensions, embeddedEditorExtensions, externalHistory } from "@/editor/api";
|
||||
import { openideaTheme } from "@/editor/core/cm/theme";
|
||||
import { openideaHighlightStyle } from "@/editor/core/cm/highlight";
|
||||
import { selectionMarks } from "@/editor/core/cm/selectionMarks";
|
||||
@@ -97,6 +97,10 @@ export function CellEditor({
|
||||
]),
|
||||
),
|
||||
keymap.of([indentWithTab, ...defaultKeymap]),
|
||||
externalHistory.of({
|
||||
undo: () => void session.undo().catch((e) => session.report(e)),
|
||||
redo: () => void session.redo().catch((e) => session.report(e)),
|
||||
}),
|
||||
embeddedEditorExtensions(session.path),
|
||||
language.of([]),
|
||||
services.current.of(languageServices(type, initialDoc.current)),
|
||||
|
||||
@@ -2,7 +2,13 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { EditorState, Prec } from "@codemirror/state";
|
||||
import { EditorView, keymap } from "@codemirror/view";
|
||||
import { getCM, Vim } from "@replit/codemirror-vim";
|
||||
import { embeddedEditorExtensions, transientChange, useEditorRegistry, onEditorEvent } from "@/editor/api";
|
||||
import {
|
||||
embeddedEditorExtensions,
|
||||
externalHistory,
|
||||
transientChange,
|
||||
useEditorRegistry,
|
||||
onEditorEvent,
|
||||
} from "@/editor/api";
|
||||
import { executeAction, registerAction } from "@/platform/actions";
|
||||
import { getContext } from "@/platform/context";
|
||||
import { _handleEx, applyRcCommands, vimExtension } from "../engine";
|
||||
@@ -115,6 +121,19 @@ describe("Vim engine", () => {
|
||||
view.destroy();
|
||||
});
|
||||
|
||||
it("sends u and Ctrl-R to an editor's own history (notebook cells)", () => {
|
||||
const history = { undo: vi.fn(), redo: vi.fn() };
|
||||
const view = makeView([vimExtension(), externalHistory.of(history)]);
|
||||
const cm = getCM(view)!;
|
||||
Vim.handleKey(cm as never, "u", "user");
|
||||
Vim.handleKey(cm as never, "<C-r>", "user");
|
||||
Vim.handleKey(cm as never, "2", "user");
|
||||
Vim.handleKey(cm as never, "u", "user");
|
||||
expect(history.undo).toHaveBeenCalledTimes(3);
|
||||
expect(history.redo).toHaveBeenCalledTimes(1);
|
||||
view.destroy();
|
||||
});
|
||||
|
||||
it("applies insert-mode mappings, accepting <esc> in any case", () => {
|
||||
const view = makeView();
|
||||
const cm = getCM(view)!;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
import { EditorState, Prec, StateEffect, StateField, Transaction, type Extension } from "@codemirror/state";
|
||||
import { EditorView, ViewPlugin, runScopeHandlers } from "@codemirror/view";
|
||||
import { Vim, getCM, vim } from "@replit/codemirror-vim";
|
||||
import { transientChange, reportInputMode, type EditorDocContext } from "@/editor/api";
|
||||
import { CodeMirror, Vim, getCM, vim } from "@replit/codemirror-vim";
|
||||
import { externalHistory, transientChange, reportInputMode, type EditorDocContext } from "@/editor/api";
|
||||
import { setContext } from "@/platform/context";
|
||||
import { executeAction, getAction } from "@/platform/actions";
|
||||
import { showStatusInfo } from "@/workbench/contributions";
|
||||
@@ -16,6 +16,17 @@ import { resolveActionId, type RcCommand } from "./rc";
|
||||
import { mapFunctionTextObjects } from "./textObjects";
|
||||
|
||||
/** Insert/Replace state as seen by transactions (mode changes are queued). */
|
||||
// Vim's `u` / `Ctrl-R` call CodeMirror's history; an editor that keeps its history elsewhere
|
||||
// (notebook cells) provides `externalHistory` and gets those keys too.
|
||||
for (const name of ["undo", "redo"] as const) {
|
||||
const own = CodeMirror.commands[name];
|
||||
CodeMirror.commands[name] = (cm) => {
|
||||
const history = cm.cm6.state.facet(externalHistory);
|
||||
if (history) history[name]();
|
||||
else own(cm);
|
||||
};
|
||||
}
|
||||
|
||||
const setVimInsert = StateEffect.define<boolean>();
|
||||
|
||||
const vimInsert = StateField.define<boolean>({
|
||||
|
||||
Reference in new issue
Заблокувати користувача