123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- 'use strict';
- const Select = require('./select');
- const highlight = (input, color) => {
- let val = input.toLowerCase();
- return str => {
- let s = str.toLowerCase();
- let i = s.indexOf(val);
- let colored = color(str.slice(i, i + val.length));
- return i >= 0 ? str.slice(0, i) + colored + str.slice(i + val.length) : str;
- };
- };
- class AutoComplete extends Select {
- constructor(options) {
- super(options);
- this.cursorShow();
- }
- moveCursor(n) {
- this.state.cursor += n;
- }
- dispatch(ch) {
- return this.append(ch);
- }
- space(ch) {
- return this.options.multiple ? super.space(ch) : this.append(ch);
- }
- append(ch) {
- let { cursor, input } = this.state;
- this.input = input.slice(0, cursor) + ch + input.slice(cursor);
- this.moveCursor(1);
- return this.complete();
- }
- delete() {
- let { cursor, input } = this.state;
- if (!input) return this.alert();
- this.input = input.slice(0, cursor - 1) + input.slice(cursor);
- this.moveCursor(-1);
- return this.complete();
- }
- deleteForward() {
- let { cursor, input } = this.state;
- if (input[cursor] === void 0) return this.alert();
- this.input = `${input}`.slice(0, cursor) + `${input}`.slice(cursor + 1);
- return this.complete();
- }
- number(ch) {
- return this.append(ch);
- }
- async complete() {
- this.completing = true;
- this.choices = await this.suggest(this.input, this.state._choices);
- this.state.limit = void 0; // allow getter/setter to reset limit
- this.index = Math.min(Math.max(this.visible.length - 1, 0), this.index);
- await this.render();
- this.completing = false;
- }
- suggest(input = this.input, choices = this.state._choices) {
- if (typeof this.options.suggest === 'function') {
- return this.options.suggest.call(this, input, choices);
- }
- let str = input.toLowerCase();
- return choices.filter(ch => ch.message.toLowerCase().includes(str));
- }
- pointer() {
- return '';
- }
- format() {
- if (!this.focused) return this.input;
- if (this.options.multiple && this.state.submitted) {
- return this.selected.map(ch => this.styles.primary(ch.message)).join(', ');
- }
- if (this.state.submitted) {
- let value = this.value = this.input = this.focused.value;
- return this.styles.primary(value);
- }
- return this.input;
- }
- async render() {
- if (this.state.status !== 'pending') return super.render();
- let style = this.options.highlight
- ? this.options.highlight.bind(this)
- : this.styles.placeholder;
- let color = highlight(this.input, style);
- let choices = this.choices;
- this.choices = choices.map(ch => ({ ...ch, message: color(ch.message) }));
- await super.render();
- this.choices = choices;
- }
- submit() {
- if (this.options.multiple) {
- this.value = this.selected.map(ch => ch.name);
- }
- return super.submit();
- }
- }
- module.exports = AutoComplete;
|