aboutsummaryrefslogtreecommitdiff
path: root/xP/public/xP.js
diff options
context:
space:
mode:
Diffstat (limited to 'xP/public/xP.js')
-rw-r--r--xP/public/xP.js98
1 files changed, 82 insertions, 16 deletions
diff --git a/xP/public/xP.js b/xP/public/xP.js
index e18d03b..b62d6c2 100644
--- a/xP/public/xP.js
+++ b/xP/public/xP.js
@@ -197,7 +197,11 @@ rpc.addEventListener('Ping', event => {
rpc.addEventListener('BufferUpdate', event => {
let e = event.detail, b = buffers.get(e.bufferName)
if (b === undefined) {
- buffers.set(e.bufferName, (b = {lines: []}))
+ buffers.set(e.bufferName, (b = {
+ lines: [],
+ history: [],
+ historyAt: 0,
+ }))
bufferResetStats(b)
}
b.hideUnimportant = e.hideUnimportant
@@ -247,6 +251,9 @@ rpc.addEventListener('BufferActivate', event => {
old.inputStart = textarea.selectionStart
old.inputEnd = textarea.selectionEnd
old.inputDirection = textarea.selectionDirection
+ // Note that we effectively overwrite the newest line
+ // with the current textarea contents, and jump there.
+ old.historyAt = old.history.length
}
textarea.value = ''
@@ -324,6 +331,15 @@ for (let i = 0; i < 24; i++) {
// ---- UI ---------------------------------------------------------------------
+// On macOS, the Alt/Option key transforms characters, which basically breaks
+// all event.altKey shortcuts, so require combining them with Control as well
+// on that system.
+function hasShortcutModifiers(event) {
+ // This method of detection only works with Blink browsers, as of writing.
+ return event.altKey && !event.metaKey &&
+ (navigator.userAgentData?.platform === 'macOS') === event.ctrlKey
+}
+
let linkRE = [
/https?:\/\//,
/([^\[\](){}<>"'\s]|\([^\[\](){}<>"'\s]*\))+/,
@@ -584,27 +600,71 @@ let Input = {
bufferName: bufferCurrent,
text: textarea.value,
})
+
+ // b.history[b.history.length] is virtual, and is represented
+ // either by textarea contents when it's currently being edited,
+ // or by b.input in all other cases.
+ let b = buffers.get(bufferCurrent)
+ b.history.push(textarea.value)
+ b.historyAt = b.history.length
textarea.value = ''
return true
},
+ previous: textarea => {
+ let b = buffers.get(bufferCurrent)
+ if (b === undefined)
+ return false
+
+ // TODO: Ding otherwise.
+ if (b.historyAt > 0) {
+ if (b.historyAt == b.history.length)
+ b.input = textarea.value
+ textarea.value = b.history[--b.historyAt]
+ }
+ return true
+ },
+
+ next: textarea => {
+ let b = buffers.get(bufferCurrent)
+ if (b === undefined)
+ return false
+
+ // TODO: Ding otherwise.
+ if (b.historyAt < b.history.length) {
+ if (++b.historyAt == b.history.length)
+ textarea.value = b.input
+ else
+ textarea.value = b.history[b.historyAt]
+ }
+ return true
+ },
+
onKeyDown: event => {
// TODO: And perhaps on other actions, too.
rpc.send({command: 'Active'})
let textarea = event.currentTarget
let handled = false
- switch (event.keyCode) {
- case 9:
- if (!event.ctrlKey && !event.metaKey && !event.altKey &&
- !event.shiftKey)
+ if (hasShortcutModifiers(event)) {
+ switch (event.key) {
+ case 'p':
+ handled = Input.previous(textarea)
+ break
+ case 'n':
+ handled = Input.next(textarea)
+ break
+ }
+ } else if (!event.altKey && !event.ctrlKey && !event.metaKey &&
+ !event.shiftKey) {
+ switch (event.keyCode) {
+ case 9:
handled = Input.complete(textarea)
- break
- case 13:
- if (!event.ctrlKey && !event.metaKey && !event.altKey &&
- !event.shiftKey)
+ break
+ case 13:
handled = Input.submit(textarea)
- break
+ break
+ }
}
if (handled)
event.preventDefault()
@@ -636,28 +696,34 @@ let Main = {
window.addEventListener('load', () => m.mount(document.body, Main))
document.addEventListener('keydown', event => {
- if (rpc.ws == undefined || event.ctrlKey || event.metaKey)
+ if (rpc.ws == undefined || !hasShortcutModifiers(event))
return
- if (event.altKey && event.key == 'Tab') {
+ switch (event.key) {
+ case 'Tab':
if (bufferLast !== undefined)
bufferActivate(bufferLast)
- } else if (event.altKey && event.key == 'h') {
+ break
+ case 'h':
bufferToggleLog()
- } else if (event.altKey && event.key == 'a') {
+ break
+ case 'a':
for (const [name, b] of buffers)
if (name !== bufferCurrent && b.newMessages) {
bufferActivate(name)
break
}
- } else if (event.altKey && event.key == '!') {
+ break
+ case '!':
for (const [name, b] of buffers)
if (name !== bufferCurrent && b.highlighted) {
bufferActivate(name)
break
}
- } else
+ break
+ default:
return
+ }
event.preventDefault()
})