Merge pull request #560 from alanbernstein/autocomplete-improvements

Autocomplete improvements
This commit is contained in:
alanbernstein 2017-05-30 10:30:10 -05:00 committed by GitHub
commit 03aeb64e11

View file

@ -1,8 +1,9 @@
class REPL {
constructor(input, output, button) {
constructor(input, output, button, completer) {
this.input = input
this.output = output
this.button = button
this.completer = completer
this.history = []
this.history_index = 0
this.history_buffer = ''
@ -16,21 +17,6 @@ class REPL {
UP_ARROW: 38,
DOWN_ARROW: 40
}
var keywords = {
// keyword: length of substring that comes after cursor
"SetBit()": 1,
"ClearBit()": 1,
"SetRowAttrs()": 1,
"SetColumnAttrs()": 1,
"Bitmap()": 1,
"Union()": 1,
"Intersect()": 1,
"Difference()": 1,
"Count()": 1,
"Range()": 1,
"TopN()": 1,
"frame=": 0,
}
this.input.addEventListener("keydown", function(e) {
if (e.keyCode == keys.UP_ARROW) {
@ -70,35 +56,7 @@ class REPL {
}
if (e.keyCode == keys.TAB) {
e.preventDefault()
// extract word fragment ending at cursor. a word fragment:
// - starts with last nonalpha character before cursor (or beginning of string)
// - ends at cursor
var word_start = repl.input.selectionEnd-1
while(word_start>0) {
var c = repl.input.value.charCodeAt(word_start)
if(!((c>64 && c<91) || (c>96 && c<123))) {
word_start++
break
}
word_start--
}
var input_word = repl.input.value.substring(word_start, repl.input.selectionEnd)
// check for keyword match and insert
// this just stops at the first match
for(var keyword in keywords) {
if(keyword.startsWith(input_word)){
var cursor_pos = repl.input.selectionEnd
var completion = keyword.substring(input_word.length)
var before = repl.input.value.substring(0, cursor_pos)
var after = repl.input.value.substring(cursor_pos)
repl.input.value = before + completion + after
var new_pos = cursor_pos + completion.length - keywords[keyword]
repl.input.setSelectionRange(new_pos, new_pos)
break
}
}
repl.completer.complete()
}
})
repl.button.onclick = function() {
@ -444,11 +402,94 @@ Date.prototype.timeNow = function () {
populate_version()
class Autocompleter {
constructor(input, output) {
this.input = input
this.output = output
this.keyword_map = this.static_keywords
this.init_dynamic_keywords()
}
get static_keywords() {
return {
// keyword: length of substring that comes after cursor
"SetBit()": 1,
"ClearBit()": 1,
"SetRowAttrs()": 1,
"SetColumnAttrs()": 1,
"Bitmap()": 1,
"Union()": 1,
"Intersect()": 1,
"Difference()": 1,
"Count()": 1,
"Range()": 1,
"TopN()": 1,
"frame=": 0,
}
}
complete() {
var completer = this
// extract word fragment ending at cursor. a word fragment:
// - starts with last nonalpha character before cursor (or beginning of string)
// - ends at cursor
var word_start = completer.input.selectionEnd-1
while(word_start>0) {
var c = completer.input.value.charCodeAt(word_start)
if(!((c>64 && c<91) || (c>96 && c<123))) {
word_start++
break
}
word_start--
}
var input_word = completer.input.value.substring(word_start, completer.input.selectionEnd)
// check for keyword match and insert if exactly one match
var matches = []
for(var keyword in this.keyword_map) {
if(keyword.startsWith(input_word)){
matches.push(keyword)
}
}
if(matches.length > 1) {
// completer.output.innerHTML = whatever
}
if(matches.length == 1) {
// completer.output.innerHTML = ""
var cursor_pos = completer.input.selectionEnd
var completion = matches[0].substring(input_word.length)
var before = completer.input.value.substring(0, cursor_pos)
var after = completer.input.value.substring(cursor_pos)
completer.input.value = before + completion + after
var new_pos = cursor_pos + completion.length - this.keyword_map[matches[0]]
completer.input.setSelectionRange(new_pos, new_pos)
}
}
init_dynamic_keywords() {
// hit /schema, parse indexes, frames, rowlabels, columnlabels, add to list
}
add_keyword() {
// call when index or frame created in webui
}
remove_keyword() {
// call when index or frame deleted in webui
// issue: if e.g. multiple indexes have same frame, removing one removes all.
// solution: maintain count. requires more elaborate representation of keywords.
}
}
var input = document.getElementById('query')
var output = document.getElementById('outputs')
var button = document.getElementById('query-btn')
var autocomplete_output = document.getElementById('autocomplete-container')
repl = new REPL(input, output, button)
autocompleter = new Autocompleter(input, autocomplete_output)
repl = new REPL(input, output, button, autocompleter)
repl.populate_index_dropdown()
repl.bind_events()