diff --git a/core/package.json b/core/package.json index 23bfac73..3547dfca 100644 --- a/core/package.json +++ b/core/package.json @@ -18,6 +18,7 @@ "@popperjs/core": "^2.11.8", "foxact": "^0.2.20", "jotai": "^2.3.1", + "monaco-vim": "^0.4.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/core/src/components/EditorZone.tsx b/core/src/components/EditorZone.tsx index ad51d31f..73c77f13 100644 --- a/core/src/components/EditorZone.tsx +++ b/core/src/components/EditorZone.tsx @@ -7,8 +7,9 @@ import React, { useState } from 'react' import Editor, { useMonaco } from '@monaco-editor/react' -import { createStore, Provider, useAtom } from 'jotai' +import { createStore, Provider, useAtom, useAtomValue } from 'jotai' import type * as monacoEditor from 'monaco-editor' +import { initVimMode } from 'monaco-vim' import { ExtensionContext } from '../contextes/Extension' import { MonacoScopeContext } from '../contextes/MonacoScope' @@ -19,7 +20,7 @@ import { classnames, isMacOS } from '../utils' import { Popover } from './base/Popover' import { BottomStatus } from './BottomStatus' import { DrawerPanel } from './DrawerPanel' -import { displayLeftBarAtom } from './EditorZoneShareAtoms' +import { displayLeftBarAtom, isVimModeAtom } from './EditorZoneShareAtoms' import { LeftBar } from './LeftBar' import type { ResizableProps } from './Resizable' import { Resizable } from './Resizable' @@ -114,6 +115,9 @@ export default function EditorZone(props: EditorZoneProps) { const [displayLeftBar, setDisplayLeftBar] = useAtom(displayLeftBarAtom) + const isVimMode = useAtomValue(isVimModeAtom) + const vimModeRef = useRef | null>(null) + const editorCursorPosition = useRef(null) useEffect(() => { @@ -151,6 +155,22 @@ export default function EditorZone(props: EditorZoneProps) { return () => dispose.forEach(func => func?.()) }, [monaco, editor, plugins]) + useEffect(() => { + if (!editor) return + + if (isVimMode) + vimModeRef.current = initVimMode(editor, null!) + else { + vimModeRef.current?.dispose() + vimModeRef.current = null + } + + return () => { + vimModeRef.current?.dispose() + vimModeRef.current = null + } + }, [editor, isVimMode]) + useDocumentEventListener('keydown', e => { if (e.key === '\\' && (e.metaKey || e.ctrlKey)) { setDisplayLeftBar(!displayLeftBar) diff --git a/core/src/components/EditorZoneShareAtoms.ts b/core/src/components/EditorZoneShareAtoms.ts index c41df717..20d1b507 100644 --- a/core/src/components/EditorZoneShareAtoms.ts +++ b/core/src/components/EditorZoneShareAtoms.ts @@ -1,3 +1,5 @@ import { atom } from 'jotai' +import { atomWithStorage } from 'jotai/utils' export const displayLeftBarAtom = atom(false) +export const isVimModeAtom = atomWithStorage('IS_VIM_MODE', false) \ No newline at end of file diff --git a/core/src/components/LeftBar.tsx b/core/src/components/LeftBar.tsx index 15fc8f5e..335b50a8 100644 --- a/core/src/components/LeftBar.tsx +++ b/core/src/components/LeftBar.tsx @@ -2,12 +2,14 @@ import './LeftBar.scss' import { useContext, useMemo } from 'react' import { classnames, messenger } from '@power-playground/core' +import { useSetAtom } from 'jotai' import PP from '../../../resources/PP_P.svg' import { ExtensionContext } from '../contextes/Extension' import { Tooltip } from './base/Tooltip' import { useDrawerPanelController } from './drawerPanelCreator' +import { isVimModeAtom } from './EditorZoneShareAtoms' import { NotImplemented } from './NotImplemented' const prefix = 'ppd-left-bar' @@ -57,6 +59,7 @@ export function LeftBar(props: LeftBarProps) { : btn }) + const toggleVimMode = useSetAtom(isVimModeAtom) return
@@ -80,6 +83,10 @@ export function LeftBar(props: LeftBarProps) {
+ {/* TODO: move to settings */} + {buildElements(bottomItems)}