mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
checkpoint cmd-fg
This commit is contained in:
@@ -51,7 +51,8 @@ CREATE TABLE screen_window (
|
||||
name varchar(50) NOT NULL,
|
||||
layout json NOT NULL,
|
||||
selectedline int NOT NULL,
|
||||
scrolltop int NOT NULL,
|
||||
anchor json NOT NULL,
|
||||
focustype varchar(12) NOT NULL,
|
||||
PRIMARY KEY (sessionid, screenid, windowid)
|
||||
);
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ CREATE TABLE screen_window (
|
||||
windowid varchar(36) NOT NULL,
|
||||
name varchar(50) NOT NULL,
|
||||
layout json NOT NULL,
|
||||
selectedline int NOT NULL,
|
||||
anchor json NOT NULL,
|
||||
focustype varchar(12) NOT NULL,
|
||||
PRIMARY KEY (sessionid, screenid, windowid)
|
||||
);
|
||||
CREATE TABLE remote_instance (
|
||||
|
||||
+29
-12
@@ -260,6 +260,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
|
||||
if sw != nil {
|
||||
updateMap := make(map[string]interface{})
|
||||
updateMap[sstore.SWField_SelectedLine] = rtnLine.LineNum
|
||||
updateMap[sstore.SWField_Focus] = sstore.SWFocusCmd
|
||||
sw, err = sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
|
||||
if err != nil {
|
||||
// ignore error again (nothing to do)
|
||||
@@ -267,10 +268,10 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
|
||||
}
|
||||
}
|
||||
update := sstore.ModelUpdate{
|
||||
Line: rtnLine,
|
||||
Cmd: cmd,
|
||||
ScreenWindow: sw,
|
||||
Interactive: pk.Interactive,
|
||||
Line: rtnLine,
|
||||
Cmd: cmd,
|
||||
ScreenWindows: []*sstore.ScreenWindowType{sw},
|
||||
Interactive: pk.Interactive,
|
||||
}
|
||||
sstore.MainBus.SendUpdate(ids.SessionId, update)
|
||||
ctxVal := ctx.Value(historyContextKey)
|
||||
@@ -444,6 +445,8 @@ func ScreenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
|
||||
return update, nil
|
||||
}
|
||||
|
||||
var swAnchorRe = regexp.MustCompile("^(\\d+)(?::(\\d+))?$")
|
||||
|
||||
func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window)
|
||||
if err != nil {
|
||||
@@ -451,12 +454,25 @@ func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
|
||||
}
|
||||
var setNonST bool // scrolltop does not receive an update
|
||||
updateMap := make(map[string]interface{})
|
||||
if pk.Kwargs["scrolltop"] != "" {
|
||||
stVal, err := resolveNonNegInt(pk.Kwargs["scrolltop"], 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/sw:set invalid scrolltop argument: %v", err)
|
||||
if pk.Kwargs["anchor"] != "" {
|
||||
m := swAnchorRe.FindStringSubmatch(pk.Kwargs["anchor"])
|
||||
if m == nil {
|
||||
return nil, fmt.Errorf("/sw:set invalid anchor argument (must be [line] or [line]:[offset])")
|
||||
}
|
||||
updateMap[sstore.SWField_ScrollTop] = stVal
|
||||
anchorLine, _ := strconv.Atoi(m[1])
|
||||
updateMap[sstore.SWField_AnchorLine] = anchorLine
|
||||
if m[2] != "" {
|
||||
anchorOffset, _ := strconv.Atoi(m[2])
|
||||
updateMap[sstore.SWField_AnchorOffset] = anchorOffset
|
||||
}
|
||||
}
|
||||
if pk.Kwargs["focus"] != "" {
|
||||
focusVal := pk.Kwargs["focus"]
|
||||
if focusVal != sstore.SWFocusInput && focusVal != sstore.SWFocusCmd && focusVal != sstore.SWFocusCmdFg {
|
||||
return nil, fmt.Errorf("/sw:set invalid focus argument %q, must be %s", focusVal, formatStrs([]string{sstore.SWFocusInput, sstore.SWFocusCmd, sstore.SWFocusCmdFg}, "or", false))
|
||||
}
|
||||
updateMap[sstore.SWField_Focus] = focusVal
|
||||
setNonST = true
|
||||
}
|
||||
if pk.Kwargs["line"] != "" {
|
||||
sw, err := sstore.GetScreenWindowByIds(ctx, ids.SessionId, ids.ScreenId, ids.WindowId)
|
||||
@@ -478,7 +494,7 @@ func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
|
||||
updateMap[sstore.SWField_SelectedLine] = ritem.Num
|
||||
}
|
||||
if len(updateMap) == 0 {
|
||||
return nil, fmt.Errorf("/sw:set no updates, can set %s", formatStrs([]string{"line", "scrolltop"}, "or", false))
|
||||
return nil, fmt.Errorf("/sw:set no updates, can set %s", formatStrs([]string{"line", "scrolltop", "focus"}, "or", false))
|
||||
}
|
||||
sw, err := sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
|
||||
if err != nil {
|
||||
@@ -487,7 +503,7 @@ func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
|
||||
if !setNonST {
|
||||
return nil, nil
|
||||
}
|
||||
return sstore.ModelUpdate{ScreenWindow: sw}, nil
|
||||
return sstore.ModelUpdate{ScreenWindows: []*sstore.ScreenWindowType{sw}}, nil
|
||||
}
|
||||
|
||||
func UnSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@@ -1258,12 +1274,13 @@ func CommentCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
}
|
||||
updateMap := make(map[string]interface{})
|
||||
updateMap[sstore.SWField_SelectedLine] = rtnLine.LineNum
|
||||
updateMap[sstore.SWField_Focus] = sstore.SWFocusInput
|
||||
sw, err := sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
|
||||
if err != nil {
|
||||
// ignore error again (nothing to do)
|
||||
fmt.Printf("/comment error updating screen-window selected line: %v\n", err)
|
||||
}
|
||||
update := sstore.ModelUpdate{Line: rtnLine, ScreenWindow: sw}
|
||||
update := sstore.ModelUpdate{Line: rtnLine, ScreenWindows: []*sstore.ScreenWindowType{sw}}
|
||||
return update, nil
|
||||
}
|
||||
|
||||
|
||||
+22
-6
@@ -494,8 +494,8 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
||||
query = `INSERT INTO screen (sessionid, screenid, name, activewindowid, screenidx, screenopts, ownerid, sharemode) VALUES (?, ?, ?, ?, ?, ?, '', 'local')`
|
||||
tx.ExecWrap(query, sessionId, newScreenId, screenName, newWindowId, maxScreenIdx+1, ScreenOptsType{})
|
||||
layout := LayoutType{Type: LayoutFull}
|
||||
query = `INSERT INTO screen_window (sessionid, screenid, windowid, name, layout, selectedline, scrolltop) VALUES (?, ?, ?, ?, ?, ?, ?)`
|
||||
tx.ExecWrap(query, sessionId, newScreenId, newWindowId, DefaultScreenWindowName, layout, 0, 0)
|
||||
query = `INSERT INTO screen_window (sessionid, screenid, windowid, name, layout, selectedline, anchor, focustype) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
tx.ExecWrap(query, sessionId, newScreenId, newWindowId, DefaultScreenWindowName, layout, 0, "", "input")
|
||||
if activate {
|
||||
query = `UPDATE session SET activescreenid = ? WHERE sessionid = ?`
|
||||
tx.ExecWrap(query, newScreenId, sessionId)
|
||||
@@ -690,6 +690,12 @@ func AppendCmdErrorPk(ctx context.Context, errPk *packet.CmdErrorPacketType) err
|
||||
})
|
||||
}
|
||||
|
||||
type SWKey struct {
|
||||
SessionId string
|
||||
ScreenId string
|
||||
WindowId string
|
||||
}
|
||||
|
||||
func HangupAllRunningCmds(ctx context.Context) error {
|
||||
return WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE cmd SET status = ? WHERE status = ?`
|
||||
@@ -1101,8 +1107,10 @@ func UpdateRemote(ctx context.Context, remoteId string, editMap map[string]inter
|
||||
}
|
||||
|
||||
const (
|
||||
SWField_ScrollTop = "scrolltop" // int
|
||||
SWField_AnchorLine = "anchorline" // int
|
||||
SWField_AnchorOffset = "anchoroffset" // int
|
||||
SWField_SelectedLine = "selectedline" // int
|
||||
SWField_Focus = "focustype" // string
|
||||
)
|
||||
|
||||
func UpdateScreenWindow(ctx context.Context, sessionId string, screenId string, windowId string, editMap map[string]interface{}) (*ScreenWindowType, error) {
|
||||
@@ -1112,14 +1120,22 @@ func UpdateScreenWindow(ctx context.Context, sessionId string, screenId string,
|
||||
if !tx.Exists(query, sessionId, screenId, windowId) {
|
||||
return fmt.Errorf("screen-window not found")
|
||||
}
|
||||
if stVal, found := editMap[SWField_ScrollTop]; found {
|
||||
query = `UPDATE screen_window SET scrolltop = ? WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
tx.ExecWrap(query, stVal, sessionId, screenId, windowId)
|
||||
if anchorLine, found := editMap[SWField_AnchorLine]; found {
|
||||
query = `UPDATE screen_window SET anchor = json_set(anchor, '$.anchorline', ?) WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
tx.ExecWrap(query, anchorLine, sessionId, screenId, windowId)
|
||||
}
|
||||
if anchorOffset, found := editMap[SWField_AnchorOffset]; found {
|
||||
query = `UPDATE screen_window SET anchor = json_set(anchor, '$.anchoroffset', ?) WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
tx.ExecWrap(query, anchorOffset, sessionId, screenId, windowId)
|
||||
}
|
||||
if sline, found := editMap[SWField_SelectedLine]; found {
|
||||
query = `UPDATE screen_window SET selectedline = ? WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
tx.ExecWrap(query, sline, sessionId, screenId, windowId)
|
||||
}
|
||||
if focusType, found := editMap[SWField_Focus]; found {
|
||||
query = `UPDATE screen_window SET focustype = ? WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
tx.ExecWrap(query, focusType, sessionId, screenId, windowId)
|
||||
}
|
||||
var sw ScreenWindowType
|
||||
query = `SELECT * FROM screen_window WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
found := tx.GetWrap(&sw, query, sessionId, screenId, windowId)
|
||||
|
||||
+27
-7
@@ -62,6 +62,12 @@ const (
|
||||
RemoteTypeSsh = "ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
SWFocusInput = "input"
|
||||
SWFocusCmd = "cmd"
|
||||
SWFocusCmdFg = "cmd-fg"
|
||||
)
|
||||
|
||||
var globalDBLock = &sync.Mutex{}
|
||||
var globalDB *sqlx.DB
|
||||
var globalDBErr error
|
||||
@@ -375,14 +381,28 @@ func (l LayoutType) Value() (driver.Value, error) {
|
||||
return quickValueJson(l)
|
||||
}
|
||||
|
||||
type SWAnchorType struct {
|
||||
AnchorLine int `json:"anchorline,omitempty"`
|
||||
AnchorOffset int `json:"anchoroffset,omitempty"`
|
||||
}
|
||||
|
||||
func (a *SWAnchorType) Scan(val interface{}) error {
|
||||
return quickScanJson(a, val)
|
||||
}
|
||||
|
||||
func (a SWAnchorType) Value() (driver.Value, error) {
|
||||
return quickValueJson(a)
|
||||
}
|
||||
|
||||
type ScreenWindowType struct {
|
||||
SessionId string `json:"sessionid"`
|
||||
ScreenId string `json:"screenid"`
|
||||
WindowId string `json:"windowid"`
|
||||
Name string `json:"name"`
|
||||
Layout LayoutType `json:"layout"`
|
||||
SelectedLine int `json:"selectedline"`
|
||||
ScrollTop int `json:"scrolltop"`
|
||||
SessionId string `json:"sessionid"`
|
||||
ScreenId string `json:"screenid"`
|
||||
WindowId string `json:"windowid"`
|
||||
Name string `json:"name"`
|
||||
Layout LayoutType `json:"layout"`
|
||||
SelectedLine int `json:"selectedline"`
|
||||
Anchor SWAnchorType `json:"anchor"`
|
||||
FocusType string `json:"focustype"`
|
||||
|
||||
// only for updates
|
||||
Remove bool `json:"remove,omitempty"`
|
||||
|
||||
+12
-12
@@ -29,18 +29,18 @@ func (PtyDataUpdate) UpdateType() string {
|
||||
}
|
||||
|
||||
type ModelUpdate struct {
|
||||
Sessions []*SessionType `json:"sessions,omitempty"`
|
||||
ActiveSessionId string `json:"activesessionid,omitempty"`
|
||||
Window *WindowType `json:"window,omitempty"`
|
||||
ScreenWindow *ScreenWindowType `json:"screenwindow,omitempty"`
|
||||
Line *LineType `json:"line,omitempty"`
|
||||
Cmd *CmdType `json:"cmd,omitempty"`
|
||||
CmdLine *CmdLineType `json:"cmdline,omitempty"`
|
||||
Info *InfoMsgType `json:"info,omitempty"`
|
||||
Remotes []interface{} `json:"remotes,omitempty"` // []*remote.RemoteState
|
||||
History *HistoryInfoType `json:"history,omitempty"`
|
||||
Interactive bool `json:"interactive"`
|
||||
Connect bool `json:"connect,omitempty"`
|
||||
Sessions []*SessionType `json:"sessions,omitempty"`
|
||||
ActiveSessionId string `json:"activesessionid,omitempty"`
|
||||
Window *WindowType `json:"window,omitempty"`
|
||||
ScreenWindows []*ScreenWindowType `json:"screenwindows,omitempty"`
|
||||
Line *LineType `json:"line,omitempty"`
|
||||
Cmd *CmdType `json:"cmd,omitempty"`
|
||||
CmdLine *CmdLineType `json:"cmdline,omitempty"`
|
||||
Info *InfoMsgType `json:"info,omitempty"`
|
||||
Remotes []interface{} `json:"remotes,omitempty"` // []*remote.RemoteState
|
||||
History *HistoryInfoType `json:"history,omitempty"`
|
||||
Interactive bool `json:"interactive"`
|
||||
Connect bool `json:"connect,omitempty"`
|
||||
}
|
||||
|
||||
func (ModelUpdate) UpdateType() string {
|
||||
|
||||
Reference in New Issue
Block a user