81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import { Callable, Callable1, InputEvent, LineEdit, Variant } from 'godot'
|
|
import { export_, onready } from 'godot.annotations'
|
|
import { Enumerable, IEnumerable } from '../enumerable-ts/src/index'
|
|
import { Action } from './dev_console'
|
|
|
|
export default class AutocompleteLine extends LineEdit {
|
|
@export_(Variant.Type.TYPE_BOOL)
|
|
private auto_suggest: boolean = true
|
|
|
|
@onready("Suggestion")
|
|
private suggestion!: LineEdit
|
|
|
|
autocomplete_list: string[] = []
|
|
current_suggestions: string[] = []
|
|
suggestion_index: number = -1
|
|
suppress_focus_change: boolean = true
|
|
|
|
_on_text_changed!: Callable1<string>
|
|
|
|
_ready(): void {
|
|
this._on_text_changed = Callable.create(this, this.suggest)
|
|
|
|
if (this.auto_suggest) {
|
|
this.text_changed.connect(this._on_text_changed)
|
|
}
|
|
}
|
|
|
|
_input(event: InputEvent): void {
|
|
if (this.has_focus() && this.suppress_focus_change && event.is_action_pressed(Action.FocusNext)) {
|
|
this.accept_event()
|
|
this.autocomplete()
|
|
}
|
|
}
|
|
|
|
suggest(value: string): boolean {
|
|
this.reset()
|
|
|
|
if (value == '') {
|
|
return false
|
|
}
|
|
|
|
this.current_suggestions = this.fuzzy_find(value)
|
|
|
|
if (this.current_suggestions.length > 0) {
|
|
const suggestion = this.current_suggestions[0]
|
|
if (suggestion != null) {
|
|
// create the illusion that the text is autocompleting
|
|
// by replacing the already typed characters with spaces
|
|
const padded = suggestion.slice(value.length).padStart(suggestion.length, ' ')
|
|
this.suggestion.text = padded
|
|
return true
|
|
}
|
|
}
|
|
|
|
this.suggestion.text = ''
|
|
return false
|
|
}
|
|
|
|
set_caret_to_end() {
|
|
this.caret_column = this.text.length + 1
|
|
}
|
|
|
|
autocomplete() {
|
|
if (this.current_suggestions.length > 0) {
|
|
this.suggestion_index = (this.suggestion_index + 1) % this.current_suggestions.length
|
|
this.text = this.current_suggestions.at(this.suggestion_index) || ''
|
|
this.suggestion.clear()
|
|
this.set_caret_to_end()
|
|
}
|
|
}
|
|
|
|
fuzzy_find(value: string): string[] {
|
|
return this.autocomplete_list.filter(text => text != null && text.startsWith(value))
|
|
}
|
|
|
|
reset() {
|
|
this.current_suggestions = []
|
|
this.suggestion_index = -1
|
|
this.suggestion.text = ''
|
|
}
|
|
}
|