diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index c4133713..705ce378 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -49,7 +49,7 @@ var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cy var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"} var WindowCmds = []string{"run", "comment", "cd", "cr", "clear", "sw", "alias", "unalias", "function", "reset"} -var NoHistCmds = []string{"compgen", "line", "history"} +var NoHistCmds = []string{"_compgen", "line", "history"} var GlobalCmds = []string{"session", "screen", "remote", "killserver"} var hostNameRe = regexp.MustCompile("^[a-z][a-z0-9.-]*$") @@ -83,7 +83,7 @@ func init() { registerCmdFn("comment", CommentCommand) // registerCmdFn("cd", CdCommand) registerCmdFn("cr", CrCommand) - registerCmdFn("compgen", CompGenCommand) + registerCmdFn("_compgen", CompGenCommand) registerCmdFn("clear", ClearCommand) registerCmdFn("reset", ResetCommand) @@ -1077,20 +1077,23 @@ func makeInfoFromComps(compType string, comps []string, hasMore bool) sstore.Upd return update } -func simpleCompMeta(ctx context.Context, prefix string, compCtx comp.CompContext, args []interface{}) (*comp.CompReturn, error) { +func simpleCompCommandMeta(ctx context.Context, prefix string, compCtx comp.CompContext, args []interface{}) (*comp.CompReturn, error) { if strings.HasPrefix(prefix, "/") { compsCmd, _ := comp.DoSimpleComp(ctx, comp.CGTypeCommand, prefix, compCtx, nil) - compsMeta, _ := simpleCompCommandMeta(ctx, prefix, compCtx, nil) + compsMeta, _ := simpleCompMeta(ctx, prefix, compCtx, nil) return comp.CombineCompReturn(comp.CGTypeCommandMeta, compsCmd, compsMeta), nil } else { return comp.DoSimpleComp(ctx, comp.CGTypeCommand, prefix, compCtx, nil) } } -func simpleCompCommandMeta(ctx context.Context, prefix string, compCtx comp.CompContext, args []interface{}) (*comp.CompReturn, error) { +func simpleCompMeta(ctx context.Context, prefix string, compCtx comp.CompContext, args []interface{}) (*comp.CompReturn, error) { rtn := comp.CompReturn{} validCommands := getValidCommands() for _, cmd := range validCommands { + if strings.HasPrefix(cmd, "/_") && !strings.HasPrefix(prefix, "/_") { + continue + } if strings.HasPrefix(cmd, prefix) { rtn.Entries = append(rtn.Entries, comp.CompEntry{Word: cmd, IsMetaCmd: true}) } @@ -1126,11 +1129,11 @@ func doCompGen(ctx context.Context, pk *scpacket.FeCommandPacketType, prefix str return doMetaCompGen(ctx, pk, prefix, forDisplay) } if !packet.IsValidCompGenType(compType) { - return nil, false, fmt.Errorf("/compgen invalid type '%s'", compType) + return nil, false, fmt.Errorf("/_compgen invalid type '%s'", compType) } ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_RemoteConnected) if err != nil { - return nil, false, fmt.Errorf("compgen error: %w", err) + return nil, false, fmt.Errorf("/_compgen error: %w", err) } cgPacket := packet.MakeCompGenPacket() cgPacket.ReqId = uuid.New().String() @@ -1154,14 +1157,14 @@ func doCompGen(ctx context.Context, pk *scpacket.FeCommandPacketType, prefix str func CompGenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { ids, err := resolveUiIds(ctx, pk, 0) // best-effort if err != nil { - return nil, fmt.Errorf("/compgen error: %w", err) + return nil, fmt.Errorf("/_compgen error: %w", err) } cmdLine := firstArg(pk) pos := len(cmdLine) if pk.Kwargs["comppos"] != "" { posArg, err := strconv.Atoi(pk.Kwargs["comppos"]) if err != nil { - return nil, fmt.Errorf("/compgen invalid comppos '%s': %w", pk.Kwargs["comppos"], err) + return nil, fmt.Errorf("/_compgen invalid comppos '%s': %w", pk.Kwargs["comppos"], err) } pos = posArg } diff --git a/pkg/cmdrunner/shparse.go b/pkg/cmdrunner/shparse.go index 3ad497eb..e6504e58 100644 --- a/pkg/cmdrunner/shparse.go +++ b/pkg/cmdrunner/shparse.go @@ -14,7 +14,7 @@ import ( "mvdan.cc/sh/v3/syntax" ) -var ValidMetaCmdRe = regexp.MustCompile("^/([a-z][a-z0-9_-]*)(?::([a-z][a-z0-9_-]*))?$") +var ValidMetaCmdRe = regexp.MustCompile("^/([a-z_][a-z0-9_-]*)(?::([a-z][a-z0-9_-]*))?$") type BareMetaCmdDecl struct { CmdStr string diff --git a/pkg/comp/simplecomp.go b/pkg/comp/simplecomp.go index f3b93d07..5c83df37 100644 --- a/pkg/comp/simplecomp.go +++ b/pkg/comp/simplecomp.go @@ -60,7 +60,7 @@ func compsToCompReturn(comps []string, hasMore bool) *CompReturn { func doCompGen(ctx context.Context, prefix string, compType string, compCtx CompContext) (*CompReturn, error) { if !packet.IsValidCompGenType(compType) { - return nil, fmt.Errorf("/compgen invalid type '%s'", compType) + return nil, fmt.Errorf("/_compgen invalid type '%s'", compType) } msh := remote.GetRemoteById(compCtx.RemotePtr.RemoteId) if msh == nil { diff --git a/pkg/shparse/comp.go b/pkg/shparse/comp.go index c0efe82c..fbc6065c 100644 --- a/pkg/shparse/comp.go +++ b/pkg/shparse/comp.go @@ -187,7 +187,7 @@ func findCompletionPosInWord(word *WordType, posInWord int, superOffset int) *Co return nil } subCmds := ParseCommands(word.Subs) - newPos := FindCompletionPos(subCmds, posInWord-word.contentStartPos(), superOffset+(word.Offset+word.contentStartPos())) + newPos := findCompletionPosInternal(subCmds, posInWord-word.contentStartPos(), superOffset+(word.Offset+word.contentStartPos())) return &newPos } if word.Type == WordTypeSimpleVar || word.Type == WordTypeVarBrace { @@ -252,17 +252,24 @@ func findCompletionPosCmds(cmds []*CmdType, pos int, superOffset int) Completion return rtn } -func FindCompletionPos(cmds []*CmdType, pos int, superOffset int) CompletionPos { +func findCompletionPosInternal(cmds []*CmdType, pos int, superOffset int) CompletionPos { cpos := findCompletionPosCmds(cmds, pos, superOffset) if cpos.CompWord == nil { return cpos } subPos := findCompletionPosInWord(cpos.CompWord, cpos.CompWordOffset, superOffset) - if subPos == nil { - return cpos - } else { + if subPos != nil { return *subPos } + return cpos +} + +func FindCompletionPos(cmds []*CmdType, pos int) CompletionPos { + cpos := findCompletionPosInternal(cmds, pos, 0) + if cpos.CompType == CompTypeCommand && cpos.SuperOffset == 0 && cpos.CompWord != nil && cpos.CompWord.Offset == 0 && strings.HasPrefix(string(cpos.CompWord.Raw), "/") { + cpos.CompType = CompTypeCommandMeta + } + return cpos } func (cpos CompletionPos) Extend(origStr utilfn.StrWithPos, extensionStr string, extensionComplete bool) utilfn.StrWithPos {