aboutsummaryrefslogtreecommitdiff
path: root/xP
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-09-18 05:53:44 +0200
committerPřemysl Eric Janouch <p@janouch.name>2022-09-18 05:54:23 +0200
commitec20fdef7badebc12621e20c0d66de94243fdb1a (patch)
treeda41981a4f7953714b2697c4ee1d66c90f99e669 /xP
parent21e5d80ab1505442c96e11075f09d98bcaa211ba (diff)
downloadxK-ec20fdef7badebc12621e20c0d66de94243fdb1a.tar.gz
xK-ec20fdef7badebc12621e20c0d66de94243fdb1a.tar.xz
xK-ec20fdef7badebc12621e20c0d66de94243fdb1a.zip
xP: show all completion options
Diffstat (limited to 'xP')
-rw-r--r--xP/public/xP.css17
-rw-r--r--xP/public/xP.js42
2 files changed, 52 insertions, 7 deletions
diff --git a/xP/public/xP.css b/xP/public/xP.css
index c231620..96d6525 100644
--- a/xP/public/xP.css
+++ b/xP/public/xP.css
@@ -91,6 +91,7 @@ button {
display: flex;
flex-direction: column;
overflow: hidden;
+ position: relative;
}
.filler {
flex: auto;
@@ -170,6 +171,22 @@ button {
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 {
font: inherit;
padding: .05em .3em;
diff --git a/xP/public/xP.js b/xP/public/xP.js
index 1cdb8b0..dbba7e2 100644
--- a/xP/public/xP.js
+++ b/xP/public/xP.js
@@ -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 = {
view: vnode => {
return m('.buffer-container', {}, [
m('.filler'),
bufferLog !== undefined ? m(Log) : m(Buffer),
+ m(Completions),
])
},
}
@@ -711,17 +728,20 @@ let Input = {
let preceding = utf8Encode(textarea.value).slice(0, resp.start)
let start = utf8Decode(preceding).length
-
- // TODO: Somehow display remaining options, or cycle through.
- if (resp.completions.length) {
+ if (resp.completions.length > 0) {
textarea.setRangeText(resp.completions[0],
start, textarea.selectionEnd, 'end')
- } else {
- beep()
}
- if (resp.completions.length === 1)
+
+ if (resp.completions.length == 1) {
textarea.setRangeText(' ',
textarea.selectionStart, textarea.selectionEnd, 'end')
+ } else {
+ beep()
+ }
+
+ if (resp.completions.length > 1)
+ Completions.reset(resp.completions.slice(1))
})
return true
},
@@ -886,7 +906,15 @@ let Input = {
},
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(),
+ })
},
}