xP: show all completion options
This commit is contained in:
parent
21e5d80ab1
commit
ec20fdef7b
@ -91,6 +91,7 @@ button {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.filler {
|
.filler {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
@ -170,6 +171,22 @@ button {
|
|||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.completions {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: #fff;
|
||||||
|
padding: .05em .3em;
|
||||||
|
border-top: 1px solid #888;
|
||||||
|
|
||||||
|
max-height: 50%;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column wrap;
|
||||||
|
column-gap: .6em;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
padding: .05em .3em;
|
padding: .05em .3em;
|
||||||
|
@ -652,11 +652,28 @@ let Log = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let Completions = {
|
||||||
|
entries: [],
|
||||||
|
|
||||||
|
reset: list => {
|
||||||
|
Completions.entries = list || []
|
||||||
|
m.redraw()
|
||||||
|
},
|
||||||
|
|
||||||
|
view: vnode => {
|
||||||
|
if (!Completions.entries.length)
|
||||||
|
return
|
||||||
|
return m('.completions', {},
|
||||||
|
Completions.entries.map(option => m('.completion', {}, option)))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
let BufferContainer = {
|
let BufferContainer = {
|
||||||
view: vnode => {
|
view: vnode => {
|
||||||
return m('.buffer-container', {}, [
|
return m('.buffer-container', {}, [
|
||||||
m('.filler'),
|
m('.filler'),
|
||||||
bufferLog !== undefined ? m(Log) : m(Buffer),
|
bufferLog !== undefined ? m(Log) : m(Buffer),
|
||||||
|
m(Completions),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -711,17 +728,20 @@ let Input = {
|
|||||||
|
|
||||||
let preceding = utf8Encode(textarea.value).slice(0, resp.start)
|
let preceding = utf8Encode(textarea.value).slice(0, resp.start)
|
||||||
let start = utf8Decode(preceding).length
|
let start = utf8Decode(preceding).length
|
||||||
|
if (resp.completions.length > 0) {
|
||||||
// TODO: Somehow display remaining options, or cycle through.
|
|
||||||
if (resp.completions.length) {
|
|
||||||
textarea.setRangeText(resp.completions[0],
|
textarea.setRangeText(resp.completions[0],
|
||||||
start, textarea.selectionEnd, 'end')
|
start, textarea.selectionEnd, 'end')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.completions.length == 1) {
|
||||||
|
textarea.setRangeText(' ',
|
||||||
|
textarea.selectionStart, textarea.selectionEnd, 'end')
|
||||||
} else {
|
} else {
|
||||||
beep()
|
beep()
|
||||||
}
|
}
|
||||||
if (resp.completions.length === 1)
|
|
||||||
textarea.setRangeText(' ',
|
if (resp.completions.length > 1)
|
||||||
textarea.selectionStart, textarea.selectionEnd, 'end')
|
Completions.reset(resp.completions.slice(1))
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
@ -886,7 +906,15 @@ let Input = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
view: vnode => {
|
view: vnode => {
|
||||||
return m('textarea#input', {rows: 1, onkeydown: Input.onKeyDown})
|
return m('textarea#input', {
|
||||||
|
rows: 1,
|
||||||
|
onkeydown: Input.onKeyDown,
|
||||||
|
oninput: event => Completions.reset(),
|
||||||
|
// Sadly only supported in Firefox as of writing.
|
||||||
|
onselectionchange: event => Completions.reset(),
|
||||||
|
// The list of completions is scrollable without receiving focus.
|
||||||
|
onblur: event => Completions.reset(),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user