import { GenericPrompt } from "./_generic_prompt.ts";import { GenericSuggestions, GenericSuggestionsKeys, GenericSuggestionsOptions, GenericSuggestionsSettings,} from "./_generic_suggestions.ts";import { dim, normalize, underline } from "./deps.ts";
export interface ListOptions extends GenericSuggestionsOptions<string[], string> { keys?: ListKeys; separator?: string; minLength?: number; maxLength?: number; minTags?: number; maxTags?: number;}
interface ListSettings extends GenericSuggestionsSettings<string[], string> { separator: string; minLength: number; maxLength: number; minTags: number; maxTags: number; keys?: ListKeys;}
export type ListKeys = GenericSuggestionsKeys;
export class List extends GenericSuggestions<string[], string> { protected readonly settings: ListSettings;
public static prompt(options: string | ListOptions): Promise<string[]> { return new this(options).prompt(); }
public static inject(value: string): void { GenericPrompt.inject(value); }
constructor(options: string | ListOptions) { super(); if (typeof options === "string") { options = { message: options }; } this.settings = this.getDefaultSettings(options); }
public getDefaultSettings(options: ListOptions): ListSettings { return { ...super.getDefaultSettings(options), separator: options.separator ?? ",", minLength: options.minLength ?? 0, maxLength: options.maxLength ?? Infinity, minTags: options.minTags ?? 0, maxTags: options.maxTags ?? Infinity, }; }
protected input(): string { const oldInput: string = this.inputValue; const tags: string[] = this.getTags(oldInput); const separator: string = this.settings.separator + " ";
if (this.settings.files && tags.length > 1) { tags[tags.length - 2] = normalize(tags[tags.length - 2]); }
this.inputValue = tags.join(separator);
const diff = oldInput.length - this.inputValue.length; this.inputIndex -= diff; this.cursor.x -= diff;
return tags .map((val: string) => underline(val)) .join(separator) + dim(this.getSuggestion()); }
protected getTags(value: string = this.inputValue): Array<string> { return value.trim().split(this.regexp()); }
protected regexp(): RegExp { return new RegExp( this.settings.separator === " " ? ` +` : ` *${this.settings.separator} *`, ); }
protected success(value: string[]): string | undefined { this.saveSuggestions(...value); return super.success(value); }
protected getValue(): string { const input = this.inputValue.replace(/,+\s*$/, "");
if (!this.settings.files) { return input; }
return this.getTags(input) .map(normalize) .join(this.settings.separator + " "); }
protected getCurrentInputValue(): string { return this.getTags().pop() ?? ""; }
protected addChar(char: string): void { switch (char) { case this.settings.separator: if ( this.inputValue.length && this.inputValue.trim().slice(-1) !== this.settings.separator ) { super.addChar(char); } this.suggestionsIndex = -1; this.suggestionsOffset = 0; break; default: super.addChar(char); } }
protected deleteChar(): void { if (this.inputValue[this.inputIndex - 1] === " ") { super.deleteChar(); } super.deleteChar(); }
protected async complete(): Promise<string> { const tags = this.getTags().slice(0, -1); tags.push(await super.complete()); return tags.join(this.settings.separator + " "); }
protected validate(value: string): boolean | string { if (typeof value !== "string") { return false; }
const values = this.transform(value);
for (const val of values) { if (val.length < this.settings.minLength) { return `Value must be longer than ${this.settings.minLength} but has a length of ${val.length}.`; } if (val.length > this.settings.maxLength) { return `Value can't be longer than ${this.settings.maxLength} but has a length of ${val.length}.`; } }
if (values.length < this.settings.minTags) { return `The minimum number of tags is ${this.settings.minTags} but got ${values.length}.`; } if (values.length > this.settings.maxTags) { return `The maximum number of tags is ${this.settings.maxTags} but got ${values.length}.`; }
return true; }
protected transform(value: string): string[] { return this.getTags(value).filter((val) => val !== ""); }
protected format(value: string[]): string { return value.join(`, `); }}