diff --git a/src/Playground.res b/src/Playground.res index d6aada34d..f78c520f1 100644 --- a/src/Playground.res +++ b/src/Playground.res @@ -1,6 +1,7 @@ %%raw(` if (typeof window !== "undefined" && typeof window.navigator !== "undefined") { require("codemirror/mode/javascript/javascript"); + require("codemirror/keymap/vim"); require("codemirror/addon/scroll/simplescrollbars"); require("plugins/cm-rescript-mode"); require("plugins/cm-reason-mode"); @@ -839,8 +840,10 @@ module Settings = { ~setConfig: Api.Config.t => unit, ~editorCode: React.ref, ~config: Api.Config.t, + ~keyMapState: (CodeMirror.KeyMap.t, (CodeMirror.KeyMap.t => CodeMirror.KeyMap.t) => unit), ) => { let {Api.Config.warn_flags: warn_flags} = config + let (keyMap, setKeyMap) = keyMapState let availableTargetLangs = Api.Version.availableLanguages(readyState.selected.apiVersion) @@ -975,6 +978,19 @@ module Settings = { } else { React.null }} +
+
{React.string("Use Vim Keymap")}
+ + switch enabled { + | CodeMirror.KeyMap.Vim => "On" + | CodeMirror.KeyMap.Default => "Off" + }} + selected=keyMap + onChange={value => setKeyMap(_ => value)} + /> +
{React.string("Module-System")}
, + ~keyMapState: (CodeMirror.KeyMap.t, (CodeMirror.KeyMap.t => CodeMirror.KeyMap.t) => unit), ~currentTab: tab, ) => { let output = @@ -1223,7 +1240,9 @@ module OutputPanel = { let config = ready.selected.config let setConfig = config => compilerDispatch(UpdateConfig(config)) - + | SetupFailed(msg) =>
{React.string("Setup failed: " ++ msg)}
| Init =>
{React.string("Initalizing Playground...")}
} @@ -1459,6 +1478,22 @@ let make = (~versions: array) => { (), ) + let overlayState = React.useState(() => false) + + let windowWidth = CodeMirror.useWindowWidth() + + let (keyMap, setKeyMap) = React.useState(() => { + Dom.Storage2.localStorage + ->Dom.Storage2.getItem("vimMode") + ->Option.map(CodeMirror.KeyMap.fromString) + ->Option.getOr(CodeMirror.KeyMap.Default) + }) + + React.useEffect1(() => { + Dom.Storage2.localStorage->Dom.Storage2.setItem("vimMode", CodeMirror.KeyMap.toString(keyMap)) + None + }, [keyMap]) + // The user can focus an error / warning on a specific line & column // which is stored in this ref and triggered by hover / click states // in the CodeMirror editor @@ -1820,6 +1855,7 @@ let make = (~versions: array) => { }} onMarkerFocus={rowCol => setFocusedRowCol(_prev => Some(rowCol))} onMarkerFocusLeave={_ => setFocusedRowCol(_ => None)} + keyMap />
// Separator @@ -1849,7 +1885,9 @@ let make = (~versions: array) => {
>))} className="overflow-auto"> - +
diff --git a/src/components/CodeMirror.res b/src/components/CodeMirror.res index b6637a961..fe726e5e4 100644 --- a/src/components/CodeMirror.res +++ b/src/components/CodeMirror.res @@ -8,6 +8,21 @@ This file is providing the core functionality and logic of our CodeMirror instances. */ +module KeyMap = { + type t = Default | Vim + let toString = (keyMap: t) => + switch keyMap { + | Default => "default" + | Vim => "vim" + } + + let fromString = (str: string) => + switch str { + | "vim" => Vim + | _ => Default + } +} + let useWindowWidth: unit => int = %raw(` () => { const isClient = typeof window === 'object'; @@ -62,6 +77,7 @@ module CM = { lineWrapping?: bool, fixedGutter?: bool, scrollbarStyle?: string, + keyMap?: string, } } @@ -527,6 +543,7 @@ let make = // props relevant for the react wrapper ~readOnly=false, ~lineNumbers=true, ~scrollbarStyle="native", + ~keyMap=KeyMap.Default, ~lineWrapping=false, ): React.element => { let inputElement = React.useRef(Nullable.null) @@ -536,7 +553,7 @@ let make = // props relevant for the react wrapper let windowWidth = useWindowWidth() let (onMouseOver, onMouseOut, onMouseMove) = useHoverTooltip(~cmStateRef, ~cmRef, ()) - React.useEffect(() => + React.useEffect(() => { switch inputElement.current->Nullable.toOption { | Some(input) => let options = { @@ -548,6 +565,7 @@ let make = // props relevant for the react wrapper readOnly, lineNumbers, scrollbarStyle, + keyMap: KeyMap.toString(keyMap), } let cm = CM.fromTextArea(input, options) @@ -590,7 +608,7 @@ let make = // props relevant for the react wrapper Some(cleanup) | None => None } - , []) + }, [keyMap]) React.useEffect(() => { cmStateRef.current.hoverHints = hoverHints diff --git a/src/components/CodeMirror.resi b/src/components/CodeMirror.resi index 0815ca43e..bdbdfb99c 100644 --- a/src/components/CodeMirror.resi +++ b/src/components/CodeMirror.resi @@ -1,3 +1,9 @@ +module KeyMap: { + type t = Default | Vim + let toString: t => string + let fromString: string => t +} + module Error: { type kind = [#Error | #Warning] @@ -36,6 +42,7 @@ module CM: { lineWrapping?: bool, fixedGutter?: bool, scrollbarStyle?: string, + keyMap?: string, } } } @@ -59,5 +66,6 @@ let make: ( ~readOnly: bool=?, ~lineNumbers: bool=?, ~scrollbarStyle: string=?, + ~keyMap: KeyMap.t=?, ~lineWrapping: bool=?, ) => React.element