diff --git a/quickinput-sample/src/extension.ts b/quickinput-sample/src/extension.ts index e2bb6371a..cdfd0dbf3 100644 --- a/quickinput-sample/src/extension.ts +++ b/quickinput-sample/src/extension.ts @@ -7,14 +7,17 @@ import { window, commands, ExtensionContext } from 'vscode'; import { showQuickPick, showInputBox } from './basicInput'; import { multiStepInput } from './multiStepInput'; import { quickOpen } from './quickOpen'; +import { getPromptCommand } from './promptCommandWithHistory'; export function activate(context: ExtensionContext) { context.subscriptions.push(commands.registerCommand('samples.quickInput', async () => { + const promptCommand = getPromptCommand(context.globalState); const options: { [key: string]: (context: ExtensionContext) => Promise } = { showQuickPick, showInputBox, multiStepInput, quickOpen, + promptCommand }; const quickPick = window.createQuickPick(); quickPick.items = Object.keys(options).map(label => ({ label })); diff --git a/quickinput-sample/src/promptCommandWithHistory.ts b/quickinput-sample/src/promptCommandWithHistory.ts new file mode 100644 index 000000000..c587fc79b --- /dev/null +++ b/quickinput-sample/src/promptCommandWithHistory.ts @@ -0,0 +1,93 @@ +import { window, Disposable, Memento } from 'vscode'; +import { QuickPickItem } from 'vscode'; + +const HISTORY_KEY = 'HISTORY_KEY'; + + +/** + * A command prompt with history + * + */ +export const getPromptCommand = (memo: Memento) => { + const pickCommand = getPickCommand(memo); + // §TODO: cache promptCommand! + return async function promptCommand() { + const command = await pickCommand(); + if (command) { + window.showInformationMessage(`You picked the following command: '${command}'`); + } + }; +}; + +class CommandItem implements QuickPickItem { + public static HISTORY: string = 'history'; + public static INPUT: string = 'input'; + + public label: string; + public description?: string; + public type: string; + + constructor(type: string, label: string, description?: string) { + this.type = type; + this.label = label; + this.description = description; + } + + static input(content: string): CommandItem { + return new CommandItem(CommandItem.INPUT, content, '(current input)'); + } + static history(content: string, description?: string): CommandItem { + return new CommandItem(CommandItem.HISTORY, content, description); + } +} + +const getPickCommand = (memo: Memento) => async function pickCommand() { + const disposables: Disposable[] = []; + try { + return await new Promise((resolve, reject) => { + const input = window.createQuickPick(); + input.placeholder = 'Type a command'; + input.items = []; + const historyItems: CommandItem[] = memo.get(HISTORY_KEY, []).map( + (cmd: string, index: number) => CommandItem.history(cmd, `(history item ${index})`) + ); + input.items = historyItems; + + const updateQuickPick = (value?: string): void => { + input.items = value + ? [CommandItem.input(value)].concat(historyItems) + : historyItems; + // §todo: add autocomplete suggestions + }; + + disposables.push( + input.onDidChangeValue(updateQuickPick), + input.onDidChangeSelection((items: CommandItem[]) => { + const item = items[0]; + if (item.type === CommandItem.HISTORY) { + resolve(item.label); + input.hide(); + // do not record new input in history + // §todo : maybe reorder + } else if (item.type === CommandItem.INPUT) { + resolve(item.label); + input.hide(); + // record new input in history + if (!item.label.startsWith(' ')) { + const currentHistory: string[] = memo.get(HISTORY_KEY, []); + currentHistory.unshift(item.label); + memo.update(HISTORY_KEY, currentHistory); + } + } + }), + input.onDidHide(() => { + resolve(undefined); + input.dispose(); + }) + ); + input.show(); + }); + } finally { + disposables.forEach(d => d.dispose()); + } +};