Files
openchamber/packages/ui/src/lib/codemirror/vimModeExtension.ts
T
2026-06-08 19:10:32 +03:00

53 lines
1.3 KiB
TypeScript

import type { Extension } from '@codemirror/state';
import type { EditorView, Panel } from '@codemirror/view';
import { drawSelection, showPanel } from '@codemirror/view';
import { getCM, vim } from '@replit/codemirror-vim';
type VimStatusPlugin = {
updateStatus: () => void;
};
const isVimStatusPlugin = (value: unknown): value is VimStatusPlugin => {
return (
value !== null
&& typeof value === 'object'
&& 'updateStatus' in value
&& typeof value.updateStatus === 'function'
);
};
const bottomVimStatusPanel = (view: EditorView): Panel => {
const dom = document.createElement('div');
dom.className = 'cm-vim-panel';
const cm = getCM(view);
if (!cm) {
return { top: false, dom };
}
cm.state.statusbar = dom;
const vimPlugin: unknown = cm.state.vimPlugin;
// The Vim package exposes only a top status panel; reuse its updater with a bottom panel.
if (isVimStatusPlugin(vimPlugin)) {
vimPlugin.updateStatus();
}
return {
top: false,
dom,
destroy() {
if (cm.state.statusbar === dom) {
cm.state.statusbar = null;
}
},
};
};
export function createVimModeExtensions(enabled: boolean | undefined): Extension[] {
if (!enabled) {
return [];
}
return [vim(), showPanel.of(bottomVimStatusPanel), drawSelection()];
}