53 lines
1.3 KiB
TypeScript
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()];
|
||
|
|
}
|