aboutsummaryrefslogtreecommitdiff
path: root/src/console/completion/hooks.ts
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2021-04-12 23:15:46 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2021-04-12 23:15:46 +0900
commit53450dd2ae595aad5b4f6deb422c50bb5e55097d (patch)
treeec401bbf80a691111333f370b0e2d35a12bef181 /src/console/completion/hooks.ts
parent69dd47fccd7be7180e932cdfa548bfd08d4d1645 (diff)
Delay completion query for users input
Diffstat (limited to 'src/console/completion/hooks.ts')
-rw-r--r--src/console/completion/hooks.ts170
1 files changed, 115 insertions, 55 deletions
diff --git a/src/console/completion/hooks.ts b/src/console/completion/hooks.ts
index aac431b..c3940c7 100644
--- a/src/console/completion/hooks.ts
+++ b/src/console/completion/hooks.ts
@@ -35,6 +35,41 @@ const propertyDocs: { [key: string]: string } = {
const completionClient = new CompletionClient();
+const useDelayedCallback = <T extends unknown, U extends unknown>(
+ callback: (arg1: T, arg2: U) => void,
+ timeout: number
+) => {
+ const [timer, setTimer] = React.useState<
+ ReturnType<typeof setTimeout> | undefined
+ >();
+ const [enabled, setEnabled] = React.useState(false);
+
+ const enableDelay = React.useCallback(() => {
+ setEnabled(true);
+ }, [setEnabled]);
+
+ const delayedCallback = React.useCallback(
+ (arg1: T, arg2: U) => {
+ if (enabled) {
+ if (typeof timer !== "undefined") {
+ clearTimeout(timer);
+ }
+ const id = setTimeout(() => {
+ callback(arg1, arg2);
+ clearTimeout(timer!);
+ setTimer(undefined);
+ }, timeout);
+ setTimer(id);
+ } else {
+ callback(arg1, arg2);
+ }
+ },
+ [enabled, timer]
+ );
+
+ return { enableDelay, delayedCallback };
+};
+
const getCommandCompletions = async (query: string): Promise<Completions> => {
const items = Object.entries(commandDocs)
.filter(([name]) => name.startsWith(query))
@@ -185,63 +220,88 @@ export const useCompletions = () => {
});
}, []);
- React.useEffect(() => {
- const text = state.completionSource;
- const phase = commandLineParser.inputPhase(text);
- if (phase === InputPhase.OnCommand) {
- getCommandCompletions(text).then((completions) =>
- dispatch(actions.setCompletions(completions))
- );
- } else {
- let cmd: CommandLine | null = null;
- try {
- cmd = commandLineParser.parse(text);
- } catch (e) {
- if (e instanceof UnknownCommandError) {
- return;
- }
- }
- switch (cmd?.command) {
- case Command.Open:
- case Command.TabOpen:
- case Command.WindowOpen:
- if (!state.completionTypes) {
- initCompletion(text);
- return;
- }
-
- getOpenCompletions(
- cmd.command,
- cmd.args,
- state.completionTypes
- ).then((completions) =>
+ const { delayedCallback: queryCompletions, enableDelay } = useDelayedCallback(
+ React.useCallback(
+ (text: string, completionTypes?: CompletionType[]) => {
+ const phase = commandLineParser.inputPhase(text);
+ if (phase === InputPhase.OnCommand) {
+ getCommandCompletions(text).then((completions) =>
dispatch(actions.setCompletions(completions))
);
- break;
- case Command.Buffer:
- getTabCompletions(cmd.command, cmd.args, false).then((completions) =>
- dispatch(actions.setCompletions(completions))
- );
- break;
- case Command.BufferDelete:
- case Command.BuffersDelete:
- getTabCompletions(cmd.command, cmd.args, true).then((completions) =>
- dispatch(actions.setCompletions(completions))
- );
- break;
- case Command.BufferDeleteForce:
- case Command.BuffersDeleteForce:
- getTabCompletions(cmd.command, cmd.args, false).then((completions) =>
- dispatch(actions.setCompletions(completions))
- );
- break;
- case Command.Set:
- getPropertyCompletions(cmd.command, cmd.args).then((completions) =>
- dispatch(actions.setCompletions(completions))
- );
- break;
- }
- }
+ } else {
+ let cmd: CommandLine | null = null;
+ try {
+ cmd = commandLineParser.parse(text);
+ } catch (e) {
+ if (e instanceof UnknownCommandError) {
+ return;
+ }
+ }
+ switch (cmd?.command) {
+ case Command.Open:
+ case Command.TabOpen:
+ case Command.WindowOpen:
+ if (!completionTypes) {
+ initCompletion(text);
+ return;
+ }
+
+ getOpenCompletions(
+ cmd.command,
+ cmd.args,
+ completionTypes
+ ).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.Buffer:
+ getTabCompletions(
+ cmd.command,
+ cmd.args,
+ false
+ ).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.BufferDelete:
+ case Command.BuffersDelete:
+ getTabCompletions(
+ cmd.command,
+ cmd.args,
+ true
+ ).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.BufferDeleteForce:
+ case Command.BuffersDeleteForce:
+ getTabCompletions(
+ cmd.command,
+ cmd.args,
+ false
+ ).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.Set:
+ getPropertyCompletions(
+ cmd.command,
+ cmd.args
+ ).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ break;
+ }
+ enableDelay();
+ }
+ },
+ [dispatch]
+ ),
+ 100
+ );
+
+ React.useEffect(() => {
+ queryCompletions(state.completionSource, state.completionTypes);
}, [state.completionSource, state.completionTypes]);
return {