mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
commands for line selection, updated resolver to allow 'S' and 'E'
This commit is contained in:
@@ -43,7 +43,7 @@ var hostNameRe = regexp.MustCompile("^[a-z][a-z0-9.-]*$")
|
||||
var userHostRe = regexp.MustCompile("^(sudo@)?([a-z][a-z0-9-]*)@([a-z][a-z0-9.-]*)(?::([0-9]+))?$")
|
||||
var remoteAliasRe = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9_-]*$")
|
||||
var genericNameRe = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9_ .()<>,/\"'\\[\\]{}=+$@!*-]*$")
|
||||
var positionRe = regexp.MustCompile("^((\\+|-)?[0-9]+|(\\+|-))$")
|
||||
var positionRe = regexp.MustCompile("^((S?\\+|E?-)?[0-9]+|(\\+|-|S|E))$")
|
||||
var wsRe = regexp.MustCompile("\\s+")
|
||||
|
||||
type contextType string
|
||||
@@ -439,6 +439,25 @@ func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
|
||||
}
|
||||
updateMap[sstore.SWField_ScrollTop] = stVal
|
||||
}
|
||||
if pk.Kwargs["line"] != "" {
|
||||
sw, err := sstore.GetScreenWindowByIds(ctx, ids.SessionId, ids.ScreenId, ids.WindowId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/sw:set cannot get screen-window: %v", err)
|
||||
}
|
||||
var selectedLineStr string
|
||||
if sw.SelectedLine > 0 {
|
||||
selectedLineStr = strconv.Itoa(sw.SelectedLine)
|
||||
}
|
||||
ritem, err := resolveLine(ctx, ids.SessionId, ids.WindowId, pk.Kwargs["line"], selectedLineStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/sw:set error resolving line: %v", err)
|
||||
}
|
||||
if ritem == nil {
|
||||
return nil, fmt.Errorf("/sw:set could not resolve line %q", pk.Kwargs["line"])
|
||||
}
|
||||
setNonST = true
|
||||
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))
|
||||
}
|
||||
|
||||
+64
-20
@@ -95,26 +95,40 @@ func boundInt(ival int, maxVal int, wrap bool) int {
|
||||
}
|
||||
|
||||
type posArgType struct {
|
||||
Pos int
|
||||
IsWrap bool
|
||||
IsRelative bool
|
||||
Pos int
|
||||
IsWrap bool
|
||||
IsRelative bool
|
||||
StartAnchor bool
|
||||
EndAnchor bool
|
||||
}
|
||||
|
||||
func parsePosArg(posStr string) *posArgType {
|
||||
if !positionRe.MatchString(posStr) {
|
||||
return nil
|
||||
}
|
||||
rtn := &posArgType{}
|
||||
rtn.IsRelative = strings.HasPrefix(posStr, "+") || strings.HasPrefix(posStr, "-")
|
||||
rtn.IsWrap = posStr == "+" || posStr == "-"
|
||||
if rtn.IsWrap && posStr == "+" {
|
||||
rtn.Pos = 1
|
||||
} else if rtn.IsWrap && posStr == "-" {
|
||||
rtn.Pos = -1
|
||||
} else {
|
||||
rtn.Pos, _ = strconv.Atoi(posStr) // don't need to check error because of positionRe.Match
|
||||
if posStr == "+" {
|
||||
return &posArgType{Pos: 1, IsWrap: true, IsRelative: true}
|
||||
} else if posStr == "-" {
|
||||
return &posArgType{Pos: -1, IsWrap: true, IsRelative: true}
|
||||
} else if posStr == "S" {
|
||||
return &posArgType{Pos: 0, IsRelative: true, StartAnchor: true}
|
||||
} else if posStr == "E" {
|
||||
return &posArgType{Pos: 0, IsRelative: true, EndAnchor: true}
|
||||
}
|
||||
return rtn
|
||||
if strings.HasPrefix(posStr, "S+") {
|
||||
pos, _ := strconv.Atoi(posStr[2:])
|
||||
return &posArgType{Pos: pos, IsRelative: true, StartAnchor: true}
|
||||
}
|
||||
if strings.HasPrefix(posStr, "E-") {
|
||||
pos, _ := strconv.Atoi(posStr[1:])
|
||||
return &posArgType{Pos: pos, IsRelative: true, EndAnchor: true}
|
||||
}
|
||||
if strings.HasPrefix(posStr, "+") || strings.HasPrefix(posStr, "-") {
|
||||
pos, _ := strconv.Atoi(posStr)
|
||||
return &posArgType{Pos: pos, IsRelative: true}
|
||||
}
|
||||
pos, _ := strconv.Atoi(posStr)
|
||||
return &posArgType{Pos: pos}
|
||||
}
|
||||
|
||||
func resolveByPosition(isNumeric bool, items []ResolveItem, curId string, posStr string) *ResolveItem {
|
||||
@@ -127,15 +141,31 @@ func resolveByPosition(isNumeric bool, items []ResolveItem, curId string, posStr
|
||||
}
|
||||
var finalPos int
|
||||
if posArg.IsRelative {
|
||||
curIdx := 1 // if no match, curIdx will be first item
|
||||
for idx, item := range items {
|
||||
if item.Id == curId {
|
||||
curIdx = idx + 1
|
||||
break
|
||||
var curIdx int
|
||||
if posArg.StartAnchor {
|
||||
curIdx = 1
|
||||
} else if posArg.EndAnchor {
|
||||
curIdx = len(items)
|
||||
} else {
|
||||
curIdx = 1 // if no match, curIdx will be first item
|
||||
for idx, item := range items {
|
||||
if item.Id == curId {
|
||||
curIdx = idx + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
finalPos = curIdx + posArg.Pos
|
||||
} else if isNumeric {
|
||||
// these resolve items have a "Num" set that should be used to look up non-relative positions
|
||||
for _, item := range items {
|
||||
if item.Num == posArg.Pos {
|
||||
return &item
|
||||
}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
// non-numeric means position is just the index
|
||||
finalPos = posArg.Pos
|
||||
}
|
||||
finalPos = boundInt(finalPos, len(items), posArg.IsWrap)
|
||||
@@ -243,12 +273,20 @@ func resolveUiIds(ctx context.Context, pk *scpacket.FeCommandPacketType, rtype i
|
||||
func resolveSessionScreen(ctx context.Context, sessionId string, screenArg string, curScreenArg string) (*ResolveItem, error) {
|
||||
screens, err := sstore.GetSessionScreens(ctx, sessionId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retreive screens for session=%s", sessionId)
|
||||
return nil, fmt.Errorf("could not retreive screens for session=%s: %v", sessionId, err)
|
||||
}
|
||||
ritems := screensToResolveItems(screens)
|
||||
return genericResolve(screenArg, curScreenArg, ritems, false, "screen")
|
||||
}
|
||||
|
||||
func resolveLine(ctx context.Context, sessionId string, windowId string, lineArg string, curLineArg string) (*ResolveItem, error) {
|
||||
lines, err := sstore.GetLineResolveItems(ctx, sessionId, windowId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get lines: %v", err)
|
||||
}
|
||||
return genericResolve(lineArg, curLineArg, lines, true, "line")
|
||||
}
|
||||
|
||||
func getSessionIds(sarr []*sstore.SessionType) []string {
|
||||
rtn := make([]string, len(sarr))
|
||||
for idx, s := range sarr {
|
||||
@@ -263,6 +301,11 @@ func isPartialUUID(s string) bool {
|
||||
return partialUUIDRe.MatchString(s)
|
||||
}
|
||||
|
||||
func isUUID(s string) bool {
|
||||
_, err := uuid.Parse(s)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func getResolveItemById(id string, items []ResolveItem) *ResolveItem {
|
||||
if id == "" {
|
||||
return nil
|
||||
@@ -290,10 +333,11 @@ func genericResolve(arg string, curArg string, items []ResolveItem, isNumeric bo
|
||||
if rtnItem != nil {
|
||||
return rtnItem, nil
|
||||
}
|
||||
isUuid := isUUID(arg)
|
||||
tryPuid := isPartialUUID(arg)
|
||||
var prefixMatches []ResolveItem
|
||||
for _, item := range items {
|
||||
if item.Id == arg || (tryPuid && strings.HasPrefix(item.Id, arg)) {
|
||||
if (isUuid && item.Id == arg) || (tryPuid && strings.HasPrefix(item.Id, arg)) {
|
||||
return &item, nil
|
||||
}
|
||||
if item.Name != "" {
|
||||
|
||||
+23
-1
@@ -1105,7 +1105,8 @@ func UpdateRemote(ctx context.Context, remoteId string, editMap map[string]inter
|
||||
}
|
||||
|
||||
const (
|
||||
SWField_ScrollTop = "scrolltop" // int
|
||||
SWField_ScrollTop = "scrolltop" // int
|
||||
SWField_SelectedLine = "selectedline" // int
|
||||
)
|
||||
|
||||
func UpdateScreenWindow(ctx context.Context, sessionId string, screenId string, windowId string, editMap map[string]interface{}) (*ScreenWindowType, error) {
|
||||
@@ -1119,6 +1120,10 @@ func UpdateScreenWindow(ctx context.Context, sessionId string, screenId string,
|
||||
query = `UPDATE screen_window SET scrolltop = ? WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
tx.ExecWrap(query, stVal, 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)
|
||||
}
|
||||
var sw ScreenWindowType
|
||||
query = `SELECT * FROM screen_window WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
found := tx.GetWrap(&sw, query, sessionId, screenId, windowId)
|
||||
@@ -1133,6 +1138,23 @@ func UpdateScreenWindow(ctx context.Context, sessionId string, screenId string,
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
func GetScreenWindowByIds(ctx context.Context, sessionId string, screenId string, windowId string) (*ScreenWindowType, error) {
|
||||
var rtn *ScreenWindowType
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
var sw ScreenWindowType
|
||||
query := `SELECT * FROM screen_window WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
||||
found := tx.GetWrap(&sw, query, sessionId, screenId, windowId)
|
||||
if found {
|
||||
rtn = &sw
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if txErr != nil {
|
||||
return nil, txErr
|
||||
}
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
func GetLineResolveItems(ctx context.Context, sessionId string, windowId string) ([]ResolveItem, error) {
|
||||
var rtn []ResolveItem
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
|
||||
Reference in New Issue
Block a user