src/includes/guide/menu/base.ts
import { QuickPickItem } from 'vscode';
import {
InputStep,
MultiStepInput
} from '../../utils/multiStepInput';
import {
AbstractState,
Guide,
} from '../base/abc';
import { AbstractMenuGuide } from './abc';
import { VSCodePreset } from '../../utils/base/vscodePreset';
import {
Command,
TerminalCommand,
Question,
QUESTION_TYPE,
} from '../../utils/base/type';
import { Optional } from '../../utils/base/optional';
import * as Constant from '../../constant';
const items = {
back: VSCodePreset.create(VSCodePreset.icons.reply, 'Return', 'Back to previous.'),
exit: VSCodePreset.create(VSCodePreset.icons.signOut, 'Exit', 'Exit this extenion.'),
};
export class MenuGuide extends AbstractMenuGuide {
public init(): void {
super.init();
this.items = this.items.concat(
this.commandItems,
this.isRoot ? [items.exit] : [items.back]
);
}
protected getExecute(label: string | undefined): (() => Promise<void>) | undefined {
switch (label) {
case items.back.label:
this.prev();
case items.exit.label:
return undefined;
default:
return this.item();
}
}
private item(): (() => Promise<void>) | undefined {
const [data, key, location] = this.getCommand(this.getLabelStringByItem);
const type = data[this.settings.itemId.type];
if (Constant.DATA_TYPE.command === type) {
this.state.command = (data as Command)[this.settings.itemId.command];
return undefined;
} else if (Constant.DATA_TYPE.terminalCommand === type) {
return this.terminalCommand(data as TerminalCommand);
} else {
this.state.title = `${this.title}/${this.getLabelStringByItem}`;
this.state.location = location;
this.state.hierarchy = this.hierarchy.concat(key);
return async () => {
this.setNextSteps([{ key: 'MenuGuide' }]);
};
}
}
private terminalCommand(command: TerminalCommand): (() => Promise<void>) | undefined {
const name = this.activeItem?.label;
const questions = Optional.ofNullable(command.questions).orElseNonNullable({});
const keys = Object.keys(questions);
if (0 < keys.length) {
const first = Optional.ofNullable(keys.shift()).orElseThrow(ReferenceError('Question not found...'));
const state = this.createBaseState('', this.settings.itemId.questions, Object.keys(questions).length, first);
const guides = [] as Array<Guide>;
keys.forEach(
(key) => {
guides.push(this.getGuide(key, command, questions));
}
);
return async () => {
this.setNextSteps([this.getGuide(
first,
command,
questions,
Object.assign(state, { guides: guides, name: name })
)]);
};
} else {
this.state.name = name;
this.state.terminalCommand = command[this.settings.itemId.command];
this.state.autoRun = Optional.ofNullable(command[this.settings.itemId.autoRun]).orElseNonNullable(true);
this.state.singleton = Optional.ofNullable(command[this.settings.itemId.singleton]).orElseNonNullable(false);
return undefined;
}
}
private getGuide(
name: string,
command: TerminalCommand,
questions: Record<string, Question>,
state?: Partial<AbstractState>,
): Guide {
const guide = {} as Guide;
const question = questions[name];
guide.key = QUESTION_TYPE.text === question.type ? 'QuestionInputGuide' : 'SelectQuestionGuide';
guide.state = state ? state : { itemId: name };
guide.args = [command, question];
return guide;
}
}
export class HistoryGuide extends AbstractMenuGuide {
public init(): void {
super.init();
this.items = this.settings.history.map((item) => {
return { label: VSCodePreset.icons.terminal.label, description: item.command } as QuickPickItem;
}).concat(
[items.exit]
);
}
public async show(input: MultiStepInput):Promise<void | InputStep> {
if (!this.settings.enableHistory) {
this.state.message = 'The history function is disabled.';
} else if (this.settings.enableHistory && 0 === this.settings.history.length) {
this.state.message = 'No history.';
} else {
await super.show(input);
}
}
protected getExecute(label: string | undefined): (() => Promise<void>) | undefined {
if (this.activeItem && items.exit.label !== label) {
const item = this.settings.history.find((item) => this.activeItem?.description === item.command);
this.state.name = item?.name;
this.state.terminalCommand = item?.command;
this.state.autoRun = item?.autoRun;
this.state.singleton = Optional.ofNullable(item?.singleton).orElseNonNullable(false);
}
return undefined;
}
}