big update to handle cmd returnstate (still need to process new state with donepacket)

This commit is contained in:
sawka
2022-10-27 00:33:50 -07:00
parent d50ed6ca6c
commit 0060c8ffc2
7 changed files with 148 additions and 171 deletions
+31
View File
@@ -182,6 +182,36 @@ func HandleGetWindow(w http.ResponseWriter, r *http.Request) {
return
}
func HandleRtnState(w http.ResponseWriter, r *http.Request) {
qvals := r.URL.Query()
sessionId := qvals.Get("sessionid")
cmdId := qvals.Get("cmdid")
if sessionId == "" || cmdId == "" {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("must specify sessionid and cmdid")))
return
}
if _, err := uuid.Parse(sessionId); err != nil {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("invalid sessionid: %v", err)))
return
}
if _, err := uuid.Parse(cmdId); err != nil {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("invalid cmdid: %v", err)))
return
}
data, err := cmdrunner.GetRtnStateDiff(r.Context(), sessionId, cmdId)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("cannot get rtnstate diff: %v", err)))
return
}
w.WriteHeader(http.StatusOK)
w.Write(data)
return
}
func HandleRemotePty(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Credentials", "true")
@@ -393,6 +423,7 @@ func main() {
gr := mux.NewRouter()
gr.HandleFunc("/api/ptyout", HandleGetPtyOut)
gr.HandleFunc("/api/remote-pty", HandleRemotePty)
gr.HandleFunc("/api/rtnstate", HandleRtnState)
gr.HandleFunc("/api/get-window", HandleGetWindow)
gr.HandleFunc("/api/run-command", HandleRunCommand).Methods("GET", "POST", "OPTIONS")
gr.HandleFunc("/api/get-client-data", HandleGetClientData)
+2 -1
View File
@@ -79,6 +79,7 @@ CREATE TABLE line (
text text NOT NULL,
cmdid varchar(36) NOT NULL,
ephemeral boolean NOT NULL,
contentheight int NOT NULL,
PRIMARY KEY (sessionid, windowid, lineid)
);
@@ -116,7 +117,7 @@ CREATE TABLE cmd (
startpk json NOT NULL,
donepk json NOT NULL,
runout json NOT NULL,
usedrows int NOT NULL,
rtnstate bool NOT NULL,
PRIMARY KEY (sessionid, cmdid)
);
+33 -133
View File
@@ -39,7 +39,7 @@ var ColorNames = []string{"black", "red", "green", "yellow", "blue", "magenta",
var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"}
var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"}
var WindowCmds = []string{"run", "comment", "cd", "cr", "setenv", "unset", "clear", "sw", "alias", "unalias", "function", "source", "reset"}
var WindowCmds = []string{"run", "comment", "cd", "cr", "clear", "sw", "alias", "unalias", "function", "reset"}
var NoHistCmds = []string{"compgen", "line", "history"}
var GlobalCmds = []string{"session", "screen", "remote"}
@@ -72,11 +72,9 @@ func init() {
registerCmdFn("run", RunCommand)
registerCmdFn("eval", EvalCommand)
registerCmdFn("comment", CommentCommand)
registerCmdFn("cd", CdCommand)
// registerCmdFn("cd", CdCommand)
registerCmdFn("cr", CrCommand)
registerCmdFn("compgen", CompGenCommand)
registerCmdFn("setenv", SetEnvCommand)
registerCmdFn("unset", UnSetCommand)
registerCmdFn("clear", ClearCommand)
registerCmdFn("reset", ResetCommand)
@@ -114,8 +112,6 @@ func init() {
registerCmdFn("line:show", LineShowCommand)
registerCmdFn("history", HistoryCommand)
registerCmdFn("source", SourceCommand)
}
func getValidCommands() []string {
@@ -239,40 +235,6 @@ func getUITermOpts(uiContext *scpacket.UIContextType) *packet.TermOpts {
return termOpts
}
func SourceCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_RemoteConnected)
if err != nil {
return nil, fmt.Errorf("/source error: %w", err)
}
if len(pk.Args) != 1 {
return nil, fmt.Errorf("/source takes one argument (the file to source)")
}
cmdId := scbase.GenSCUUID()
runPacket := packet.MakeRunPacket()
runPacket.ReqId = uuid.New().String()
runPacket.CK = base.MakeCommandKey(ids.SessionId, cmdId)
runPacket.State = ids.Remote.RemoteState
runPacket.StateComplete = true
runPacket.UsePty = true
runPacket.TermOpts = getUITermOpts(pk.UIContext)
runPacket.Command = strings.TrimSpace(fmt.Sprintf("source %s", shellescape.Quote(pk.Args[0])))
runPacket.ReturnState = true
cmd, callback, err := remote.RunCommand(ctx, cmdId, ids.Remote.RemotePtr, ids.Remote.RemoteState, runPacket)
if callback != nil {
defer callback()
}
if err != nil {
return nil, err
}
update, err := addLineForCmd(ctx, "/source", true, ids, cmd)
if err != nil {
return nil, err
}
update.Interactive = pk.Interactive
sstore.MainBus.SendUpdate(ids.SessionId, update)
return nil, nil
}
func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_RemoteConnected)
if err != nil {
@@ -280,6 +242,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
}
cmdId := scbase.GenSCUUID()
cmdStr := firstArg(pk)
isRtnStateCmd := IsReturnStateCommand(cmdStr)
runPacket := packet.MakeRunPacket()
runPacket.ReqId = uuid.New().String()
runPacket.CK = base.MakeCommandKey(ids.SessionId, cmdId)
@@ -288,6 +251,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
runPacket.UsePty = true
runPacket.TermOpts = getUITermOpts(pk.UIContext)
runPacket.Command = strings.TrimSpace(cmdStr)
runPacket.ReturnState = resolveBool(pk.Kwargs["rtnstate"], isRtnStateCmd)
cmd, callback, err := remote.RunCommand(ctx, cmdId, ids.Remote.RemotePtr, ids.Remote.RemoteState, runPacket)
if callback != nil {
defer callback()
@@ -522,43 +486,6 @@ func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
return sstore.ModelUpdate{ScreenWindows: []*sstore.ScreenWindowType{sw}}, nil
}
func UnSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_RemoteConnected)
if err != nil {
return nil, fmt.Errorf("cannot unset: %v", err)
}
declMap := shexec.DeclMapFromState(ids.Remote.RemoteState)
unsetVars := make(map[string]bool)
for _, argStr := range pk.Args {
eqIdx := strings.Index(argStr, "=")
if eqIdx != -1 {
return nil, fmt.Errorf("invalid argument to setenv, '%s' (cannot contain equal sign)", argStr)
}
delete(declMap, argStr)
unsetVars[argStr] = true
}
if len(unsetVars) == 0 {
return nil, fmt.Errorf("no variables provided to unset")
}
state := *ids.Remote.RemoteState
state.ShellVars = shexec.SerializeDeclMap(declMap)
remoteInst, err := sstore.UpdateRemoteState(ctx, ids.SessionId, ids.WindowId, ids.Remote.RemotePtr, state)
if err != nil {
return nil, err
}
var cmdOutput bytes.Buffer
displayStateUpdate(&cmdOutput, *ids.Remote.RemoteState, remoteInst.State)
cmd, err := makeStaticCmd(ctx, "unset", ids, pk.GetRawStr(), cmdOutput.Bytes())
update, err := addLineForCmd(ctx, "/unset", false, ids, cmd)
if err != nil {
// TODO tricky error since the command was a success, but we can't show the output
return nil, err
}
update.Interactive = pk.Interactive
update.Sessions = sstore.MakeSessionsUpdateForRemote(ids.SessionId, remoteInst)
return update, nil
}
func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
if err != nil {
@@ -939,56 +866,6 @@ func RemoteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
return nil, fmt.Errorf("/remote requires a subcommand: %s", formatStrs([]string{"show"}, "or", false))
}
func SetEnvCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_RemoteConnected)
if err != nil {
return nil, fmt.Errorf("cannot setenv: %v", err)
}
declMap := shexec.DeclMapFromState(ids.Remote.RemoteState)
if len(pk.Args) == 0 {
var infoLines []string
for _, decl := range declMap {
line := fmt.Sprintf("%s=%s", decl.Name, shellescape.Quote(decl.Value))
infoLines = append(infoLines, line)
}
update := sstore.ModelUpdate{
Info: &sstore.InfoMsgType{
InfoTitle: fmt.Sprintf("environment for remote [%s]", ids.Remote.DisplayName),
InfoLines: infoLines,
},
}
return update, nil
}
setVars := make(map[string]bool)
for _, argStr := range pk.Args {
eqIdx := strings.Index(argStr, "=")
if eqIdx == -1 {
return nil, fmt.Errorf("invalid argument to setenv, '%s' (no equal sign)", argStr)
}
envName := argStr[:eqIdx]
envVal := argStr[eqIdx+1:]
declMap[envName] = &shexec.DeclareDeclType{Args: "x", Name: envName, Value: envVal}
setVars[envName] = true
}
state := *ids.Remote.RemoteState
state.ShellVars = shexec.SerializeDeclMap(declMap)
remoteInst, err := sstore.UpdateRemoteState(ctx, ids.SessionId, ids.WindowId, ids.Remote.RemotePtr, state)
if err != nil {
return nil, err
}
var cmdOutput bytes.Buffer
displayStateUpdate(&cmdOutput, *ids.Remote.RemoteState, remoteInst.State)
cmd, err := makeStaticCmd(ctx, "setenv", ids, pk.GetRawStr(), cmdOutput.Bytes())
update, err := addLineForCmd(ctx, "/setenv", false, ids, cmd)
if err != nil {
// TODO tricky error since the command was a success, but we can't show the output
return nil, err
}
update.Interactive = pk.Interactive
update.Sessions = sstore.MakeSessionsUpdateForRemote(ids.SessionId, remoteInst)
return update, nil
}
func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window)
if err != nil {
@@ -1814,21 +1691,25 @@ func formatTextTable(totalCols int, data [][]string, colMeta []ColMeta) []string
func displayStateUpdate(buf *bytes.Buffer, oldState packet.ShellState, newState packet.ShellState) {
if newState.Cwd != oldState.Cwd {
buf.WriteString(fmt.Sprintf("cwd %s\r\n", newState.Cwd))
buf.WriteString(fmt.Sprintf("cwd %s\n", newState.Cwd))
}
if !bytes.Equal(newState.ShellVars, oldState.ShellVars) {
newEnvMap := shexec.DeclMapFromState(&newState)
oldEnvMap := shexec.DeclMapFromState(&oldState)
for key, newVal := range newEnvMap {
oldVal, found := oldEnvMap[key]
if !found || oldVal.Value != newVal.Value {
buf.WriteString(fmt.Sprintf("%s=%s\r\n", key, shellescape.Quote(newVal.Value)))
if !found || ((oldVal.Value != newVal.Value) || (oldVal.IsExport() != newVal.IsExport())) {
var exportStr string
if newVal.IsExport() {
exportStr = "export "
}
buf.WriteString(fmt.Sprintf("%s%s=%s\n", exportStr, key, ShellQuote(newVal.Value, false, 50)))
}
}
for key, _ := range oldEnvMap {
_, found := newEnvMap[key]
if !found {
buf.WriteString(fmt.Sprintf("unset %s\r\n", key))
buf.WriteString(fmt.Sprintf("unset %s\n", key))
}
}
}
@@ -1844,7 +1725,7 @@ func displayStateUpdate(buf *bytes.Buffer, oldState packet.ShellState, newState
for aliasName, _ := range oldAliasMap {
_, found := newAliasMap[aliasName]
if !found {
buf.WriteString(fmt.Sprintf("unalias %s\r\n", shellescape.Quote(aliasName)))
buf.WriteString(fmt.Sprintf("unalias %s\n", shellescape.Quote(aliasName)))
}
}
}
@@ -1860,8 +1741,27 @@ func displayStateUpdate(buf *bytes.Buffer, oldState packet.ShellState, newState
for funcName, _ := range oldFuncMap {
_, found := newFuncMap[funcName]
if !found {
buf.WriteString(fmt.Sprintf("unset -f %s\r\n", shellescape.Quote(funcName)))
buf.WriteString(fmt.Sprintf("unset -f %s\n", shellescape.Quote(funcName)))
}
}
}
}
func GetRtnStateDiff(ctx context.Context, sessionId string, cmdId string) ([]byte, error) {
cmd, err := sstore.GetCmdById(ctx, sessionId, cmdId)
if err != nil {
return nil, err
}
if cmd == nil {
return nil, nil
}
if !cmd.RtnState {
return nil, nil
}
if cmd.DonePk == nil || cmd.DonePk.FinalState == nil {
return nil, nil
}
var outputBytes bytes.Buffer
displayStateUpdate(&outputBytes, cmd.RemoteState, *cmd.DonePk.FinalState)
return outputBytes.Bytes(), nil
}
+53 -13
View File
@@ -59,14 +59,8 @@ type BareMetaCmdDecl struct {
}
var BareMetaCmds = []BareMetaCmdDecl{
BareMetaCmdDecl{"cd", "cd"},
BareMetaCmdDecl{"cr", "cr"},
BareMetaCmdDecl{"setenv", "setenv"},
BareMetaCmdDecl{"export", "setenv"},
BareMetaCmdDecl{"unset", "unset"},
BareMetaCmdDecl{"clear", "clear"},
BareMetaCmdDecl{".", "source"},
BareMetaCmdDecl{"source", "source"},
BareMetaCmdDecl{"reset", "reset"},
}
@@ -123,7 +117,7 @@ func onlyRawArgs(metaCmd string, metaSubCmd string) bool {
}
// minimum maxlen=6
func ForceQuote(val string, maxLen int) string {
func ShellQuote(val string, forceQuote bool, maxLen int) string {
if maxLen < 6 {
maxLen = 6
}
@@ -134,10 +128,17 @@ func ForceQuote(val string, maxLen int) string {
}
return rtn
}
if len(rtn) > maxLen-2 {
return "\"" + rtn[0:maxLen-5] + "...\""
if forceQuote {
if len(rtn) > maxLen-2 {
return "\"" + rtn[0:maxLen-5] + "...\""
}
return "\"" + rtn + "\""
} else {
if len(rtn) > maxLen {
return rtn[0:maxLen-3] + "..."
}
return rtn
}
return "\"" + rtn + "\""
}
func setBracketArgs(argMap map[string]string, bracketStr string) error {
@@ -163,7 +164,7 @@ func setBracketArgs(argMap map[string]string, bracketStr string) error {
varVal = litStr[eqIdx+1:]
}
if !shexec.IsValidBashIdentifier(varName) {
wordErr = fmt.Errorf("invalid identifier %s in bracket args", ForceQuote(varName, 20))
wordErr = fmt.Errorf("invalid identifier %s in bracket args", ShellQuote(varName, true, 20))
return false
}
if varVal == "" {
@@ -181,6 +182,35 @@ func setBracketArgs(argMap map[string]string, bracketStr string) error {
return nil
}
// detects: export, declare, ., source, X=1, unset
func IsReturnStateCommand(cmdStr string) bool {
cmdReader := strings.NewReader(cmdStr)
parser := syntax.NewParser(syntax.Variant(syntax.LangBash))
file, err := parser.Parse(cmdReader, "cmd")
if err != nil {
return false
}
for _, stmt := range file.Stmts {
if callExpr, ok := stmt.Cmd.(*syntax.CallExpr); ok {
if len(callExpr.Assigns) > 0 && len(callExpr.Args) == 0 {
return true
}
if len(callExpr.Args) > 0 && len(callExpr.Args[0].Parts) > 0 {
lit, ok := callExpr.Args[0].Parts[0].(*syntax.Lit)
if ok {
if lit.Value == "." || lit.Value == "source" || lit.Value == "unset" || lit.Value == "cd" {
return true
}
}
}
} else if _, ok := stmt.Cmd.(*syntax.DeclClause); ok {
return true
}
}
return false
}
func EvalBracketArgs(origCmdStr string) (map[string]string, string, error) {
rtn := make(map[string]string)
if strings.HasPrefix(origCmdStr, " ") {
@@ -210,7 +240,11 @@ func EvalMetaCommand(ctx context.Context, origPk *scpacket.FeCommandPacketType)
if strings.TrimSpace(origPk.Args[0]) == "" {
return nil, fmt.Errorf("empty command")
}
metaCmd, metaSubCmd, commandArgs := parseMetaCmd(origPk.Args[0])
bracketArgs, cmdStr, err := EvalBracketArgs(origPk.Args[0])
if err != nil {
return nil, err
}
metaCmd, metaSubCmd, commandArgs := parseMetaCmd(cmdStr)
rtnPk := scpacket.MakeFeCommandPacket()
rtnPk.MetaCmd = metaCmd
rtnPk.MetaSubCmd = metaSubCmd
@@ -220,6 +254,9 @@ func EvalMetaCommand(ctx context.Context, origPk *scpacket.FeCommandPacketType)
for key, val := range origPk.Kwargs {
rtnPk.Kwargs[key] = val
}
for key, val := range bracketArgs {
rtnPk.Kwargs[key] = val
}
if onlyRawArgs(metaCmd, metaSubCmd) {
// don't evaluate arguments for /run or /comment
rtnPk.Args = []string{commandArgs}
@@ -228,7 +265,7 @@ func EvalMetaCommand(ctx context.Context, origPk *scpacket.FeCommandPacketType)
commandReader := strings.NewReader(commandArgs)
parser := syntax.NewParser(syntax.Variant(syntax.LangBash))
var words []*syntax.Word
err := parser.Words(commandReader, func(w *syntax.Word) bool {
err = parser.Words(commandReader, func(w *syntax.Word) bool {
words = append(words, w)
return true
})
@@ -338,6 +375,9 @@ func ParseFuncs(funcs string) (map[string]string, error) {
fmt.Printf("stmt-err: %v\n", err)
continue
}
if strings.HasPrefix(funcName, "_scripthaus_") {
continue
}
if funcName != "" {
rtn[funcName] = funcVal
}
+1
View File
@@ -1106,6 +1106,7 @@ func RunCommand(ctx context.Context, cmdId string, remotePtr sstore.RemotePtrTyp
StartPk: startPk,
DonePk: nil,
RunOut: nil,
RtnState: runPacket.ReturnState,
}
err = sstore.CreateCmdPtyFile(ctx, cmd.SessionId, cmd.CmdId, cmd.TermOpts.MaxPtySize)
if err != nil {
+4 -4
View File
@@ -623,8 +623,8 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
query = `SELECT nextlinenum FROM window WHERE sessionid = ? AND windowid = ?`
nextLineNum := tx.GetInt(query, line.SessionId, line.WindowId)
line.LineNum = int64(nextLineNum)
query = `INSERT INTO line ( sessionid, windowid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, ephemeral)
VALUES (:sessionid,:windowid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:ephemeral)`
query = `INSERT INTO line ( sessionid, windowid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, ephemeral, contentheight)
VALUES (:sessionid,:windowid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:ephemeral,:contentheight)`
tx.NamedExecWrap(query, line)
query = `UPDATE window SET nextlinenum = ? WHERE sessionid = ? AND windowid = ?`
tx.ExecWrap(query, nextLineNum+1, line.SessionId, line.WindowId)
@@ -632,8 +632,8 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
cmd.OrigTermOpts = cmd.TermOpts
cmdMap := cmd.ToMap()
query = `
INSERT INTO cmd ( sessionid, cmdid, remoteownerid, remoteid, remotename, cmdstr, remotestate, termopts, origtermopts, status, startpk, donepk, runout, usedrows)
VALUES (:sessionid,:cmdid,:remoteownerid,:remoteid,:remotename,:cmdstr,:remotestate,:termopts,:origtermopts,:status,:startpk,:donepk,:runout,:usedrows)
INSERT INTO cmd ( sessionid, cmdid, remoteownerid, remoteid, remotename, cmdstr, remotestate, termopts, origtermopts, status, startpk, donepk, rtnstate, runout)
VALUES (:sessionid,:cmdid,:remoteownerid,:remoteid,:remotename,:cmdstr,:remotestate,:termopts,:origtermopts,:status,:startpk,:donepk,:rtnstate,:runout)
`
tx.NamedExecWrap(query, cmdMap)
}
+24 -20
View File
@@ -28,6 +28,7 @@ import (
const LineTypeCmd = "cmd"
const LineTypeText = "text"
const LineNoHeight = -1
const DBFileName = "sh2.db"
const DefaultSessionName = "default"
@@ -496,19 +497,20 @@ func RIFromMap(m map[string]interface{}) *RemoteInstance {
}
type LineType struct {
SessionId string `json:"sessionid"`
WindowId string `json:"windowid"`
UserId string `json:"userid"`
LineId string `json:"lineid"`
Ts int64 `json:"ts"`
LineNum int64 `json:"linenum"`
LineNumTemp bool `json:"linenumtemp,omitempty"`
LineLocal bool `json:"linelocal"`
LineType string `json:"linetype"`
Text string `json:"text,omitempty"`
CmdId string `json:"cmdid,omitempty"`
Ephemeral bool `json:"ephemeral,omitempty"`
Remove bool `json:"remove,omitempty"`
SessionId string `json:"sessionid"`
WindowId string `json:"windowid"`
UserId string `json:"userid"`
LineId string `json:"lineid"`
Ts int64 `json:"ts"`
LineNum int64 `json:"linenum"`
LineNumTemp bool `json:"linenumtemp,omitempty"`
LineLocal bool `json:"linelocal"`
LineType string `json:"linetype"`
Text string `json:"text,omitempty"`
CmdId string `json:"cmdid,omitempty"`
Ephemeral bool `json:"ephemeral,omitempty"`
Remove bool `json:"remove,omitempty"`
ContentHeight int64 `json:"contentheight,omitempty"`
}
type ResolveItem struct {
@@ -575,11 +577,11 @@ type CmdType struct {
TermOpts TermOpts `json:"termopts"`
OrigTermOpts TermOpts `json:"origtermopts"`
Status string `json:"status"`
StartPk *packet.CmdStartPacketType `json:"startpk"`
DonePk *packet.CmdDonePacketType `json:"donepk"`
UsedRows int64 `json:"usedrows"`
RunOut []packet.PacketType `json:"runout"`
Remove bool `json:"remove"`
StartPk *packet.CmdStartPacketType `json:"startpk,omitempty"`
DonePk *packet.CmdDonePacketType `json:"donepk,omitempty"`
RunOut []packet.PacketType `json:"runout,omitempty"`
RtnState bool `json:"rtnstate,omitempty"`
Remove bool `json:"remove,omitempty"`
}
func (r *RemoteType) ToMap() map[string]interface{} {
@@ -644,7 +646,7 @@ func (cmd *CmdType) ToMap() map[string]interface{} {
rtn["startpk"] = quickJson(cmd.StartPk)
rtn["donepk"] = quickJson(cmd.DonePk)
rtn["runout"] = quickJson(cmd.RunOut)
rtn["usedrows"] = cmd.UsedRows
rtn["rtnstate"] = cmd.RtnState
return rtn
}
@@ -666,7 +668,7 @@ func CmdFromMap(m map[string]interface{}) *CmdType {
quickSetJson(&cmd.StartPk, m, "startpk")
quickSetJson(&cmd.DonePk, m, "donepk")
quickSetJson(&cmd.RunOut, m, "runout")
quickSetInt64(&cmd.UsedRows, m, "usedrows")
quickSetBool(&cmd.RtnState, m, "rtnstate")
return &cmd
}
@@ -680,6 +682,7 @@ func makeNewLineCmd(sessionId string, windowId string, userId string, cmdId stri
rtn.LineLocal = true
rtn.LineType = LineTypeCmd
rtn.CmdId = cmdId
rtn.ContentHeight = LineNoHeight
return rtn
}
@@ -693,6 +696,7 @@ func makeNewLineText(sessionId string, windowId string, userId string, text stri
rtn.LineLocal = true
rtn.LineType = LineTypeText
rtn.Text = text
rtn.ContentHeight = LineNoHeight
return rtn
}