Skip to content

Commit

Permalink
feat(prompt): improve search and suggestions (#153)
Browse files Browse the repository at this point in the history
  • Loading branch information
c4spar committed Mar 5, 2021
1 parent e1a6bb2 commit 6597205
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 46 deletions.
28 changes: 28 additions & 0 deletions _utils/distance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export function distance(a: string, b: string): number {
if (a.length == 0) {
return b.length;
}
if (b.length == 0) {
return a.length;
}
const matrix = [];
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
Math.min(matrix[i][j - 1] + 1, matrix[i - 1][j] + 1),
);
}
}
}
return matrix[b.length][a.length];
}
30 changes: 1 addition & 29 deletions flags/_utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { IFlagOptions } from "./types.ts";
import { distance } from "../_utils/distance.ts";

/** Convert param case string to camel case. */
export function paramCaseToCamelCase(str: string): string {
Expand Down Expand Up @@ -76,35 +77,6 @@ function isOption(option: IFlagOptions, name: string) {
(option.aliases && option.aliases.indexOf(name) !== -1);
}

function distance(a: string, b: string) {
if (a.length == 0) {
return b.length;
}
if (b.length == 0) {
return a.length;
}
const matrix = [];
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1,
Math.min(matrix[i][j - 1] + 1, matrix[i - 1][j] + 1),
);
}
}
}
return matrix[b.length][a.length];
}

function closest(str: string, arr: string[]): string | undefined {
let minDistance = Infinity;
let minIndex = 0;
Expand Down
33 changes: 22 additions & 11 deletions prompt/_generic_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "./_generic_input.ts";
import { blue, bold, dim, stripColor, yellow } from "./deps.ts";
import { Figures } from "./figures.ts";
import { distance } from "../_utils/distance.ts";

/** Select key options. */
export interface GenericListKeys extends GenericInputKeys {
Expand Down Expand Up @@ -105,13 +106,19 @@ export abstract class GenericList<T, V, S extends GenericListSettings<T, V>>
}

protected match(): void {
this.options = this.settings.options.filter(
(option: GenericListOption) =>
stripColor(option.name ?? option.value).toString().toLowerCase()
.startsWith(
this.getCurrentInputValue().toLowerCase(),
),
);
const input: string = this.getCurrentInputValue().toLowerCase();
if (!input.length) {
this.options = this.settings.options.slice();
} else {
this.options = this.settings.options
.filter((option: GenericListOptionSettings) =>
match(option.name) ||
(option.name !== option.value && match(option.value))
)
.sort((a: GenericListOptionSettings, b: GenericListOptionSettings) =>
distance(a.name, input) - distance(b.name, input)
);
}
this.listIndex = Math.max(
0,
Math.min(this.options.length - 1, this.listIndex),
Expand All @@ -123,6 +130,12 @@ export abstract class GenericList<T, V, S extends GenericListSettings<T, V>>
this.listOffset,
),
);

function match(value: string): boolean {
return stripColor(value)
.toLowerCase()
.includes(input);
}
}

protected message(): string {
Expand All @@ -146,15 +159,13 @@ export abstract class GenericList<T, V, S extends GenericListSettings<T, V>>
return "";
}
const selected: number = this.listIndex + 1;
const actions: Array<[string, Array<string>]> = [];

actions.push(
const actions: Array<[string, Array<string>]> = [
["Next", [Figures.ARROW_DOWN]],
["Previous", [Figures.ARROW_UP]],
["Next Page", [Figures.PAGE_DOWN]],
["Previous Page", [Figures.PAGE_UP]],
["Submit", [Figures.ENTER]],
);
];

return "\n" + this.settings.indent + blue(Figures.INFO) +
bold(` ${selected}/${this.options.length} `) +
Expand Down
22 changes: 16 additions & 6 deletions prompt/_generic_suggestions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "./_generic_input.ts";
import { blue, bold, dim, stripColor, underline } from "./deps.ts";
import { Figures } from "./figures.ts";
import { distance } from "../_utils/distance.ts";

/** Input keys options. */
export interface GenericSuggestionsKeys extends GenericInputKeys {
Expand Down Expand Up @@ -79,12 +80,21 @@ export abstract class GenericSuggestions<
if (!this.settings.suggestions?.length) {
return;
}
this.suggestions = this.settings.suggestions.filter(
(value: string | number) =>
stripColor(value.toString()).toLowerCase().startsWith(
this.getCurrentInputValue().toLowerCase(),
),
);
const input: string = this.getCurrentInputValue().toLowerCase();
if (!input.length) {
this.suggestions = this.settings.suggestions.slice();
} else {
this.suggestions = this.settings.suggestions
.filter((value: string | number) =>
stripColor(value.toString())
.toLowerCase()
.startsWith(input)
)
.sort((a: string | number, b: string | number) =>
distance((a || a).toString(), input) -
distance((b || b).toString(), input)
);
}
this.suggestionsIndex = Math.max(
this.getCurrentInputValue().trim().length === 0 ? -1 : 0,
Math.min(this.suggestions.length - 1, this.suggestionsIndex),
Expand Down

0 comments on commit 6597205

Please sign in to comment.