uiwjs / react-codemirror

CodeMirror 6 component for React. @codemirror https://uiwjs.github.io/react-codemirror/
https://uiwjs.github.io/react-codemirror/
MIT License
1.65k stars 132 forks source link

call function on vim command :w #501

Closed kimfucious closed 1 year ago

kimfucious commented 1 year ago

First, thanks for this excellent package. It makes CodeMirror, which is kinda hard to implement, easy to use in React.

I've scoured the docs and have come up short trying to detect vim commands.

For example, if I type :w, that's the vim command for write.

I'd like to call the handleSave() function in the below when :w is executed.

import { useCallback, useContext } from "react";
import { ActionType } from "../../types";
import { EditorView, ViewUpdate } from "@codemirror/view";
import { markdown } from "@codemirror/lang-markdown";
import { saveScene } from "../../actions";
import { solarizedLight } from "@uiw/codemirror-theme-solarized";
import { ThemeContext } from "../../contexts/ThemeProvider";
import { useAppDispatch, useAppSelector } from "../../hooks/reduxHooks";
import { vim } from "@replit/codemirror-vim";
import CodeMirror from "@uiw/react-codemirror";

interface Props {
    isSceneDirty: boolean;
}
export default function CodeMirrorEditor({ isSceneDirty }: Props) {
    const { isDark } = useContext(ThemeContext);
    const {
        app: state,
        sizes,
        user: {
            settings: { editorFontSize },
        },
    } = useAppSelector((state) => state);
    const dispatch = useAppDispatch();

    const onChange = useCallback(
        (value: string, viewUpdate: ViewUpdate) => {
            dispatch({
                type: ActionType.SET_DRAFT_ACTIVE_SCENE_TEXT,
                payload: value,
            });
        },
        [dispatch]
    );

    /* I want to run this on vim :w */
    async function handleSave() {
        try {
            if (isSceneDirty) {
                await dispatch(saveScene());
            }
        } catch (error) {
            // handle error
        }
    }

    return (
        <div className="d-flex justify-content-center w-100 my-3">
            <CodeMirror
                autoFocus
                basicSetup={{
                    foldGutter: false,
                    highlightActiveLine: false,
                }}
                value={state.draftActiveSceneText}
                theme={isDark ? "dark" : solarizedLight}
                height={`calc(100vh - ${sizes.totalHeightOffset + 32}px)`}
                width={`calc(36em + 74px)`}
                extensions={[
                    vim({ status: true }),
                    markdown(),
                    EditorView.lineWrapping,
                    EditorView.contentAttributes.of({ spellcheck: "true" }),
                ]}
                onChange={onChange}
                style={{ fontSize: editorFontSize }}
            />
        </div>
    );
}

Any help on this would be greatly appreciated!

jaywcjlove commented 1 year ago

@kimfucious https://www.npmjs.com/package/@replit/codemirror-vim

import {Vim, getCM} from "@replit/codemirror-vim"

Vim.defineEx('write', 'w', function() {
    // save the file
});
kimfucious commented 1 year ago

Thank you very much @jaywcjlove!

I was digging around here, trying to find other commands that I could implement.

I could not find things like: :q, :wq, or :x, so I used this pattern:

Vim.defineEx("x", undefined, () => {
    handleExit();
});

Is that the right way to do it?

jaywcjlove commented 1 year ago

@kimfucious

https://github.com/replit/codemirror-vim/blob/a77ce378576a888d3fdfc8830f722796a393dc5a/src/vim.js#L268-L303

image
kimfucious commented 1 year ago

Thanks @jaywcjlove.

Yes, I got that pattern for "write," however, I was asking about commands that are other than write such as :q, :x, etc.

The below, all seem to work. I'm just asking if the patterns are "best practice."

Vim.defineEx("write", "w", () => {
    handleQuit();
});

Vim.defineEx("q", undefined, () => {
    handleExit();
});

Vim.defineEx("x", undefined, () => {
    handleExit();
});

Vim.defineEx("wq", undefined, () => {
    handleExit();
});
jaywcjlove commented 1 year ago

I didn't find a good solution, you can define your own package.

kimfucious commented 1 year ago

Thanks... I'm good with what I'm using, as mentioned prior.