From 564cce24627439c4566b0d04f769dd63825ff88a Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Mon, 8 Nov 2021 16:33:36 +0530 Subject: [PATCH] feat: autocomplete cm6 --- .../helpers/editor/codemirror.ts | 56 ++++++++++++++++--- packages/hoppscotch-app/package.json | 1 + pnpm-lock.yaml | 2 + 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/packages/hoppscotch-app/helpers/editor/codemirror.ts b/packages/hoppscotch-app/helpers/editor/codemirror.ts index 0ae6fb63d..c5d8a5d07 100644 --- a/packages/hoppscotch-app/helpers/editor/codemirror.ts +++ b/packages/hoppscotch-app/helpers/editor/codemirror.ts @@ -41,6 +41,7 @@ import { javascriptLanguage } from "@codemirror/lang-javascript" import { Language, LanguageSupport } from "@codemirror/language" import { linter } from "@codemirror/lint" import { jsonLanguage } from "@codemirror/lang-json" +import { Completion, autocompletion } from "@codemirror/autocomplete" import { onBeforeUnmount } from "@vue/runtime-dom" import { pipe } from "fp-ts/function" import * as O from "fp-ts/Option" @@ -233,6 +234,34 @@ export function useCodemirror( } } +const hoppCompleterExt = (completer: Completer): Extension => { + return autocompletion({ + override: [ + async (context) => { + // Expensive operation! Disable on bigger files ? + const text = context.state.doc.toJSON().join(context.state.lineBreak) + + const line = context.state.doc.lineAt(context.pos).from + const ch = context.pos - line + + const result = await completer(text, { line, ch }) + + // Use more completion features ? + const completions = + result?.completions.map((comp) => ({ + label: comp.text, + detail: comp.meta, + })) ?? [] + + return { + from: context.state.wordAt(context.pos)?.from ?? context.pos, + options: completions, + } + }, + ], + }) +} + const hoppLinterExt = (hoppLinter: LinterDefinition): Extension => { return linter(async (view) => { // Requires full document scan, hence expensive on big files, force disable on big files ? @@ -257,9 +286,15 @@ const hoppLinterExt = (hoppLinter: LinterDefinition): Extension => { const hoppLang = ( language: Language, - linter?: LinterDefinition | undefined + linter?: LinterDefinition | undefined, + completer?: Completer | undefined ) => { - return new LanguageSupport(language, linter ? [hoppLinterExt(linter)] : []) + const exts: Extension[] = [] + + if (linter) exts.push(hoppLinterExt(linter)) + if (completer) exts.push(hoppCompleterExt(completer)) + + return new LanguageSupport(language, exts) } const getLanguage = (langMime: string): Language | null => { @@ -275,11 +310,12 @@ const getLanguage = (langMime: string): Language | null => { const getEditorLanguage = ( langMime: string, - linter: LinterDefinition | undefined + linter: LinterDefinition | undefined, + completer: Completer | undefined ): Extension => pipe( O.fromNullable(getLanguage(langMime)), - O.map((lang) => hoppLang(lang, linter)), + O.map((lang) => hoppLang(lang, linter, completer)), O.getOrElseW(() => []) ) @@ -338,7 +374,8 @@ export function useNewCodemirror( language.of( getEditorLanguage( (options.extendedEditorConfig.mode as any) ?? "", - options.linter ?? undefined + options.linter ?? undefined, + options.completer ?? undefined ) ), lineWrapping.of( @@ -396,13 +433,18 @@ export function useNewCodemirror( ) watch( - () => [options.extendedEditorConfig.mode, options.linter], + () => [ + options.extendedEditorConfig.mode, + options.linter, + options.completer, + ], () => { dispatch({ effects: language.reconfigure( getEditorLanguage( (options.extendedEditorConfig.mode as any) ?? "", - options.linter ?? undefined + options.linter ?? undefined, + options.completer ?? undefined ) ), }) diff --git a/packages/hoppscotch-app/package.json b/packages/hoppscotch-app/package.json index 43f53fec1..5fb794e4b 100644 --- a/packages/hoppscotch-app/package.json +++ b/packages/hoppscotch-app/package.json @@ -34,6 +34,7 @@ }, "dependencies": { "@apollo/client": "^3.4.16", + "@codemirror/autocomplete": "^0.19.4", "@codemirror/basic-setup": "^0.19.0", "@codemirror/commands": "^0.19.5", "@codemirror/gutter": "^0.19.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b98b58718..a00e0c481 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,7 @@ importers: '@apollo/client': ^3.4.16 '@babel/core': ^7.16.0 '@babel/preset-env': ^7.16.0 + '@codemirror/autocomplete': ^0.19.4 '@codemirror/basic-setup': ^0.19.0 '@codemirror/commands': ^0.19.5 '@codemirror/gutter': ^0.19.4 @@ -135,6 +136,7 @@ importers: yargs-parser: ^20.2.9 dependencies: '@apollo/client': 3.4.16_f3f7eb5e21785ef7d5faca94c1a68824 + '@codemirror/autocomplete': 0.19.4 '@codemirror/basic-setup': 0.19.0 '@codemirror/commands': 0.19.5 '@codemirror/gutter': 0.19.4