@@ -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);