diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2021-04-04 21:34:13 +0900 |
---|---|---|
committer | Shin'ya Ueoka <ueokande@i-beam.org> | 2021-04-05 22:21:33 +0900 |
commit | 3a7e55fd292196f600c11fad36425014677a1351 (patch) | |
tree | 53827f62aaea916cf8c76f6d3e08866f1db0d716 /src/console/actions/completion.ts | |
parent | 39f96db5a3187b4ce2e7df529eaa456ee862dd68 (diff) |
Separate Command and Completion reducer
Diffstat (limited to 'src/console/actions/completion.ts')
-rw-r--r-- | src/console/actions/completion.ts | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/src/console/actions/completion.ts b/src/console/actions/completion.ts new file mode 100644 index 0000000..2f6f82f --- /dev/null +++ b/src/console/actions/completion.ts @@ -0,0 +1,243 @@ +import { Command } from "../../shared/Command"; +import CompletionClient from "../clients/CompletionClient"; +import CompletionType from "../../shared/CompletionType"; +import Completions from "../Completions"; +import TabFlag from "../../shared/TabFlag"; + +const completionClient = new CompletionClient(); + +const commandDocs = { + [Command.Set]: "Set a value of the property", + [Command.Open]: "Open a URL or search by keywords in current tab", + [Command.TabOpen]: "Open a URL or search by keywords in new tab", + [Command.WindowOpen]: "Open a URL or search by keywords in new window", + [Command.Buffer]: "Select tabs by matched keywords", + [Command.BufferDelete]: "Close a certain tab matched by keywords", + [Command.BuffersDelete]: "Close all tabs matched by keywords", + [Command.Quit]: "Close the current tab", + [Command.QuitAll]: "Close all tabs", + [Command.AddBookmark]: "Add current page to bookmarks", + [Command.Help]: "Open Vim Vixen help in new tab", +}; + +const propertyDocs: { [key: string]: string } = { + hintchars: "hint characters on follow mode", + smoothscroll: "smooth scroll", + complete: "which are completed at the open page", + colorscheme: "color scheme of the console", +}; + +export const COMPLETION_START_COMPLETION = "console.start.completion"; +export const COMPLETION_SET_COMPLETIONS = "console.set.completions"; +export const COMPLETION_COMPLETION_NEXT = "completion.completion.next"; +export const COMPLETION_COMPLETION_PREV = "completion.completion.prev"; + +export interface CompletionStartCompletionAction { + type: typeof COMPLETION_START_COMPLETION; + completionTypes: CompletionType[]; +} + +export interface SetCompletionsAction { + type: typeof COMPLETION_SET_COMPLETIONS; + completions: Completions; + completionSource: string; +} + +export interface CompletionNextAction { + type: typeof COMPLETION_COMPLETION_NEXT; +} + +export interface CompletionPrevAction { + type: typeof COMPLETION_COMPLETION_PREV; +} + +export type CompletionAction = + | CompletionStartCompletionAction + | SetCompletionsAction + | CompletionNextAction + | CompletionPrevAction; +const startCompletion = async (): Promise<CompletionStartCompletionAction> => { + const completionTypes = await completionClient.getCompletionTypes(); + return { + type: COMPLETION_START_COMPLETION, + completionTypes, + }; +}; + +const getCommandCompletions = (text: string): SetCompletionsAction => { + const items = Object.entries(commandDocs) + .filter(([name]) => name.startsWith(text.trimLeft())) + .map(([name, doc]) => ({ + caption: name, + content: name, + url: doc, + })); + const completions = [ + { + name: "Console Command", + items, + }, + ]; + return { + type: COMPLETION_SET_COMPLETIONS, + completions, + completionSource: text, + }; +}; + +const getOpenCompletions = async ( + types: CompletionType[], + original: string, + command: Command, + query: string +): Promise<SetCompletionsAction> => { + const completions: Completions = []; + for (const type of types) { + switch (type) { + case CompletionType.SearchEngines: { + const items = await completionClient.requestSearchEngines(query); + if (items.length === 0) { + break; + } + completions.push({ + name: "Search Engines", + items: items.map((key) => ({ + caption: key.title, + content: command + " " + key.title, + })), + }); + break; + } + case CompletionType.History: { + const items = await completionClient.requestHistory(query); + if (items.length === 0) { + break; + } + completions.push({ + name: "History", + items: items.map((item) => ({ + caption: item.title, + content: command + " " + item.url, + url: item.url, + })), + }); + break; + } + case CompletionType.Bookmarks: { + const items = await completionClient.requestBookmarks(query); + if (items.length === 0) { + break; + } + completions.push({ + name: "Bookmarks", + items: items.map((item) => ({ + caption: item.title, + content: command + " " + item.url, + url: item.url, + })), + }); + break; + } + } + } + + return { + type: COMPLETION_SET_COMPLETIONS, + completions, + completionSource: original, + }; +}; + +const getTabCompletions = async ( + original: string, + command: Command, + query: string, + excludePinned: boolean +): Promise<SetCompletionsAction> => { + const items = await completionClient.requestTabs(query, excludePinned); + let completions: Completions = []; + if (items.length > 0) { + completions = [ + { + name: "Buffers", + items: items.map((item) => ({ + content: command + " " + item.url, + caption: `${item.index}: ${ + item.flag != TabFlag.None ? item.flag : " " + } ${item.title}`, + url: item.url, + icon: item.faviconUrl, + })), + }, + ]; + } + return { + type: COMPLETION_SET_COMPLETIONS, + completions, + completionSource: original, + }; +}; + +const getPropertyCompletions = async ( + original: string, + command: Command, + query: string +): Promise<SetCompletionsAction> => { + const properties = await completionClient.getProperties(); + const items = properties + .map((item) => { + const desc = propertyDocs[item.name] || ""; + if (item.type === "boolean") { + return [ + { + caption: item.name, + content: command + " " + item.name, + url: "Enable " + desc, + }, + { + caption: "no" + item.name, + content: command + " no" + item.name, + url: "Disable " + desc, + }, + ]; + } else { + return [ + { + caption: item.name, + content: command + " " + item.name, + url: "Set " + desc, + }, + ]; + } + }) + .reduce((acc, val) => acc.concat(val), []) + .filter((item) => item.caption.startsWith(query)); + const completions: Completions = [{ name: "Properties", items }]; + return { + type: COMPLETION_SET_COMPLETIONS, + completions, + completionSource: original, + }; +}; + +const completionNext = (): CompletionNextAction => { + return { + type: COMPLETION_COMPLETION_NEXT, + }; +}; + +const completionPrev = (): CompletionPrevAction => { + return { + type: COMPLETION_COMPLETION_PREV, + }; +}; + +export { + startCompletion, + getCommandCompletions, + getOpenCompletions, + getTabCompletions, + getPropertyCompletions, + completionNext, + completionPrev, +}; |