Spaces:
Runtime error
Runtime error
; | |
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; | |