diff --git a/stdlib/stdlib.go b/stdlib/stdlib.go index 9080b15..83f40fd 100644 --- a/stdlib/stdlib.go +++ b/stdlib/stdlib.go @@ -143,6 +143,13 @@ func GenFuncTable() ast.FuncTable { Args: -1, }, + "split": &ast.Function{ + Function: Split, + Name: "split", + TimesCalled: 0, + Args: 2, + }, + "exit": &ast.Function{ Function: ExitShell, Name: "exit", diff --git a/stdlib/string.go b/stdlib/string.go index 3cae616..e9f00be 100644 --- a/stdlib/string.go +++ b/stdlib/string.go @@ -19,6 +19,7 @@ package stdlib import ( "fmt" + "strings" "strconv" "gitlab.com/whom/shs/ast" "gitlab.com/whom/shs/log" @@ -59,6 +60,47 @@ func StrCast(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { return res } +/* Takes 2 arguments, a string and a delimiter + * returns a list of substrings found delimited by the delimiter from the parent string + * Filters out all empty segments between delimiters + * + * Example: (split "/path/to/file" "/") -> ("path" "to" "file") + */ +func Split(in *ast.Token, vt ast.VarTable, ft ast.FuncTable) *ast.Token { + in = in.Eval(ft, vt, false) + if in == nil || in.Tag != ast.STRING || in.Next == nil || in.Next.Tag != ast.STRING { + log.Log(log.ERR, + "Args must be two strings", + "split") + return nil + } + + body := in.Value() + delim := in.Next.Value() + if len(body) < len(delim) { + log.Log(log.DEBUG, + "possibly mismatched args" + + "delimiter longer than body", + "split") + } + + var res *ast.Token + builder := &res + strtoks := strings.Split(body, delim) + for _, i := range strtoks { + if i == "" { + continue + } + + *builder = &ast.Token{Tag: ast.STRING} + (*builder).Set(i) + builder = &(*builder).Next + } + + return res +} + + /* Takes one arg, returns nil * Prints a string to stdout * Unquotes string so user can add escaped chars like \n, \t, etc