waveterm/wavesrv/pkg/cmdrunner/shparse.go

473 lines
11 KiB
Go
Raw Normal View History

2023-10-17 06:31:13 +02:00
// Copyright 2023, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
2022-08-26 22:12:17 +02:00
package cmdrunner
import (
"context"
"fmt"
"regexp"
"strings"
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
"github.com/wavetermdev/waveterm/waveshell/pkg/shellapi"
2023-10-16 22:30:10 +02:00
"github.com/wavetermdev/waveterm/waveshell/pkg/simpleexpand"
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
"github.com/wavetermdev/waveterm/waveshell/pkg/utilfn"
2023-10-16 22:30:10 +02:00
"github.com/wavetermdev/waveterm/wavesrv/pkg/scpacket"
2022-08-26 22:12:17 +02:00
"mvdan.cc/sh/v3/expand"
"mvdan.cc/sh/v3/syntax"
)
var ValidMetaCmdRe = regexp.MustCompile("^/([a-z_][a-z0-9_-]*)(?::([a-z][a-z0-9_-]*))?$")
type BareMetaCmdDecl struct {
CmdStr string
MetaCmd string
}
var BareMetaCmds = []BareMetaCmdDecl{
2023-12-05 19:49:30 +01:00
{"cr", "cr"},
{"connect", "cr"},
{"clear", "clear"},
{"reset", "reset"},
{"codeedit", "codeedit"},
{"codeview", "codeview"},
{"imageview", "imageview"},
{"markdownview", "markdownview"},
{"mdview", "markdownview"},
{"csvview", "csvview"},
{"pdfview", "pdfview"},
{"mediaview", "mediaview"},
}
2023-05-04 10:01:13 +02:00
const (
CmdParseTypePositional = "pos"
CmdParseTypeRaw = "raw"
)
var CmdParseOverrides map[string]string = map[string]string{
"setenv": CmdParseTypePositional,
"unset": CmdParseTypePositional,
"set": CmdParseTypePositional,
"run": CmdParseTypeRaw,
"comment": CmdParseTypeRaw,
2023-05-09 02:54:38 +02:00
"chat": CmdParseTypeRaw,
2023-05-04 10:01:13 +02:00
}
2022-08-26 22:12:17 +02:00
func DumpPacket(pk *scpacket.FeCommandPacketType) {
if pk == nil || pk.MetaCmd == "" {
fmt.Printf("[no metacmd]\n")
return
}
if pk.MetaSubCmd == "" {
fmt.Printf("/%s\n", pk.MetaCmd)
} else {
fmt.Printf("/%s:%s\n", pk.MetaCmd, pk.MetaSubCmd)
}
for _, arg := range pk.Args {
fmt.Printf(" %q\n", arg)
}
for key, val := range pk.Kwargs {
fmt.Printf(" [%s]=%q\n", key, val)
}
}
func isQuoted(source string, w *syntax.Word) bool {
if w == nil {
return false
}
offset := w.Pos().Offset()
if int(offset) >= len(source) {
return false
}
return source[offset] == '"' || source[offset] == '\''
}
func getSourceStr(source string, w *syntax.Word) string {
if w == nil {
return ""
}
offset := w.Pos().Offset()
end := w.End().Offset()
return source[offset:end]
}
func SubMetaCmd(cmd string) string {
switch cmd {
case "s":
return "screen"
case "r":
return "run"
case "c":
return "comment"
case "e":
return "eval"
case "export":
return "setenv"
2023-04-05 06:52:20 +02:00
case "connection":
return "remote"
2022-08-26 22:12:17 +02:00
default:
return cmd
}
}
// returns (metaCmd, metaSubCmd, rest)
// if metaCmd is "" then this isn't a valid metacmd string
func parseMetaCmd(origCommandStr string) (string, string, string) {
commandStr := strings.TrimSpace(origCommandStr)
if len(commandStr) < 2 {
return "run", "", origCommandStr
}
fields := strings.SplitN(commandStr, " ", 2)
firstArg := fields[0]
rest := ""
if len(fields) > 1 {
rest = strings.TrimSpace(fields[1])
}
for _, decl := range BareMetaCmds {
if firstArg == decl.CmdStr {
return decl.MetaCmd, "", rest
}
}
m := ValidMetaCmdRe.FindStringSubmatch(firstArg)
if m == nil {
return "run", "", origCommandStr
}
return SubMetaCmd(m[1]), m[2], rest
}
func onlyPositionalArgs(metaCmd string, metaSubCmd string) bool {
2023-05-04 10:01:13 +02:00
return (CmdParseOverrides[metaCmd] == CmdParseTypePositional) && metaSubCmd == ""
2022-08-26 22:12:17 +02:00
}
func onlyRawArgs(metaCmd string, metaSubCmd string) bool {
2023-05-04 10:01:13 +02:00
return CmdParseOverrides[metaCmd] == CmdParseTypeRaw
2022-08-26 22:12:17 +02:00
}
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
var waveValidIdentifierRe = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
func isValidWaveParamName(name string) bool {
return waveValidIdentifierRe.MatchString(name)
}
2022-10-26 23:51:12 +02:00
func setBracketArgs(argMap map[string]string, bracketStr string) error {
bracketStr = strings.TrimSpace(bracketStr)
if bracketStr == "" {
return nil
}
strReader := strings.NewReader(bracketStr)
parser := syntax.NewParser(syntax.Variant(syntax.LangBash))
var wordErr error
var ectx simpleexpand.SimpleExpandContext // do not set HomeDir (we don't expand ~ in bracket args)
2022-10-26 23:51:12 +02:00
err := parser.Words(strReader, func(w *syntax.Word) bool {
litStr, _ := simpleexpand.SimpleExpandWord(ectx, w, bracketStr)
2022-10-26 23:51:12 +02:00
eqIdx := strings.Index(litStr, "=")
var varName, varVal string
if eqIdx == -1 {
varName = litStr
} else {
varName = litStr[0:eqIdx]
varVal = litStr[eqIdx+1:]
}
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
if !isValidWaveParamName(varName) {
2022-11-10 22:52:51 +01:00
wordErr = fmt.Errorf("invalid identifier %s in bracket args", utilfn.ShellQuote(varName, true, 20))
2022-10-26 23:51:12 +02:00
return false
}
if varVal == "" {
varVal = "1"
}
argMap[varName] = varVal
return true
})
if err != nil {
return err
}
if wordErr != nil {
return wordErr
}
return nil
}
2023-11-17 08:51:02 +01:00
var literalRtnStateCommands = []string{
".",
"source",
"unset",
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
"unsetopt",
2023-11-17 08:51:02 +01:00
"cd",
"alias",
"unalias",
"deactivate",
"eval",
"asdf",
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
"sdk",
2023-11-17 08:54:27 +01:00
"nvm",
"virtualenv",
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
"builtin",
"typeset",
"declare",
"float",
"functions",
"integer",
"local",
"readonly",
"unfunction",
"shopt",
"enable",
"disable",
"function",
"zmodload",
"module",
2023-11-17 08:51:02 +01:00
}
func getCallExprLitArg(callExpr *syntax.CallExpr, argNum int) string {
if len(callExpr.Args) <= argNum {
return ""
}
arg := callExpr.Args[argNum]
if len(arg.Parts) == 0 {
return ""
}
lit, ok := arg.Parts[0].(*syntax.Lit)
if !ok {
return ""
}
return lit.Value
}
func isRtnStateCmd(cmd syntax.Command) bool {
if cmd == nil {
return false
}
if _, ok := cmd.(*syntax.FuncDecl); ok {
return true
}
if blockExpr, ok := cmd.(*syntax.Block); ok {
for _, stmt := range blockExpr.Stmts {
if isRtnStateCmd(stmt.Cmd) {
return true
}
}
return false
}
if binExpr, ok := cmd.(*syntax.BinaryCmd); ok {
if isRtnStateCmd(binExpr.X.Cmd) || isRtnStateCmd(binExpr.Y.Cmd) {
return true
}
} else if callExpr, ok := cmd.(*syntax.CallExpr); ok {
if len(callExpr.Assigns) > 0 && len(callExpr.Args) == 0 {
return true
}
arg0 := getCallExprLitArg(callExpr, 0)
if arg0 != "" && utilfn.ContainsStr(literalRtnStateCommands, arg0) {
return true
}
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
arg1 := getCallExprLitArg(callExpr, 1)
if arg0 == "git" {
if arg1 == "checkout" || arg1 == "co" || arg1 == "switch" {
return true
}
}
if arg0 == "conda" {
if arg1 == "activate" || arg1 == "deactivate" {
return true
}
}
} else if _, ok := cmd.(*syntax.DeclClause); ok {
return true
}
return false
}
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
func checkSimpleRtnStateCmd(cmdStr string) bool {
cmdStr = strings.TrimSpace(cmdStr)
if strings.HasPrefix(cmdStr, "function ") {
return true
}
firstSpace := strings.Index(cmdStr, " ")
if firstSpace != -1 {
firstWord := strings.TrimSpace(cmdStr[:firstSpace])
if strings.HasSuffix(firstWord, "()") {
return true
}
}
return false
}
// 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 {
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
if checkSimpleRtnStateCmd(cmdStr) {
return true
}
return false
}
for _, stmt := range file.Stmts {
if isRtnStateCmd(stmt.Cmd) {
return true
}
}
return false
}
Sudo Caching (#573) * feat: share sudo between pty sessions This is a first pass at a feature to cache the sudo password and share it between different pty sessions. This makes it possible to not require manual password entry every time sudo is used. * feat: allow error handling and canceling sudo cmds This adds the missing functionality that prevented failed sudo commands from automatically closing. * feat: restrict sudo caching to dev mode for now * modify fullCmdStr not pk.Command * refactor: condense ecdh encryptor creation This refactors the common pieces needed to create an encryptor from an ecdh key pair into a common function. * refactor: rename promptenc to waveenc * feat: add command to clear sudo password We currently do not provide use of the sudo -k and sudo -K commands to clear the sudo password. This adds a /sudo:clear command to handle it in the meantime. * feat: add kwarg to force sudo In cases where parsing for sudo doesn't work, this provides an alternate wave kwarg to use instead. It can be used with [sudo=1] at the beginning of a command. * refactor: simplify sudoArg parsing * feat: allow user to clear all sudo passwords This introduces the "all" kwarg for the sudo:clear command in order to clear all sudo passwords. * fix: handle deadline with real time Golang's time module uses monatomic time by default, but that is not desired for the password timeout since we want the timer to continue even if the computer is asleep. We now avoid this by directly comparing the unix timestamps. * fix: remove sudo restriction to dev mode This allows it to be used in regular builds as well. * fix: switch to password timeout without wait group This removes an unnecessary waiting period for sudo password entry. * fix: update deadline in sudo:clear This allows sudo:clear to cancel the goroutine for watching the password timer. * fix: pluralize sudo:clear message when all=1 This changes the output message for /sudo:clear to indicate multiple passwords cleared if the all=1 kwarg is used. * fix: use GetRemoteMap for getting remotes in clear The sudo:clear command was directly looping over the GlobalStore.Map which is not thread safe. Switched to GetRemoteMap which uses a lock internally. * fix: allow sudo metacmd to set sudo false This fixes the logic for resolving if a command is a sudo command. This change makes it possible for the sudo metacmd kwarg to force sudo to be false.
2024-04-17 01:58:17 +02:00
func checkSimpleSudoCmd(cmdStr string) bool {
cmdStr = strings.TrimSpace(cmdStr)
return strings.HasPrefix(cmdStr, "sudo ")
}
func isSudoCmd(cmd syntax.Command) bool {
if cmd == nil {
return false
}
if _, ok := cmd.(*syntax.FuncDecl); ok {
return false
}
if blockExpr, ok := cmd.(*syntax.Block); ok {
for _, stmt := range blockExpr.Stmts {
if isSudoCmd(stmt.Cmd) {
return true
}
}
return false
}
if binExpr, ok := cmd.(*syntax.BinaryCmd); ok {
if isSudoCmd(binExpr.X.Cmd) || isSudoCmd(binExpr.Y.Cmd) {
return true
}
} else if callExpr, ok := cmd.(*syntax.CallExpr); ok {
arg0 := getCallExprLitArg(callExpr, 0)
if arg0 != "" && utilfn.ContainsStr([]string{"sudo"}, arg0) {
return true
}
}
return false
}
func IsSudoCommand(cmdStr string) bool {
cmdReader := strings.NewReader(cmdStr)
parser := syntax.NewParser(syntax.Variant(syntax.LangBash))
file, err := parser.Parse(cmdReader, "sudo")
if err != nil {
return checkSimpleSudoCmd(cmdStr)
}
for _, stmt := range file.Stmts {
if isSudoCmd(stmt.Cmd) {
return true
}
}
return false
}
2022-10-26 23:51:12 +02:00
func EvalBracketArgs(origCmdStr string) (map[string]string, string, error) {
rtn := make(map[string]string)
if strings.HasPrefix(origCmdStr, " ") {
reinit updates (#500) * 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
2024-03-27 08:22:57 +01:00
rtn[KwArgNoHist] = "1"
2022-10-26 23:51:12 +02:00
}
cmdStr := strings.TrimSpace(origCmdStr)
if !strings.HasPrefix(cmdStr, "[") {
return rtn, origCmdStr, nil
}
rbIdx := strings.Index(cmdStr, "]")
if rbIdx == -1 {
return nil, "", fmt.Errorf("unmatched '[' found in command")
}
bracketStr := cmdStr[1:rbIdx]
restStr := strings.TrimSpace(cmdStr[rbIdx+1:])
err := setBracketArgs(rtn, bracketStr)
if err != nil {
return nil, "", err
}
return rtn, restStr, nil
}
2023-09-16 20:15:09 +02:00
func unescapeBackSlashes(s string) string {
if strings.Index(s, "\\") == -1 {
return s
}
var newStr []rune
var lastSlash bool
for _, r := range s {
if lastSlash {
lastSlash = false
newStr = append(newStr, r)
continue
}
if r == '\\' {
lastSlash = true
continue
}
newStr = append(newStr, r)
}
return string(newStr)
}
2022-08-26 22:12:17 +02:00
func EvalMetaCommand(ctx context.Context, origPk *scpacket.FeCommandPacketType) (*scpacket.FeCommandPacketType, error) {
if len(origPk.Args) == 0 {
return nil, fmt.Errorf("empty command (no fields)")
}
if strings.TrimSpace(origPk.Args[0]) == "" {
return nil, fmt.Errorf("empty command")
}
bracketArgs, cmdStr, err := EvalBracketArgs(origPk.Args[0])
if err != nil {
return nil, err
}
metaCmd, metaSubCmd, commandArgs := parseMetaCmd(cmdStr)
2022-08-26 22:12:17 +02:00
rtnPk := scpacket.MakeFeCommandPacket()
rtnPk.MetaCmd = metaCmd
rtnPk.MetaSubCmd = metaSubCmd
rtnPk.Kwargs = make(map[string]string)
rtnPk.UIContext = origPk.UIContext
2022-10-19 03:03:02 +02:00
rtnPk.RawStr = origPk.RawStr
2023-12-18 08:46:53 +01:00
rtnPk.Interactive = origPk.Interactive
rtnPk.EphemeralOpts = origPk.EphemeralOpts
2022-08-26 22:12:17 +02:00
for key, val := range origPk.Kwargs {
rtnPk.Kwargs[key] = val
}
for key, val := range bracketArgs {
rtnPk.Kwargs[key] = val
}
2022-08-26 22:12:17 +02:00
if onlyRawArgs(metaCmd, metaSubCmd) {
// don't evaluate arguments for /run or /comment
rtnPk.Args = []string{commandArgs}
return rtnPk, nil
}
commandReader := strings.NewReader(commandArgs)
parser := syntax.NewParser(syntax.Variant(syntax.LangBash))
var words []*syntax.Word
err = parser.Words(commandReader, func(w *syntax.Word) bool {
2022-08-26 22:12:17 +02:00
words = append(words, w)
return true
})
if err != nil {
return nil, fmt.Errorf("parsing metacmd, position %v", err)
}
2023-03-15 00:37:22 +01:00
envMap := make(map[string]string) // later we can add vars like session, screen, remote, and user
zsh support (#227) adds zsh support to waveterm. big change, lots going on here. lots of other improvements and bug fixes added while debugging and building out the feature. Commits: * refactor shexec parser.go into new package shellenv. separate out bash specific parsing from generic functions * checkpoint * work on refactoring shexec. created two new packages shellapi (for bash/zsh specific stuff), and shellutil (shared between shellapi and shexec) * more refactoring * create shellapi interface to abstract bash specific functionality * more refactoring, move bash shell state parsing to shellapi * move makeRcFile to shellapi. remove all of the 'client' options CLI options from waveshell * get shellType passed through to server/single paths for waveshell * add a local shelltype detector * mock out a zshapi * move shelltype through more of the code * get a command to run via zsh * zsh can now switch directories. poc, needs cleanup * working on ShellState encoding differences between zsh/bash. Working on parsing zsh decls. move utilfn package into waveshell (shouldn't have been in wavesrv) * switch to use []byte for vardecl serialization + diffs * progress on zsh environment. still have issues reconciling init environment with trap environment * fix typeset argument parsing * parse promptvars, more zsh specific ignores * fix bug with promptvar not getting set (wrong check in FeState func) * add sdk (issue #188) to list of rtnstate commands * more zsh compatibility -- working with a larger ohmyzsh environment. ignore more variables, handle exit trap better. unique path/fpath. add a processtype variable to base. * must return a value * zsh alias parsing/restoring. diff changes (and rtnstate changes). introduces linediff v1. * force zmodload of zsh/parameter * starting work on zsh functions * need a v1 of mapdiff as well (to handle null chars) * pack/unpack of ints was wrong (one used int and one use uint). turned out we only ever encoded '0' so it worked. that also means it is safe to change unpack to unpackUInt * reworking for binary encoding of aliases and functions (because of zsh allows any character, including nulls, in names and values) * fixes, working on functions, issue with line endings * zsh functions. lots of ugliness here around dealing with line dicipline and cooked stty. new runcommand function to grab output from a non-tty fd. note that we still to run the actual command in a stty to get the proper output. * write uuid tempdir, cleanup with tmprcfilename code * hack in some simple zsh function declaration finding code for rtnstate. create function diff for rtnstate that supports zsh * make sure key order is constant so shell hashes are consistent * fix problems with state diffs to support new zsh formats. add diff/apply code to shellapi (moved from shellenv), that is now specific to zsh or bash * add log packet and new shellstate packets * switch to shellstate map that's also keyed by shelltype * add shelltype to remoteinstance * remove shell argument from waveshell * added new shelltype statemap to remote.go (msh), deal with fallout * move shellstate out of init packet, and move to an explicit reinit call. try to initialize all of the active shell states * change dont always store init state (only store on demand). initialize shell states on demand (if not already initialized). allow reset to change shells * add shellpref field to remote table. use to drive the default shell choice for new tabs * show shelltag on cmdinput, pass through ri and remote (defaultshellstate) * bump mshell version to v0.4 * better version validation for shellstate. also relax compatibility requirements for diffing states (shelltype + major version need to match) * better error handling, check shellstate compatibility during run (on waveshell server) * add extra separator for bash shellstate processing to deal with spurious output from rc files * special migration for v30 -- flag invalid bash shell states and show special button in UI to fix * format * remove zsh-decls (unused) * remove test code * remove debug print * fix typo
2024-01-17 01:11:04 +01:00
cfg := shellapi.GetParserConfig(envMap)
2022-08-26 22:12:17 +02:00
// process arguments
for idx, w := range words {
literalVal, err := expand.Literal(cfg, w)
if err != nil {
return nil, fmt.Errorf("error evaluating metacmd argument %d [%s]: %v", idx+1, getSourceStr(commandArgs, w), err)
}
if isQuoted(commandArgs, w) || onlyPositionalArgs(metaCmd, metaSubCmd) {
rtnPk.Args = append(rtnPk.Args, literalVal)
continue
}
eqIdx := strings.Index(literalVal, "=")
if eqIdx != -1 && eqIdx != 0 {
varName := literalVal[:eqIdx]
varVal := literalVal[eqIdx+1:]
rtnPk.Kwargs[varName] = varVal
continue
}
2023-09-16 20:15:09 +02:00
rtnPk.Args = append(rtnPk.Args, unescapeBackSlashes(literalVal))
2022-08-26 22:12:17 +02:00
}
if resolveBool(rtnPk.Kwargs["dump"], false) {
DumpPacket(rtnPk)
}
2022-08-26 22:12:17 +02:00
return rtnPk, nil
}