From cc058490b2583590db7cfed3b13793f628b02359 Mon Sep 17 00:00:00 2001 From: sawka Date: Tue, 16 Aug 2022 15:59:28 -0700 Subject: [PATCH] cmd-up cmd-down working, new line type, remotealias --- src/emain.ts | 9 +++ src/main.tsx | 26 +++++--- src/model.ts | 167 +++++++++++++++++++++++++++++++++++++++++++++++-- src/preload.js | 2 + src/sh2.ts | 1 + src/term.ts | 3 +- src/types.ts | 8 ++- src/util.ts | 6 +- 8 files changed, 203 insertions(+), 19 deletions(-) diff --git a/src/emain.ts b/src/emain.ts index d58ff75a..f88434f9 100644 --- a/src/emain.ts +++ b/src/emain.ts @@ -73,6 +73,15 @@ function createWindow() { } return; } + if (input.meta && (input.code == "ArrowUp" || input.code == "ArrowDown")) { + if (input.code == "ArrowUp") { + win.webContents.send("meta-arrowup"); + } else { + win.webContents.send("meta-arrowdown"); + } + e.preventDefault(); + return; + } if (input.code.startsWith("Digit") && input.meta) { let digitNum = parseInt(input.code.substr(5)); if (isNaN(digitNum) || digitNum < 1 || digitNum > 9) { diff --git a/src/main.tsx b/src/main.tsx index 74051c35..4c956e24 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -120,7 +120,7 @@ class LineText extends React.Component<{sw : ScreenWindow, line : LineType}, {}> let line = this.props.line; let formattedTime = getLineDateStr(line.ts); return ( -
+
S
@@ -139,7 +139,7 @@ class LineText extends React.Component<{sw : ScreenWindow, line : LineType}, {}> } @mobxReact.observer -class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width : number, interObs : IntersectionObserver, initVis : boolean}, {}> { +class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width : number, interObs : IntersectionObserver, initVis : boolean, cmdRefNum : number}, {}> { termLoaded : mobx.IObservableValue = mobx.observable.box(false); lineRef : React.RefObject = React.createRef(); iobsVal : InterObsValue = null; @@ -249,7 +249,7 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width render() { let {sw, line, width} = this.props; let model = GlobalModel; - let lineid = line.lineid.toString(); + let lineid = line.lineid; let formattedTime = getLineDateStr(line.ts); let cmd = model.getCmd(line); if (cmd == null) { @@ -271,11 +271,12 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width let detached = (status == "detached"); let termOpts = cmd.getTermOpts(); let isFocused = sw.getIsFocused(line.cmdid); + let cmdRefNumStr = (this.props.cmdRefNum == null ? "?" : this.props.cmdRefNum.toString()); return ( -
+
-
= 5}, {"running": running}, {"detached": detached})} onClick={this.doRefresh}> - {lineid} +
= 5}, {"running": running}, {"detached": detached})} onClick={this.doRefresh}> + {cmdRefNumStr}
@@ -301,7 +302,7 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width } @mobxReact.observer -class Line extends React.Component<{sw : ScreenWindow, line : LineType, width : number, interObs : IntersectionObserver, initVis : boolean}, {}> { +class Line extends React.Component<{sw : ScreenWindow, line : LineType, width : number, interObs : IntersectionObserver, initVis : boolean, cmdRefNum : number}, {}> { render() { let line = this.props.line; if (line.linetype == "text") { @@ -702,6 +703,15 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> { if (win.lines.length == 0) { linesStyle.display = "none"; } + let cmdRefMap : Record = {}; + let cmdNum = 1; + for (let i=0; i
@@ -709,7 +719,7 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
- win.lines.length-1-7}/> + win.lines.length-1-7} cmdRefNum={cmdRefMap[line.lineid] ?? 0}/>
diff --git a/src/model.ts b/src/model.ts index 42f98e63..0147e189 100644 --- a/src/model.ts +++ b/src/model.ts @@ -28,6 +28,8 @@ type ElectronApi = { getId : () => string, onTCmd : (callback : (mods : KeyModsType) => void) => void, onICmd : (callback : (mods : KeyModsType) => void) => void, + onMetaArrowUp : (callback : () => void) => void, + onMetaArrowDown : (callback : () => void) => void, onBracketCmd : (callback : (event : any, arg : {relative : number}, mods : KeyModsType) => void) => void, onDigitCmd : (callback : (event : any, arg : {digit : number}, mods : KeyModsType) => void) => void, contextScreen : (screenOpts : {screenId : string}, position : {x : number, y : number}) => void, @@ -285,7 +287,8 @@ class Window { if (load) { this.loaded.set(true); } - genMergeSimpleData(this.lines, win.lines, (l : LineType) => String(l.lineid), (l : LineType) => l.lineid); + genMergeSimpleData(this.lines, win.lines, (l : LineType) => String(l.lineid), (l : LineType) => sprintf("%013d:%s", l.ts, l.lineid)); + let cmds = win.cmds || []; for (let i=0; i line.lineid) { + if (curTs > line.ts || (curTs == line.ts && lineId > line.lineid)) { break; } } @@ -637,6 +660,13 @@ class InputModel { } }; +type LineFocusType = { + cmdInputFocus : boolean, + lineid? : string, + windowid? : string, + cmdid? : string, +}; + class Model { clientId : string; activeSessionId : OV = mobx.observable.box(null); @@ -661,6 +691,8 @@ class Model { this.inputModel = new InputModel(); getApi().onTCmd(this.onTCmd.bind(this)); getApi().onICmd(this.onICmd.bind(this)); + getApi().onMetaArrowUp(this.onMetaArrowUp.bind(this)); + getApi().onMetaArrowDown(this.onMetaArrowDown.bind(this)); getApi().onBracketCmd(this.onBracketCmd.bind(this)); getApi().onDigitCmd(this.onDigitCmd.bind(this)); } @@ -726,13 +758,122 @@ class Model { GlobalInput.createNewScreen(); } - onICmd(mods : KeyModsType) { + focusCmdInput() : void { let elem = document.getElementById("main-cmd-input"); if (elem != null) { elem.focus(); } } + onICmd(mods : KeyModsType) { + this.focusCmdInput(); + } + + getFocusedLine() : LineFocusType { + let elem = document.getElementById("main-cmd-input"); + if (document.activeElement == elem) { + return {cmdInputFocus: true}; + } + let lineElem : any = document.activeElement.closest(".line[data-lineid]"); + if (lineElem == null) { + return null; + } + return { + cmdInputFocus: false, + lineid: lineElem.dataset.lineid, + windowid: lineElem.dataset.windowid, + cmdid: lineElem.dataset.cmdid, + }; + } + + onMetaArrowUp() : void { + let focus = this.getFocusedLine(); + if (focus == null) { + return; + } + let sw : ScreenWindow = null; + if (focus.cmdInputFocus) { + sw = this.getActiveSW(); + } + else { + sw = this.getSWByWindowId(focus.windowid); + } + if (sw == null) { + return; + } + let win = sw.getWindow(); + if (win == null) { + return; + } + let runningLines = win.getRunningCmdLines(); + if (runningLines.length == 0) { + return; + } + let switchLine : LineType = null; + if (focus.cmdInputFocus) { + switchLine = runningLines[runningLines.length-1]; + } + else { + let foundIdx = -1; + for (let i=0; i 0) { + switchLine = runningLines[foundIdx-1]; + } + } + if (switchLine == null || switchLine.cmdid == null) { + return; + } + let termWrap = sw.getTermWrap(switchLine.cmdid); + if (termWrap == null || termWrap.terminal == null) { + return; + } + termWrap.terminal.focus(); + console.log("arrow-up", this.getFocusedLine(), "=>", switchLine); + } + + onMetaArrowDown() : void { + let focus = this.getFocusedLine(); + if (focus == null || focus.cmdInputFocus) { + return; + } + let sw = this.getSWByWindowId(focus.windowid); + if (sw == null) { + return; + } + let win = sw.getWindow(); + if (win == null) { + return; + } + let runningLines = win.getRunningCmdLines(); + if (runningLines.length == 0) { + this.focusCmdInput(); + return; + } + let foundIdx = -1; + for (let i=0; i", interactive, update); + // console.log("run-update>", interactive, update); } getActiveSession() : Session { @@ -872,6 +1013,22 @@ class Model { return this.windows.get(screen.sessionId + "/" + activeWindowId); } + getActiveSW() : ScreenWindow { + let screen = this.getActiveScreen(); + if (screen == null) { + return null; + } + return screen.getActiveSW(); + } + + getSWByWindowId(windowId : string) : ScreenWindow { + let screen = this.getActiveScreen(); + if (screen == null) { + return null; + } + return screen.getSW(windowId); + } + getActiveScreen() : Screen { let session = this.getActiveSession(); if (session == null) { @@ -1049,7 +1206,7 @@ class Model { getRemoteByName(name : string) : RemoteType { for (let i=0; i ipcRenderer.sendSync("get-id"), onTCmd: (callback) => ipcRenderer.on("t-cmd", callback), onICmd: (callback) => ipcRenderer.on("i-cmd", callback), + onMetaArrowUp: (callback) => ipcRenderer.on("meta-arrowup", callback), + onMetaArrowDown: (callback) => ipcRenderer.on("meta-arrowdown", callback), onBracketCmd: (callback) => ipcRenderer.on("bracket-cmd", callback), onDigitCmd: (callback) => ipcRenderer.on("digit-cmd", callback), contextScreen: (screenOpts, position) => ipcRenderer.send("context-screen", screenOpts, position), diff --git a/src/sh2.ts b/src/sh2.ts index 90a808fe..09e22955 100644 --- a/src/sh2.ts +++ b/src/sh2.ts @@ -19,5 +19,6 @@ document.addEventListener("DOMContentLoaded", () => { }); (window as any).mobx = mobx; +(window as any).sprintf = sprintf; console.log("SCRIPTHAUS", VERSION) diff --git a/src/term.ts b/src/term.ts index c3742d08..5c981d0c 100644 --- a/src/term.ts +++ b/src/term.ts @@ -194,8 +194,9 @@ class TermWrap { this.dataUpdates.push({data: data, pos: pos}); return; } + console.log("pty-update", this.cmdId, this.ptyPos, data.length); if (pos > this.ptyPos) { - throw new Error(sprintf("invalid pty-update, data-pos[%d] does not match term-pos[%d]", pos, this.ptyPos)); + throw new Error(sprintf("invalid pty-update, data-pos[%d] does not match term-pos[%d] cmdid[%s]", pos, this.ptyPos, this.cmdId)); } if (pos < this.ptyPos) { let diff = this.ptyPos - pos; diff --git a/src/types.ts b/src/types.ts index e01cc66d..ace44d52 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,7 +17,7 @@ type SessionDataType = { type LineType = { sessionid : string, windowid : string, - lineid : number, + lineid : string, ts : number, userid : string, linetype : string, @@ -71,7 +71,9 @@ type ScreenWindowType = { type RemoteType = { remotetype : string, remoteid : string, - remotename : string, + physicalid : string, + remotealias : string, + remotecanonicalname : string, remotevars : Record, status : string, defaultstate : RemoteStateType, @@ -112,7 +114,7 @@ type HistoryItem = { sessionid : string, screenid : string, windowid : string, - lineid : number, + lineid : string, haderror : boolean, cmdid : string, cmdstr : string, diff --git a/src/util.ts b/src/util.ts index b32a3c71..b2072997 100644 --- a/src/util.ts +++ b/src/util.ts @@ -62,7 +62,7 @@ interface ISimpleDataType { remove? : boolean; } -function genMergeSimpleData(objs : mobx.IObservableArray, dataArr : T[], idFn : (obj : T) => string, sortIdxFn : (obj : T) => number) { +function genMergeSimpleData(objs : mobx.IObservableArray, dataArr : T[], idFn : (obj : T) => string, sortIdxFn : (obj : T) => string) { if (dataArr == null || dataArr.length == 0) { return; } @@ -86,7 +86,9 @@ function genMergeSimpleData(objs : mobx.IObservableAr let newObjs = Object.values(objMap); if (sortIdxFn) { newObjs.sort((a, b) => { - return sortIdxFn(a) - sortIdxFn(b); + let astr = sortIdxFn(a); + let bstr = sortIdxFn(b); + return astr.localeCompare(bstr); }); } objs.replace(newObjs);