diff options
Diffstat (limited to 'src/console/components')
-rw-r--r-- | src/console/components/CommandPrompt.tsx | 219 | ||||
-rw-r--r-- | src/console/components/Console.tsx | 2 |
2 files changed, 65 insertions, 156 deletions
diff --git a/src/console/components/CommandPrompt.tsx b/src/console/components/CommandPrompt.tsx index f6f4d8f..24f46ae 100644 --- a/src/console/components/CommandPrompt.tsx +++ b/src/console/components/CommandPrompt.tsx @@ -1,17 +1,12 @@ import React from "react"; import * as consoleActions from "../actions/console"; -import * as completionActions from "../actions/completion"; import AppContext from "./AppContext"; -import CommandLineParser, { - InputPhase, -} from "../commandline/CommandLineParser"; import Completion from "./console/Completion"; import Input from "./console//Input"; -import { Command } from "../../shared/Command"; import styled from "styled-components"; -import reducer, { defaultState, completedText } from "../reducers/completion"; -import CompletionType from "../../shared/CompletionType"; +import { useCompletions, useSelectCompletion } from "../completion/hooks"; import useAutoResize from "../hooks/useAutoResize"; +import { CompletionProvider } from "../completion/provider"; const COMPLETION_MAX_ITEMS = 33; @@ -19,13 +14,20 @@ const ConsoleWrapper = styled.div` border-top: 1px solid gray; `; -const CommandPrompt: React.FC = () => { - const { state, dispatch } = React.useContext(AppContext); - const [completionState, completionDispatch] = React.useReducer( - reducer, - defaultState - ); - const commandLineParser = new CommandLineParser(); +interface Props { + initialInputValue: string; +} + +const CommandPromptInner: React.FC<Props> = ({ initialInputValue }) => { + const { dispatch } = React.useContext(AppContext); + const [inputValue, setInputValue] = React.useState(initialInputValue); + const { completions, updateCompletions } = useCompletions(); + const { + select, + currentValue, + selectNext, + selectPrev, + } = useSelectCompletion(); useAutoResize(); @@ -33,174 +35,81 @@ const CommandPrompt: React.FC = () => { dispatch(consoleActions.hideCommand()); }; - const doEnter = (e: React.KeyboardEvent<HTMLInputElement>) => { - e.stopPropagation(); - e.preventDefault(); + const isCancelKey = React.useCallback( + (e: React.KeyboardEvent<HTMLInputElement>) => + e.key === "Escape" || + (e.ctrlKey && e.key === "[") || + (e.ctrlKey && e.key === "c"), + [] + ); - const value = (e.target as HTMLInputElement).value; - dispatch(consoleActions.enterCommand(value)); - }; + const isNextKey = React.useCallback( + (e: React.KeyboardEvent<HTMLInputElement>) => + (!e.shiftKey && e.key === "Tab") || (e.ctrlKey && e.key === "n"), + [] + ); - const selectNext = (e: React.KeyboardEvent<HTMLInputElement>) => { - completionDispatch(completionActions.completionNext()); - e.stopPropagation(); - e.preventDefault(); - }; + const isPrevKey = React.useCallback( + (e: React.KeyboardEvent<HTMLInputElement>) => + (e.shiftKey && e.key === "Tab") || (e.ctrlKey && e.key === "p"), + [] + ); - const selectPrev = (e: React.KeyboardEvent<HTMLInputElement>) => { - completionDispatch(completionActions.completionPrev()); - e.stopPropagation(); - e.preventDefault(); - }; + const isEnterKey = React.useCallback( + (e: React.KeyboardEvent<HTMLInputElement>) => + e.key === "Enter" || (e.ctrlKey && e.key === "m"), + [] + ); const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { - switch (e.key) { - case "Escape": - dispatch(consoleActions.hideCommand()); - break; - case "Enter": - doEnter(e); - break; - case "Tab": - if (e.shiftKey) { - completionDispatch(completionActions.completionPrev()); - } else { - completionDispatch(completionActions.completionNext()); - } - e.stopPropagation(); - e.preventDefault(); - break; - case "[": - if (e.ctrlKey) { - e.preventDefault(); - dispatch(consoleActions.hideCommand()); - } - break; - case "c": - if (e.ctrlKey) { - e.preventDefault(); - dispatch(consoleActions.hideCommand()); - } - break; - case "m": - if (e.ctrlKey) { - doEnter(e); - } - break; - case "n": - if (e.ctrlKey) { - selectNext(e); - } - break; - case "p": - if (e.ctrlKey) { - selectPrev(e); - } - break; + if (isCancelKey(e)) { + dispatch(consoleActions.hideCommand()); + } else if (isEnterKey(e)) { + const value = (e.target as HTMLInputElement).value; + dispatch(consoleActions.enterCommand(value)); + } else if (isNextKey(e)) { + selectNext(); + } else if (isPrevKey(e)) { + selectPrev(); + } else { + return; } + + e.stopPropagation(); + e.preventDefault(); }; const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { const text = e.target.value; - dispatch(consoleActions.setConsoleText(text)); - const action = getCompletionAction(text); - Promise.resolve(action).then((a) => { - if (a) { - completionDispatch(a); - } - }); + setInputValue(text); }; React.useEffect(() => { - completionActions.startCompletion().then((action) => { - completionDispatch(action); - - const completionAction = getCompletionAction( - state.consoleText, - action.completionTypes - ); - Promise.resolve(completionAction).then((a) => { - if (a) { - completionDispatch(a); - } - }); - }); - }, []); - - const getCompletionAction = ( - text: string, - completionTypes: CompletionType[] | undefined = undefined - ) => { - const types = completionTypes || completionState.completionTypes; - const phase = commandLineParser.inputPhase(text); - if (phase === InputPhase.OnCommand) { - return completionActions.getCommandCompletions(text); - } else { - const cmd = commandLineParser.parse(text); - switch (cmd.command) { - case Command.Open: - case Command.TabOpen: - case Command.WindowOpen: - return completionActions.getOpenCompletions( - types, - text, - cmd.command, - cmd.args - ); - case Command.Buffer: - return completionActions.getTabCompletions( - text, - cmd.command, - cmd.args, - false - ); - case Command.BufferDelete: - case Command.BuffersDelete: - return completionActions.getTabCompletions( - text, - cmd.command, - cmd.args, - true - ); - case Command.BufferDeleteForce: - case Command.BuffersDeleteForce: - return completionActions.getTabCompletions( - text, - cmd.command, - cmd.args, - false - ); - case Command.Set: - return completionActions.getPropertyCompletions( - text, - cmd.command, - cmd.args - ); - } - } - return undefined; - }; + updateCompletions(inputValue); + }, [inputValue]); return ( <ConsoleWrapper> <Completion size={COMPLETION_MAX_ITEMS} - completions={completionState.completions} - select={completionState.select} + completions={completions} + select={select} /> <Input prompt={":"} onBlur={onBlur} onKeyDown={onKeyDown} onChange={onChange} - value={ - completionState.select < 0 - ? state.consoleText - : completedText(completionState) - } + value={select == -1 ? inputValue : currentValue} /> </ConsoleWrapper> ); }; +const CommandPrompt: React.FC<Props> = ({ initialInputValue }) => ( + <CompletionProvider initialInputValue={initialInputValue}> + <CommandPromptInner initialInputValue={initialInputValue} /> + </CompletionProvider> +); + export default CommandPrompt; diff --git a/src/console/components/Console.tsx b/src/console/components/Console.tsx index f6f4234..508c6eb 100644 --- a/src/console/components/Console.tsx +++ b/src/console/components/Console.tsx @@ -16,7 +16,7 @@ const Console: React.FC = () => { switch (state.mode) { case "command": - return <CommandPrompt />; + return <CommandPrompt initialInputValue={state.consoleText} />; case "find": return <FindPrompt />; case "info": |