mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
add simple history expansion
This commit is contained in:
+11
-11
@@ -95,7 +95,7 @@ CREATE TABLE cmd (
|
||||
runout json NOT NULL,
|
||||
rtnstate boolean NOT NULL,
|
||||
rtnbasehash varchar(36) NOT NULL,
|
||||
rtndiffhasharr json NOT NULL,
|
||||
rtndiffhasharr json NOT NULL, screenid varchar(36) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (sessionid, cmdid)
|
||||
);
|
||||
CREATE TABLE history (
|
||||
@@ -113,7 +113,16 @@ CREATE TABLE history (
|
||||
cmdstr text NOT NULL,
|
||||
ismetacmd boolean,
|
||||
incognito boolean
|
||||
);
|
||||
, linenum int NOT NULL DEFAULT 0);
|
||||
CREATE TABLE activity (
|
||||
day varchar(20) PRIMARY KEY,
|
||||
uploaded boolean NOT NULL,
|
||||
tdata json NOT NULL,
|
||||
tzname varchar(50) NOT NULL,
|
||||
tzoffset int NOT NULL,
|
||||
clientversion varchar(20) NOT NULL,
|
||||
clientarch varchar(20) NOT NULL
|
||||
, buildtime varchar(20) NOT NULL DEFAULT '-', osrelease varchar(20) NOT NULL DEFAULT '-');
|
||||
CREATE TABLE bookmark (
|
||||
bookmarkid varchar(36) PRIMARY KEY,
|
||||
createdts bigint NOT NULL,
|
||||
@@ -134,15 +143,6 @@ CREATE TABLE bookmark_cmd (
|
||||
cmdid varchar(36) NOT NULL,
|
||||
PRIMARY KEY (bookmarkid, sessionid, cmdid)
|
||||
);
|
||||
CREATE TABLE activity (
|
||||
day varchar(20) PRIMARY KEY,
|
||||
uploaded boolean NOT NULL,
|
||||
tdata json NOT NULL,
|
||||
tzname varchar(50) NOT NULL,
|
||||
tzoffset int NOT NULL,
|
||||
clientversion varchar(50) NOT NULL,
|
||||
clientarch varchar(50) NOT NULL
|
||||
, buildtime varchar(20) NOT NULL DEFAULT '-', osrelease varchar(20) NOT NULL DEFAULT '-');
|
||||
CREATE TABLE playbook (
|
||||
playbookid varchar(36) PRIMARY KEY,
|
||||
playbookname varchar(100) NOT NULL,
|
||||
|
||||
@@ -47,6 +47,7 @@ const DefaultPTERM = "MxM"
|
||||
const MaxCommandLen = 4096
|
||||
const MaxSignalLen = 12
|
||||
const MaxSignalNum = 64
|
||||
const MaxEvalDepth = 5
|
||||
|
||||
var ColorNames = []string{"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"}
|
||||
var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"}
|
||||
@@ -87,6 +88,7 @@ var sigNameRe = regexp.MustCompile("^((SIG[A-Z0-9]+)|(\\d+))$")
|
||||
type contextType string
|
||||
|
||||
var historyContextKey = contextType("history")
|
||||
var depthContextKey = contextType("depth")
|
||||
|
||||
type SetVarScope struct {
|
||||
ScopeName string
|
||||
@@ -323,6 +325,68 @@ func resolveNonNegInt(arg string, def int) (int, error) {
|
||||
return ival, nil
|
||||
}
|
||||
|
||||
var histExpansionRe = regexp.MustCompile(`^!(\d+)$`)
|
||||
|
||||
func doCmdHistoryExpansion(ctx context.Context, ids resolvedIds, cmdStr string) (string, error) {
|
||||
if !strings.HasPrefix(cmdStr, "!") {
|
||||
return "", nil
|
||||
}
|
||||
if strings.HasPrefix(cmdStr, "! ") {
|
||||
return "", nil
|
||||
}
|
||||
if cmdStr == "!!" {
|
||||
return doHistoryExpansion(ctx, ids, -1)
|
||||
}
|
||||
if strings.HasPrefix(cmdStr, "!-") {
|
||||
return "", fmt.Errorf("prompt does not support negative history offsets, use a stable positive history offset instead: '![linenum]'")
|
||||
}
|
||||
m := histExpansionRe.FindStringSubmatch(cmdStr)
|
||||
if m == nil {
|
||||
return "", fmt.Errorf("unsupported history substitution, can use '!!' or '![linenum]'")
|
||||
}
|
||||
ival, err := strconv.Atoi(m[1])
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid history expansion")
|
||||
}
|
||||
return doHistoryExpansion(ctx, ids, ival)
|
||||
}
|
||||
|
||||
func doHistoryExpansion(ctx context.Context, ids resolvedIds, hnum int) (string, error) {
|
||||
if hnum == 0 {
|
||||
return "", fmt.Errorf("invalid history expansion, cannot expand line number '0'")
|
||||
}
|
||||
if hnum < -1 {
|
||||
return "", fmt.Errorf("invalid history expansion, cannot expand negative history offsets")
|
||||
}
|
||||
foundHistoryNum := hnum
|
||||
if hnum == -1 {
|
||||
var err error
|
||||
foundHistoryNum, err = sstore.GetLastHistoryLineNum(ctx, ids.ScreenId)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot expand history, error finding last history item: %v", err)
|
||||
}
|
||||
if foundHistoryNum == 0 {
|
||||
return "", fmt.Errorf("cannot expand history, no last history item")
|
||||
}
|
||||
}
|
||||
hitem, err := sstore.GetHistoryItemByLineNum(ctx, ids.ScreenId, foundHistoryNum)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot get history item '%d': %v", foundHistoryNum, err)
|
||||
}
|
||||
if hitem == nil {
|
||||
return "", fmt.Errorf("cannot expand history, history item '%d' not found", foundHistoryNum)
|
||||
}
|
||||
return hitem.CmdStr, nil
|
||||
}
|
||||
|
||||
func getEvalDepth(ctx context.Context) int {
|
||||
depthVal := ctx.Value(depthContextKey)
|
||||
if depthVal == nil {
|
||||
return 0
|
||||
}
|
||||
return depthVal.(int)
|
||||
}
|
||||
|
||||
func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_RemoteConnected)
|
||||
if err != nil {
|
||||
@@ -333,6 +397,22 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
|
||||
}
|
||||
renderer := pk.Kwargs["renderer"]
|
||||
cmdStr := firstArg(pk)
|
||||
expandedCmdStr, err := doCmdHistoryExpansion(ctx, ids, cmdStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if expandedCmdStr != "" {
|
||||
newPk := scpacket.MakeFeCommandPacket()
|
||||
newPk.MetaCmd = "eval"
|
||||
newPk.Args = []string{expandedCmdStr}
|
||||
newPk.Kwargs = pk.Kwargs
|
||||
newPk.RawStr = pk.RawStr
|
||||
newPk.UIContext = pk.UIContext
|
||||
newPk.Interactive = pk.Interactive
|
||||
evalDepth := getEvalDepth(ctx)
|
||||
ctxWithDepth := context.WithValue(ctx, depthContextKey, evalDepth+1)
|
||||
return EvalCommand(ctxWithDepth, newPk)
|
||||
}
|
||||
isRtnStateCmd := IsReturnStateCommand(cmdStr)
|
||||
// runPacket.State is set in remote.RunCommand()
|
||||
runPacket := packet.MakeRunPacket()
|
||||
@@ -410,6 +490,9 @@ func EvalCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.
|
||||
// fall through (non-fatal error)
|
||||
}
|
||||
}
|
||||
if getEvalDepth(ctx) > MaxEvalDepth {
|
||||
return nil, fmt.Errorf("alias/history expansion max-depth exceeded")
|
||||
}
|
||||
var historyContext historyContextType
|
||||
ctxWithHistory := context.WithValue(ctx, historyContextKey, &historyContext)
|
||||
var update sstore.UpdatePacket
|
||||
|
||||
@@ -341,6 +341,22 @@ func GetHistoryItems(ctx context.Context, opts HistoryQueryOpts) (*HistoryQueryR
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
func GetHistoryItemByLineNum(ctx context.Context, screenId string, lineNum int) (*HistoryItemType, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (*HistoryItemType, error) {
|
||||
query := `SELECT * FROM history WHERE screenid = ? AND linenum = ?`
|
||||
hitem := GetMapGen[*HistoryItemType](tx, query, screenId, lineNum)
|
||||
return hitem, nil
|
||||
})
|
||||
}
|
||||
|
||||
func GetLastHistoryLineNum(ctx context.Context, screenId string) (int, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (int, error) {
|
||||
query := `SELECT COALESCE(max(linenum), 0) FROM history WHERE screenid = ?`
|
||||
maxLineNum := tx.GetInt(query, screenId)
|
||||
return maxLineNum, nil
|
||||
})
|
||||
}
|
||||
|
||||
// includes archived sessions
|
||||
func GetBareSessions(ctx context.Context) ([]*SessionType, error) {
|
||||
var rtn []*SessionType
|
||||
|
||||
Reference in New Issue
Block a user