Skip to content

Commit

Permalink
refactor(prompt): refactor prompt rendering (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
c4spar committed Nov 27, 2020
1 parent 0e14b51 commit f4ca0bb
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 103 deletions.
3 changes: 2 additions & 1 deletion prompt/_generic_input.ts
Expand Up @@ -63,13 +63,14 @@ export abstract class GenericInput<T, S extends GenericInputPromptSettings<T>>
* Set prompt message.
* @param message Prompt message.
*/
protected setPrompt(message: string) {
protected render(message: string) {
message += " " + this.settings.pointer + " ";

const length = stripColor(message).length;

message += underline(this.input);

this.clear();
this.write(message);

this.screen.cursorTo(length + this.index + 1);
Expand Down
17 changes: 2 additions & 15 deletions prompt/_generic_list.ts
Expand Up @@ -51,19 +51,6 @@ export abstract class GenericList<T, V, S extends GenericListSettings<T, V>>
return { value: label, disabled: true };
}

/**
* Map string option values to options.
* @param optValues List options.
*/
protected static mapValues(
optValues: GenericListValueOptions,
): GenericListOption[] {
return Object.values(optValues)
.map((item: string | GenericListOption) =>
typeof item === "string" ? { value: item } : item
);
}

/**
* Set list option defaults.
* @param item List option.
Expand All @@ -80,9 +67,9 @@ export abstract class GenericList<T, V, S extends GenericListSettings<T, V>>
* Set prompt message.
* @param message Prompt message.
*/
protected setPrompt(message: string): void {
protected render(message: string): void {
this.clear();
this.writeLine(message);

this.writeListItems();
}

Expand Down
17 changes: 5 additions & 12 deletions prompt/_generic_prompt.ts
Expand Up @@ -47,7 +47,6 @@ export abstract class GenericPrompt<

protected screen = AnsiEscape.from(Deno.stdout);
protected lastError: string | undefined;
protected isRunning = false;
protected value: T | undefined;

/**
Expand All @@ -71,10 +70,10 @@ export abstract class GenericPrompt<
}

/**
* Set prompt message.
* Render prompt.
* @param message Prompt message.
*/
protected abstract setPrompt(message: string): void | Promise<void>;
protected abstract render(message: string): void | Promise<void>;

/**
* Handle user input event.
Expand Down Expand Up @@ -114,17 +113,12 @@ export abstract class GenericPrompt<

/** Execute the prompt. */
protected async execute(): Promise<T> {
if (this.lastError || this.isRunning) {
this.clear();
}

this.isRunning = true;

// be sure there are empty lines after the cursor to fix restoring the cursor if terminal output is bigger than terminal window.
const message: string = await this.getMessage();
// be sure there are empty lines after the cursor to fix restoring the
// cursor if terminal output is longer than terminal window.
this.preBufferEmptyLines(this.lastError || this.settings.hint || "");

await this.setPrompt(message);
await this.render(message);

if (this.lastError || this.settings.hint) {
this.screen.cursorSave();
Expand Down Expand Up @@ -152,7 +146,6 @@ export abstract class GenericPrompt<
this.screen.cursorShow();

GenericPrompt.injectedValue = undefined;
this.isRunning = false;

return this.value;
}
Expand Down
47 changes: 15 additions & 32 deletions prompt/checkbox.ts
Expand Up @@ -109,37 +109,18 @@ export class Checkbox
* @param options Checkbox options.
*/
protected static mapOptions(options: CheckboxOptions): CheckboxValueSettings {
return this.mapValues(options.options)
.map((item) => this.mapItem(item, options.default));
}

/**
* Map string option values to options.
* @param optValues Checkbox option.
*/
protected static mapValues(
optValues: CheckboxValueOptions,
): CheckboxOption[] {
return super.mapValues(optValues) as CheckboxOption[];
}

/**
* Set checkbox option defaults.
* @param item Checkbox option.
* @param defaults Checkbox defaults.
*/
protected static mapItem(
item: CheckboxOption,
defaults?: string[],
): CheckboxOptionSettings {
return {
...super.mapItem(item),
checked: typeof item.checked === "undefined" && defaults &&
defaults.indexOf(item.value) !== -1
? true
: !!item.checked,
icon: typeof item.icon === "undefined" ? true : item.icon,
};
return options.options
.map((item: string | CheckboxOption) =>
typeof item === "string" ? { value: item } : item
)
.map((item) => ({
...this.mapItem(item),
checked: typeof item.checked === "undefined" &&
options.default?.indexOf(item.value) !== -1
? true
: !!item.checked,
icon: typeof item.icon === "undefined" ? true : item.icon,
}));
}

/**
Expand Down Expand Up @@ -232,7 +213,9 @@ export class Checkbox
value.every((val) =>
typeof val === "string" &&
val.length > 0 &&
this.settings.options.findIndex((option) => option.value === val) !== -1
this.settings.options.findIndex((option: CheckboxOptionSettings) =>
option.value === val
) !== -1
);

if (!isValidValue) {
Expand Down
17 changes: 7 additions & 10 deletions prompt/list.ts
Expand Up @@ -53,24 +53,21 @@ export class List extends GenericInput<string[], ListSettings> {
* Set prompt message.
* @param message Prompt message.
*/
protected setPrompt(message: string) {
protected render(message: string) {
message += " " + this.settings.pointer + " ";

const length = new TextEncoder().encode(stripColor(message)).length;

const oldInput: string = this.input;
const oldInputParts: string[] = oldInput.trimLeft().split(this.regexp());
const separator: string = this.settings.separator + " ";

this.input = oldInputParts.join(`${this.settings.separator} `);

message += oldInputParts.map((val: string) => underline(val)).join(
`${this.settings.separator} `,
);

const inputDiff = oldInput.length - this.input.length;
message += oldInputParts.map((val: string) => underline(val))
.join(separator);

this.index -= inputDiff;
this.input = oldInputParts.join(separator);
this.index -= oldInput.length - this.input.length;

this.clear();
this.write(message);

this.screen.cursorTo(length - 1 + this.index);
Expand Down
5 changes: 2 additions & 3 deletions prompt/secret.ts
Expand Up @@ -50,19 +50,18 @@ export class Secret extends GenericInput<string, SecretSettings> {
* Set prompt message.
* @param message Prompt message.
*/
protected setPrompt(message: string) {
protected render(message: string) {
if (this.settings.hidden) {
this.screen.cursorHide();
}

message += " " + this.settings.pointer + " ";

const length = new TextEncoder().encode(stripColor(message)).length;

const secret = this.settings.hidden ? "" : "*".repeat(this.input.length);

message += underline(secret);

this.clear();
this.write(message);

this.screen.cursorTo(length - 1 + this.index);
Expand Down
26 changes: 5 additions & 21 deletions prompt/select.ts
Expand Up @@ -77,28 +77,12 @@ export class Select extends GenericList<string, string, SelectSettings> {
}).prompt();
}

/**
* Map string option values to options and set option defaults.
* @param options List options.
*/
protected static mapOptions(options: SelectOptions): SelectValueSettings {
return this.mapValues(options.options).map((item) => this.mapItem(item));
}

/**
* Map string option values to options.
* @param optValues Select option.
*/
protected static mapValues(optValues: SelectValueOptions): SelectOption[] {
return super.mapValues(optValues) as SelectOption[];
}

/**
* Set select option defaults.
* @param item Select option.
*/
protected static mapItem(item: SelectOption): SelectOptionSettings {
return super.mapItem(item) as SelectOptionSettings;
return options.options
.map((item: string | SelectOption) =>
typeof item === "string" ? { value: item } : item
)
.map((item) => this.mapItem(item));
}

/**
Expand Down
17 changes: 8 additions & 9 deletions prompt/toggle.ts
Expand Up @@ -63,21 +63,20 @@ export class Toggle extends GenericPrompt<boolean, string, ToggleSettings> {
* Set prompt message.
* @param message Prompt message.
*/
protected setPrompt(message: string) {
message += ` ${this.settings.pointer} `;
protected render(message: string) {
message += " " + this.settings.pointer + " ";

if (this.status === this.settings.active) {
message += `${dim(`${this.settings.inactive} /`)} ${
underline(this.settings.active)
}`;
message += dim(this.settings.inactive + " /") + " " +
underline(this.settings.active);
} else if (this.status === this.settings.inactive) {
message += `${underline(this.settings.inactive)} ${
dim(`/ ${this.settings.active}`)
}`;
message += underline(this.settings.inactive) + " " +
dim("/ " + this.settings.active);
} else {
message += dim(`${this.settings.inactive} / ${this.settings.active}`);
message += dim(this.settings.inactive + " / " + this.settings.active);
}

this.clear();
this.write(message);
}

Expand Down

0 comments on commit f4ca0bb

Please sign in to comment.