mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-08 19:38:51 +01:00
3c3eec73aa
* working on re-init when you create a tab. some refactoring of existing reinit to make the messaging clearer. auto-connect, etc. * working to remove the 'default' shell states out of MShellProc. each tab should have its own state that gets set on open. * refactor newtab settings into individual components (and move to a new file) * more refactoring of tab settings -- use same control in settings and newtab * have screensettings use the same newtab settings components * use same conn dropdown, fix classes, update some of the confirm messages to be less confusing (replace screen with tab) * force a cr on a new tab to initialize state in a new line. poc right now, need to add to new workspace workflow as well * small fixups * remove nohist from GetRawStr, make const * update hover behavior for tabs * fix interaction between change remote dropdown, cmdinput, error handling, and selecting a remote * only switch screen remote if the activemainview is session (new remote flow). don't switch it if we're on the connections page which is confusing. also make it interactive * fix wording on tos modal * allow empty workspaces. also allow the last workspace to be deleted. (prep for new startup sequence where we initialize the first session after tos modal) * add some dead code that might come in use later (when we change how we show connection in cmdinput) * working a cople different angles. new settings tab-pulldown (likely orphaned). and then allowing null activeScreen and null activeSession in workspaceview (show appropriate messages, and give buttons to create new tabs/workspaces). prep for new startup flow * don't call initActiveShells anymore. also call ensureWorkspace() on TOS close * trying to use new pulldown screen settings * experiment with an escape keybinding * working on tab settings close triggers * close tab settings on tab switch * small updates to tos popup, reorder, update button text/size, small wording updates * when deleting a screen, send SIGHUP to all running commands * not sure how this happened, lineid should not be passed to setLineFocus * remove context timeouts for ReInit (it is now interactive, so it gets canceled like a normal command -- via ^C, and should not timeout on its own) * deal with screen/session tombstones updates (ignore to quite warning) * remove defaultfestate from remote * fix issue with removing default ris * remove dead code * open the settings pulldown for new screens * update prompt to show when the shell is still initializing (or if it failed) * switch buttons to use wave button class, update messages, and add warning for no shell state * all an override of rptr for dyncmds. needed for the 'connect' command (we need to set the rptr to the *new* connection rather than the old one) * remove old commented out code
221 lines
5.8 KiB
Go
221 lines
5.8 KiB
Go
// Copyright 2023, Command Line Inc.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package scpacket
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"reflect"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/alessio/shellescape"
|
|
"github.com/google/uuid"
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/utilfn"
|
|
)
|
|
|
|
var RemoteNameRe = regexp.MustCompile("^\\*?[a-zA-Z0-9_-]+$")
|
|
|
|
type RemotePtrType struct {
|
|
OwnerId string `json:"ownerid"`
|
|
RemoteId string `json:"remoteid"`
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
func (r RemotePtrType) IsSessionScope() bool {
|
|
return strings.HasPrefix(r.Name, "*")
|
|
}
|
|
|
|
func (rptr *RemotePtrType) GetDisplayName(baseDisplayName string) string {
|
|
name := baseDisplayName
|
|
if rptr == nil {
|
|
return name
|
|
}
|
|
if rptr.Name != "" {
|
|
name = name + ":" + rptr.Name
|
|
}
|
|
if rptr.OwnerId != "" {
|
|
name = "@" + rptr.OwnerId + ":" + name
|
|
}
|
|
return name
|
|
}
|
|
|
|
func (r RemotePtrType) Validate() error {
|
|
if r.OwnerId != "" {
|
|
if _, err := uuid.Parse(r.OwnerId); err != nil {
|
|
return fmt.Errorf("invalid ownerid format: %v", err)
|
|
}
|
|
}
|
|
if r.RemoteId != "" {
|
|
if _, err := uuid.Parse(r.RemoteId); err != nil {
|
|
return fmt.Errorf("invalid remoteid format: %v", err)
|
|
}
|
|
}
|
|
if r.Name != "" {
|
|
ok := RemoteNameRe.MatchString(r.Name)
|
|
if !ok {
|
|
return fmt.Errorf("invalid remote name")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r RemotePtrType) MakeFullRemoteRef() string {
|
|
if r.RemoteId == "" {
|
|
return ""
|
|
}
|
|
if r.OwnerId == "" && r.Name == "" {
|
|
return r.RemoteId
|
|
}
|
|
if r.OwnerId != "" && r.Name == "" {
|
|
return fmt.Sprintf("@%s:%s", r.OwnerId, r.RemoteId)
|
|
}
|
|
if r.OwnerId == "" && r.Name != "" {
|
|
return fmt.Sprintf("%s:%s", r.RemoteId, r.Name)
|
|
}
|
|
return fmt.Sprintf("@%s:%s:%s", r.OwnerId, r.RemoteId, r.Name)
|
|
}
|
|
|
|
const FeCommandPacketStr = "fecmd"
|
|
const WatchScreenPacketStr = "watchscreen"
|
|
const FeInputPacketStr = "feinput"
|
|
const RemoteInputPacketStr = "remoteinput"
|
|
const CmdInputTextPacketStr = "cmdinputtext"
|
|
|
|
type FeCommandPacketType struct {
|
|
Type string `json:"type"`
|
|
MetaCmd string `json:"metacmd"`
|
|
MetaSubCmd string `json:"metasubcmd,omitempty"`
|
|
Args []string `json:"args,omitempty"`
|
|
Kwargs map[string]string `json:"kwargs,omitempty"`
|
|
RawStr string `json:"rawstr,omitempty"`
|
|
UIContext *UIContextType `json:"uicontext,omitempty"`
|
|
Interactive bool `json:"interactive"`
|
|
}
|
|
|
|
func (pk *FeCommandPacketType) GetRawStr() string {
|
|
if pk.RawStr != "" {
|
|
return pk.RawStr
|
|
}
|
|
cmd := "/" + pk.MetaCmd
|
|
if pk.MetaSubCmd != "" {
|
|
cmd = cmd + ":" + pk.MetaSubCmd
|
|
}
|
|
var args []string
|
|
for k, v := range pk.Kwargs {
|
|
if k == "nohist" {
|
|
continue
|
|
}
|
|
argStr := fmt.Sprintf("%s=%s", shellescape.Quote(k), shellescape.Quote(v))
|
|
args = append(args, argStr)
|
|
}
|
|
for _, arg := range pk.Args {
|
|
args = append(args, shellescape.Quote(arg))
|
|
}
|
|
if len(args) == 0 {
|
|
return cmd
|
|
}
|
|
return cmd + " " + strings.Join(args, " ")
|
|
}
|
|
|
|
type UIContextType struct {
|
|
SessionId string `json:"sessionid"`
|
|
ScreenId string `json:"screenid"`
|
|
Remote *RemotePtrType `json:"remote,omitempty"`
|
|
WinSize *packet.WinSize `json:"winsize,omitempty"`
|
|
Build string `json:"build,omitempty"`
|
|
}
|
|
|
|
type FeInputPacketType struct {
|
|
Type string `json:"type"`
|
|
CK base.CommandKey `json:"ck"`
|
|
Remote RemotePtrType `json:"remote"`
|
|
InputData64 string `json:"inputdata64"`
|
|
SigName string `json:"signame,omitempty"`
|
|
WinSize *packet.WinSize `json:"winsize,omitempty"`
|
|
}
|
|
|
|
type RemoteInputPacketType struct {
|
|
Type string `json:"type"`
|
|
RemoteId string `json:"remoteid"`
|
|
InputData64 string `json:"inputdata64"`
|
|
}
|
|
|
|
type WatchScreenPacketType struct {
|
|
Type string `json:"type"`
|
|
SessionId string `json:"sessionid"`
|
|
ScreenId string `json:"screenid"`
|
|
Connect bool `json:"connect"`
|
|
AuthKey string `json:"authkey"`
|
|
}
|
|
|
|
type CmdInputTextPacketType struct {
|
|
Type string `json:"type"`
|
|
SeqNum int `json:"seqnum"`
|
|
ScreenId string `json:"screenid"`
|
|
Text utilfn.StrWithPos `json:"text"`
|
|
}
|
|
|
|
func init() {
|
|
packet.RegisterPacketType(FeCommandPacketStr, reflect.TypeOf(FeCommandPacketType{}))
|
|
packet.RegisterPacketType(WatchScreenPacketStr, reflect.TypeOf(WatchScreenPacketType{}))
|
|
packet.RegisterPacketType(FeInputPacketStr, reflect.TypeOf(FeInputPacketType{}))
|
|
packet.RegisterPacketType(RemoteInputPacketStr, reflect.TypeOf(RemoteInputPacketType{}))
|
|
packet.RegisterPacketType(CmdInputTextPacketStr, reflect.TypeOf(CmdInputTextPacketType{}))
|
|
}
|
|
|
|
type PacketType interface {
|
|
GetType() string
|
|
}
|
|
|
|
func (*CmdInputTextPacketType) GetType() string {
|
|
return CmdInputTextPacketStr
|
|
}
|
|
|
|
func MakeCmdInputTextPacket(screenId string) *CmdInputTextPacketType {
|
|
return &CmdInputTextPacketType{Type: CmdInputTextPacketStr, ScreenId: screenId}
|
|
}
|
|
|
|
func (*FeCommandPacketType) GetType() string {
|
|
return FeCommandPacketStr
|
|
}
|
|
|
|
func MakeFeCommandPacket() *FeCommandPacketType {
|
|
return &FeCommandPacketType{Type: FeCommandPacketStr}
|
|
}
|
|
|
|
func (*FeInputPacketType) GetType() string {
|
|
return FeInputPacketStr
|
|
}
|
|
|
|
func MakeFeInputPacket() *FeInputPacketType {
|
|
return &FeInputPacketType{Type: FeInputPacketStr}
|
|
}
|
|
|
|
func (pk *FeInputPacketType) DecodeData() ([]byte, error) {
|
|
return base64.StdEncoding.DecodeString(pk.InputData64)
|
|
}
|
|
|
|
func (pk *FeInputPacketType) SetData(data []byte) {
|
|
pk.InputData64 = base64.StdEncoding.EncodeToString(data)
|
|
}
|
|
|
|
func (*WatchScreenPacketType) GetType() string {
|
|
return WatchScreenPacketStr
|
|
}
|
|
|
|
func MakeWatchScreenPacket() *WatchScreenPacketType {
|
|
return &WatchScreenPacketType{Type: WatchScreenPacketStr}
|
|
}
|
|
|
|
func MakeRemoteInputPacket() *RemoteInputPacketType {
|
|
return &RemoteInputPacketType{Type: RemoteInputPacketStr}
|
|
}
|
|
|
|
func (*RemoteInputPacketType) GetType() string {
|
|
return RemoteInputPacketStr
|
|
}
|