1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
import React from "react";
import Completion from "./console/Completion";
import Input from "./console//Input";
import styled from "styled-components";
import { useCompletions, useSelectCompletion } from "../completion/hooks";
import useAutoResize from "../hooks/useAutoResize";
import { CompletionProvider } from "../completion/provider";
import { useExecCommand, useHide } from "../app/hooks";
const COMPLETION_MAX_ITEMS = 33;
const ConsoleWrapper = styled.div`
border-top: 1px solid gray;
`;
interface Props {
initialInputValue: string;
}
const CommandPromptInner: React.FC<Props> = ({ initialInputValue }) => {
const hide = useHide();
const [inputValue, setInputValue] = React.useState(initialInputValue);
const { completions, updateCompletions } = useCompletions();
const { select, currentValue, selectNext, selectPrev } =
useSelectCompletion();
const execCommand = useExecCommand();
useAutoResize();
const onBlur = () => {
hide();
};
const isCancelKey = React.useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) =>
e.key === "Escape" ||
(e.ctrlKey && e.key === "[") ||
(e.ctrlKey && e.key === "c"),
[]
);
const isNextKey = React.useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) =>
(!e.shiftKey && e.key === "Tab") || (e.ctrlKey && e.key === "n"),
[]
);
const isPrevKey = React.useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) =>
(e.shiftKey && e.key === "Tab") || (e.ctrlKey && e.key === "p"),
[]
);
const isEnterKey = React.useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) =>
e.key === "Enter" || (e.ctrlKey && e.key === "m"),
[]
);
const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (isCancelKey(e)) {
hide();
} else if (isEnterKey(e)) {
const value = (e.target as HTMLInputElement).value;
execCommand(value);
hide();
} 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;
setInputValue(text);
};
React.useEffect(() => {
updateCompletions(inputValue);
}, [inputValue]);
return (
<ConsoleWrapper>
<Completion
size={COMPLETION_MAX_ITEMS}
completions={completions}
select={select}
/>
<Input
prompt={":"}
onBlur={onBlur}
onKeyDown={onKeyDown}
onChange={onChange}
value={select == -1 ? inputValue : currentValue}
/>
</ConsoleWrapper>
);
};
const CommandPrompt: React.FC<Props> = ({ initialInputValue }) => (
<CompletionProvider initialInputValue={initialInputValue}>
<CommandPromptInner initialInputValue={initialInputValue} />
</CompletionProvider>
);
export default CommandPrompt;
|